@final-commerce/common 2.3.0-staging.7 → 2.3.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.js CHANGED
@@ -21,11 +21,6 @@ var index_exports = {};
21
21
  __export(index_exports, {
22
22
  ADYEN_ROLLOUT_COUNTRY_CODES: () => ADYEN_ROLLOUT_COUNTRY_CODES,
23
23
  AttributeType: () => AttributeType,
24
- BookingRatePeriod: () => BookingRatePeriod,
25
- BookingResourceKind: () => BookingResourceKind,
26
- BookingResourceStatus: () => BookingResourceStatus,
27
- BookingRulesError: () => BookingRulesError,
28
- BookingType: () => BookingType,
29
24
  CONDITION_OPERATORS: () => CONDITION_OPERATORS,
30
25
  COUNTRY_CURRENCIES: () => COUNTRY_CURRENCIES,
31
26
  CURRENCY_CONFIG: () => CURRENCY_CONFIG,
@@ -36,7 +31,6 @@ __export(index_exports, {
36
31
  DEFAULT_CONFIG: () => DEFAULT_CONFIG,
37
32
  DEFAULT_CROSS_AXIS_RULES: () => DEFAULT_CROSS_AXIS_RULES,
38
33
  DEFAULT_DISPLAY_STATE_MAP: () => DEFAULT_DISPLAY_STATE_MAP,
39
- DEFAULT_HOLD_MINUTES: () => DEFAULT_HOLD_MINUTES,
40
34
  DEFAULT_RESOLVED_CONFIG: () => DEFAULT_RESOLVED_CONFIG,
41
35
  DEFAULT_UNIT_ID: () => DEFAULT_UNIT_ID,
42
36
  DualWriteStrategy: () => DualWriteStrategy,
@@ -80,10 +74,8 @@ __export(index_exports, {
80
74
  REPORT_NEGATE_PATHS: () => REPORT_NEGATE_PATHS,
81
75
  ReceiptSendChannel: () => ReceiptSendChannel,
82
76
  ReceiptType: () => ReceiptType,
83
- ReservationStatus: () => ReservationStatus,
84
77
  ResidualPaymentMethod: () => ResidualPaymentMethod,
85
78
  ResidualStatus: () => ResidualStatus,
86
- ResourceAvailabilityState: () => ResourceAvailabilityState,
87
79
  STATE_SCHEMA: () => STATE_SCHEMA,
88
80
  STRIPE_SUPPORTED_COUNTRIES: () => STRIPE_SUPPORTED_COUNTRIES,
89
81
  SYSTEM_FAMILIES: () => SYSTEM_FAMILIES,
@@ -104,8 +96,6 @@ __export(index_exports, {
104
96
  baseFulfillmentDefinitions: () => baseFulfillmentDefinitions,
105
97
  baseOf: () => baseOf,
106
98
  basePaymentDefinitions: () => basePaymentDefinitions,
107
- buildAvailability: () => buildAvailability,
108
- buildGrid: () => buildGrid,
109
99
  buildOrderContext: () => buildOrderContext,
110
100
  buildPosPresetConfig: () => buildPosPresetConfig,
111
101
  buildResolvedConfig: () => buildResolvedConfig,
@@ -145,7 +135,6 @@ __export(index_exports, {
145
135
  getPricingRegionFromCountry: () => getPricingRegionFromCountry,
146
136
  getSettlementTotal: () => getSettlementTotal,
147
137
  getTotalCollected: () => getTotalCollected,
148
- holdExpiresAt: () => holdExpiresAt,
149
138
  inferStatesFromLegacyStatus: () => inferStatesFromLegacyStatus,
150
139
  isAdyenRolloutCountry: () => isAdyenRolloutCountry,
151
140
  isConditionOperator: () => isConditionOperator,
@@ -160,12 +149,9 @@ __export(index_exports, {
160
149
  mergeFragment: () => mergeFragment,
161
150
  multiplyAmount: () => multiplyAmount,
162
151
  normalizeMongoIdString: () => normalizeMongoIdString,
163
- occupancyIn: () => occupancyIn,
164
152
  parseAmountToMinorUnits: () => parseAmountToMinorUnits,
165
153
  parseCurrencyCode: () => parseCurrencyCode,
166
154
  parseStripeCurrencyCode: () => parseStripeCurrencyCode,
167
- planWindow: () => planWindow,
168
- presentAt: () => presentAt,
169
155
  removeFragment: () => removeFragment,
170
156
  resolveFamily: () => resolveFamily,
171
157
  resolveTemplate: () => resolveTemplate,
@@ -174,16 +160,13 @@ __export(index_exports, {
174
160
  sameFamily: () => sameFamily,
175
161
  setOrderState: () => setOrderState,
176
162
  signReportForDisplay: () => signReportForDisplay,
177
- slotsForWindow: () => slotsForWindow,
178
163
  stringifyMinorUnits: () => stringifyMinorUnits,
179
164
  subtractAmounts: () => subtractAmounts,
180
165
  toBase: () => toBase,
181
166
  toMinorUnits: () => toMinorUnits,
182
167
  validateConfig: () => validateConfig,
183
168
  validateFragmentCompatibility: () => validateFragmentCompatibility,
184
- violatesFinancialInvariant: () => violatesFinancialInvariant,
185
- windowEndsAt: () => windowEndsAt,
186
- withinPresence: () => withinPresence
169
+ violatesFinancialInvariant: () => violatesFinancialInvariant
187
170
  });
188
171
  module.exports = __toCommonJS(index_exports);
189
172
 
@@ -611,7 +594,6 @@ var StripeCurrencyCode = /* @__PURE__ */ ((StripeCurrencyCode2) => {
611
594
  var ProductType = /* @__PURE__ */ ((ProductType2) => {
612
595
  ProductType2["SIMPLE"] = "simple";
613
596
  ProductType2["VARIABLE"] = "variable";
614
- ProductType2["BOOKING"] = "booking";
615
597
  return ProductType2;
616
598
  })(ProductType || {});
617
599
  var ProductStatus = /* @__PURE__ */ ((ProductStatus2) => {
@@ -629,50 +611,6 @@ var PaymentProcessor = /* @__PURE__ */ ((PaymentProcessor2) => {
629
611
  return PaymentProcessor2;
630
612
  })(PaymentProcessor || {});
631
613
 
632
- // enums/booking.enum.ts
633
- var BookingType = /* @__PURE__ */ ((BookingType3) => {
634
- BookingType3["RENTAL"] = "rental";
635
- BookingType3["APPOINTMENT"] = "appointment";
636
- BookingType3["OVERNIGHT"] = "overnight";
637
- BookingType3["GROUP"] = "group";
638
- return BookingType3;
639
- })(BookingType || {});
640
- var BookingRatePeriod = /* @__PURE__ */ ((BookingRatePeriod2) => {
641
- BookingRatePeriod2["SLOT"] = "slot";
642
- BookingRatePeriod2["DAY"] = "day";
643
- BookingRatePeriod2["NIGHT"] = "night";
644
- BookingRatePeriod2["WEEK"] = "week";
645
- BookingRatePeriod2["MONTH"] = "month";
646
- return BookingRatePeriod2;
647
- })(BookingRatePeriod || {});
648
- var BookingResourceKind = /* @__PURE__ */ ((BookingResourceKind2) => {
649
- BookingResourceKind2["ASSET"] = "asset";
650
- BookingResourceKind2["ROOM"] = "room";
651
- BookingResourceKind2["PROPERTY"] = "property";
652
- BookingResourceKind2["SPACE"] = "space";
653
- BookingResourceKind2["STAFF"] = "staff";
654
- BookingResourceKind2["TABLE"] = "table";
655
- return BookingResourceKind2;
656
- })(BookingResourceKind || {});
657
- var ReservationStatus = /* @__PURE__ */ ((ReservationStatus2) => {
658
- ReservationStatus2["HELD"] = "held";
659
- ReservationStatus2["CONFIRMED"] = "confirmed";
660
- ReservationStatus2["CANCELLED"] = "cancelled";
661
- ReservationStatus2["EXPIRED"] = "expired";
662
- return ReservationStatus2;
663
- })(ReservationStatus || {});
664
- var BookingResourceStatus = /* @__PURE__ */ ((BookingResourceStatus2) => {
665
- BookingResourceStatus2["ACTIVE"] = "active";
666
- BookingResourceStatus2["INACTIVE"] = "inactive";
667
- return BookingResourceStatus2;
668
- })(BookingResourceStatus || {});
669
- var ResourceAvailabilityState = /* @__PURE__ */ ((ResourceAvailabilityState2) => {
670
- ResourceAvailabilityState2["AVAILABLE"] = "available";
671
- ResourceAvailabilityState2["FULLY_BOOKED"] = "fullyBooked";
672
- ResourceAvailabilityState2["NO_HOURS_IN_RANGE"] = "noHoursInRange";
673
- return ResourceAvailabilityState2;
674
- })(ResourceAvailabilityState || {});
675
-
676
614
  // utils/currency.util.ts
677
615
  var CURRENCY_CONFIG = {
678
616
  // Major currencies with 2 decimal places
@@ -1479,6 +1417,8 @@ var REPORT_NEGATE_PATHS = /* @__PURE__ */ new Set([
1479
1417
  // Fees breakdown — refunded magnitudes are money flowing back out
1480
1418
  "feesBreakdown.productFee.refundedProductFees",
1481
1419
  "feesBreakdown.cartFee.refundedCartFees",
1420
+ // Modifiers breakdown — refunded magnitudes are money flowing back out
1421
+ "modifiersBreakdown.refundTotal",
1482
1422
  // Discounts breakdown — refunded magnitudes reverse discount reductions
1483
1423
  "discountsBreakdown.productDiscounts.refundedProductDiscounts",
1484
1424
  "discountsBreakdown.cartDiscounts.refundedCartDiscounts",
@@ -1882,15 +1822,6 @@ function sumRefundQuantities(refunds) {
1882
1822
  }
1883
1823
  return t;
1884
1824
  }
1885
- var asCount = (value) => typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : 0;
1886
- function countsOf(row) {
1887
- const quantity = asCount(row.quantity);
1888
- return {
1889
- quantity,
1890
- fulfilled: Math.min(asCount(row.fulfilledQuantity), quantity),
1891
- returned: Math.min(asCount(row.returnedQuantity), quantity)
1892
- };
1893
- }
1894
1825
  function buildOrderContext(order, extras) {
1895
1826
  const o = order ?? {};
1896
1827
  const total = typeof o.total === "number" && Number.isFinite(o.total) ? o.total : 0;
@@ -1898,7 +1829,6 @@ function buildOrderContext(order, extras) {
1898
1829
  const paymentMethods = o.paymentMethods ?? [];
1899
1830
  const refunds = o.refunds ?? o.refund ?? [];
1900
1831
  const lineItems = o.lineItems ?? [];
1901
- const reservations = o.reservations ?? [];
1902
1832
  const totalPaid = sumNumbers(paymentMethods);
1903
1833
  const totalRefunded = sumRefundQuantities(refunds);
1904
1834
  const isFullyPaid = total > 0 ? balance <= 0 : totalPaid > 0 && balance <= 0;
@@ -1906,11 +1836,13 @@ function buildOrderContext(order, extras) {
1906
1836
  let itemCount = 0;
1907
1837
  let fulfilledItemCount = 0;
1908
1838
  let returnedItemCount = 0;
1909
- for (const row of [...lineItems, ...reservations]) {
1910
- const { quantity, fulfilled, returned } = countsOf(row);
1911
- itemCount += quantity;
1912
- fulfilledItemCount += fulfilled;
1913
- returnedItemCount += returned;
1839
+ for (const li of lineItems) {
1840
+ const q = typeof li.quantity === "number" && Number.isFinite(li.quantity) ? Math.max(0, li.quantity) : 0;
1841
+ itemCount += q;
1842
+ const fq = typeof li.fulfilledQuantity === "number" && Number.isFinite(li.fulfilledQuantity) ? Math.max(0, li.fulfilledQuantity) : 0;
1843
+ fulfilledItemCount += Math.min(fq, q);
1844
+ const rq = typeof li.returnedQuantity === "number" && Number.isFinite(li.returnedQuantity) ? Math.max(0, li.returnedQuantity) : 0;
1845
+ returnedItemCount += Math.min(rq, q);
1914
1846
  }
1915
1847
  const isFullyReturned = itemCount > 0 ? returnedItemCount >= itemCount : returnedItemCount > 0;
1916
1848
  const hasPartialReturns = returnedItemCount > 0 && !isFullyReturned;
@@ -1920,8 +1852,7 @@ function buildOrderContext(order, extras) {
1920
1852
  balance,
1921
1853
  paymentMethods,
1922
1854
  refunds,
1923
- lineItems,
1924
- reservations
1855
+ lineItems
1925
1856
  },
1926
1857
  computed: {
1927
1858
  balance,
@@ -3001,358 +2932,6 @@ var ORDER_STATE_EVENTS = {
3001
2932
  configUpdated: "config-updated"
3002
2933
  };
3003
2934
 
3004
- // booking/types.ts
3005
- var BookingRulesError = class extends Error {
3006
- constructor(message) {
3007
- super(message);
3008
- this.name = "BookingRulesError";
3009
- }
3010
- };
3011
-
3012
- // booking/zoned-time.ts
3013
- var MINUTE = 6e4;
3014
- var formatters = /* @__PURE__ */ new Map();
3015
- var formatterFor = (timeZone) => {
3016
- const existing = formatters.get(timeZone);
3017
- if (existing) return existing;
3018
- let created;
3019
- try {
3020
- created = new Intl.DateTimeFormat("en-US", {
3021
- timeZone,
3022
- hour12: false,
3023
- year: "numeric",
3024
- month: "2-digit",
3025
- day: "2-digit",
3026
- hour: "2-digit",
3027
- minute: "2-digit",
3028
- second: "2-digit",
3029
- weekday: "short"
3030
- });
3031
- } catch {
3032
- throw new BookingRulesError(`Booking rules: "${timeZone}" is not a known time zone`);
3033
- }
3034
- formatters.set(timeZone, created);
3035
- return created;
3036
- };
3037
- var WEEKDAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
3038
- function zonedParts(instant, timeZone) {
3039
- const parts = {};
3040
- for (const { type, value } of formatterFor(timeZone).formatToParts(instant)) parts[type] = value;
3041
- const hour = Number(parts.hour) % 24;
3042
- return {
3043
- year: Number(parts.year),
3044
- month: Number(parts.month),
3045
- day: Number(parts.day),
3046
- hour,
3047
- minute: Number(parts.minute),
3048
- second: Number(parts.second),
3049
- weekday: WEEKDAYS.indexOf(parts.weekday)
3050
- };
3051
- }
3052
- function offsetAt(instant, timeZone) {
3053
- const { year, month, day, hour, minute, second } = zonedParts(instant, timeZone);
3054
- return Date.UTC(year, month - 1, day, hour, minute, second) - Math.floor(instant.getTime() / 1e3) * 1e3;
3055
- }
3056
- function instantFromLocal(year, month, day, minutes, timeZone) {
3057
- const naive = Date.UTC(year, month - 1, day) + minutes * MINUTE;
3058
- const firstGuess = naive - offsetAt(new Date(naive), timeZone);
3059
- return new Date(naive - offsetAt(new Date(firstGuess), timeZone));
3060
- }
3061
- function startOfZonedDay(instant, timeZone) {
3062
- const { year, month, day } = zonedParts(instant, timeZone);
3063
- return instantFromLocal(year, month, day, 0, timeZone);
3064
- }
3065
- function nextZonedDay(dayStart, timeZone) {
3066
- const { year, month, day } = zonedParts(dayStart, timeZone);
3067
- return instantFromLocal(year, month, day + 1, 0, timeZone);
3068
- }
3069
- function atZonedMinute(dayStart, minutes, timeZone) {
3070
- const { year, month, day } = zonedParts(dayStart, timeZone);
3071
- return instantFromLocal(year, month, day, minutes, timeZone);
3072
- }
3073
-
3074
- // booking/grid.ts
3075
- var MINUTE2 = 6e4;
3076
- var MAX_RANGE_DAYS = 366;
3077
- var asTime = (value, field) => {
3078
- if (value == null) return void 0;
3079
- const time = new Date(value).getTime();
3080
- if (Number.isNaN(time)) throw new BookingRulesError(`Booking rules: ${field} is not a date, got "${String(value)}"`);
3081
- return time;
3082
- };
3083
- function parseHhMm(value, field) {
3084
- const [hours, minutes] = value.split(":").map(Number);
3085
- if (!Number.isInteger(hours) || !Number.isInteger(minutes)) {
3086
- throw new BookingRulesError(`Booking rules: ${field} must be "HH:mm", got "${value}"`);
3087
- }
3088
- return hours * 60 + minutes;
3089
- }
3090
- function windowEndsAt(rule, now) {
3091
- const { maxAdvanceDays, bookableTo } = rule.window;
3092
- const ends = Math.min(
3093
- maxAdvanceDays ? now.getTime() + maxAdvanceDays * 1440 * MINUTE2 : Number.POSITIVE_INFINITY,
3094
- asTime(bookableTo, "window.bookableTo") ?? Number.POSITIVE_INFINITY
3095
- );
3096
- return Number.isFinite(ends) ? new Date(ends) : null;
3097
- }
3098
- function periodSlot(dayStart, timeZone, rule, openMinute, closeMinute) {
3099
- const { ratePeriod, slot, checkInTime, checkOutTime } = rule;
3100
- const at = (minutes) => atZonedMinute(dayStart, minutes, timeZone);
3101
- if (ratePeriod === "night" /* NIGHT */) {
3102
- if (!checkInTime || !checkOutTime) {
3103
- throw new BookingRulesError("Overnight booking rules need both checkInTime and checkOutTime");
3104
- }
3105
- const checkIn = parseHhMm(checkInTime, "checkInTime");
3106
- const checkOut = parseHhMm(checkOutTime, "checkOutTime");
3107
- return {
3108
- startAt: at(checkIn),
3109
- endAt: at(1440 + checkOut),
3110
- // Housekeeping sits between check-out and the next check-in: it costs no night.
3111
- bufferEndAt: at(1440 + checkIn),
3112
- canStart: true
3113
- };
3114
- }
3115
- const from = ratePeriod === "day" /* DAY */ ? openMinute ?? 0 : 0;
3116
- const to = ratePeriod === "day" /* DAY */ ? closeMinute ?? 1440 : 1440;
3117
- return {
3118
- startAt: at(from),
3119
- endAt: at(to),
3120
- bufferEndAt: at(to + (slot.bufferMinutes ?? 0)),
3121
- canStart: true
3122
- };
3123
- }
3124
- function freeGaps(openAt, closeAt, busy) {
3125
- const inside = busy.map(({ startAt, bufferEndAt }) => ({ from: +startAt, to: +bufferEndAt })).filter(({ from, to }) => to > openAt && from < closeAt).sort((first, second) => first.from - second.from);
3126
- const gaps = [];
3127
- let cursor = openAt;
3128
- for (const { from, to } of inside) {
3129
- if (from > cursor) gaps.push({ from: cursor, to: from, endsAtBooking: true });
3130
- cursor = Math.max(cursor, to);
3131
- if (cursor >= closeAt) break;
3132
- }
3133
- if (cursor < closeAt) gaps.push({ from: cursor, to: closeAt, endsAtBooking: false });
3134
- return gaps;
3135
- }
3136
- function buildGrid(rule, timeZone, from, to, now, busy = []) {
3137
- if (to.getTime() - from.getTime() > MAX_RANGE_DAYS * 1440 * MINUTE2) {
3138
- throw new BookingRulesError(`A booking range may span at most ${MAX_RANGE_DAYS} days`);
3139
- }
3140
- const { availability, slot, window, ratePeriod } = rule;
3141
- const periodMode = ratePeriod !== "slot" /* SLOT */;
3142
- const weeklyHours = availability.weeklyHours ?? [];
3143
- const notBefore = Math.max(
3144
- now.getTime() + (window.minNoticeMinutes ?? 0) * MINUTE2,
3145
- asTime(window.bookableFrom, "window.bookableFrom") ?? 0,
3146
- asTime(availability.availableFrom, "availability.availableFrom") ?? 0
3147
- );
3148
- const notAfter = windowEndsAt(rule, now)?.getTime() ?? Number.POSITIVE_INFINITY;
3149
- const blocked = (availability.offMarket ?? []).map(({ from: blockFrom, to: blockTo }) => ({
3150
- from: asTime(blockFrom, "availability.offMarket.from"),
3151
- to: asTime(blockTo, "availability.offMarket.to")
3152
- }));
3153
- const arrivalDays = availability.arrivalDays;
3154
- const step = slot.lengthMinutes + (slot.bufferMinutes ?? 0);
3155
- const slots = [];
3156
- const lastDay = startOfZonedDay(to, timeZone).getTime();
3157
- let dayStart = startOfZonedDay(from, timeZone);
3158
- while (dayStart.getTime() <= lastDay) {
3159
- const weekday = zonedParts(dayStart, timeZone).weekday;
3160
- const rows = weeklyHours.filter((entry) => entry.weekday === weekday);
3161
- if (periodMode) {
3162
- const openToday = weeklyHours.length === 0 || rows.length > 0;
3163
- if (openToday) {
3164
- const built = periodSlot(dayStart, timeZone, rule, rows[0]?.openMinute, rows[0]?.closeMinute);
3165
- slots.push({ ...built, canStart: !arrivalDays?.length || arrivalDays.includes(weekday) });
3166
- }
3167
- } else {
3168
- for (const row of rows) {
3169
- const openAt = +atZonedMinute(dayStart, row.openMinute, timeZone);
3170
- const closeAt = +atZonedMinute(dayStart, row.closeMinute, timeZone);
3171
- for (const gap of freeGaps(openAt, closeAt, busy)) {
3172
- const mustFit = (gap.endsAtBooking ? step : slot.lengthMinutes) * MINUTE2;
3173
- for (let start = gap.from; start + mustFit <= gap.to; start += step * MINUTE2) {
3174
- slots.push({
3175
- startAt: new Date(start),
3176
- endAt: new Date(start + slot.lengthMinutes * MINUTE2),
3177
- bufferEndAt: new Date(start + step * MINUTE2),
3178
- canStart: true
3179
- });
3180
- }
3181
- }
3182
- }
3183
- }
3184
- dayStart = nextZonedDay(dayStart, timeZone);
3185
- }
3186
- const askedFrom = from.getTime();
3187
- const askedTo = to.getTime();
3188
- return slots.filter(({ startAt, bufferEndAt }) => {
3189
- const start = startAt.getTime();
3190
- if (start < askedFrom || start >= askedTo) return false;
3191
- if (start < notBefore || start > notAfter) return false;
3192
- return !blocked.some(({ from: blockFrom, to: blockTo }) => start < blockTo && bufferEndAt.getTime() > blockFrom);
3193
- }).sort((first, second) => +first.startAt - +second.startAt);
3194
- }
3195
- function slotsForWindow(grid, startAt, endAt) {
3196
- const startIndex = grid.findIndex((entry) => entry.startAt.getTime() === startAt.getTime());
3197
- if (startIndex < 0) {
3198
- throw new BookingRulesError(`${startAt.toISOString()} is not a bookable slot start for these rules`);
3199
- }
3200
- if (!grid[startIndex].canStart) {
3201
- throw new BookingRulesError(`${startAt.toISOString()} is not an arrival day for these rules`);
3202
- }
3203
- const covered = [];
3204
- for (let index = startIndex; index < grid.length; index++) {
3205
- const entry = grid[index];
3206
- const previous = covered[covered.length - 1];
3207
- if (previous && entry.startAt.getTime() !== previous.bufferEndAt.getTime()) break;
3208
- covered.push(entry);
3209
- if (entry.endAt.getTime() === endAt.getTime()) return covered;
3210
- if (entry.endAt.getTime() > endAt.getTime()) break;
3211
- }
3212
- throw new BookingRulesError(
3213
- `${startAt.toISOString()} \u2192 ${endAt.toISOString()} does not line up with the bookable grid`
3214
- );
3215
- }
3216
-
3217
- // booking/availability.ts
3218
- var withinPresence = (slot, timeZone, presence) => {
3219
- if (!presence?.length) return true;
3220
- const dayStart = startOfZonedDay(slot.startAt, timeZone);
3221
- const weekday = zonedParts(dayStart, timeZone).weekday;
3222
- return presence.some(
3223
- (shift) => shift.weekday === weekday && slot.startAt.getTime() >= atZonedMinute(dayStart, shift.openMinute, timeZone).getTime() && slot.endAt.getTime() <= atZonedMinute(dayStart, shift.closeMinute, timeZone).getTime()
3224
- );
3225
- };
3226
- var overlaps = (entry, startAt, bufferEndAt) => entry.startAt.getTime() < bufferEndAt.getTime() && entry.bufferEndAt.getTime() > startAt.getTime();
3227
- function occupancyIn(occupied, productId, startAt, bufferEndAt, shared) {
3228
- const clashing = occupied.filter((entry) => overlaps(entry, startAt, bufferEndAt));
3229
- const foreign = shared ? void 0 : clashing.find((entry) => entry.productId !== productId);
3230
- return {
3231
- taken: clashing.filter((entry) => shared || entry.productId === productId).reduce((sum, entry) => sum + entry.qty, 0),
3232
- foreignProductId: foreign?.productId
3233
- };
3234
- }
3235
- var stateFor = (hasShift, offerable, free) => {
3236
- if (offerable === 0) {
3237
- return hasShift() ? "fullyBooked" /* FULLY_BOOKED */ : "noHoursInRange" /* NO_HOURS_IN_RANGE */;
3238
- }
3239
- return free === 0 ? "fullyBooked" /* FULLY_BOOKED */ : "available" /* AVAILABLE */;
3240
- };
3241
- function buildAvailability({
3242
- productId,
3243
- bookingRulesId,
3244
- bookingType,
3245
- rule,
3246
- resources,
3247
- occupied,
3248
- from,
3249
- to,
3250
- now
3251
- }) {
3252
- const shared = rule.slot.sharedAcrossProducts ?? false;
3253
- const bookableUntil = windowEndsAt(rule, now);
3254
- const header = {
3255
- productId,
3256
- bookingRulesId,
3257
- bookingType,
3258
- ratePeriod: rule.ratePeriod,
3259
- // Passed through for the UI to label: a group slot under minimumToRun may not run.
3260
- minimumToRun: rule.slot.minimumToRun,
3261
- minStay: rule.slot.minStay,
3262
- maxStay: rule.slot.maxStay,
3263
- // Why a day can come back empty. Past this instant the rule refuses everything, so the UI
3264
- // can say "beyond the booking window" where it would otherwise claim "nothing free".
3265
- bookableUntil,
3266
- // The comparison itself, not just the boundary: deciding whether a day lies past the
3267
- // window is a rule, and a UI that re-derives it owns a copy of that rule — which is how
3268
- // the same empty grid ends up explained one way on the till and another in a flow.
3269
- beyondWindow: !!bookableUntil && from.getTime() > bookableUntil.getTime()
3270
- };
3271
- const byResource = /* @__PURE__ */ new Map();
3272
- for (const entry of occupied) {
3273
- byResource.set(entry.resourceId, [...byResource.get(entry.resourceId) ?? [], entry]);
3274
- }
3275
- const grids = resources.map((resource) => {
3276
- const mine = byResource.get(resource.id) ?? [];
3277
- const busy = (resource.seats ?? 1) === 1 ? mine : [];
3278
- const slots = buildGrid(rule, resource.timeZone, from, to, now, busy).filter(
3279
- (slot) => withinPresence(slot, resource.timeZone, resource.presence)
3280
- );
3281
- return { resource, slots };
3282
- });
3283
- const byInstant = /* @__PURE__ */ new Map();
3284
- const freeSlotsPerResource = /* @__PURE__ */ new Map();
3285
- for (const { resource, slots } of grids) {
3286
- const capacity = resource.seats ?? 1;
3287
- const mine = byResource.get(resource.id) ?? [];
3288
- for (const slot of slots) {
3289
- const { taken, foreignProductId } = occupancyIn(mine, productId, slot.startAt, slot.bufferEndAt, shared);
3290
- const free = foreignProductId ? 0 : Math.max(capacity - taken, 0);
3291
- const entry = byInstant.get(+slot.startAt) ?? { ...slot, capacity: 0, booked: 0, free: 0, resources: [] };
3292
- entry.capacity += capacity;
3293
- entry.booked += foreignProductId ? capacity : taken;
3294
- entry.free += free;
3295
- entry.canStart = entry.canStart || slot.canStart;
3296
- entry.resources.push({ resourceId: resource.id, name: resource.name, capacity, booked: taken, free });
3297
- if (free > 0) freeSlotsPerResource.set(resource.id, (freeSlotsPerResource.get(resource.id) ?? 0) + 1);
3298
- byInstant.set(+slot.startAt, entry);
3299
- }
3300
- }
3301
- const inWindow = grids.map(({ resource, slots }) => {
3302
- const free = freeSlotsPerResource.get(resource.id) ?? 0;
3303
- return {
3304
- resourceId: resource.id,
3305
- name: resource.name,
3306
- slots: slots.length,
3307
- free,
3308
- // Lazily: the shift grid is a second walk, and only an empty answer needs it.
3309
- state: stateFor(
3310
- () => buildGrid(rule, resource.timeZone, from, to, now).filter(
3311
- (slot) => withinPresence(slot, resource.timeZone, resource.presence)
3312
- ).length > 0,
3313
- slots.length,
3314
- free
3315
- )
3316
- };
3317
- });
3318
- return {
3319
- ...header,
3320
- resources: inWindow,
3321
- slots: [...byInstant.values()].sort((first, second) => +first.startAt - +second.startAt)
3322
- };
3323
- }
3324
- function presentAt(resources, rows, outletId) {
3325
- const byResource = /* @__PURE__ */ new Map();
3326
- for (const row of rows) {
3327
- byResource.set(row.resourceId, [...byResource.get(row.resourceId) ?? [], row]);
3328
- }
3329
- return resources.flatMap((resource) => {
3330
- const own = byResource.get(resource.id) ?? [];
3331
- if (own.length === 0 || !outletId) return [{ resource }];
3332
- const here = own.find((row) => row.outletId === outletId);
3333
- return here ? [{ resource, presence: here.weeklyHours }] : [];
3334
- });
3335
- }
3336
-
3337
- // booking/plan.ts
3338
- var DEFAULT_HOLD_MINUTES = 10;
3339
- function planWindow({ rule, timeZone, presence, startAt, endAt, now, busy = [] }) {
3340
- const grid = buildGrid(rule, timeZone, startAt, endAt, now, busy).filter(
3341
- (slot) => withinPresence(slot, timeZone, presence)
3342
- );
3343
- const slots = slotsForWindow(grid, startAt, endAt);
3344
- const { minStay, maxStay } = rule.slot;
3345
- if (minStay && slots.length < minStay) {
3346
- throw new BookingRulesError(`These rules ask for at least ${minStay} period(s), got ${slots.length}`);
3347
- }
3348
- if (maxStay && slots.length > maxStay) {
3349
- throw new BookingRulesError(`These rules allow at most ${maxStay} period(s), got ${slots.length}`);
3350
- }
3351
- const last = slots[slots.length - 1];
3352
- return { slots, endAt: last.endAt, bufferEndAt: last.bufferEndAt };
3353
- }
3354
- var holdExpiresAt = (rule, now) => new Date(now.getTime() + (rule.window.holdMinutes ?? DEFAULT_HOLD_MINUTES) * 6e4);
3355
-
3356
2935
  // constants/adyen.constants.ts
3357
2936
  var ADYEN_ROLLOUT_COUNTRY_CODES = /* @__PURE__ */ new Set(["CA"]);
3358
2937
  function isAdyenRolloutCountry(alpha2) {
@@ -3362,11 +2941,6 @@ function isAdyenRolloutCountry(alpha2) {
3362
2941
  0 && (module.exports = {
3363
2942
  ADYEN_ROLLOUT_COUNTRY_CODES,
3364
2943
  AttributeType,
3365
- BookingRatePeriod,
3366
- BookingResourceKind,
3367
- BookingResourceStatus,
3368
- BookingRulesError,
3369
- BookingType,
3370
2944
  CONDITION_OPERATORS,
3371
2945
  COUNTRY_CURRENCIES,
3372
2946
  CURRENCY_CONFIG,
@@ -3377,7 +2951,6 @@ function isAdyenRolloutCountry(alpha2) {
3377
2951
  DEFAULT_CONFIG,
3378
2952
  DEFAULT_CROSS_AXIS_RULES,
3379
2953
  DEFAULT_DISPLAY_STATE_MAP,
3380
- DEFAULT_HOLD_MINUTES,
3381
2954
  DEFAULT_RESOLVED_CONFIG,
3382
2955
  DEFAULT_UNIT_ID,
3383
2956
  DualWriteStrategy,
@@ -3421,10 +2994,8 @@ function isAdyenRolloutCountry(alpha2) {
3421
2994
  REPORT_NEGATE_PATHS,
3422
2995
  ReceiptSendChannel,
3423
2996
  ReceiptType,
3424
- ReservationStatus,
3425
2997
  ResidualPaymentMethod,
3426
2998
  ResidualStatus,
3427
- ResourceAvailabilityState,
3428
2999
  STATE_SCHEMA,
3429
3000
  STRIPE_SUPPORTED_COUNTRIES,
3430
3001
  SYSTEM_FAMILIES,
@@ -3445,8 +3016,6 @@ function isAdyenRolloutCountry(alpha2) {
3445
3016
  baseFulfillmentDefinitions,
3446
3017
  baseOf,
3447
3018
  basePaymentDefinitions,
3448
- buildAvailability,
3449
- buildGrid,
3450
3019
  buildOrderContext,
3451
3020
  buildPosPresetConfig,
3452
3021
  buildResolvedConfig,
@@ -3486,7 +3055,6 @@ function isAdyenRolloutCountry(alpha2) {
3486
3055
  getPricingRegionFromCountry,
3487
3056
  getSettlementTotal,
3488
3057
  getTotalCollected,
3489
- holdExpiresAt,
3490
3058
  inferStatesFromLegacyStatus,
3491
3059
  isAdyenRolloutCountry,
3492
3060
  isConditionOperator,
@@ -3501,12 +3069,9 @@ function isAdyenRolloutCountry(alpha2) {
3501
3069
  mergeFragment,
3502
3070
  multiplyAmount,
3503
3071
  normalizeMongoIdString,
3504
- occupancyIn,
3505
3072
  parseAmountToMinorUnits,
3506
3073
  parseCurrencyCode,
3507
3074
  parseStripeCurrencyCode,
3508
- planWindow,
3509
- presentAt,
3510
3075
  removeFragment,
3511
3076
  resolveFamily,
3512
3077
  resolveTemplate,
@@ -3515,15 +3080,12 @@ function isAdyenRolloutCountry(alpha2) {
3515
3080
  sameFamily,
3516
3081
  setOrderState,
3517
3082
  signReportForDisplay,
3518
- slotsForWindow,
3519
3083
  stringifyMinorUnits,
3520
3084
  subtractAmounts,
3521
3085
  toBase,
3522
3086
  toMinorUnits,
3523
3087
  validateConfig,
3524
3088
  validateFragmentCompatibility,
3525
- violatesFinancialInvariant,
3526
- windowEndsAt,
3527
- withinPresence
3089
+ violatesFinancialInvariant
3528
3090
  });
3529
3091
  //# sourceMappingURL=index.js.map