@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.js CHANGED
@@ -19,13 +19,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  // index.ts
20
20
  var index_exports = {};
21
21
  __export(index_exports, {
22
+ ADYEN_JOB_TITLE_ASSOCIATION_TYPES: () => ADYEN_JOB_TITLE_ASSOCIATION_TYPES,
23
+ ADYEN_LEGAL_ENTITY_STATE_PROVINCE_COUNTRIES: () => ADYEN_LEGAL_ENTITY_STATE_PROVINCE_COUNTRIES,
24
+ ADYEN_NO_TAX_NUMBER_ABSENT_COUNTRIES: () => ADYEN_NO_TAX_NUMBER_ABSENT_COUNTRIES,
22
25
  ADYEN_ROLLOUT_COUNTRY_CODES: () => ADYEN_ROLLOUT_COUNTRY_CODES,
26
+ ADYEN_STORE_STATE_PROVINCE_COUNTRIES: () => ADYEN_STORE_STATE_PROVINCE_COUNTRIES,
27
+ ADYEN_TAX_NUMBER_FORMATS: () => ADYEN_TAX_NUMBER_FORMATS,
28
+ ADYEN_TAX_NUMBER_MIN_LENGTH: () => ADYEN_TAX_NUMBER_MIN_LENGTH,
23
29
  AttributeType: () => AttributeType,
24
- BookingRatePeriod: () => BookingRatePeriod,
25
- BookingResourceKind: () => BookingResourceKind,
26
- BookingResourceStatus: () => BookingResourceStatus,
27
- BookingRulesError: () => BookingRulesError,
28
- BookingType: () => BookingType,
29
30
  CONDITION_OPERATORS: () => CONDITION_OPERATORS,
30
31
  COUNTRY_CURRENCIES: () => COUNTRY_CURRENCIES,
31
32
  CURRENCY_CONFIG: () => CURRENCY_CONFIG,
@@ -36,7 +37,6 @@ __export(index_exports, {
36
37
  DEFAULT_CONFIG: () => DEFAULT_CONFIG,
37
38
  DEFAULT_CROSS_AXIS_RULES: () => DEFAULT_CROSS_AXIS_RULES,
38
39
  DEFAULT_DISPLAY_STATE_MAP: () => DEFAULT_DISPLAY_STATE_MAP,
39
- DEFAULT_HOLD_MINUTES: () => DEFAULT_HOLD_MINUTES,
40
40
  DEFAULT_RESOLVED_CONFIG: () => DEFAULT_RESOLVED_CONFIG,
41
41
  DEFAULT_UNIT_ID: () => DEFAULT_UNIT_ID,
42
42
  DualWriteStrategy: () => DualWriteStrategy,
@@ -80,10 +80,8 @@ __export(index_exports, {
80
80
  REPORT_NEGATE_PATHS: () => REPORT_NEGATE_PATHS,
81
81
  ReceiptSendChannel: () => ReceiptSendChannel,
82
82
  ReceiptType: () => ReceiptType,
83
- ReservationStatus: () => ReservationStatus,
84
83
  ResidualPaymentMethod: () => ResidualPaymentMethod,
85
84
  ResidualStatus: () => ResidualStatus,
86
- ResourceAvailabilityState: () => ResourceAvailabilityState,
87
85
  STATE_SCHEMA: () => STATE_SCHEMA,
88
86
  STRIPE_SUPPORTED_COUNTRIES: () => STRIPE_SUPPORTED_COUNTRIES,
89
87
  SYSTEM_FAMILIES: () => SYSTEM_FAMILIES,
@@ -97,6 +95,11 @@ __export(index_exports, {
97
95
  TopMetericsSort: () => TopMetericsSort,
98
96
  UserTypes: () => UserTypes,
99
97
  addAmounts: () => addAmounts,
98
+ adyenLegalEntityRequiresStateOrProvince: () => adyenLegalEntityRequiresStateOrProvince,
99
+ adyenRequiresJobTitle: () => adyenRequiresJobTitle,
100
+ adyenStoreRequiresStateOrProvince: () => adyenStoreRequiresStateOrProvince,
101
+ adyenSupportsTaxNumberAbsent: () => adyenSupportsTaxNumberAbsent,
102
+ adyenTaxNumberFormat: () => adyenTaxNumberFormat,
100
103
  amountToString: () => amountToString,
101
104
  assertUnitSane: () => assertUnitSane,
102
105
  availableIn: () => availableIn,
@@ -104,8 +107,6 @@ __export(index_exports, {
104
107
  baseFulfillmentDefinitions: () => baseFulfillmentDefinitions,
105
108
  baseOf: () => baseOf,
106
109
  basePaymentDefinitions: () => basePaymentDefinitions,
107
- buildAvailability: () => buildAvailability,
108
- buildGrid: () => buildGrid,
109
110
  buildOrderContext: () => buildOrderContext,
110
111
  buildPosPresetConfig: () => buildPosPresetConfig,
111
112
  buildResolvedConfig: () => buildResolvedConfig,
@@ -145,7 +146,6 @@ __export(index_exports, {
145
146
  getPricingRegionFromCountry: () => getPricingRegionFromCountry,
146
147
  getSettlementTotal: () => getSettlementTotal,
147
148
  getTotalCollected: () => getTotalCollected,
148
- holdExpiresAt: () => holdExpiresAt,
149
149
  inferStatesFromLegacyStatus: () => inferStatesFromLegacyStatus,
150
150
  isAdyenRolloutCountry: () => isAdyenRolloutCountry,
151
151
  isConditionOperator: () => isConditionOperator,
@@ -160,12 +160,9 @@ __export(index_exports, {
160
160
  mergeFragment: () => mergeFragment,
161
161
  multiplyAmount: () => multiplyAmount,
162
162
  normalizeMongoIdString: () => normalizeMongoIdString,
163
- occupancyIn: () => occupancyIn,
164
163
  parseAmountToMinorUnits: () => parseAmountToMinorUnits,
165
164
  parseCurrencyCode: () => parseCurrencyCode,
166
165
  parseStripeCurrencyCode: () => parseStripeCurrencyCode,
167
- planWindow: () => planWindow,
168
- presentAt: () => presentAt,
169
166
  removeFragment: () => removeFragment,
170
167
  resolveFamily: () => resolveFamily,
171
168
  resolveTemplate: () => resolveTemplate,
@@ -173,19 +170,14 @@ __export(index_exports, {
173
170
  roundToPrecision: () => roundToPrecision,
174
171
  sameFamily: () => sameFamily,
175
172
  setOrderState: () => setOrderState,
176
- shopDayKey: () => shopDayKey,
177
- shopDayRange: () => shopDayRange,
178
173
  signReportForDisplay: () => signReportForDisplay,
179
- slotsForWindow: () => slotsForWindow,
180
174
  stringifyMinorUnits: () => stringifyMinorUnits,
181
175
  subtractAmounts: () => subtractAmounts,
182
176
  toBase: () => toBase,
183
177
  toMinorUnits: () => toMinorUnits,
184
178
  validateConfig: () => validateConfig,
185
179
  validateFragmentCompatibility: () => validateFragmentCompatibility,
186
- violatesFinancialInvariant: () => violatesFinancialInvariant,
187
- windowEndsAt: () => windowEndsAt,
188
- withinPresence: () => withinPresence
180
+ violatesFinancialInvariant: () => violatesFinancialInvariant
189
181
  });
190
182
  module.exports = __toCommonJS(index_exports);
191
183
 
@@ -613,7 +605,6 @@ var StripeCurrencyCode = /* @__PURE__ */ ((StripeCurrencyCode2) => {
613
605
  var ProductType = /* @__PURE__ */ ((ProductType2) => {
614
606
  ProductType2["SIMPLE"] = "simple";
615
607
  ProductType2["VARIABLE"] = "variable";
616
- ProductType2["BOOKING"] = "booking";
617
608
  return ProductType2;
618
609
  })(ProductType || {});
619
610
  var ProductStatus = /* @__PURE__ */ ((ProductStatus2) => {
@@ -631,50 +622,6 @@ var PaymentProcessor = /* @__PURE__ */ ((PaymentProcessor2) => {
631
622
  return PaymentProcessor2;
632
623
  })(PaymentProcessor || {});
633
624
 
634
- // enums/booking.enum.ts
635
- var BookingType = /* @__PURE__ */ ((BookingType3) => {
636
- BookingType3["RENTAL"] = "rental";
637
- BookingType3["APPOINTMENT"] = "appointment";
638
- BookingType3["OVERNIGHT"] = "overnight";
639
- BookingType3["GROUP"] = "group";
640
- return BookingType3;
641
- })(BookingType || {});
642
- var BookingRatePeriod = /* @__PURE__ */ ((BookingRatePeriod2) => {
643
- BookingRatePeriod2["SLOT"] = "slot";
644
- BookingRatePeriod2["DAY"] = "day";
645
- BookingRatePeriod2["NIGHT"] = "night";
646
- BookingRatePeriod2["WEEK"] = "week";
647
- BookingRatePeriod2["MONTH"] = "month";
648
- return BookingRatePeriod2;
649
- })(BookingRatePeriod || {});
650
- var BookingResourceKind = /* @__PURE__ */ ((BookingResourceKind2) => {
651
- BookingResourceKind2["ASSET"] = "asset";
652
- BookingResourceKind2["ROOM"] = "room";
653
- BookingResourceKind2["PROPERTY"] = "property";
654
- BookingResourceKind2["SPACE"] = "space";
655
- BookingResourceKind2["STAFF"] = "staff";
656
- BookingResourceKind2["TABLE"] = "table";
657
- return BookingResourceKind2;
658
- })(BookingResourceKind || {});
659
- var ReservationStatus = /* @__PURE__ */ ((ReservationStatus2) => {
660
- ReservationStatus2["HELD"] = "held";
661
- ReservationStatus2["CONFIRMED"] = "confirmed";
662
- ReservationStatus2["CANCELLED"] = "cancelled";
663
- ReservationStatus2["EXPIRED"] = "expired";
664
- return ReservationStatus2;
665
- })(ReservationStatus || {});
666
- var BookingResourceStatus = /* @__PURE__ */ ((BookingResourceStatus2) => {
667
- BookingResourceStatus2["ACTIVE"] = "active";
668
- BookingResourceStatus2["INACTIVE"] = "inactive";
669
- return BookingResourceStatus2;
670
- })(BookingResourceStatus || {});
671
- var ResourceAvailabilityState = /* @__PURE__ */ ((ResourceAvailabilityState2) => {
672
- ResourceAvailabilityState2["AVAILABLE"] = "available";
673
- ResourceAvailabilityState2["FULLY_BOOKED"] = "fullyBooked";
674
- ResourceAvailabilityState2["NO_HOURS_IN_RANGE"] = "noHoursInRange";
675
- return ResourceAvailabilityState2;
676
- })(ResourceAvailabilityState || {});
677
-
678
625
  // utils/currency.util.ts
679
626
  var CURRENCY_CONFIG = {
680
627
  // Major currencies with 2 decimal places
@@ -1886,15 +1833,6 @@ function sumRefundQuantities(refunds) {
1886
1833
  }
1887
1834
  return t;
1888
1835
  }
1889
- var asCount = (value) => typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : 0;
1890
- function countsOf(row) {
1891
- const quantity = asCount(row.quantity);
1892
- return {
1893
- quantity,
1894
- fulfilled: Math.min(asCount(row.fulfilledQuantity), quantity),
1895
- returned: Math.min(asCount(row.returnedQuantity), quantity)
1896
- };
1897
- }
1898
1836
  function buildOrderContext(order, extras) {
1899
1837
  const o = order ?? {};
1900
1838
  const total = typeof o.total === "number" && Number.isFinite(o.total) ? o.total : 0;
@@ -1902,7 +1840,6 @@ function buildOrderContext(order, extras) {
1902
1840
  const paymentMethods = o.paymentMethods ?? [];
1903
1841
  const refunds = o.refunds ?? o.refund ?? [];
1904
1842
  const lineItems = o.lineItems ?? [];
1905
- const reservations = o.reservations ?? [];
1906
1843
  const totalPaid = sumNumbers(paymentMethods);
1907
1844
  const totalRefunded = sumRefundQuantities(refunds);
1908
1845
  const isFullyPaid = total > 0 ? balance <= 0 : totalPaid > 0 && balance <= 0;
@@ -1910,11 +1847,13 @@ function buildOrderContext(order, extras) {
1910
1847
  let itemCount = 0;
1911
1848
  let fulfilledItemCount = 0;
1912
1849
  let returnedItemCount = 0;
1913
- for (const row of [...lineItems, ...reservations]) {
1914
- const { quantity, fulfilled, returned } = countsOf(row);
1915
- itemCount += quantity;
1916
- fulfilledItemCount += fulfilled;
1917
- returnedItemCount += returned;
1850
+ for (const li of lineItems) {
1851
+ const q = typeof li.quantity === "number" && Number.isFinite(li.quantity) ? Math.max(0, li.quantity) : 0;
1852
+ itemCount += q;
1853
+ const fq = typeof li.fulfilledQuantity === "number" && Number.isFinite(li.fulfilledQuantity) ? Math.max(0, li.fulfilledQuantity) : 0;
1854
+ fulfilledItemCount += Math.min(fq, q);
1855
+ const rq = typeof li.returnedQuantity === "number" && Number.isFinite(li.returnedQuantity) ? Math.max(0, li.returnedQuantity) : 0;
1856
+ returnedItemCount += Math.min(rq, q);
1918
1857
  }
1919
1858
  const isFullyReturned = itemCount > 0 ? returnedItemCount >= itemCount : returnedItemCount > 0;
1920
1859
  const hasPartialReturns = returnedItemCount > 0 && !isFullyReturned;
@@ -1924,8 +1863,7 @@ function buildOrderContext(order, extras) {
1924
1863
  balance,
1925
1864
  paymentMethods,
1926
1865
  refunds,
1927
- lineItems,
1928
- reservations
1866
+ lineItems
1929
1867
  },
1930
1868
  computed: {
1931
1869
  balance,
@@ -3005,392 +2943,44 @@ var ORDER_STATE_EVENTS = {
3005
2943
  configUpdated: "config-updated"
3006
2944
  };
3007
2945
 
3008
- // booking/types.ts
3009
- var BookingRulesError = class extends Error {
3010
- constructor(message) {
3011
- super(message);
3012
- this.name = "BookingRulesError";
3013
- }
3014
- };
3015
-
3016
- // booking/zoned-time.ts
3017
- var MINUTE = 6e4;
3018
- var formatters = /* @__PURE__ */ new Map();
3019
- var formatterFor = (timeZone) => {
3020
- const existing = formatters.get(timeZone);
3021
- if (existing) return existing;
3022
- let created;
3023
- try {
3024
- created = new Intl.DateTimeFormat("en-US", {
3025
- timeZone,
3026
- hour12: false,
3027
- year: "numeric",
3028
- month: "2-digit",
3029
- day: "2-digit",
3030
- hour: "2-digit",
3031
- minute: "2-digit",
3032
- second: "2-digit",
3033
- weekday: "short"
3034
- });
3035
- } catch {
3036
- throw new BookingRulesError(`Booking rules: "${timeZone}" is not a known time zone`);
3037
- }
3038
- formatters.set(timeZone, created);
3039
- return created;
3040
- };
3041
- var WEEKDAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
3042
- function zonedParts(instant, timeZone) {
3043
- const parts = {};
3044
- for (const { type, value } of formatterFor(timeZone).formatToParts(instant)) parts[type] = value;
3045
- const hour = Number(parts.hour) % 24;
3046
- return {
3047
- year: Number(parts.year),
3048
- month: Number(parts.month),
3049
- day: Number(parts.day),
3050
- hour,
3051
- minute: Number(parts.minute),
3052
- second: Number(parts.second),
3053
- weekday: WEEKDAYS.indexOf(parts.weekday)
3054
- };
3055
- }
3056
- function offsetAt(instant, timeZone) {
3057
- const { year, month, day, hour, minute, second } = zonedParts(instant, timeZone);
3058
- return Date.UTC(year, month - 1, day, hour, minute, second) - Math.floor(instant.getTime() / 1e3) * 1e3;
3059
- }
3060
- function instantFromLocal(year, month, day, minutes, timeZone) {
3061
- const naive = Date.UTC(year, month - 1, day) + minutes * MINUTE;
3062
- const firstGuess = naive - offsetAt(new Date(naive), timeZone);
3063
- return new Date(naive - offsetAt(new Date(firstGuess), timeZone));
3064
- }
3065
- function startOfZonedDay(instant, timeZone) {
3066
- const { year, month, day } = zonedParts(instant, timeZone);
3067
- return instantFromLocal(year, month, day, 0, timeZone);
3068
- }
3069
- function nextZonedDay(dayStart, timeZone) {
3070
- const { year, month, day } = zonedParts(dayStart, timeZone);
3071
- return instantFromLocal(year, month, day + 1, 0, timeZone);
3072
- }
3073
- function atZonedMinute(dayStart, minutes, timeZone) {
3074
- const { year, month, day } = zonedParts(dayStart, timeZone);
3075
- return instantFromLocal(year, month, day, minutes, timeZone);
2946
+ // constants/adyen.constants.ts
2947
+ var ADYEN_ROLLOUT_COUNTRY_CODES = /* @__PURE__ */ new Set(["CA"]);
2948
+ function isAdyenRolloutCountry(alpha2) {
2949
+ return ADYEN_ROLLOUT_COUNTRY_CODES.has(alpha2);
3076
2950
  }
3077
-
3078
- // booking/grid.ts
3079
- var MINUTE2 = 6e4;
3080
- var MAX_RANGE_DAYS = 366;
3081
- var asTime = (value, field) => {
3082
- if (value == null) return void 0;
3083
- const time = new Date(value).getTime();
3084
- if (Number.isNaN(time)) throw new BookingRulesError(`Booking rules: ${field} is not a date, got "${String(value)}"`);
3085
- return time;
3086
- };
3087
- function parseHhMm(value, field) {
3088
- const [hours, minutes] = value.split(":").map(Number);
3089
- if (!Number.isInteger(hours) || !Number.isInteger(minutes)) {
3090
- throw new BookingRulesError(`Booking rules: ${field} must be "HH:mm", got "${value}"`);
3091
- }
3092
- return hours * 60 + minutes;
3093
- }
3094
- function windowEndsAt(rule, now) {
3095
- const { maxAdvanceDays, bookableTo } = rule.window;
3096
- const ends = Math.min(
3097
- maxAdvanceDays ? now.getTime() + maxAdvanceDays * 1440 * MINUTE2 : Number.POSITIVE_INFINITY,
3098
- asTime(bookableTo, "window.bookableTo") ?? Number.POSITIVE_INFINITY
3099
- );
3100
- return Number.isFinite(ends) ? new Date(ends) : null;
3101
- }
3102
- function periodSlot(dayStart, timeZone, rule, openMinute, closeMinute) {
3103
- const { ratePeriod, slot, checkInTime, checkOutTime } = rule;
3104
- const at = (minutes) => atZonedMinute(dayStart, minutes, timeZone);
3105
- if (ratePeriod === "night" /* NIGHT */) {
3106
- if (!checkInTime || !checkOutTime) {
3107
- throw new BookingRulesError("Overnight booking rules need both checkInTime and checkOutTime");
3108
- }
3109
- const checkIn = parseHhMm(checkInTime, "checkInTime");
3110
- const checkOut = parseHhMm(checkOutTime, "checkOutTime");
3111
- return {
3112
- startAt: at(checkIn),
3113
- endAt: at(1440 + checkOut),
3114
- // Housekeeping sits between check-out and the next check-in: it costs no night.
3115
- bufferEndAt: at(1440 + checkIn),
3116
- canStart: true
3117
- };
3118
- }
3119
- const from = ratePeriod === "day" /* DAY */ ? openMinute ?? 0 : 0;
3120
- const to = ratePeriod === "day" /* DAY */ ? closeMinute ?? 1440 : 1440;
3121
- return {
3122
- startAt: at(from),
3123
- endAt: at(to),
3124
- bufferEndAt: at(to + (slot.bufferMinutes ?? 0)),
3125
- canStart: true
3126
- };
2951
+ var ADYEN_STORE_STATE_PROVINCE_COUNTRIES = /* @__PURE__ */ new Set(["AU", "BR", "CA", "IN", "MX", "NZ", "US"]);
2952
+ function adyenStoreRequiresStateOrProvince(alpha2) {
2953
+ return !!alpha2 && ADYEN_STORE_STATE_PROVINCE_COUNTRIES.has(alpha2);
3127
2954
  }
3128
- function freeGaps(openAt, closeAt, busy) {
3129
- const inside = busy.map(({ startAt, bufferEndAt }) => ({ from: +startAt, to: +bufferEndAt })).filter(({ from, to }) => to > openAt && from < closeAt).sort((first, second) => first.from - second.from);
3130
- const gaps = [];
3131
- let cursor = openAt;
3132
- for (const { from, to } of inside) {
3133
- if (from > cursor) gaps.push({ from: cursor, to: from, endsAtBooking: true });
3134
- cursor = Math.max(cursor, to);
3135
- if (cursor >= closeAt) break;
3136
- }
3137
- if (cursor < closeAt) gaps.push({ from: cursor, to: closeAt, endsAtBooking: false });
3138
- return gaps;
3139
- }
3140
- function buildGrid(rule, timeZone, from, to, now, busy = []) {
3141
- if (to.getTime() - from.getTime() > MAX_RANGE_DAYS * 1440 * MINUTE2) {
3142
- throw new BookingRulesError(`A booking range may span at most ${MAX_RANGE_DAYS} days`);
3143
- }
3144
- const { availability, slot, window, ratePeriod } = rule;
3145
- const periodMode = ratePeriod !== "slot" /* SLOT */;
3146
- const weeklyHours = availability.weeklyHours ?? [];
3147
- const notBefore = Math.max(
3148
- now.getTime() + (window.minNoticeMinutes ?? 0) * MINUTE2,
3149
- asTime(window.bookableFrom, "window.bookableFrom") ?? 0,
3150
- asTime(availability.availableFrom, "availability.availableFrom") ?? 0
3151
- );
3152
- const notAfter = windowEndsAt(rule, now)?.getTime() ?? Number.POSITIVE_INFINITY;
3153
- const blocked = (availability.offMarket ?? []).map(({ from: blockFrom, to: blockTo }) => ({
3154
- from: asTime(blockFrom, "availability.offMarket.from"),
3155
- to: asTime(blockTo, "availability.offMarket.to")
3156
- }));
3157
- const arrivalDays = availability.arrivalDays;
3158
- const step = slot.lengthMinutes + (slot.bufferMinutes ?? 0);
3159
- const slots = [];
3160
- const lastDay = startOfZonedDay(to, timeZone).getTime();
3161
- let dayStart = startOfZonedDay(from, timeZone);
3162
- while (dayStart.getTime() <= lastDay) {
3163
- const weekday = zonedParts(dayStart, timeZone).weekday;
3164
- const rows = weeklyHours.filter((entry) => entry.weekday === weekday);
3165
- if (periodMode) {
3166
- const openToday = weeklyHours.length === 0 || rows.length > 0;
3167
- if (openToday) {
3168
- const built = periodSlot(dayStart, timeZone, rule, rows[0]?.openMinute, rows[0]?.closeMinute);
3169
- slots.push({ ...built, canStart: !arrivalDays?.length || arrivalDays.includes(weekday) });
3170
- }
3171
- } else {
3172
- for (const row of rows) {
3173
- const openAt = +atZonedMinute(dayStart, row.openMinute, timeZone);
3174
- const closeAt = +atZonedMinute(dayStart, row.closeMinute, timeZone);
3175
- for (const gap of freeGaps(openAt, closeAt, busy)) {
3176
- const mustFit = (gap.endsAtBooking ? step : slot.lengthMinutes) * MINUTE2;
3177
- for (let start = gap.from; start + mustFit <= gap.to; start += step * MINUTE2) {
3178
- slots.push({
3179
- startAt: new Date(start),
3180
- endAt: new Date(start + slot.lengthMinutes * MINUTE2),
3181
- bufferEndAt: new Date(start + step * MINUTE2),
3182
- canStart: true
3183
- });
3184
- }
3185
- }
3186
- }
3187
- }
3188
- dayStart = nextZonedDay(dayStart, timeZone);
3189
- }
3190
- const askedFrom = from.getTime();
3191
- const askedTo = to.getTime();
3192
- return slots.filter(({ startAt, bufferEndAt }) => {
3193
- const start = startAt.getTime();
3194
- if (start < askedFrom || start >= askedTo) return false;
3195
- if (start < notBefore || start > notAfter) return false;
3196
- return !blocked.some(({ from: blockFrom, to: blockTo }) => start < blockTo && bufferEndAt.getTime() > blockFrom);
3197
- }).sort((first, second) => +first.startAt - +second.startAt);
3198
- }
3199
- function slotsForWindow(grid, startAt, endAt) {
3200
- const startIndex = grid.findIndex((entry) => entry.startAt.getTime() === startAt.getTime());
3201
- if (startIndex < 0) {
3202
- throw new BookingRulesError(`${startAt.toISOString()} is not a bookable slot start for these rules`);
3203
- }
3204
- if (!grid[startIndex].canStart) {
3205
- throw new BookingRulesError(`${startAt.toISOString()} is not an arrival day for these rules`);
3206
- }
3207
- const covered = [];
3208
- for (let index = startIndex; index < grid.length; index++) {
3209
- const entry = grid[index];
3210
- const previous = covered[covered.length - 1];
3211
- if (previous && entry.startAt.getTime() !== previous.bufferEndAt.getTime()) break;
3212
- covered.push(entry);
3213
- if (entry.endAt.getTime() === endAt.getTime()) return covered;
3214
- if (entry.endAt.getTime() > endAt.getTime()) break;
3215
- }
3216
- throw new BookingRulesError(
3217
- `${startAt.toISOString()} \u2192 ${endAt.toISOString()} does not line up with the bookable grid`
3218
- );
2955
+ var ADYEN_LEGAL_ENTITY_STATE_PROVINCE_COUNTRIES = /* @__PURE__ */ new Set(["AU", "BR", "CA", "IN", "MX", "NZ", "US"]);
2956
+ function adyenLegalEntityRequiresStateOrProvince(alpha2) {
2957
+ return !!alpha2 && ADYEN_LEGAL_ENTITY_STATE_PROVINCE_COUNTRIES.has(alpha2);
3219
2958
  }
3220
-
3221
- // booking/availability.ts
3222
- var withinPresence = (slot, timeZone, presence) => {
3223
- if (!presence?.length) return true;
3224
- const dayStart = startOfZonedDay(slot.startAt, timeZone);
3225
- const weekday = zonedParts(dayStart, timeZone).weekday;
3226
- return presence.some(
3227
- (shift) => shift.weekday === weekday && slot.startAt.getTime() >= atZonedMinute(dayStart, shift.openMinute, timeZone).getTime() && slot.endAt.getTime() <= atZonedMinute(dayStart, shift.closeMinute, timeZone).getTime()
3228
- );
3229
- };
3230
- var overlaps = (entry, startAt, bufferEndAt) => entry.startAt.getTime() < bufferEndAt.getTime() && entry.bufferEndAt.getTime() > startAt.getTime();
3231
- function occupancyIn(occupied, productId, startAt, bufferEndAt, shared) {
3232
- const clashing = occupied.filter((entry) => overlaps(entry, startAt, bufferEndAt));
3233
- const foreign = shared ? void 0 : clashing.find((entry) => entry.productId !== productId);
3234
- return {
3235
- taken: clashing.filter((entry) => shared || entry.productId === productId).reduce((sum, entry) => sum + entry.qty, 0),
3236
- foreignProductId: foreign?.productId
3237
- };
2959
+ var ADYEN_NO_TAX_NUMBER_ABSENT_COUNTRIES = /* @__PURE__ */ new Set(["CA"]);
2960
+ function adyenSupportsTaxNumberAbsent(alpha2) {
2961
+ return !!alpha2 && !ADYEN_NO_TAX_NUMBER_ABSENT_COUNTRIES.has(alpha2);
3238
2962
  }
3239
- var stateFor = (hasShift, offerable, free) => {
3240
- if (offerable === 0) {
3241
- return hasShift() ? "fullyBooked" /* FULLY_BOOKED */ : "noHoursInRange" /* NO_HOURS_IN_RANGE */;
3242
- }
3243
- return free === 0 ? "fullyBooked" /* FULLY_BOOKED */ : "available" /* AVAILABLE */;
2963
+ var ADYEN_TAX_NUMBER_FORMATS = {
2964
+ CA: { pattern: /^\d{9}$/, length: 9 }
3244
2965
  };
3245
- function shopDayKey(instant, timeZone) {
3246
- const { year, month, day } = zonedParts(instant, timeZone);
3247
- const pad = (value) => String(value).padStart(2, "0");
3248
- return `${year}-${pad(month)}-${pad(day)}`;
3249
- }
3250
- function shopDayRange(fromDayKey, count, timeZone) {
3251
- const [year, month, day] = fromDayKey.split("-").map(Number);
3252
- return {
3253
- from: instantFromLocal(year, month, day, 0, timeZone),
3254
- to: instantFromLocal(year, month, day + Math.max(1, count), 0, timeZone)
3255
- };
3256
- }
3257
- function buildAvailability({
3258
- productId,
3259
- bookingRulesId,
3260
- bookingType,
3261
- rule,
3262
- resources,
3263
- occupied,
3264
- from,
3265
- to,
3266
- now
3267
- }) {
3268
- const shared = rule.slot.sharedAcrossProducts ?? false;
3269
- const bookableUntil = windowEndsAt(rule, now);
3270
- const header = {
3271
- productId,
3272
- bookingRulesId,
3273
- bookingType,
3274
- ratePeriod: rule.ratePeriod,
3275
- // Passed through for the UI to label: a group slot under minimumToRun may not run.
3276
- minimumToRun: rule.slot.minimumToRun,
3277
- minStay: rule.slot.minStay,
3278
- maxStay: rule.slot.maxStay,
3279
- // Why a day can come back empty. Past this instant the rule refuses everything, so the UI
3280
- // can say "beyond the booking window" where it would otherwise claim "nothing free".
3281
- bookableUntil,
3282
- // The comparison itself, not just the boundary: deciding whether a day lies past the
3283
- // window is a rule, and a UI that re-derives it owns a copy of that rule — which is how
3284
- // the same empty grid ends up explained one way on the till and another in a flow.
3285
- beyondWindow: !!bookableUntil && from.getTime() > bookableUntil.getTime()
3286
- };
3287
- const byResource = /* @__PURE__ */ new Map();
3288
- for (const entry of occupied) {
3289
- byResource.set(entry.resourceId, [...byResource.get(entry.resourceId) ?? [], entry]);
3290
- }
3291
- const grids = resources.map((resource) => {
3292
- const mine = byResource.get(resource.id) ?? [];
3293
- const busy = (resource.seats ?? 1) === 1 ? mine : [];
3294
- const slots2 = buildGrid(rule, resource.timeZone, from, to, now, busy).filter(
3295
- (slot) => withinPresence(slot, resource.timeZone, resource.presence)
3296
- );
3297
- return { resource, slots: slots2 };
3298
- });
3299
- const byInstant = /* @__PURE__ */ new Map();
3300
- const freeSlotsPerResource = /* @__PURE__ */ new Map();
3301
- for (const { resource, slots: slots2 } of grids) {
3302
- const capacity = resource.seats ?? 1;
3303
- const mine = byResource.get(resource.id) ?? [];
3304
- for (const slot of slots2) {
3305
- const { taken, foreignProductId } = occupancyIn(mine, productId, slot.startAt, slot.bufferEndAt, shared);
3306
- const free = foreignProductId ? 0 : Math.max(capacity - taken, 0);
3307
- const entry = byInstant.get(+slot.startAt) ?? { ...slot, capacity: 0, booked: 0, free: 0, resources: [], dayKey: shopDayKey(slot.startAt, resource.timeZone) };
3308
- entry.capacity += capacity;
3309
- entry.booked += foreignProductId ? capacity : taken;
3310
- entry.free += free;
3311
- entry.canStart = entry.canStart || slot.canStart;
3312
- entry.resources.push({ resourceId: resource.id, name: resource.name, capacity, booked: taken, free });
3313
- if (free > 0) freeSlotsPerResource.set(resource.id, (freeSlotsPerResource.get(resource.id) ?? 0) + 1);
3314
- byInstant.set(+slot.startAt, entry);
3315
- }
3316
- }
3317
- const inWindow = grids.map(({ resource, slots: slots2 }) => {
3318
- const free = freeSlotsPerResource.get(resource.id) ?? 0;
3319
- return {
3320
- resourceId: resource.id,
3321
- name: resource.name,
3322
- slots: slots2.length,
3323
- free,
3324
- // Lazily: the shift grid is a second walk, and only an empty answer needs it.
3325
- state: stateFor(
3326
- () => buildGrid(rule, resource.timeZone, from, to, now).filter(
3327
- (slot) => withinPresence(slot, resource.timeZone, resource.presence)
3328
- ).length > 0,
3329
- slots2.length,
3330
- free
3331
- )
3332
- };
3333
- });
3334
- const slots = [...byInstant.values()].sort((first, second) => +first.startAt - +second.startAt);
3335
- return {
3336
- ...header,
3337
- resources: inWindow,
3338
- slots,
3339
- /**
3340
- * The clock every instant above reads on. Returned rather than assumed: without it a caller
3341
- * has to fetch the zone from somewhere else and hope it is the same one the grid used.
3342
- */
3343
- timeZone: resources[0]?.timeZone ?? null,
3344
- /** The shop days this answer covers, in order — what a day picker lists. */
3345
- days: [...new Set(slots.map((slot) => slot.dayKey))]
3346
- };
3347
- }
3348
- function presentAt(resources, rows, outletId) {
3349
- const byResource = /* @__PURE__ */ new Map();
3350
- for (const row of rows) {
3351
- byResource.set(row.resourceId, [...byResource.get(row.resourceId) ?? [], row]);
3352
- }
3353
- return resources.flatMap((resource) => {
3354
- const own = byResource.get(resource.id) ?? [];
3355
- if (own.length === 0 || !outletId) return [{ resource }];
3356
- const here = own.find((row) => row.outletId === outletId);
3357
- return here ? [{ resource, presence: here.weeklyHours }] : [];
3358
- });
3359
- }
3360
-
3361
- // booking/plan.ts
3362
- var DEFAULT_HOLD_MINUTES = 10;
3363
- function planWindow({ rule, timeZone, presence, startAt, endAt, now, busy = [] }) {
3364
- const grid = buildGrid(rule, timeZone, startAt, endAt, now, busy).filter(
3365
- (slot) => withinPresence(slot, timeZone, presence)
3366
- );
3367
- const slots = slotsForWindow(grid, startAt, endAt);
3368
- const { minStay, maxStay } = rule.slot;
3369
- if (minStay && slots.length < minStay) {
3370
- throw new BookingRulesError(`These rules ask for at least ${minStay} period(s), got ${slots.length}`);
3371
- }
3372
- if (maxStay && slots.length > maxStay) {
3373
- throw new BookingRulesError(`These rules allow at most ${maxStay} period(s), got ${slots.length}`);
3374
- }
3375
- const last = slots[slots.length - 1];
3376
- return { slots, endAt: last.endAt, bufferEndAt: last.bufferEndAt };
2966
+ function adyenTaxNumberFormat(alpha2) {
2967
+ return alpha2 ? ADYEN_TAX_NUMBER_FORMATS[alpha2] : void 0;
3377
2968
  }
3378
- var holdExpiresAt = (rule, now) => new Date(now.getTime() + (rule.window.holdMinutes ?? DEFAULT_HOLD_MINUTES) * 6e4);
3379
-
3380
- // constants/adyen.constants.ts
3381
- var ADYEN_ROLLOUT_COUNTRY_CODES = /* @__PURE__ */ new Set(["CA"]);
3382
- function isAdyenRolloutCountry(alpha2) {
3383
- return ADYEN_ROLLOUT_COUNTRY_CODES.has(alpha2);
2969
+ var ADYEN_TAX_NUMBER_MIN_LENGTH = 5;
2970
+ var ADYEN_JOB_TITLE_ASSOCIATION_TYPES = ["signatory", "uboThroughControl"];
2971
+ function adyenRequiresJobTitle(associationType) {
2972
+ return ADYEN_JOB_TITLE_ASSOCIATION_TYPES.includes(associationType);
3384
2973
  }
3385
2974
  // Annotate the CommonJS export names for ESM import in node:
3386
2975
  0 && (module.exports = {
2976
+ ADYEN_JOB_TITLE_ASSOCIATION_TYPES,
2977
+ ADYEN_LEGAL_ENTITY_STATE_PROVINCE_COUNTRIES,
2978
+ ADYEN_NO_TAX_NUMBER_ABSENT_COUNTRIES,
3387
2979
  ADYEN_ROLLOUT_COUNTRY_CODES,
2980
+ ADYEN_STORE_STATE_PROVINCE_COUNTRIES,
2981
+ ADYEN_TAX_NUMBER_FORMATS,
2982
+ ADYEN_TAX_NUMBER_MIN_LENGTH,
3388
2983
  AttributeType,
3389
- BookingRatePeriod,
3390
- BookingResourceKind,
3391
- BookingResourceStatus,
3392
- BookingRulesError,
3393
- BookingType,
3394
2984
  CONDITION_OPERATORS,
3395
2985
  COUNTRY_CURRENCIES,
3396
2986
  CURRENCY_CONFIG,
@@ -3401,7 +2991,6 @@ function isAdyenRolloutCountry(alpha2) {
3401
2991
  DEFAULT_CONFIG,
3402
2992
  DEFAULT_CROSS_AXIS_RULES,
3403
2993
  DEFAULT_DISPLAY_STATE_MAP,
3404
- DEFAULT_HOLD_MINUTES,
3405
2994
  DEFAULT_RESOLVED_CONFIG,
3406
2995
  DEFAULT_UNIT_ID,
3407
2996
  DualWriteStrategy,
@@ -3445,10 +3034,8 @@ function isAdyenRolloutCountry(alpha2) {
3445
3034
  REPORT_NEGATE_PATHS,
3446
3035
  ReceiptSendChannel,
3447
3036
  ReceiptType,
3448
- ReservationStatus,
3449
3037
  ResidualPaymentMethod,
3450
3038
  ResidualStatus,
3451
- ResourceAvailabilityState,
3452
3039
  STATE_SCHEMA,
3453
3040
  STRIPE_SUPPORTED_COUNTRIES,
3454
3041
  SYSTEM_FAMILIES,
@@ -3462,6 +3049,11 @@ function isAdyenRolloutCountry(alpha2) {
3462
3049
  TopMetericsSort,
3463
3050
  UserTypes,
3464
3051
  addAmounts,
3052
+ adyenLegalEntityRequiresStateOrProvince,
3053
+ adyenRequiresJobTitle,
3054
+ adyenStoreRequiresStateOrProvince,
3055
+ adyenSupportsTaxNumberAbsent,
3056
+ adyenTaxNumberFormat,
3465
3057
  amountToString,
3466
3058
  assertUnitSane,
3467
3059
  availableIn,
@@ -3469,8 +3061,6 @@ function isAdyenRolloutCountry(alpha2) {
3469
3061
  baseFulfillmentDefinitions,
3470
3062
  baseOf,
3471
3063
  basePaymentDefinitions,
3472
- buildAvailability,
3473
- buildGrid,
3474
3064
  buildOrderContext,
3475
3065
  buildPosPresetConfig,
3476
3066
  buildResolvedConfig,
@@ -3510,7 +3100,6 @@ function isAdyenRolloutCountry(alpha2) {
3510
3100
  getPricingRegionFromCountry,
3511
3101
  getSettlementTotal,
3512
3102
  getTotalCollected,
3513
- holdExpiresAt,
3514
3103
  inferStatesFromLegacyStatus,
3515
3104
  isAdyenRolloutCountry,
3516
3105
  isConditionOperator,
@@ -3525,12 +3114,9 @@ function isAdyenRolloutCountry(alpha2) {
3525
3114
  mergeFragment,
3526
3115
  multiplyAmount,
3527
3116
  normalizeMongoIdString,
3528
- occupancyIn,
3529
3117
  parseAmountToMinorUnits,
3530
3118
  parseCurrencyCode,
3531
3119
  parseStripeCurrencyCode,
3532
- planWindow,
3533
- presentAt,
3534
3120
  removeFragment,
3535
3121
  resolveFamily,
3536
3122
  resolveTemplate,
@@ -3538,18 +3124,13 @@ function isAdyenRolloutCountry(alpha2) {
3538
3124
  roundToPrecision,
3539
3125
  sameFamily,
3540
3126
  setOrderState,
3541
- shopDayKey,
3542
- shopDayRange,
3543
3127
  signReportForDisplay,
3544
- slotsForWindow,
3545
3128
  stringifyMinorUnits,
3546
3129
  subtractAmounts,
3547
3130
  toBase,
3548
3131
  toMinorUnits,
3549
3132
  validateConfig,
3550
3133
  validateFragmentCompatibility,
3551
- violatesFinancialInvariant,
3552
- windowEndsAt,
3553
- withinPresence
3134
+ violatesFinancialInvariant
3554
3135
  });
3555
3136
  //# sourceMappingURL=index.js.map