@pisell/pisellos 2.2.299 → 2.2.300
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/modules/ResourcePlanner/planner.d.ts +2 -2
- package/dist/modules/ResourcePlanner/planner.js +151 -41
- package/dist/modules/ResourcePlanner/types.d.ts +10 -0
- package/dist/solution/UnifiedBookingSales/index.js +88 -19
- package/lib/model/strategy/adapter/promotion/index.js +46 -1
- package/lib/modules/ResourcePlanner/planner.d.ts +2 -2
- package/lib/modules/ResourcePlanner/planner.js +125 -30
- package/lib/modules/ResourcePlanner/types.d.ts +10 -0
- package/lib/solution/UnifiedBookingSales/index.js +80 -20
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AvailabilityProjection, AvailabilityProjectionInput, AvailabilityQuery, AvailabilityQueryResult, AvailabilitySelectionValidationParams, AvailabilitySelectionValidationResult, GetProductTimeRangesRequest, GetProductTimeRangesRuntimeOptions, ProductTimeRangeGroup } from './types';
|
|
2
2
|
export declare function createAvailabilityProjection(input: AvailabilityProjectionInput): AvailabilityProjection;
|
|
3
3
|
export declare function getProductTimeRanges(projection: AvailabilityProjection, request?: GetProductTimeRangesRequest, runtimeOptions?: GetProductTimeRangesRuntimeOptions): ProductTimeRangeGroup[];
|
|
4
|
-
export declare function queryAvailabilityProjection(projection: AvailabilityProjection, request: AvailabilityQuery): AvailabilityQueryResult;
|
|
5
|
-
export declare function validateAvailabilitySelection(projection: AvailabilityProjection, params: AvailabilitySelectionValidationParams): AvailabilitySelectionValidationResult;
|
|
4
|
+
export declare function queryAvailabilityProjection(projection: AvailabilityProjection, request: AvailabilityQuery, runtimeOptions?: GetProductTimeRangesRuntimeOptions): AvailabilityQueryResult;
|
|
5
|
+
export declare function validateAvailabilitySelection(projection: AvailabilityProjection, params: AvailabilitySelectionValidationParams, runtimeOptions?: GetProductTimeRangesRuntimeOptions): AvailabilitySelectionValidationResult;
|
|
@@ -175,8 +175,70 @@ function addLeadWindow(base, unit, unitType, _timezoneName) {
|
|
|
175
175
|
if (unitType === 'hours') return addLocalHours(base, unit);
|
|
176
176
|
return addLocalMinutes(base, unit);
|
|
177
177
|
}
|
|
178
|
+
function normalizedWindowContainsRange(windows, candidateRange, timezoneName) {
|
|
179
|
+
return windows.some(function (window) {
|
|
180
|
+
var normalized = normalizeAbsoluteRange(window, timezoneName);
|
|
181
|
+
return Boolean(normalized && contains(normalized, candidateRange));
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
function normalizedWindowsContainDate(windows, date, timezoneName) {
|
|
185
|
+
return windows.some(function (window) {
|
|
186
|
+
var normalized = normalizeAbsoluteRange(window, timezoneName);
|
|
187
|
+
return Boolean(normalized && formatDate(normalized.start, timezoneName) === date);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
function isRangeFromExcludedWindows(params) {
|
|
191
|
+
var candidateDate = formatDate(params.candidateRange.start, params.timezoneName);
|
|
192
|
+
var hasNormalWindowOnDate = normalizedWindowsContainDate(params.normalWindows, candidateDate, params.timezoneName);
|
|
193
|
+
var hasExcludedWindowOnDate = normalizedWindowsContainDate(params.excludedWindows, candidateDate, params.timezoneName);
|
|
194
|
+
if (!hasNormalWindowOnDate && hasExcludedWindowOnDate) return true;
|
|
195
|
+
return !normalizedWindowContainsRange(params.normalWindows, params.candidateRange, params.timezoneName) && normalizedWindowContainsRange(params.excludedWindows, params.candidateRange, params.timezoneName);
|
|
196
|
+
}
|
|
197
|
+
function isCandidateFromExcludedScheduleDate(params) {
|
|
198
|
+
var projection = params.projection,
|
|
199
|
+
product = params.product,
|
|
200
|
+
candidate = params.candidate,
|
|
201
|
+
candidateRange = params.candidateRange;
|
|
202
|
+
var operatingHours = projection.meta.defaults.operatingHours;
|
|
203
|
+
if (isRangeFromExcludedWindows({
|
|
204
|
+
normalWindows: operatingHours.windows,
|
|
205
|
+
excludedWindows: operatingHours.excludedWindows || [],
|
|
206
|
+
candidateRange: candidateRange,
|
|
207
|
+
timezoneName: projection.meta.timezone
|
|
208
|
+
})) {
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
if (product.kind !== 'session' && product.kind !== 'venue_slot') {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
if (candidate.source !== 'session_schedule') {
|
|
215
|
+
var hasNormalRule = (product.sessionRules || []).some(function (rule) {
|
|
216
|
+
return matchesScheduleRuleDate(rule, candidate.date, projection.meta.timezone);
|
|
217
|
+
});
|
|
218
|
+
var hasExcludedOverrideRule = (product.sessionRules || []).some(function (rule) {
|
|
219
|
+
return !matchesScheduleRuleDate(rule, candidate.date, projection.meta.timezone) && matchesScheduleRuleDate(rule, candidate.date, projection.meta.timezone, true);
|
|
220
|
+
});
|
|
221
|
+
return !hasNormalRule && hasExcludedOverrideRule;
|
|
222
|
+
}
|
|
223
|
+
var candidateDateRange = {
|
|
224
|
+
startDate: candidate.date,
|
|
225
|
+
endDate: candidate.date
|
|
226
|
+
};
|
|
227
|
+
var candidateIdentity = getProductTimeRangeIdentity(candidate);
|
|
228
|
+
var normalRanges = getSessionRangesForProduct(projection, product, candidateDateRange);
|
|
229
|
+
if (normalRanges.some(function (range) {
|
|
230
|
+
return getProductTimeRangeIdentity(range) === candidateIdentity;
|
|
231
|
+
})) {
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
return getSessionRangesForProduct(projection, product, candidateDateRange, true).some(function (range) {
|
|
235
|
+
return getProductTimeRangeIdentity(range) === candidateIdentity;
|
|
236
|
+
});
|
|
237
|
+
}
|
|
178
238
|
function evaluateCandidateTimeGate(params) {
|
|
179
|
-
var
|
|
239
|
+
var projection = params.projection,
|
|
240
|
+
product = params.product,
|
|
241
|
+
candidate = params.candidate,
|
|
180
242
|
candidateRange = params.candidateRange,
|
|
181
243
|
evaluationContext = params.evaluationContext,
|
|
182
244
|
timezoneName = params.timezoneName;
|
|
@@ -188,6 +250,18 @@ function evaluateCandidateTimeGate(params) {
|
|
|
188
250
|
conflictCode: 'past'
|
|
189
251
|
};
|
|
190
252
|
}
|
|
253
|
+
if (evaluationContext.allowExcludedScheduleDateOverride && isCandidateFromExcludedScheduleDate({
|
|
254
|
+
projection: projection,
|
|
255
|
+
product: product,
|
|
256
|
+
candidate: candidate,
|
|
257
|
+
candidateRange: candidateRange
|
|
258
|
+
})) {
|
|
259
|
+
return {
|
|
260
|
+
status: 'unavailable',
|
|
261
|
+
reasonCodes: ['schedule_excluded_date'],
|
|
262
|
+
conflictCode: 'schedule_excluded_date'
|
|
263
|
+
};
|
|
264
|
+
}
|
|
191
265
|
var policy = product.cutOffPolicy;
|
|
192
266
|
if (!policy) return null;
|
|
193
267
|
if (resolveCutOffPolicyIssue(policy)) {
|
|
@@ -334,7 +408,8 @@ function normalizeCoverage(input) {
|
|
|
334
408
|
};
|
|
335
409
|
}
|
|
336
410
|
function normalizeResourceWindow(resource, coverage, timezoneName) {
|
|
337
|
-
|
|
411
|
+
var includeExcludedWindows = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
412
|
+
return mergeRanges([].concat(_toConsumableArray(resource.windows || []), _toConsumableArray(includeExcludedWindows ? resource.excludedWindows || [] : [])).map(function (window) {
|
|
338
413
|
return normalizeAbsoluteRange(window, timezoneName);
|
|
339
414
|
}).filter(function (window) {
|
|
340
415
|
return Boolean(window);
|
|
@@ -407,12 +482,15 @@ function normalizeResources(resources) {
|
|
|
407
482
|
capacity: Math.max(1, Number(resource.capacity || 1) || 1),
|
|
408
483
|
windows: (resource.windows || []).map(function (window) {
|
|
409
484
|
return _objectSpread({}, window);
|
|
485
|
+
}),
|
|
486
|
+
excludedWindows: (resource.excludedWindows || []).map(function (window) {
|
|
487
|
+
return _objectSpread({}, window);
|
|
410
488
|
})
|
|
411
489
|
});
|
|
412
490
|
});
|
|
413
491
|
}
|
|
414
492
|
function normalizeOperatingHours(params) {
|
|
415
|
-
var _params$input, _params$input2, _params$input3;
|
|
493
|
+
var _params$input, _params$input2, _params$input3, _params$input4;
|
|
416
494
|
var fallbackWindows = enumerateDates(params.dateRange.startDate, params.dateRange.endDate).map(function (date) {
|
|
417
495
|
var start = toDateTimeInDate(date, params.businessHours.startTime, params.timezoneName);
|
|
418
496
|
var end = toDateTimeInDate(date, params.businessHours.endTime, params.timezoneName);
|
|
@@ -430,26 +508,32 @@ function normalizeOperatingHours(params) {
|
|
|
430
508
|
endAt: formatDateTime(range.end, params.timezoneName, params.fixedOffsetMinutes)
|
|
431
509
|
};
|
|
432
510
|
});
|
|
433
|
-
var
|
|
434
|
-
return
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
source: ((_params$input = params.input) === null || _params$input === void 0 ? void 0 : _params$input.source) || params.fallbackSource,
|
|
449
|
-
scheduleIds: uniqById(((_params$input2 = params.input) === null || _params$input2 === void 0 ? void 0 : _params$input2.scheduleIds) || []),
|
|
450
|
-
missingScheduleIds: uniqById(((_params$input3 = params.input) === null || _params$input3 === void 0 ? void 0 : _params$input3.missingScheduleIds) || []),
|
|
451
|
-
windows: windows
|
|
511
|
+
var normalizeWindows = function normalizeWindows(source) {
|
|
512
|
+
return mergeRanges(source.map(function (window) {
|
|
513
|
+
return normalizeAbsoluteRange(window, params.timezoneName);
|
|
514
|
+
}).filter(function (window) {
|
|
515
|
+
return Boolean(window);
|
|
516
|
+
}).map(function (window) {
|
|
517
|
+
return clipRange(window, params.coverage);
|
|
518
|
+
}).filter(function (window) {
|
|
519
|
+
return Boolean(window);
|
|
520
|
+
})).map(function (range) {
|
|
521
|
+
return {
|
|
522
|
+
startAt: formatDateTime(range.start, params.timezoneName, params.fixedOffsetMinutes),
|
|
523
|
+
endAt: formatDateTime(range.end, params.timezoneName, params.fixedOffsetMinutes)
|
|
524
|
+
};
|
|
525
|
+
});
|
|
452
526
|
};
|
|
527
|
+
var windows = normalizeWindows(sourceWindows);
|
|
528
|
+
var excludedWindows = normalizeWindows(((_params$input = params.input) === null || _params$input === void 0 ? void 0 : _params$input.excludedWindows) || []);
|
|
529
|
+
return _objectSpread({
|
|
530
|
+
source: ((_params$input2 = params.input) === null || _params$input2 === void 0 ? void 0 : _params$input2.source) || params.fallbackSource,
|
|
531
|
+
scheduleIds: uniqById(((_params$input3 = params.input) === null || _params$input3 === void 0 ? void 0 : _params$input3.scheduleIds) || []),
|
|
532
|
+
missingScheduleIds: uniqById(((_params$input4 = params.input) === null || _params$input4 === void 0 ? void 0 : _params$input4.missingScheduleIds) || []),
|
|
533
|
+
windows: windows
|
|
534
|
+
}, excludedWindows.length > 0 ? {
|
|
535
|
+
excludedWindows: excludedWindows
|
|
536
|
+
} : {});
|
|
453
537
|
}
|
|
454
538
|
function matchesRequirementGroup(requirementGroup, resource, product) {
|
|
455
539
|
var _requirementGroup$res;
|
|
@@ -759,11 +843,12 @@ function resolveProjectionDateRange(projection, requestDateRange) {
|
|
|
759
843
|
};
|
|
760
844
|
}
|
|
761
845
|
function buildOperatingRanges(projection, dateRange) {
|
|
846
|
+
var includeExcludedWindows = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
762
847
|
var coverage = {
|
|
763
848
|
start: toDateStart(dateRange.startDate, projection.meta.timezone),
|
|
764
849
|
end: toDateEnd(nextDate(dateRange.endDate), projection.meta.timezone)
|
|
765
850
|
};
|
|
766
|
-
return mergeRanges(projection.meta.defaults.operatingHours.windows.map(function (window) {
|
|
851
|
+
return mergeRanges([].concat(_toConsumableArray(projection.meta.defaults.operatingHours.windows), _toConsumableArray(includeExcludedWindows ? projection.meta.defaults.operatingHours.excludedWindows || [] : [])).map(function (window) {
|
|
767
852
|
return normalizeAbsoluteRange(window, projection.meta.timezone);
|
|
768
853
|
}).filter(function (window) {
|
|
769
854
|
return Boolean(window);
|
|
@@ -774,12 +859,13 @@ function buildOperatingRanges(projection, dateRange) {
|
|
|
774
859
|
}));
|
|
775
860
|
}
|
|
776
861
|
function buildResourceWindowIndex(projection) {
|
|
862
|
+
var includeExcludedWindows = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
777
863
|
var coverage = {
|
|
778
864
|
start: toDateTime(projection.meta.coverage.startAt, projection.meta.timezone),
|
|
779
865
|
end: toDateTime(projection.meta.coverage.endAt, projection.meta.timezone)
|
|
780
866
|
};
|
|
781
867
|
return new Map(projection.resources.map(function (resource) {
|
|
782
|
-
return [String(resource.id), normalizeResourceWindow(resource, coverage, projection.meta.timezone)];
|
|
868
|
+
return [String(resource.id), normalizeResourceWindow(resource, coverage, projection.meta.timezone, includeExcludedWindows)];
|
|
783
869
|
}));
|
|
784
870
|
}
|
|
785
871
|
function buildGroupWorkingRanges(params) {
|
|
@@ -801,7 +887,7 @@ function buildGroupWorkingRanges(params) {
|
|
|
801
887
|
return !filteredResourceIdSet || filteredResourceIdSet.has(String(resource.id));
|
|
802
888
|
}).map(function (resource) {
|
|
803
889
|
var _params$resourceWindo;
|
|
804
|
-
var windows = ((_params$resourceWindo = params.resourceWindowIndex) === null || _params$resourceWindo === void 0 ? void 0 : _params$resourceWindo.get(String(resource.id))) || normalizeResourceWindow(resource, coverage, projection.meta.timezone);
|
|
890
|
+
var windows = ((_params$resourceWindo = params.resourceWindowIndex) === null || _params$resourceWindo === void 0 ? void 0 : _params$resourceWindo.get(String(resource.id))) || normalizeResourceWindow(resource, coverage, projection.meta.timezone, params.includeExcludedWindows === true);
|
|
805
891
|
return windows.map(function (window) {
|
|
806
892
|
return clipRange(window, coverage);
|
|
807
893
|
}).filter(function (window) {
|
|
@@ -848,11 +934,12 @@ function buildGroupWorkingRanges(params) {
|
|
|
848
934
|
return mergeRanges(satisfiedRanges);
|
|
849
935
|
}
|
|
850
936
|
function materializeScheduleRules(rules, dateRange, timezoneName, fixedOffsetMinutes) {
|
|
937
|
+
var allowExcludedScheduleDates = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
851
938
|
var dates = enumerateDates(dateRange.startDate, dateRange.endDate);
|
|
852
939
|
var seen = new Map();
|
|
853
940
|
rules.forEach(function (rule) {
|
|
854
941
|
dates.forEach(function (date) {
|
|
855
|
-
if (!matchesScheduleRuleDate(rule, date, timezoneName)) return;
|
|
942
|
+
if (!matchesScheduleRuleDate(rule, date, timezoneName, allowExcludedScheduleDates)) return;
|
|
856
943
|
var start = toDateTimeInDate(date, rule.startTime, timezoneName);
|
|
857
944
|
var end = toDateTimeInDate(date, rule.endTime, timezoneName);
|
|
858
945
|
if (end <= start) end = toDateTimeInDate(nextDate(date, timezoneName), rule.endTime, timezoneName);
|
|
@@ -885,8 +972,9 @@ function materializeScheduleRules(rules, dateRange, timezoneName, fixedOffsetMin
|
|
|
885
972
|
}
|
|
886
973
|
function matchesScheduleRuleDate(rule, date, _timezoneName) {
|
|
887
974
|
var _rule$includeDates, _rule$excludeDates;
|
|
975
|
+
var allowExcludedScheduleDate = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
888
976
|
if ((_rule$includeDates = rule.includeDates) !== null && _rule$includeDates !== void 0 && _rule$includeDates.includes(date)) return true;
|
|
889
|
-
if ((_rule$excludeDates = rule.excludeDates) !== null && _rule$excludeDates !== void 0 && _rule$excludeDates.includes(date)) return false;
|
|
977
|
+
if (!allowExcludedScheduleDate && (_rule$excludeDates = rule.excludeDates) !== null && _rule$excludeDates !== void 0 && _rule$excludeDates.includes(date)) return false;
|
|
890
978
|
if (rule.startDate && date < rule.startDate) return false;
|
|
891
979
|
if (rule.endDate && date > rule.endDate) return false;
|
|
892
980
|
if (rule.mode === 'designation') {
|
|
@@ -942,6 +1030,7 @@ function buildGroupResourceIndex(params) {
|
|
|
942
1030
|
}
|
|
943
1031
|
function getSessionRangesForProduct(projection, product, dateRange) {
|
|
944
1032
|
var _extractFixedOffsetMi2;
|
|
1033
|
+
var allowExcludedScheduleDates = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
945
1034
|
var fixedOffsetMinutes = (_extractFixedOffsetMi2 = extractFixedOffsetMinutes(projection.meta.now)) !== null && _extractFixedOffsetMi2 !== void 0 ? _extractFixedOffsetMi2 : captureRuntimeOffsetMinutes();
|
|
946
1035
|
var ranges = (product.sessionRanges || []).map(function (range) {
|
|
947
1036
|
var _range$scheduleRefs2;
|
|
@@ -967,7 +1056,7 @@ function getSessionRangesForProduct(projection, product, dateRange) {
|
|
|
967
1056
|
primaryScheduleRef: (_range$scheduleRefs2 = range.scheduleRefs) === null || _range$scheduleRefs2 === void 0 ? void 0 : _range$scheduleRefs2[0]
|
|
968
1057
|
};
|
|
969
1058
|
}).filter(Boolean);
|
|
970
|
-
var ruleRanges = materializeScheduleRules(product.sessionRules || [], dateRange, projection.meta.timezone, fixedOffsetMinutes);
|
|
1059
|
+
var ruleRanges = materializeScheduleRules(product.sessionRules || [], dateRange, projection.meta.timezone, fixedOffsetMinutes, allowExcludedScheduleDates);
|
|
971
1060
|
return dedupeProductRanges([].concat(_toConsumableArray(ranges), _toConsumableArray(ruleRanges.map(function (range) {
|
|
972
1061
|
return _objectSpread(_objectSpread({}, range), {}, {
|
|
973
1062
|
key: "".concat(String(product.id), ":").concat(range.startAt, ":").concat(range.endAt),
|
|
@@ -1022,7 +1111,8 @@ export function getProductTimeRanges(projection) {
|
|
|
1022
1111
|
var dateRange = resolveProjectionDateRange(projection, request.dateRange);
|
|
1023
1112
|
var slotStepMinutes = projection.meta.defaults.slotStepMinutes;
|
|
1024
1113
|
var fixedOffsetMinutes = (_extractFixedOffsetMi3 = extractFixedOffsetMinutes(projection.meta.now)) !== null && _extractFixedOffsetMi3 !== void 0 ? _extractFixedOffsetMi3 : captureRuntimeOffsetMinutes();
|
|
1025
|
-
var
|
|
1114
|
+
var allowExcludedScheduleDateOverride = runtimeOptions.allowExcludedScheduleDateOverride === true;
|
|
1115
|
+
var resourceWindowIndex = buildResourceWindowIndex(projection, allowExcludedScheduleDateOverride);
|
|
1026
1116
|
var filteredProductIdSet = (_request$productIds = request.productIds) !== null && _request$productIds !== void 0 && _request$productIds.length ? new Set(request.productIds.map(String)) : null;
|
|
1027
1117
|
return projection.products.filter(function (product) {
|
|
1028
1118
|
return !filteredProductIdSet || filteredProductIdSet.has(String(product.id));
|
|
@@ -1037,7 +1127,7 @@ export function getProductTimeRanges(projection) {
|
|
|
1037
1127
|
};
|
|
1038
1128
|
}
|
|
1039
1129
|
if (product.kind === 'session' || product.kind === 'venue_slot') {
|
|
1040
|
-
var fixedRanges = getSessionRangesForProduct(projection, product, dateRange);
|
|
1130
|
+
var fixedRanges = getSessionRangesForProduct(projection, product, dateRange, allowExcludedScheduleDateOverride);
|
|
1041
1131
|
var customRanges = [];
|
|
1042
1132
|
var customDurationMinutes = resolveRequestedSessionDurationMinutes(product, request, runtimeOptions.allowSessionCustomRanges === true);
|
|
1043
1133
|
var _requestedStartTimes = resolveRequestedDurationStartTimes(product, request, runtimeOptions.allowSessionCustomRanges === true);
|
|
@@ -1059,7 +1149,7 @@ export function getProductTimeRanges(projection) {
|
|
|
1059
1149
|
var requiredGroups = (product.requirementGroups || []).filter(function (group) {
|
|
1060
1150
|
return group.required !== false;
|
|
1061
1151
|
});
|
|
1062
|
-
var operatingRanges = buildOperatingRanges(projection, dateRange);
|
|
1152
|
+
var operatingRanges = buildOperatingRanges(projection, dateRange, allowExcludedScheduleDateOverride);
|
|
1063
1153
|
var operatingEndAt = dateRange.startDate === dateRange.endDate && operatingRanges.length > 0 ? formatDateTime(Math.max.apply(Math, _toConsumableArray(operatingRanges.map(function (range) {
|
|
1064
1154
|
return range.end;
|
|
1065
1155
|
}))), projection.meta.timezone, fixedOffsetMinutes) : undefined;
|
|
@@ -1071,7 +1161,8 @@ export function getProductTimeRanges(projection) {
|
|
|
1071
1161
|
dateRange: dateRange,
|
|
1072
1162
|
resourceIds: request.resourceIds,
|
|
1073
1163
|
partySize: normalizedPartySize,
|
|
1074
|
-
resourceWindowIndex: resourceWindowIndex
|
|
1164
|
+
resourceWindowIndex: resourceWindowIndex,
|
|
1165
|
+
includeExcludedWindows: allowExcludedScheduleDateOverride
|
|
1075
1166
|
});
|
|
1076
1167
|
}).reduce(function (current, ranges) {
|
|
1077
1168
|
return current === null ? ranges : intersectRangeLists(current, ranges);
|
|
@@ -1353,7 +1444,8 @@ function buildEvaluationContext(params) {
|
|
|
1353
1444
|
evaluatedAt: evaluatedAt,
|
|
1354
1445
|
evaluatedAtMs: evaluatedAt,
|
|
1355
1446
|
resourceIdSet: (_params$resourceIds2 = params.resourceIds) !== null && _params$resourceIds2 !== void 0 && _params$resourceIds2.length ? new Set(params.resourceIds.map(String)) : null,
|
|
1356
|
-
selectionsByGroupKey: selectionsByGroupKey
|
|
1447
|
+
selectionsByGroupKey: selectionsByGroupKey,
|
|
1448
|
+
allowExcludedScheduleDateOverride: params.allowExcludedScheduleDateOverride === true
|
|
1357
1449
|
};
|
|
1358
1450
|
}
|
|
1359
1451
|
function summarizeStatuses(statuses) {
|
|
@@ -1525,7 +1617,8 @@ function evaluateCandidateSummary(projection, candidate, request) {
|
|
|
1525
1617
|
var evaluationContext = request.evaluationContext || buildEvaluationContext({
|
|
1526
1618
|
projection: projection,
|
|
1527
1619
|
evaluatedAt: request.evaluatedAt,
|
|
1528
|
-
resourceIds: request.resourceIds
|
|
1620
|
+
resourceIds: request.resourceIds,
|
|
1621
|
+
allowExcludedScheduleDateOverride: request.allowExcludedScheduleDateOverride
|
|
1529
1622
|
});
|
|
1530
1623
|
var requestedPartySize = normalizePartySize(request.partySize);
|
|
1531
1624
|
var requiredGroups = (product.requirementGroups || []).filter(function (group) {
|
|
@@ -1543,7 +1636,9 @@ function evaluateCandidateSummary(projection, candidate, request) {
|
|
|
1543
1636
|
});
|
|
1544
1637
|
});
|
|
1545
1638
|
var gate = evaluateCandidateTimeGate({
|
|
1639
|
+
projection: projection,
|
|
1546
1640
|
product: product,
|
|
1641
|
+
candidate: candidate,
|
|
1547
1642
|
candidateRange: candidateRange,
|
|
1548
1643
|
evaluationContext: evaluationContext,
|
|
1549
1644
|
timezoneName: projection.meta.timezone
|
|
@@ -1598,7 +1693,8 @@ function evaluateCandidate(projection, candidate, request) {
|
|
|
1598
1693
|
projection: projection,
|
|
1599
1694
|
evaluatedAt: request.evaluatedAt,
|
|
1600
1695
|
resourceIds: request.resourceIds,
|
|
1601
|
-
requirementSelections: request.requirementSelections
|
|
1696
|
+
requirementSelections: request.requirementSelections,
|
|
1697
|
+
allowExcludedScheduleDateOverride: request.allowExcludedScheduleDateOverride
|
|
1602
1698
|
});
|
|
1603
1699
|
var requestedPartySize = normalizePartySize(request.partySize);
|
|
1604
1700
|
var partySize = requestedPartySize !== null && requestedPartySize !== void 0 ? requestedPartySize : 1;
|
|
@@ -1621,6 +1717,12 @@ function evaluateCandidate(projection, candidate, request) {
|
|
|
1621
1717
|
var options = matchedResources.map(function (resource) {
|
|
1622
1718
|
var _request$cellIndex, _resource$raw2;
|
|
1623
1719
|
var matchedCell = aggregateMatchedCells(product.id, requirementGroup.id, resource.id, candidateRange, ((_request$cellIndex = request.cellIndex) === null || _request$cellIndex === void 0 ? void 0 : _request$cellIndex.get([String(product.id), requirementGroup.id, String(resource.id)].join(':'))) || []);
|
|
1720
|
+
var isExcludedScheduleDate = evaluationContext.allowExcludedScheduleDateOverride && isRangeFromExcludedWindows({
|
|
1721
|
+
normalWindows: resource.windows || [],
|
|
1722
|
+
excludedWindows: resource.excludedWindows || [],
|
|
1723
|
+
candidateRange: candidateRange,
|
|
1724
|
+
timezoneName: projection.meta.timezone
|
|
1725
|
+
});
|
|
1624
1726
|
if (!matchedCell) {
|
|
1625
1727
|
var _resource$raw;
|
|
1626
1728
|
var _isPast = candidateRange.endMs <= evaluationContext.evaluatedAtMs;
|
|
@@ -1632,7 +1734,7 @@ function evaluateCandidate(projection, candidate, request) {
|
|
|
1632
1734
|
resourceType: resource.resourceType,
|
|
1633
1735
|
status: _isPast ? 'past' : 'unavailable',
|
|
1634
1736
|
maxPartySize: 0,
|
|
1635
|
-
reasonCodes: _isPast ? ['past'] : ['outside_resource_window']
|
|
1737
|
+
reasonCodes: _isPast ? ['past'] : [].concat(_toConsumableArray(isExcludedScheduleDate ? ['schedule_excluded_date'] : []), ['outside_resource_window'])
|
|
1636
1738
|
};
|
|
1637
1739
|
}
|
|
1638
1740
|
var remainingCapacity = matchedCell.remainingCapacity;
|
|
@@ -1640,6 +1742,7 @@ function evaluateCandidate(projection, candidate, request) {
|
|
|
1640
1742
|
var isPast = candidateRange.endMs <= evaluationContext.evaluatedAtMs;
|
|
1641
1743
|
var maxPartySize = isPast ? 0 : Math.max(0, remainingCapacity || 0);
|
|
1642
1744
|
var requiredCapacity = resolveRequiredCapacity(requirementGroup, product, requestedPartySize);
|
|
1745
|
+
var reasonCodes = Array.from(new Set([].concat(_toConsumableArray(matchedCell.reasonCodes), _toConsumableArray(isExcludedScheduleDate ? ['schedule_excluded_date'] : []))));
|
|
1643
1746
|
var status = function () {
|
|
1644
1747
|
if (isPast) return 'past';
|
|
1645
1748
|
if (matchedCell.status === 'unavailable') return 'unavailable';
|
|
@@ -1657,7 +1760,7 @@ function evaluateCandidate(projection, candidate, request) {
|
|
|
1657
1760
|
remainingCapacity: remainingCapacity,
|
|
1658
1761
|
maxCapacity: maxCapacity,
|
|
1659
1762
|
maxPartySize: maxPartySize,
|
|
1660
|
-
reasonCodes: isPast ? Array.from(new Set([].concat(
|
|
1763
|
+
reasonCodes: isPast ? Array.from(new Set([].concat(reasonCodes, ['past']))) : reasonCodes,
|
|
1661
1764
|
matchedCell: matchedCell
|
|
1662
1765
|
};
|
|
1663
1766
|
});
|
|
@@ -1715,7 +1818,9 @@ function evaluateCandidate(projection, candidate, request) {
|
|
|
1715
1818
|
return group.status;
|
|
1716
1819
|
});
|
|
1717
1820
|
var gate = evaluateCandidateTimeGate({
|
|
1821
|
+
projection: projection,
|
|
1718
1822
|
product: product,
|
|
1823
|
+
candidate: candidate,
|
|
1719
1824
|
candidateRange: candidateRange,
|
|
1720
1825
|
evaluationContext: evaluationContext,
|
|
1721
1826
|
timezoneName: projection.meta.timezone
|
|
@@ -1804,6 +1909,7 @@ function assertRangesWithinProjection(projection, ranges) {
|
|
|
1804
1909
|
}
|
|
1805
1910
|
export function queryAvailabilityProjection(projection, request) {
|
|
1806
1911
|
var _extractFixedOffsetMi6, _request$productIds2;
|
|
1912
|
+
var runtimeOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
1807
1913
|
var normalizedPartySize = normalizePartySize(request.partySize);
|
|
1808
1914
|
var evaluatedAt = formatDateTime(localDateToScalar(new Date()), projection.meta.timezone, (_extractFixedOffsetMi6 = extractFixedOffsetMinutes(projection.meta.now)) !== null && _extractFixedOffsetMi6 !== void 0 ? _extractFixedOffsetMi6 : captureRuntimeOffsetMinutes());
|
|
1809
1915
|
if (request.target === 'time') {
|
|
@@ -1826,7 +1932,8 @@ export function queryAvailabilityProjection(projection, request) {
|
|
|
1826
1932
|
var evaluationContext = buildEvaluationContext({
|
|
1827
1933
|
projection: projection,
|
|
1828
1934
|
evaluatedAt: evaluatedAt,
|
|
1829
|
-
resourceIds: request.resourceIds
|
|
1935
|
+
resourceIds: request.resourceIds,
|
|
1936
|
+
allowExcludedScheduleDateOverride: runtimeOptions.allowExcludedScheduleDateOverride
|
|
1830
1937
|
});
|
|
1831
1938
|
if (request.target === 'time') {
|
|
1832
1939
|
var candidates = dedupeProductRanges(request.candidates);
|
|
@@ -1914,7 +2021,8 @@ export function queryAvailabilityProjection(projection, request) {
|
|
|
1914
2021
|
resourceIds: request.resourceIds,
|
|
1915
2022
|
partySize: normalizedPartySize
|
|
1916
2023
|
}, {
|
|
1917
|
-
evaluatedAt: evaluatedAt
|
|
2024
|
+
evaluatedAt: evaluatedAt,
|
|
2025
|
+
allowExcludedScheduleDateOverride: runtimeOptions.allowExcludedScheduleDateOverride
|
|
1918
2026
|
});
|
|
1919
2027
|
var candidateGroupMap = new Map(candidateGroups.map(function (group) {
|
|
1920
2028
|
return [String(group.productId), group];
|
|
@@ -2092,6 +2200,7 @@ function summarizeProductStatus(statuses) {
|
|
|
2092
2200
|
}
|
|
2093
2201
|
export function validateAvailabilitySelection(projection, params) {
|
|
2094
2202
|
var _extractFixedOffsetMi7;
|
|
2203
|
+
var runtimeOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
2095
2204
|
var normalizedPartySize = normalizePartySize(params.partySize);
|
|
2096
2205
|
var normalizedBookingCount = normalizeBookingCount(params.bookingCount);
|
|
2097
2206
|
assertRangesWithinProjection(projection, [params.candidate]);
|
|
@@ -2112,14 +2221,15 @@ export function validateAvailabilitySelection(projection, params) {
|
|
|
2112
2221
|
evaluationContext: buildEvaluationContext({
|
|
2113
2222
|
projection: projection,
|
|
2114
2223
|
evaluatedAt: evaluatedAt,
|
|
2115
|
-
requirementSelections: params.requirementSelections
|
|
2224
|
+
requirementSelections: params.requirementSelections,
|
|
2225
|
+
allowExcludedScheduleDateOverride: runtimeOptions.allowExcludedScheduleDateOverride
|
|
2116
2226
|
})
|
|
2117
2227
|
});
|
|
2118
2228
|
var conflicts = [];
|
|
2119
2229
|
if (evaluated.gate) {
|
|
2120
2230
|
conflicts.push({
|
|
2121
2231
|
code: evaluated.gate.conflictCode,
|
|
2122
|
-
message: evaluated.gate.
|
|
2232
|
+
message: evaluated.gate.conflictCode === 'past' ? '候选时间已过期' : evaluated.gate.conflictCode === 'schedule_excluded_date' ? '候选日期已被日程排除' : '候选时间不满足预订时间门禁',
|
|
2123
2233
|
reasonCodes: evaluated.gate.reasonCodes,
|
|
2124
2234
|
productId: params.candidate.productId,
|
|
2125
2235
|
candidateKey: params.candidate.key
|
|
@@ -101,6 +101,9 @@ export interface AvailabilityOperatingHoursSnapshot {
|
|
|
101
101
|
scheduleIds: AvailabilityId[];
|
|
102
102
|
missingScheduleIds: AvailabilityId[];
|
|
103
103
|
windows: AvailabilityResourceWindow[];
|
|
104
|
+
/** Schedule windows omitted only because their date is excluded. POS may use
|
|
105
|
+
* these to surface an unavailable, manually selectable candidate. */
|
|
106
|
+
excludedWindows?: AvailabilityResourceWindow[];
|
|
104
107
|
}
|
|
105
108
|
export interface AvailabilityResource {
|
|
106
109
|
id: AvailabilityId;
|
|
@@ -110,6 +113,8 @@ export interface AvailabilityResource {
|
|
|
110
113
|
resourceType: AvailabilityResourceType;
|
|
111
114
|
capacity: number;
|
|
112
115
|
windows: AvailabilityResourceWindow[];
|
|
116
|
+
/** Resource work windows omitted only by an excluded schedule date. */
|
|
117
|
+
excludedWindows?: AvailabilityResourceWindow[];
|
|
113
118
|
raw?: Record<string, any>;
|
|
114
119
|
}
|
|
115
120
|
export interface AvailabilityOccupancy extends AvailabilityAbsoluteRange {
|
|
@@ -252,6 +257,11 @@ export interface GetProductTimeRangesRuntimeOptions {
|
|
|
252
257
|
* disabled.
|
|
253
258
|
*/
|
|
254
259
|
allowSessionCustomRanges?: boolean;
|
|
260
|
+
/**
|
|
261
|
+
* Internal POS capability: materialize candidates whose schedule date was
|
|
262
|
+
* explicitly excluded, while availability evaluation keeps them unavailable.
|
|
263
|
+
*/
|
|
264
|
+
allowExcludedScheduleDateOverride?: boolean;
|
|
255
265
|
}
|
|
256
266
|
export interface QueryAvailabilityBaseRequest {
|
|
257
267
|
productIds?: AvailabilityId[];
|