@final-commerce/common 2.3.0-staging.6 → 2.3.0
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 -193
- package/dist/index.d.ts +19 -193
- package/dist/index.js +12 -450
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +11 -432
- package/dist/index.mjs.map +1 -1
- package/dist/pos-types/index.d.mts +101 -143
- package/dist/pos-types/index.d.ts +101 -143
- package/dist/pos-types/index.js.map +1 -1
- package/dist/pos-types/index.mjs.map +1 -1
- package/package.json +1 -1
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
|
|
1910
|
-
const
|
|
1911
|
-
itemCount +=
|
|
1912
|
-
|
|
1913
|
-
|
|
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
|