@pisell/pisellos 2.2.313 → 2.2.315
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.ts +2 -0
- package/dist/index.js +3 -1
- package/dist/model/strategy/adapter/itemRule/adapter.d.ts +3 -1
- package/dist/model/strategy/adapter/itemRule/adapter.js +74 -7
- package/dist/model/strategy/adapter/itemRule/evaluator.d.ts +3 -1
- package/dist/model/strategy/adapter/itemRule/evaluator.js +13 -0
- package/dist/model/strategy/adapter/itemRule/type.d.ts +40 -1
- package/dist/model/strategy/adapter/itemRule/type.js +10 -0
- package/dist/modules/BookingContext/utils/productExtend.d.ts +7 -0
- package/dist/modules/BookingContext/utils/productExtend.js +62 -18
- package/dist/modules/BookingContext/utils/resources.js +1 -1
- package/dist/modules/BusinessAvailability/index.d.ts +30 -0
- package/dist/modules/BusinessAvailability/index.js +204 -0
- package/dist/modules/Cart/index.js +4 -3
- package/dist/modules/Cart/types.d.ts +2 -0
- package/dist/modules/Cart/utils/cartProduct.d.ts +3 -1
- package/dist/modules/Cart/utils/cartProduct.js +59 -32
- package/dist/modules/FulfillmentTiming/index.d.ts +11 -0
- package/dist/modules/FulfillmentTiming/index.js +407 -0
- package/dist/modules/FulfillmentTiming/types.d.ts +67 -0
- package/dist/modules/FulfillmentTiming/types.js +1 -0
- package/dist/modules/OpenData/types.d.ts +14 -0
- package/dist/modules/Order/index.d.ts +14 -2
- package/dist/modules/Order/index.js +856 -486
- package/dist/modules/Order/localEftposState.d.ts +13 -0
- package/dist/modules/Order/localEftposState.js +39 -0
- package/dist/modules/Order/pickupTiming.d.ts +46 -0
- package/dist/modules/Order/pickupTiming.js +53 -0
- package/dist/modules/Order/types.d.ts +30 -2
- package/dist/modules/Order/utils.js +25 -7
- package/dist/modules/Payment/index.js +9 -10
- package/dist/modules/Product/types.d.ts +11 -0
- package/dist/modules/ProductList/index.js +1 -1
- package/dist/modules/ResourcePlanner/planner.d.ts +2 -0
- package/dist/modules/ResourcePlanner/planner.js +332 -23
- package/dist/modules/ResourcePlanner/types.d.ts +29 -0
- package/dist/modules/Schedule/index.d.ts +8 -0
- package/dist/modules/Schedule/index.js +141 -39
- package/dist/modules/index.d.ts +1 -0
- package/dist/modules/index.js +1 -0
- package/dist/plugins/request.d.ts +7 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1536 -1309
- package/dist/server/modules/form/index.d.ts +19 -0
- package/dist/server/modules/form/index.js +205 -0
- package/dist/server/modules/form/types.d.ts +13 -0
- package/dist/server/modules/form/types.js +3 -0
- package/dist/server/modules/index.d.ts +3 -0
- package/dist/server/modules/index.js +4 -0
- package/dist/server/modules/order/index.d.ts +15 -0
- package/dist/server/modules/order/index.js +920 -688
- package/dist/server/modules/order/types.d.ts +1 -0
- package/dist/server/test.json +1 -1
- package/dist/server/utils/small-ticket.d.ts +1 -85
- package/dist/server/utils/small-ticket.js +2 -2542
- package/dist/shared/payment/loadPaymentMethods.d.ts +9 -0
- package/dist/shared/payment/loadPaymentMethods.js +66 -0
- package/dist/shared/receipt/customerInvoiceLanguages.d.ts +8 -0
- package/dist/shared/receipt/customerInvoiceLanguages.js +60 -0
- package/dist/shared/receipt/loadCustomerInvoiceLayout.d.ts +27 -0
- package/dist/shared/receipt/loadCustomerInvoiceLayout.js +184 -0
- package/dist/shared/receipt/small-ticket.d.ts +96 -0
- package/dist/shared/receipt/small-ticket.js +2751 -0
- package/dist/shared/receipt/templateVisibility.d.ts +23 -0
- package/dist/shared/receipt/templateVisibility.js +64 -0
- package/dist/shared/sales/loadSalesOrderSnapshot.d.ts +9 -0
- package/dist/shared/sales/loadSalesOrderSnapshot.js +21 -0
- package/dist/solution/BaseSales/fulfillmentItemRules.d.ts +27 -0
- package/dist/solution/BaseSales/fulfillmentItemRules.js +750 -0
- package/dist/solution/BaseSales/index.d.ts +39 -16
- package/dist/solution/BaseSales/index.js +1754 -1154
- package/dist/solution/BaseSales/pickupTiming.d.ts +47 -0
- package/dist/solution/BaseSales/pickupTiming.js +616 -0
- package/dist/solution/BaseSales/types.d.ts +11 -0
- package/dist/solution/BaseSales/utils/parseSalesResponse.js +3 -0
- package/dist/solution/BookingByStep/index.d.ts +4 -2
- package/dist/solution/BookingByStep/index.js +8 -3
- package/dist/solution/BookingTicket/index.d.ts +8 -2
- package/dist/solution/BookingTicket/index.js +513 -436
- package/dist/solution/BookingTicket/utils/addProductDecision.d.ts +0 -1
- package/dist/solution/BookingTicket/utils/addProductDecision.js +1 -1
- package/dist/solution/BookingTicket/utils/cartView.js +3 -1
- package/dist/solution/OrderInvoicePreview/index.d.ts +66 -0
- package/dist/solution/OrderInvoicePreview/index.js +340 -0
- package/dist/solution/RegisterAndLogin/config.js +54 -11
- package/dist/solution/RegisterAndLogin/index.d.ts +2 -0
- package/dist/solution/RegisterAndLogin/index.js +1 -1
- package/dist/solution/RegisterAndLogin/utils.d.ts +12 -4
- package/dist/solution/RegisterAndLogin/utils.js +36 -16
- package/dist/solution/Sales/index.js +1 -1
- package/dist/solution/UnifiedBookingSales/businessAvailability.d.ts +27 -0
- package/dist/solution/UnifiedBookingSales/businessAvailability.js +292 -0
- package/dist/solution/UnifiedBookingSales/index.d.ts +36 -4
- package/dist/solution/UnifiedBookingSales/index.js +1714 -905
- package/dist/solution/UnifiedBookingSales/types.d.ts +16 -2
- package/dist/solution/VenueBooking/index.d.ts +15 -2
- package/dist/solution/VenueBooking/index.js +1062 -785
- package/dist/solution/VenueBooking/types.d.ts +2 -1
- package/dist/solution/VenueBooking/types.js +1 -0
- package/dist/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
- package/dist/solution/VenueBooking/utils/dateSummary.js +7 -4
- package/dist/solution/VenueBooking/utils/smartPricing.d.ts +71 -0
- package/dist/solution/VenueBooking/utils/smartPricing.js +273 -0
- package/dist/solution/VenueBooking/utils/timeSlot.d.ts +1 -0
- package/dist/solution/VenueBooking/utils/timeSlot.js +6 -3
- package/dist/solution/index.d.ts +1 -0
- package/dist/solution/index.js +2 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.js +21 -1
- package/lib/model/strategy/adapter/itemRule/adapter.d.ts +3 -1
- package/lib/model/strategy/adapter/itemRule/adapter.js +54 -4
- package/lib/model/strategy/adapter/itemRule/evaluator.d.ts +3 -1
- package/lib/model/strategy/adapter/itemRule/evaluator.js +9 -0
- package/lib/model/strategy/adapter/itemRule/type.d.ts +40 -1
- package/lib/model/strategy/adapter/itemRule/type.js +10 -0
- package/lib/modules/BookingContext/utils/productExtend.d.ts +7 -0
- package/lib/modules/BookingContext/utils/productExtend.js +45 -2
- package/lib/modules/BookingContext/utils/resources.js +1 -1
- package/lib/modules/BusinessAvailability/index.d.ts +30 -0
- package/lib/modules/BusinessAvailability/index.js +146 -0
- package/lib/modules/Cart/index.js +4 -2
- package/lib/modules/Cart/types.d.ts +2 -0
- package/lib/modules/Cart/utils/cartProduct.d.ts +3 -1
- package/lib/modules/Cart/utils/cartProduct.js +39 -20
- package/lib/modules/FulfillmentTiming/index.d.ts +11 -0
- package/lib/modules/FulfillmentTiming/index.js +359 -0
- package/lib/modules/FulfillmentTiming/types.d.ts +67 -0
- package/lib/modules/FulfillmentTiming/types.js +5 -0
- package/lib/modules/OpenData/types.d.ts +14 -0
- package/lib/modules/Order/index.d.ts +14 -2
- package/lib/modules/Order/index.js +240 -38
- package/lib/modules/Order/localEftposState.d.ts +13 -0
- package/lib/modules/Order/localEftposState.js +44 -0
- package/lib/modules/Order/pickupTiming.d.ts +46 -0
- package/lib/modules/Order/pickupTiming.js +61 -0
- package/lib/modules/Order/types.d.ts +30 -2
- package/lib/modules/Order/utils.js +21 -5
- package/lib/modules/Payment/index.js +3 -4
- package/lib/modules/Product/types.d.ts +11 -0
- package/lib/modules/ProductList/index.js +1 -1
- package/lib/modules/ResourcePlanner/planner.d.ts +2 -0
- package/lib/modules/ResourcePlanner/planner.js +252 -8
- package/lib/modules/ResourcePlanner/types.d.ts +29 -0
- package/lib/modules/Schedule/index.d.ts +8 -0
- package/lib/modules/Schedule/index.js +68 -12
- package/lib/modules/index.d.ts +1 -0
- package/lib/modules/index.js +11 -0
- package/lib/plugins/request.d.ts +7 -0
- package/lib/server/index.d.ts +1 -0
- package/lib/server/index.js +158 -37
- package/lib/server/modules/form/index.d.ts +19 -0
- package/lib/server/modules/form/index.js +73 -0
- package/lib/server/modules/form/types.d.ts +13 -0
- package/lib/server/modules/form/types.js +9 -0
- package/lib/server/modules/index.d.ts +3 -0
- package/lib/server/modules/index.js +15 -1
- package/lib/server/modules/order/index.d.ts +15 -0
- package/lib/server/modules/order/index.js +114 -3
- package/lib/server/modules/order/types.d.ts +1 -0
- package/lib/server/test.json +1 -1
- package/lib/server/utils/small-ticket.d.ts +1 -85
- package/lib/server/utils/small-ticket.js +9 -2305
- package/lib/shared/payment/loadPaymentMethods.d.ts +9 -0
- package/lib/shared/payment/loadPaymentMethods.js +40 -0
- package/lib/shared/receipt/customerInvoiceLanguages.d.ts +8 -0
- package/lib/shared/receipt/customerInvoiceLanguages.js +58 -0
- package/lib/shared/receipt/loadCustomerInvoiceLayout.d.ts +27 -0
- package/lib/shared/receipt/loadCustomerInvoiceLayout.js +124 -0
- package/lib/shared/receipt/small-ticket.d.ts +96 -0
- package/lib/shared/receipt/small-ticket.js +2546 -0
- package/lib/shared/receipt/templateVisibility.d.ts +23 -0
- package/lib/shared/receipt/templateVisibility.js +63 -0
- package/lib/shared/sales/loadSalesOrderSnapshot.d.ts +9 -0
- package/lib/shared/sales/loadSalesOrderSnapshot.js +22 -0
- package/lib/solution/BaseSales/fulfillmentItemRules.d.ts +27 -0
- package/lib/solution/BaseSales/fulfillmentItemRules.js +259 -0
- package/lib/solution/BaseSales/index.d.ts +39 -16
- package/lib/solution/BaseSales/index.js +333 -31
- package/lib/solution/BaseSales/pickupTiming.d.ts +47 -0
- package/lib/solution/BaseSales/pickupTiming.js +290 -0
- package/lib/solution/BaseSales/types.d.ts +11 -0
- package/lib/solution/BaseSales/utils/parseSalesResponse.js +3 -0
- package/lib/solution/BookingByStep/index.d.ts +4 -2
- package/lib/solution/BookingByStep/index.js +7 -3
- package/lib/solution/BookingTicket/index.d.ts +8 -2
- package/lib/solution/BookingTicket/index.js +65 -6
- package/lib/solution/BookingTicket/utils/addProductDecision.d.ts +0 -1
- package/lib/solution/BookingTicket/utils/addProductDecision.js +1 -1
- package/lib/solution/BookingTicket/utils/cartView.js +3 -1
- package/lib/solution/OrderInvoicePreview/index.d.ts +66 -0
- package/lib/solution/OrderInvoicePreview/index.js +246 -0
- package/lib/solution/RegisterAndLogin/config.js +57 -11
- package/lib/solution/RegisterAndLogin/index.d.ts +2 -0
- package/lib/solution/RegisterAndLogin/index.js +9 -1
- package/lib/solution/RegisterAndLogin/utils.d.ts +12 -4
- package/lib/solution/RegisterAndLogin/utils.js +24 -17
- package/lib/solution/Sales/index.js +1 -1
- package/lib/solution/UnifiedBookingSales/businessAvailability.d.ts +27 -0
- package/lib/solution/UnifiedBookingSales/businessAvailability.js +138 -0
- package/lib/solution/UnifiedBookingSales/index.d.ts +36 -4
- package/lib/solution/UnifiedBookingSales/index.js +561 -74
- package/lib/solution/UnifiedBookingSales/types.d.ts +16 -2
- package/lib/solution/VenueBooking/index.d.ts +15 -2
- package/lib/solution/VenueBooking/index.js +243 -96
- package/lib/solution/VenueBooking/types.d.ts +2 -1
- package/lib/solution/VenueBooking/types.js +1 -0
- package/lib/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
- package/lib/solution/VenueBooking/utils/dateSummary.js +7 -4
- package/lib/solution/VenueBooking/utils/smartPricing.d.ts +71 -0
- package/lib/solution/VenueBooking/utils/smartPricing.js +224 -0
- package/lib/solution/VenueBooking/utils/timeSlot.d.ts +1 -0
- package/lib/solution/VenueBooking/utils/timeSlot.js +5 -2
- package/lib/solution/index.d.ts +1 -0
- package/lib/solution/index.js +11 -0
- package/package.json +1 -1
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
3
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
4
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
5
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
2
6
|
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
3
7
|
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
4
8
|
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
@@ -171,7 +175,11 @@ function resolveCutOffPolicyIssue(policy) {
|
|
|
171
175
|
return null;
|
|
172
176
|
}
|
|
173
177
|
function addLeadWindow(base, unit, unitType, _timezoneName) {
|
|
174
|
-
if (unitType === 'days')
|
|
178
|
+
if (unitType === 'days') {
|
|
179
|
+
var leadDate = addLocalCalendarDays(base, unit);
|
|
180
|
+
// Positive day lead times start at midnight; zero days keeps the current-time boundary.
|
|
181
|
+
return Math.trunc(unit) > 0 ? localDateToScalarStart(formatLocalDate(leadDate)) : leadDate;
|
|
182
|
+
}
|
|
175
183
|
if (unitType === 'hours') return addLocalHours(base, unit);
|
|
176
184
|
return addLocalMinutes(base, unit);
|
|
177
185
|
}
|
|
@@ -263,6 +271,18 @@ function evaluateCandidateTimeGate(params) {
|
|
|
263
271
|
};
|
|
264
272
|
}
|
|
265
273
|
var policy = product.cutOffPolicy;
|
|
274
|
+
// Current duration items can be shown outside business hours. Their real
|
|
275
|
+
// interval must remain unavailable, including products with no resource groups.
|
|
276
|
+
if (evaluationContext.useDurationTimeGrid && product.kind === 'duration' && !projection.meta.defaults.operatingHours.windows.some(function (window) {
|
|
277
|
+
var range = normalizeAbsoluteRange(window);
|
|
278
|
+
return range && contains(range, candidateRange);
|
|
279
|
+
})) {
|
|
280
|
+
return {
|
|
281
|
+
status: 'unavailable',
|
|
282
|
+
reasonCodes: ['outside_operating_hours'],
|
|
283
|
+
conflictCode: 'booking_cutoff'
|
|
284
|
+
};
|
|
285
|
+
}
|
|
266
286
|
if (!policy) return null;
|
|
267
287
|
if (resolveCutOffPolicyIssue(policy)) {
|
|
268
288
|
return {
|
|
@@ -299,8 +319,8 @@ function evaluateCandidateTimeGate(params) {
|
|
|
299
319
|
// otherwise a minute refresh turns it into 0 capacity and incorrectly
|
|
300
320
|
// advances a create flow to the next slot. The earlier `past` gate still
|
|
301
321
|
// rejects the anchor once its booking range has ended.
|
|
302
|
-
var isActivePosDurationAnchor = evaluationContext.useExactDurationCandidateMinute && product.kind === 'duration' && !product.isFlexibleDuration && evaluationContext.durationCandidateAnchorAtMs === candidateRange.start;
|
|
303
|
-
var usesMinutePrecision = product.isFlexibleDuration || evaluationContext.useExactDurationCandidateMinute && product.kind === 'duration';
|
|
322
|
+
var isActivePosDurationAnchor = evaluationContext.useExactDurationCandidateMinute && !evaluationContext.enforceSaleCutoff && product.kind === 'duration' && !product.isFlexibleDuration && evaluationContext.durationCandidateAnchorAtMs === candidateRange.start;
|
|
323
|
+
var usesMinutePrecision = product.isFlexibleDuration || evaluationContext.useDurationTimeGrid || evaluationContext.useExactDurationCandidateMinute && product.kind === 'duration';
|
|
304
324
|
var hasNotReachedStart = isActivePosDurationAnchor || (usesMinutePrecision ? floorToMinute(now) <= candidateRange.start : now < candidateRange.start);
|
|
305
325
|
if (hasNotReachedStart) return null;
|
|
306
326
|
return {
|
|
@@ -494,7 +514,7 @@ function normalizeResources(resources) {
|
|
|
494
514
|
});
|
|
495
515
|
}
|
|
496
516
|
function normalizeOperatingHours(params) {
|
|
497
|
-
var _params$input, _params$input2, _params$input3, _params$input4;
|
|
517
|
+
var _params$input, _params$input2, _params$input3, _params$input4, _params$input5, _params$input6;
|
|
498
518
|
var fallbackWindows = enumerateDates(params.dateRange.startDate, params.dateRange.endDate).map(function (date) {
|
|
499
519
|
var start = toDateTimeInDate(date, params.businessHours.startTime, params.timezoneName);
|
|
500
520
|
var end = toDateTimeInDate(date, params.businessHours.endTime, params.timezoneName);
|
|
@@ -530,11 +550,43 @@ function normalizeOperatingHours(params) {
|
|
|
530
550
|
};
|
|
531
551
|
var windows = normalizeWindows(sourceWindows);
|
|
532
552
|
var excludedWindows = normalizeWindows(((_params$input = params.input) === null || _params$input === void 0 ? void 0 : _params$input.excludedWindows) || []);
|
|
553
|
+
// Keep original dates and opening anchors separately: the availability
|
|
554
|
+
// windows below may be clipped at midnight or merged without segment identity.
|
|
555
|
+
var periodMap = new Map();
|
|
556
|
+
var originalPeriods = ((_params$input2 = params.input) === null || _params$input2 === void 0 ? void 0 : _params$input2.businessPeriods) || [].concat(_toConsumableArray(sourceWindows), _toConsumableArray(((_params$input3 = params.input) === null || _params$input3 === void 0 ? void 0 : _params$input3.excludedWindows) || [])).map(function (window) {
|
|
557
|
+
return {
|
|
558
|
+
businessDate: window.businessDate || window.startAt.slice(0, 10),
|
|
559
|
+
startAt: window.openingAnchorAt || window.startAt,
|
|
560
|
+
endAt: window.endAt
|
|
561
|
+
};
|
|
562
|
+
});
|
|
563
|
+
originalPeriods.forEach(function (period) {
|
|
564
|
+
var range = normalizeAbsoluteRange(period);
|
|
565
|
+
if (!range) return;
|
|
566
|
+
var previous = periodMap.get(period.businessDate);
|
|
567
|
+
periodMap.set(period.businessDate, {
|
|
568
|
+
start: previous ? Math.min(previous.start, range.start) : range.start,
|
|
569
|
+
end: previous ? Math.max(previous.end, range.end) : range.end
|
|
570
|
+
});
|
|
571
|
+
});
|
|
572
|
+
var businessPeriods = Array.from(periodMap, function (_ref) {
|
|
573
|
+
var _ref2 = _slicedToArray(_ref, 2),
|
|
574
|
+
businessDate = _ref2[0],
|
|
575
|
+
range = _ref2[1];
|
|
576
|
+
return {
|
|
577
|
+
businessDate: businessDate,
|
|
578
|
+
startAt: formatDateTime(range.start, params.timezoneName, params.fixedOffsetMinutes),
|
|
579
|
+
endAt: formatDateTime(range.end, params.timezoneName, params.fixedOffsetMinutes)
|
|
580
|
+
};
|
|
581
|
+
}).sort(function (left, right) {
|
|
582
|
+
return left.startAt.localeCompare(right.startAt);
|
|
583
|
+
});
|
|
533
584
|
return _objectSpread({
|
|
534
|
-
source: ((_params$
|
|
535
|
-
scheduleIds: uniqById(((_params$
|
|
536
|
-
missingScheduleIds: uniqById(((_params$
|
|
537
|
-
windows: windows
|
|
585
|
+
source: ((_params$input4 = params.input) === null || _params$input4 === void 0 ? void 0 : _params$input4.source) || params.fallbackSource,
|
|
586
|
+
scheduleIds: uniqById(((_params$input5 = params.input) === null || _params$input5 === void 0 ? void 0 : _params$input5.scheduleIds) || []),
|
|
587
|
+
missingScheduleIds: uniqById(((_params$input6 = params.input) === null || _params$input6 === void 0 ? void 0 : _params$input6.missingScheduleIds) || []),
|
|
588
|
+
windows: windows,
|
|
589
|
+
businessPeriods: businessPeriods
|
|
538
590
|
}, excludedWindows.length > 0 ? {
|
|
539
591
|
excludedWindows: excludedWindows
|
|
540
592
|
} : {});
|
|
@@ -553,8 +605,8 @@ function matchesRequirementGroup(requirementGroup, resource, product) {
|
|
|
553
605
|
return resource.capacity >= resolveRequiredCapacity(requirementGroup, product, partySize);
|
|
554
606
|
}
|
|
555
607
|
function resolveRequiredCapacity(requirementGroup, product, partySize) {
|
|
556
|
-
var
|
|
557
|
-
return Math.max(1, Number((
|
|
608
|
+
var _ref3, _ref4;
|
|
609
|
+
return Math.max(1, Number((_ref3 = (_ref4 = partySize !== null && partySize !== void 0 ? partySize : requirementGroup.capacityRequired) !== null && _ref4 !== void 0 ? _ref4 : product.capacityRequired) !== null && _ref3 !== void 0 ? _ref3 : 1) || 1);
|
|
558
610
|
}
|
|
559
611
|
function buildCellKey(params) {
|
|
560
612
|
return [String(params.productId), params.groupId, String(params.resourceId), params.start, params.end].join(':');
|
|
@@ -608,8 +660,8 @@ function buildCells(projection) {
|
|
|
608
660
|
boundaries.add(window.start);
|
|
609
661
|
boundaries.add(window.end);
|
|
610
662
|
});
|
|
611
|
-
occupancies.forEach(function (
|
|
612
|
-
var range =
|
|
663
|
+
occupancies.forEach(function (_ref5) {
|
|
664
|
+
var range = _ref5.range;
|
|
613
665
|
boundaries.add(range.start);
|
|
614
666
|
boundaries.add(range.end);
|
|
615
667
|
});
|
|
@@ -627,11 +679,11 @@ function buildCells(projection) {
|
|
|
627
679
|
var isInsideWorkingWindow = windows.some(function (window) {
|
|
628
680
|
return contains(window, segment);
|
|
629
681
|
});
|
|
630
|
-
var segmentOccupancies = isInsideWorkingWindow ? occupancies.filter(function (
|
|
631
|
-
var range =
|
|
682
|
+
var segmentOccupancies = isInsideWorkingWindow ? occupancies.filter(function (_ref6) {
|
|
683
|
+
var range = _ref6.range;
|
|
632
684
|
return overlaps(range, segment);
|
|
633
|
-
}).map(function (
|
|
634
|
-
var occupancy =
|
|
685
|
+
}).map(function (_ref7) {
|
|
686
|
+
var occupancy = _ref7.occupancy;
|
|
635
687
|
return occupancy;
|
|
636
688
|
}) : [];
|
|
637
689
|
var usedCapacity = segmentOccupancies.reduce(function (sum, occupancy) {
|
|
@@ -1108,6 +1160,211 @@ function createDurationTimeRangeWithEnd(product, start, bookingEnd, projection,
|
|
|
1108
1160
|
scheduleRefs: []
|
|
1109
1161
|
};
|
|
1110
1162
|
}
|
|
1163
|
+
|
|
1164
|
+
/** Resolve the label without changing the real calendar timestamp. */
|
|
1165
|
+
export function getDurationBusinessDate(projection, startAt) {
|
|
1166
|
+
var start = toDateTime(startAt);
|
|
1167
|
+
var periods = projection.meta.defaults.operatingHours.businessPeriods || [];
|
|
1168
|
+
var period = _toConsumableArray(periods).reverse().find(function (item) {
|
|
1169
|
+
var range = normalizeAbsoluteRange(item);
|
|
1170
|
+
return range && range.start <= start && start < range.end;
|
|
1171
|
+
});
|
|
1172
|
+
return (period === null || period === void 0 ? void 0 : period.businessDate) || startAt.slice(0, 10);
|
|
1173
|
+
}
|
|
1174
|
+
function getAlignedDurationRanges(params) {
|
|
1175
|
+
var _request$rememberedSt, _request$editingStart;
|
|
1176
|
+
var projection = params.projection,
|
|
1177
|
+
product = params.product,
|
|
1178
|
+
request = params.request,
|
|
1179
|
+
runtimeOptions = params.runtimeOptions,
|
|
1180
|
+
dateRange = params.dateRange,
|
|
1181
|
+
operatingRanges = params.operatingRanges,
|
|
1182
|
+
baseRanges = params.baseRanges,
|
|
1183
|
+
resourceWindowIndex = params.resourceWindowIndex,
|
|
1184
|
+
fixedOffsetMinutes = params.fixedOffsetMinutes;
|
|
1185
|
+
var step = projection.meta.defaults.slotStepMinutes;
|
|
1186
|
+
var now = floorToMinute(toDateTime(runtimeOptions.evaluatedAt || projection.meta.durationCandidateAnchorAt));
|
|
1187
|
+
if (!Number.isFinite(now)) throw availabilityError('INVALID_TARGET_FILTER', 'evaluatedAt 必须是有效时间');
|
|
1188
|
+
var nowAt = formatDateTime(now, projection.meta.timezone, fixedOffsetMinutes);
|
|
1189
|
+
var currentBusinessDate = getDurationBusinessDate(projection, nowAt);
|
|
1190
|
+
var inRequestedDays = function inRequestedDays(date) {
|
|
1191
|
+
return date >= dateRange.startDate && date <= dateRange.endDate;
|
|
1192
|
+
};
|
|
1193
|
+
var periods = (projection.meta.defaults.operatingHours.businessPeriods || []).filter(function (period) {
|
|
1194
|
+
return inRequestedDays(period.businessDate);
|
|
1195
|
+
});
|
|
1196
|
+
// A prepared month includes tomorrow's windows too; the single-day UI must
|
|
1197
|
+
// receive the selected business cycle's end, not tomorrow's closing time.
|
|
1198
|
+
var operatingEndAt = dateRange.startDate === dateRange.endDate && periods.length ? periods.reduce(function (latest, period) {
|
|
1199
|
+
return period.endAt > latest ? period.endAt : latest;
|
|
1200
|
+
}, periods[0].endAt) : undefined;
|
|
1201
|
+
var ranges = [];
|
|
1202
|
+
var duration = resolveRequestedDurationMinutes(product, request);
|
|
1203
|
+
var addRange = function addRange(start, end, businessDate) {
|
|
1204
|
+
if (end <= start) return;
|
|
1205
|
+
var candidate = createDurationTimeRangeWithEnd(product, start, end, projection, fixedOffsetMinutes);
|
|
1206
|
+
candidate.businessDate = businessDate || getDurationBusinessDate(projection, candidate.startAt);
|
|
1207
|
+
if (inRequestedDays(candidate.businessDate)) ranges.push(candidate);
|
|
1208
|
+
};
|
|
1209
|
+
// A flexible end comes from resources that actually cover this exact start,
|
|
1210
|
+
// never from the next future window. Keep alternative real ends separate.
|
|
1211
|
+
var flexibleEnds = function flexibleEnds(start) {
|
|
1212
|
+
var _projection$meta$defa;
|
|
1213
|
+
var operating = operatingRanges.find(function (range) {
|
|
1214
|
+
return range.start <= start && start < range.end;
|
|
1215
|
+
});
|
|
1216
|
+
if (!operating) return [];
|
|
1217
|
+
var businessDate = getDurationBusinessDate(projection, formatDateTime(start, projection.meta.timezone, fixedOffsetMinutes));
|
|
1218
|
+
var period = (_projection$meta$defa = projection.meta.defaults.operatingHours.businessPeriods) === null || _projection$meta$defa === void 0 ? void 0 : _projection$meta$defa.find(function (item) {
|
|
1219
|
+
return item.businessDate === businessDate;
|
|
1220
|
+
});
|
|
1221
|
+
var operatingEnd = Math.min(operating.end, period ? toDateTime(period.endAt) : operating.end);
|
|
1222
|
+
var requiredGroups = (product.requirementGroups || []).filter(function (group) {
|
|
1223
|
+
return group.required !== false;
|
|
1224
|
+
});
|
|
1225
|
+
var groups = requiredGroups.map(function (group) {
|
|
1226
|
+
return projection.resources.filter(function (resource) {
|
|
1227
|
+
return matchesRequirementGroup(group, resource, product, request.partySize);
|
|
1228
|
+
}).filter(function (resource) {
|
|
1229
|
+
var _request$resourceIds;
|
|
1230
|
+
return !((_request$resourceIds = request.resourceIds) !== null && _request$resourceIds !== void 0 && _request$resourceIds.length) || request.resourceIds.some(function (id) {
|
|
1231
|
+
return sameId(id, resource.id);
|
|
1232
|
+
});
|
|
1233
|
+
}).flatMap(function (resource) {
|
|
1234
|
+
return (resourceWindowIndex.get(String(resource.id)) || []).filter(function (range) {
|
|
1235
|
+
return range.start <= start && start < range.end;
|
|
1236
|
+
}).map(function (range) {
|
|
1237
|
+
return Math.min(range.end, operatingEnd);
|
|
1238
|
+
});
|
|
1239
|
+
});
|
|
1240
|
+
});
|
|
1241
|
+
if (groups.some(function (ends) {
|
|
1242
|
+
return ends.length === 0;
|
|
1243
|
+
})) return [];
|
|
1244
|
+
if (!groups.length) return [operatingEnd];
|
|
1245
|
+
return Array.from(new Set(groups.flat())).filter(function (end) {
|
|
1246
|
+
return groups.every(function (ends) {
|
|
1247
|
+
return ends.some(function (availableEnd) {
|
|
1248
|
+
return availableEnd >= end;
|
|
1249
|
+
});
|
|
1250
|
+
});
|
|
1251
|
+
}).sort(function (left, right) {
|
|
1252
|
+
return left - right;
|
|
1253
|
+
});
|
|
1254
|
+
};
|
|
1255
|
+
if (product.isFlexibleDuration) {
|
|
1256
|
+
// Preserve the existing continuous-window UI, with the business-day label.
|
|
1257
|
+
periods.forEach(function (period) {
|
|
1258
|
+
var periodRange = normalizeAbsoluteRange(period);
|
|
1259
|
+
baseRanges.forEach(function (range) {
|
|
1260
|
+
var start = Math.max(range.start, periodRange.start, now);
|
|
1261
|
+
var end = Math.min(range.end, periodRange.end);
|
|
1262
|
+
if (start < end) addRange(start, end, period.businessDate);
|
|
1263
|
+
});
|
|
1264
|
+
});
|
|
1265
|
+
} else {
|
|
1266
|
+
periods.forEach(function (period) {
|
|
1267
|
+
var periodRange = normalizeAbsoluteRange(period);
|
|
1268
|
+
var anchor = 60 % step === 0 ? toDateStart(period.businessDate) : periodRange.start;
|
|
1269
|
+
baseRanges.forEach(function (range) {
|
|
1270
|
+
var lower = Math.max(range.start, periodRange.start, now);
|
|
1271
|
+
var upper = Math.min(range.end, periodRange.end);
|
|
1272
|
+
var cursor = anchor + Math.ceil((lower - anchor) / (step * 60000)) * step * 60000;
|
|
1273
|
+
for (; cursor + duration * 60000 <= upper; cursor += step * 60000) {
|
|
1274
|
+
addRange(cursor, cursor + duration * 60000, period.businessDate);
|
|
1275
|
+
}
|
|
1276
|
+
});
|
|
1277
|
+
});
|
|
1278
|
+
}
|
|
1279
|
+
var unavailableCurrentTime;
|
|
1280
|
+
if (inRequestedDays(currentBusinessDate)) {
|
|
1281
|
+
if (product.isFlexibleDuration) {
|
|
1282
|
+
var ends = flexibleEnds(now);
|
|
1283
|
+
ends.forEach(function (end) {
|
|
1284
|
+
return addRange(now, end, currentBusinessDate);
|
|
1285
|
+
});
|
|
1286
|
+
if (!ends.length) {
|
|
1287
|
+
unavailableCurrentTime = {
|
|
1288
|
+
productId: product.id,
|
|
1289
|
+
startAt: nowAt,
|
|
1290
|
+
date: formatDate(now),
|
|
1291
|
+
businessDate: currentBusinessDate,
|
|
1292
|
+
startTime: formatTime(now),
|
|
1293
|
+
status: 'unavailable',
|
|
1294
|
+
reasonCodes: [operatingRanges.some(function (range) {
|
|
1295
|
+
return range.start <= now && now < range.end;
|
|
1296
|
+
}) ? 'outside_resource_window' : 'outside_operating_hours']
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1299
|
+
} else {
|
|
1300
|
+
// Even outside a working window the fixed product has a real end. Query
|
|
1301
|
+
// reports unavailable; POS manual capabilities remain a separate policy.
|
|
1302
|
+
addRange(now, now + duration * 60000, currentBusinessDate);
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
var rememberedAt = (_request$rememberedSt = request.rememberedStartAtByProductId) === null || _request$rememberedSt === void 0 ? void 0 : _request$rememberedSt[String(product.id)];
|
|
1306
|
+
if (rememberedAt !== undefined) {
|
|
1307
|
+
var start = toDateTime(rememberedAt);
|
|
1308
|
+
if (!Number.isFinite(start)) throw availabilityError('INVALID_TARGET_FILTER', '记忆开始时间必须是完整日期时间');
|
|
1309
|
+
if (product.isFlexibleDuration) {
|
|
1310
|
+
flexibleEnds(start).forEach(function (end) {
|
|
1311
|
+
return addRange(start, end);
|
|
1312
|
+
});
|
|
1313
|
+
} else {
|
|
1314
|
+
addRange(start, start + duration * 60000);
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
var editingAt = (_request$editingStart = request.editingStartAtByProductId) === null || _request$editingStart === void 0 ? void 0 : _request$editingStart[String(product.id)];
|
|
1318
|
+
if (editingAt !== undefined) {
|
|
1319
|
+
var _request$durationMinu3;
|
|
1320
|
+
var _start = toDateTime(editingAt);
|
|
1321
|
+
var editingDuration = Number((_request$durationMinu3 = request.durationMinutesByProductId) === null || _request$durationMinu3 === void 0 ? void 0 : _request$durationMinu3[String(product.id)]);
|
|
1322
|
+
if (!Number.isFinite(_start) || !Number.isInteger(editingDuration) || editingDuration <= 0) {
|
|
1323
|
+
throw availabilityError('INVALID_TARGET_FILTER', '编辑时间必须包含完整开始日期时间和明确的正整数时长');
|
|
1324
|
+
}
|
|
1325
|
+
// Editing restores the original interval, including its actual overnight
|
|
1326
|
+
// date. It neither adopts the current grid nor recomputes a flexible end.
|
|
1327
|
+
if (request.allowOutsideOperatingHoursForRequestedStartTimes || operatingRanges.some(function (range) {
|
|
1328
|
+
return range.start <= _start && _start < range.end;
|
|
1329
|
+
})) {
|
|
1330
|
+
addRange(_start, addMinutesZoned(_start, editingDuration, projection.meta.timezone));
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
// Explicit custom input keeps its existing start + requested duration
|
|
1335
|
+
// semantics. Remembered input above must never use this default-30 path.
|
|
1336
|
+
if (dateRange.startDate === dateRange.endDate) {
|
|
1337
|
+
resolveRequestedDurationStartTimes(product, request).forEach(function (startTime) {
|
|
1338
|
+
var sameDayStart = toDateTimeInDate(dateRange.startDate, startTime);
|
|
1339
|
+
var period = periods.find(function (item) {
|
|
1340
|
+
return item.businessDate === dateRange.startDate;
|
|
1341
|
+
});
|
|
1342
|
+
var periodRange = period ? normalizeAbsoluteRange(period) : null;
|
|
1343
|
+
var nextDayStart = addLocalCalendarDays(sameDayStart, 1);
|
|
1344
|
+
// HH:mm is entered within a selected business day, whose early hours
|
|
1345
|
+
// may belong to the next calendar day. Do not move other out-of-hours
|
|
1346
|
+
// manual input to tomorrow merely because the business closes overnight.
|
|
1347
|
+
var start = periodRange && !(periodRange.start <= sameDayStart && sameDayStart < periodRange.end) && periodRange.start <= nextDayStart && nextDayStart < periodRange.end ? nextDayStart : sameDayStart;
|
|
1348
|
+
if (request.allowOutsideOperatingHoursForRequestedStartTimes || operatingRanges.some(function (range) {
|
|
1349
|
+
return range.start <= start && start < range.end;
|
|
1350
|
+
})) {
|
|
1351
|
+
addRange(start, start + duration * 60000);
|
|
1352
|
+
}
|
|
1353
|
+
});
|
|
1354
|
+
}
|
|
1355
|
+
return _objectSpread(_objectSpread({
|
|
1356
|
+
productId: product.id,
|
|
1357
|
+
title: product.title,
|
|
1358
|
+
kind: product.kind,
|
|
1359
|
+
slotStepMinutes: step
|
|
1360
|
+
}, operatingEndAt ? {
|
|
1361
|
+
operatingEndAt: operatingEndAt
|
|
1362
|
+
} : {}), {}, {
|
|
1363
|
+
ranges: dedupeProductRanges(ranges)
|
|
1364
|
+
}, unavailableCurrentTime ? {
|
|
1365
|
+
unavailableCurrentTime: unavailableCurrentTime
|
|
1366
|
+
} : {});
|
|
1367
|
+
}
|
|
1111
1368
|
export function getProductTimeRanges(projection) {
|
|
1112
1369
|
var _extractFixedOffsetMi3, _request$productIds;
|
|
1113
1370
|
var request = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
@@ -1173,6 +1430,19 @@ export function getProductTimeRanges(projection) {
|
|
|
1173
1430
|
return current === null ? ranges : intersectRangeLists(current, ranges);
|
|
1174
1431
|
}, null) || [] : null;
|
|
1175
1432
|
var baseRanges = resourceRanges === null ? operatingRanges : intersectRangeLists(resourceRanges, operatingRanges);
|
|
1433
|
+
if (runtimeOptions.useDurationTimeGrid) {
|
|
1434
|
+
return getAlignedDurationRanges({
|
|
1435
|
+
projection: projection,
|
|
1436
|
+
product: product,
|
|
1437
|
+
request: request,
|
|
1438
|
+
runtimeOptions: runtimeOptions,
|
|
1439
|
+
dateRange: dateRange,
|
|
1440
|
+
operatingRanges: operatingRanges,
|
|
1441
|
+
baseRanges: baseRanges,
|
|
1442
|
+
resourceWindowIndex: resourceWindowIndex,
|
|
1443
|
+
fixedOffsetMinutes: fixedOffsetMinutes
|
|
1444
|
+
});
|
|
1445
|
+
}
|
|
1176
1446
|
var durationMinutes = resolveRequestedDurationMinutes(product, request);
|
|
1177
1447
|
var flexibleStartAt = function () {
|
|
1178
1448
|
if (!product.isFlexibleDuration) return undefined;
|
|
@@ -1454,7 +1724,9 @@ function buildEvaluationContext(params) {
|
|
|
1454
1724
|
selectionsByGroupKey: selectionsByGroupKey,
|
|
1455
1725
|
useExactDurationCandidateMinute: params.useExactDurationCandidateMinute === true,
|
|
1456
1726
|
durationCandidateAnchorAtMs: Number.isFinite(durationCandidateAnchorAt) ? floorToMinute(durationCandidateAnchorAt) : null,
|
|
1457
|
-
allowExcludedScheduleDateOverride: params.allowExcludedScheduleDateOverride === true
|
|
1727
|
+
allowExcludedScheduleDateOverride: params.allowExcludedScheduleDateOverride === true,
|
|
1728
|
+
useDurationTimeGrid: params.useDurationTimeGrid === true,
|
|
1729
|
+
enforceSaleCutoff: params.enforceSaleCutoff === true
|
|
1458
1730
|
};
|
|
1459
1731
|
}
|
|
1460
1732
|
function summarizeStatuses(statuses) {
|
|
@@ -1504,7 +1776,7 @@ function summarizeStatusAggregate(aggregate) {
|
|
|
1504
1776
|
return 'unavailable';
|
|
1505
1777
|
}
|
|
1506
1778
|
function evaluateMatchedResourceSummary(params) {
|
|
1507
|
-
var
|
|
1779
|
+
var _ref8, _params$matchedCell$m;
|
|
1508
1780
|
var isPast = params.candidateRange.endMs <= params.evaluationContext.evaluatedAtMs;
|
|
1509
1781
|
if (!params.matchedCell) {
|
|
1510
1782
|
return {
|
|
@@ -1516,7 +1788,7 @@ function evaluateMatchedResourceSummary(params) {
|
|
|
1516
1788
|
};
|
|
1517
1789
|
}
|
|
1518
1790
|
var remainingCapacity = Math.max(0, params.matchedCell.remainingCapacity || 0);
|
|
1519
|
-
var maxCapacity = Math.max(0, (
|
|
1791
|
+
var maxCapacity = Math.max(0, (_ref8 = (_params$matchedCell$m = params.matchedCell.maxCapacity) !== null && _params$matchedCell$m !== void 0 ? _params$matchedCell$m : params.resourceCapacity) !== null && _ref8 !== void 0 ? _ref8 : 0);
|
|
1520
1792
|
var maxPartySize = isPast ? 0 : remainingCapacity;
|
|
1521
1793
|
var status = function () {
|
|
1522
1794
|
if (isPast) return 'past';
|
|
@@ -1942,6 +2214,8 @@ export function queryAvailabilityProjection(projection, request) {
|
|
|
1942
2214
|
projection: projection,
|
|
1943
2215
|
evaluatedAt: evaluatedAt,
|
|
1944
2216
|
resourceIds: request.resourceIds,
|
|
2217
|
+
useDurationTimeGrid: runtimeOptions.useDurationTimeGrid,
|
|
2218
|
+
enforceSaleCutoff: runtimeOptions.enforceSaleCutoff,
|
|
1945
2219
|
useExactDurationCandidateMinute: runtimeOptions.useExactDurationCandidateMinute,
|
|
1946
2220
|
allowExcludedScheduleDateOverride: runtimeOptions.allowExcludedScheduleDateOverride
|
|
1947
2221
|
});
|
|
@@ -2032,6 +2306,8 @@ export function queryAvailabilityProjection(projection, request) {
|
|
|
2032
2306
|
partySize: normalizedPartySize
|
|
2033
2307
|
}, {
|
|
2034
2308
|
evaluatedAt: evaluatedAt,
|
|
2309
|
+
useDurationTimeGrid: runtimeOptions.useDurationTimeGrid,
|
|
2310
|
+
enforceSaleCutoff: runtimeOptions.enforceSaleCutoff,
|
|
2035
2311
|
useExactDurationCandidateMinute: runtimeOptions.useExactDurationCandidateMinute,
|
|
2036
2312
|
allowExcludedScheduleDateOverride: runtimeOptions.allowExcludedScheduleDateOverride
|
|
2037
2313
|
});
|
|
@@ -2060,7 +2336,8 @@ export function queryAvailabilityProjection(projection, request) {
|
|
|
2060
2336
|
candidateRangeCache: candidateRangeCache,
|
|
2061
2337
|
evaluationContext: evaluationContext
|
|
2062
2338
|
});
|
|
2063
|
-
var
|
|
2339
|
+
var candidateDate = runtimeOptions.useDurationTimeGrid ? candidate.businessDate || candidate.date : candidate.date;
|
|
2340
|
+
var aggregate = byDate.get(candidateDate) || {
|
|
2064
2341
|
availableCount: 0,
|
|
2065
2342
|
totalCount: 0,
|
|
2066
2343
|
maxPartySize: 0,
|
|
@@ -2080,8 +2357,26 @@ export function queryAvailabilityProjection(projection, request) {
|
|
|
2080
2357
|
evaluated.reasonCodes.forEach(function (reasonCode) {
|
|
2081
2358
|
return aggregate.reasonCodeSet.add(reasonCode);
|
|
2082
2359
|
});
|
|
2083
|
-
byDate.set(
|
|
2360
|
+
byDate.set(candidateDate, aggregate);
|
|
2084
2361
|
});
|
|
2362
|
+
if (group.unavailableCurrentTime) {
|
|
2363
|
+
var current = group.unavailableCurrentTime;
|
|
2364
|
+
var aggregate = byDate.get(current.businessDate) || {
|
|
2365
|
+
availableCount: 0,
|
|
2366
|
+
totalCount: 0,
|
|
2367
|
+
maxPartySize: 0,
|
|
2368
|
+
remainingCapacity: 0,
|
|
2369
|
+
maxCapacity: 0,
|
|
2370
|
+
reasonCodeSet: new Set(),
|
|
2371
|
+
statusAggregate: createStatusAggregate()
|
|
2372
|
+
};
|
|
2373
|
+
aggregate.totalCount += 1;
|
|
2374
|
+
pushStatusAggregate(aggregate.statusAggregate, 'unavailable');
|
|
2375
|
+
current.reasonCodes.forEach(function (reason) {
|
|
2376
|
+
return aggregate.reasonCodeSet.add(reason);
|
|
2377
|
+
});
|
|
2378
|
+
byDate.set(current.businessDate, aggregate);
|
|
2379
|
+
}
|
|
2085
2380
|
var dates = enumerateDates(dateRange.startDate, dateRange.endDate).map(function (date) {
|
|
2086
2381
|
var aggregate = byDate.get(date);
|
|
2087
2382
|
return {
|
|
@@ -2143,10 +2438,22 @@ export function queryAvailabilityProjection(projection, request) {
|
|
|
2143
2438
|
evaluated.reasonCodes.forEach(function (reasonCode) {
|
|
2144
2439
|
return productReasonCodeSet.add(reasonCode);
|
|
2145
2440
|
});
|
|
2146
|
-
var
|
|
2441
|
+
var candidateDate = runtimeOptions.useDurationTimeGrid ? candidate.businessDate || candidate.date : candidate.date;
|
|
2442
|
+
var dateAggregate = dateStatusMap.get(candidateDate) || createStatusAggregate();
|
|
2147
2443
|
pushStatusAggregate(dateAggregate, evaluated.status);
|
|
2148
|
-
dateStatusMap.set(
|
|
2444
|
+
dateStatusMap.set(candidateDate, dateAggregate);
|
|
2149
2445
|
});
|
|
2446
|
+
if (group.unavailableCurrentTime) {
|
|
2447
|
+
var current = group.unavailableCurrentTime;
|
|
2448
|
+
totalTimeCount += 1;
|
|
2449
|
+
pushStatusAggregate(productStatusAggregate, 'unavailable');
|
|
2450
|
+
current.reasonCodes.forEach(function (reason) {
|
|
2451
|
+
return productReasonCodeSet.add(reason);
|
|
2452
|
+
});
|
|
2453
|
+
var dateAggregate = dateStatusMap.get(current.businessDate) || createStatusAggregate();
|
|
2454
|
+
pushStatusAggregate(dateAggregate, 'unavailable');
|
|
2455
|
+
dateStatusMap.set(current.businessDate, dateAggregate);
|
|
2456
|
+
}
|
|
2150
2457
|
var availableDateCount = Array.from(dateStatusMap.values()).filter(function (aggregate) {
|
|
2151
2458
|
var status = summarizeStatusAggregate(aggregate);
|
|
2152
2459
|
return status === 'available' || status === 'limited';
|
|
@@ -2233,6 +2540,8 @@ export function validateAvailabilitySelection(projection, params) {
|
|
|
2233
2540
|
projection: projection,
|
|
2234
2541
|
evaluatedAt: evaluatedAt,
|
|
2235
2542
|
requirementSelections: params.requirementSelections,
|
|
2543
|
+
useDurationTimeGrid: runtimeOptions.useDurationTimeGrid,
|
|
2544
|
+
enforceSaleCutoff: runtimeOptions.enforceSaleCutoff,
|
|
2236
2545
|
useExactDurationCandidateMinute: runtimeOptions.useExactDurationCandidateMinute,
|
|
2237
2546
|
allowExcludedScheduleDateOverride: runtimeOptions.allowExcludedScheduleDateOverride
|
|
2238
2547
|
})
|
|
@@ -92,6 +92,9 @@ export interface AvailabilityProduct {
|
|
|
92
92
|
raw?: Record<string, any>;
|
|
93
93
|
}
|
|
94
94
|
export interface AvailabilityResourceWindow extends AvailabilityAbsoluteRange {
|
|
95
|
+
/** Original business day and opening anchor, before coverage clipping. */
|
|
96
|
+
businessDate?: string;
|
|
97
|
+
openingAnchorAt?: string;
|
|
95
98
|
source?: string;
|
|
96
99
|
raw?: Record<string, any>;
|
|
97
100
|
}
|
|
@@ -101,10 +104,15 @@ export interface AvailabilityOperatingHoursSnapshot {
|
|
|
101
104
|
scheduleIds: AvailabilityId[];
|
|
102
105
|
missingScheduleIds: AvailabilityId[];
|
|
103
106
|
windows: AvailabilityResourceWindow[];
|
|
107
|
+
/** Complete business cycles; lunch gaps remain in windows, not in this envelope. */
|
|
108
|
+
businessPeriods?: AvailabilityBusinessPeriod[];
|
|
104
109
|
/** Schedule windows omitted only because their date is excluded. POS may use
|
|
105
110
|
* these to surface an unavailable, manually selectable candidate. */
|
|
106
111
|
excludedWindows?: AvailabilityResourceWindow[];
|
|
107
112
|
}
|
|
113
|
+
export interface AvailabilityBusinessPeriod extends AvailabilityAbsoluteRange {
|
|
114
|
+
businessDate: string;
|
|
115
|
+
}
|
|
108
116
|
export interface AvailabilityResource {
|
|
109
117
|
id: AvailabilityId;
|
|
110
118
|
formId?: AvailabilityId;
|
|
@@ -212,6 +220,17 @@ export interface ProductTimeRange extends AvailabilityDisplayRange {
|
|
|
212
220
|
bookingEndAt: string;
|
|
213
221
|
scheduleRefs: AvailabilityScheduleRef[];
|
|
214
222
|
primaryScheduleRef?: AvailabilityScheduleRef;
|
|
223
|
+
/** Business-day label. date/startAt keep the actual calendar date. */
|
|
224
|
+
businessDate?: string;
|
|
225
|
+
}
|
|
226
|
+
export interface UnavailableCurrentTime {
|
|
227
|
+
productId: AvailabilityId;
|
|
228
|
+
startAt: string;
|
|
229
|
+
date: string;
|
|
230
|
+
businessDate: string;
|
|
231
|
+
startTime: string;
|
|
232
|
+
status: 'unavailable';
|
|
233
|
+
reasonCodes: string[];
|
|
215
234
|
}
|
|
216
235
|
export interface ProductTimeRangeGroup {
|
|
217
236
|
productId: AvailabilityId;
|
|
@@ -221,6 +240,8 @@ export interface ProductTimeRangeGroup {
|
|
|
221
240
|
/** 单日查询对应营业窗口的最终结束时刻,不受资源排班是否为空影响。 */
|
|
222
241
|
operatingEndAt?: string;
|
|
223
242
|
ranges: ProductTimeRange[];
|
|
243
|
+
/** A display-only current item when flexible duration has no valid end. Never submit it. */
|
|
244
|
+
unavailableCurrentTime?: UnavailableCurrentTime;
|
|
224
245
|
}
|
|
225
246
|
export interface AvailabilityAssignment extends AvailabilityAbsoluteRange {
|
|
226
247
|
productId: AvailabilityId;
|
|
@@ -242,6 +263,10 @@ export interface GetProductTimeRangesRequest {
|
|
|
242
263
|
partySize?: number;
|
|
243
264
|
durationMinutesByProductId?: Record<string, number>;
|
|
244
265
|
durationStartTimesByProductId?: Record<string, string[]>;
|
|
266
|
+
/** Restore only the exact remembered start; recompute the end from current product/windows. */
|
|
267
|
+
rememberedStartAtByProductId?: Record<string, string>;
|
|
268
|
+
/** Edit only: preserve the full actual start plus an explicit durationMinutesByProductId. */
|
|
269
|
+
editingStartAtByProductId?: Record<string, string>;
|
|
245
270
|
/**
|
|
246
271
|
* POS 手工输入时间的兼容开关:只为明确请求的 start time 补候选,
|
|
247
272
|
* 不改变常规候选列表仍按营业时间生成的规则。
|
|
@@ -250,6 +275,10 @@ export interface GetProductTimeRangesRequest {
|
|
|
250
275
|
}
|
|
251
276
|
export interface GetProductTimeRangesRuntimeOptions {
|
|
252
277
|
evaluatedAt?: string;
|
|
278
|
+
/** Enabled by the POS/Kiosk facade only; other consumers retain their existing grid. */
|
|
279
|
+
useDurationTimeGrid?: boolean;
|
|
280
|
+
/** Automatic remembered selection must not use POS opening-minute cutoff exceptions. */
|
|
281
|
+
enforceSaleCutoff?: boolean;
|
|
253
282
|
/**
|
|
254
283
|
* Internal POS capability: fixed-duration candidates start from the stable
|
|
255
284
|
* context anchor's current minute instead of rounding up to ten minutes, and
|
|
@@ -10,6 +10,10 @@ export declare class ScheduleModule extends BaseModule implements Module, Schedu
|
|
|
10
10
|
private openCache;
|
|
11
11
|
private fatherModule;
|
|
12
12
|
private hasLoadedScheduleList;
|
|
13
|
+
private scheduleListPromise;
|
|
14
|
+
private scheduleListRequestVersion;
|
|
15
|
+
private scheduleCatalogScope;
|
|
16
|
+
private otherParams;
|
|
13
17
|
constructor(name?: string, version?: string);
|
|
14
18
|
initialize(core: PisellCore, options: ModuleOptions): Promise<void>;
|
|
15
19
|
/**
|
|
@@ -19,6 +23,9 @@ export declare class ScheduleModule extends BaseModule implements Module, Schedu
|
|
|
19
23
|
* scheduleModule.updateOtherParams({ openCache: true, cacheId: 'cache-2' });
|
|
20
24
|
*/
|
|
21
25
|
updateOtherParams(params: Record<string, any>): void;
|
|
26
|
+
private syncScheduleCatalogScope;
|
|
27
|
+
private resetScheduleCatalog;
|
|
28
|
+
destroy(): void;
|
|
22
29
|
/**
|
|
23
30
|
* 加载当前店铺下所有 schedule
|
|
24
31
|
*
|
|
@@ -27,6 +34,7 @@ export declare class ScheduleModule extends BaseModule implements Module, Schedu
|
|
|
27
34
|
loadAllSchedule(options?: {
|
|
28
35
|
useCache?: boolean;
|
|
29
36
|
}): Promise<void>;
|
|
37
|
+
private loadScheduleCatalog;
|
|
30
38
|
setScheduleList(list: ScheduleItem[]): void;
|
|
31
39
|
private syncScheduleMap;
|
|
32
40
|
getScheduleList(): ScheduleItem[];
|