@pisell/pisellos 2.3.48 → 2.3.50
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/Discount/index.d.ts +1 -0
- package/dist/modules/Discount/index.js +40 -11
- package/dist/modules/Discount/types.d.ts +1 -0
- package/dist/modules/Holder/index.d.ts +48 -0
- package/dist/modules/Holder/index.js +640 -0
- package/dist/modules/Holder/types.d.ts +123 -0
- package/dist/modules/Holder/types.js +1 -0
- package/dist/modules/Holder/utils.d.ts +13 -0
- package/dist/modules/Holder/utils.js +34 -0
- package/dist/modules/OpenData/index.js +2 -2
- package/dist/modules/Order/index.d.ts +3 -1
- package/dist/modules/Order/index.js +54 -25
- package/dist/modules/Order/types.d.ts +9 -0
- package/dist/modules/Order/utils.d.ts +10 -0
- package/dist/modules/Order/utils.js +35 -3
- package/dist/modules/Product/types.d.ts +1 -0
- package/dist/modules/ProductList/index.js +33 -14
- package/dist/modules/Quotation/index.d.ts +1 -1
- package/dist/modules/Quotation/index.js +2 -2
- package/dist/modules/ResourcePlanner/index.d.ts +24 -0
- package/dist/modules/ResourcePlanner/index.js +181 -0
- package/dist/modules/ResourcePlanner/planner.d.ts +14 -0
- package/dist/modules/ResourcePlanner/planner.js +1069 -0
- package/dist/modules/ResourcePlanner/types.d.ts +227 -0
- package/dist/modules/ResourcePlanner/types.js +1 -0
- package/dist/modules/Rules/index.js +47 -13
- package/dist/modules/SalesSummary/index.js +12 -13
- package/dist/modules/ScanOrderLogger/index.d.ts +2 -0
- package/dist/modules/ScanOrderLogger/index.js +15 -2
- package/dist/modules/ScanOrderLogger/providers/feishu.js +45 -27
- package/dist/modules/ScanOrderLogger/types.d.ts +1 -0
- package/dist/modules/Schedule/index.d.ts +3 -1
- package/dist/modules/Schedule/index.js +21 -16
- package/dist/modules/Summary/utils.js +38 -13
- package/dist/modules/index.d.ts +2 -0
- package/dist/modules/index.js +3 -1
- package/dist/plugins/window.d.ts +1 -0
- package/dist/server/index.d.ts +14 -0
- package/dist/server/index.js +907 -793
- package/dist/server/modules/index.d.ts +1 -1
- package/dist/server/modules/order/index.d.ts +0 -16
- package/dist/server/modules/order/index.js +776 -964
- package/dist/server/modules/order/types.d.ts +0 -14
- package/dist/server/modules/order/types.js +0 -6
- package/dist/solution/BaseSales/index.d.ts +7 -0
- package/dist/solution/BaseSales/index.js +64 -42
- package/dist/solution/BookingByStep/index.d.ts +16 -1
- package/dist/solution/BookingByStep/index.js +294 -215
- package/dist/solution/BookingByStep/types.d.ts +2 -1
- package/dist/solution/BookingByStep/types.js +3 -1
- package/dist/solution/BookingByStep/utils/capacity.js +17 -1
- package/dist/solution/BookingByStep/utils/timeslots.d.ts +3 -1
- package/dist/solution/BookingByStep/utils/timeslots.js +19 -12
- package/dist/solution/BookingTicket/index.js +2 -2
- package/dist/solution/BookingTicket/utils/scan/handleScan.d.ts +3 -1
- package/dist/solution/BookingTicket/utils/scan/handleScan.js +10 -2
- package/dist/solution/ScanOrder/index.d.ts +26 -14
- package/dist/solution/ScanOrder/index.js +1142 -739
- package/dist/solution/ScanOrder/types.d.ts +21 -1
- package/dist/solution/ScanOrder/utils.d.ts +8 -0
- package/dist/solution/ScanOrder/utils.js +66 -25
- package/dist/solution/ShopDiscount/index.d.ts +1 -0
- package/dist/solution/ShopDiscount/index.js +125 -87
- package/dist/solution/UnifiedBookingSales/index.d.ts +183 -0
- package/dist/solution/UnifiedBookingSales/index.js +1891 -0
- package/dist/solution/UnifiedBookingSales/types.d.ts +143 -0
- package/dist/solution/UnifiedBookingSales/types.js +11 -0
- package/dist/solution/VenueBooking/index.d.ts +39 -11
- package/dist/solution/VenueBooking/index.js +1167 -841
- package/dist/solution/VenueBooking/types.d.ts +3 -0
- package/dist/solution/VenueBooking/utils/resource.js +1 -0
- package/dist/solution/VenueBooking/utils/slotMerge.d.ts +4 -4
- package/dist/solution/VenueBooking/utils/slotMerge.js +10 -5
- package/dist/solution/index.d.ts +1 -0
- package/dist/solution/index.js +2 -1
- package/dist/types/index.d.ts +1 -0
- package/lib/modules/Discount/index.d.ts +1 -0
- package/lib/modules/Discount/index.js +9 -0
- package/lib/modules/Discount/types.d.ts +1 -0
- package/lib/modules/Holder/index.d.ts +48 -0
- package/lib/modules/Holder/index.js +402 -0
- package/lib/modules/Holder/types.d.ts +123 -0
- package/lib/modules/Holder/types.js +17 -0
- package/lib/modules/Holder/utils.d.ts +13 -0
- package/lib/modules/Holder/utils.js +71 -0
- package/lib/modules/OpenData/index.js +1 -1
- package/lib/modules/Order/index.d.ts +3 -1
- package/lib/modules/Order/index.js +26 -10
- package/lib/modules/Order/types.d.ts +9 -0
- package/lib/modules/Order/utils.d.ts +10 -0
- package/lib/modules/Order/utils.js +36 -5
- package/lib/modules/Product/types.d.ts +1 -0
- package/lib/modules/ProductList/index.js +40 -31
- package/lib/modules/Quotation/index.d.ts +1 -1
- package/lib/modules/Quotation/index.js +2 -2
- package/lib/modules/ResourcePlanner/index.d.ts +24 -0
- package/lib/modules/ResourcePlanner/index.js +148 -0
- package/lib/modules/ResourcePlanner/planner.d.ts +14 -0
- package/lib/modules/ResourcePlanner/planner.js +933 -0
- package/lib/modules/ResourcePlanner/types.d.ts +227 -0
- package/lib/modules/ResourcePlanner/types.js +17 -0
- package/lib/modules/Rules/index.js +33 -16
- package/lib/modules/SalesSummary/index.js +6 -7
- package/lib/modules/ScanOrderLogger/index.d.ts +2 -0
- package/lib/modules/ScanOrderLogger/index.js +13 -1
- package/lib/modules/ScanOrderLogger/providers/feishu.js +15 -6
- package/lib/modules/ScanOrderLogger/types.d.ts +1 -0
- package/lib/modules/Schedule/index.d.ts +3 -1
- package/lib/modules/Schedule/index.js +10 -8
- package/lib/modules/Summary/utils.js +21 -1
- package/lib/modules/index.d.ts +2 -0
- package/lib/modules/index.js +5 -1
- package/lib/plugins/window.d.ts +1 -0
- package/lib/server/index.d.ts +14 -0
- package/lib/server/index.js +72 -15
- package/lib/server/modules/index.d.ts +1 -1
- package/lib/server/modules/order/index.d.ts +0 -16
- package/lib/server/modules/order/index.js +4 -140
- package/lib/server/modules/order/types.d.ts +0 -14
- package/lib/server/modules/order/types.js +0 -1
- package/lib/solution/BaseSales/index.d.ts +7 -0
- package/lib/solution/BaseSales/index.js +24 -8
- package/lib/solution/BookingByStep/index.d.ts +16 -1
- package/lib/solution/BookingByStep/index.js +60 -18
- package/lib/solution/BookingByStep/types.d.ts +2 -1
- package/lib/solution/BookingByStep/types.js +5 -0
- package/lib/solution/BookingByStep/utils/capacity.js +20 -1
- package/lib/solution/BookingByStep/utils/timeslots.d.ts +3 -1
- package/lib/solution/BookingByStep/utils/timeslots.js +19 -11
- package/lib/solution/BookingTicket/index.js +10 -2
- package/lib/solution/BookingTicket/utils/scan/handleScan.d.ts +3 -1
- package/lib/solution/BookingTicket/utils/scan/handleScan.js +2 -2
- package/lib/solution/ScanOrder/index.d.ts +26 -14
- package/lib/solution/ScanOrder/index.js +449 -182
- package/lib/solution/ScanOrder/types.d.ts +21 -1
- package/lib/solution/ScanOrder/utils.d.ts +8 -0
- package/lib/solution/ScanOrder/utils.js +31 -0
- package/lib/solution/ShopDiscount/index.d.ts +1 -0
- package/lib/solution/ShopDiscount/index.js +14 -0
- package/lib/solution/UnifiedBookingSales/index.d.ts +183 -0
- package/lib/solution/UnifiedBookingSales/index.js +1084 -0
- package/lib/solution/UnifiedBookingSales/types.d.ts +143 -0
- package/lib/solution/UnifiedBookingSales/types.js +33 -0
- package/lib/solution/VenueBooking/index.d.ts +39 -11
- package/lib/solution/VenueBooking/index.js +322 -110
- package/lib/solution/VenueBooking/types.d.ts +3 -0
- package/lib/solution/VenueBooking/utils/resource.js +1 -0
- package/lib/solution/VenueBooking/utils/slotMerge.d.ts +4 -4
- package/lib/solution/VenueBooking/utils/slotMerge.js +6 -4
- package/lib/solution/index.d.ts +1 -0
- package/lib/solution/index.js +3 -1
- package/lib/types/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1069 @@
|
|
|
1
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
2
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
3
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
4
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
5
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
6
|
+
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
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."); }
|
|
8
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
9
|
+
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
10
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
11
|
+
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); }
|
|
12
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
13
|
+
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); }
|
|
14
|
+
import dayjs from 'dayjs';
|
|
15
|
+
export var DEFAULT_RESOURCE_PLANNER_CONTEXT = {
|
|
16
|
+
products: [],
|
|
17
|
+
resources: [],
|
|
18
|
+
externalEvents: [],
|
|
19
|
+
slotDurationMinutes: 30,
|
|
20
|
+
businessStartTime: '09:00',
|
|
21
|
+
businessEndTime: '18:00'
|
|
22
|
+
};
|
|
23
|
+
export var DEFAULT_RESOURCE_PLANNER_SELECTION = {
|
|
24
|
+
productIds: [],
|
|
25
|
+
resourceIds: [],
|
|
26
|
+
assignments: []
|
|
27
|
+
};
|
|
28
|
+
export function normalizePlannerContext() {
|
|
29
|
+
var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
30
|
+
return {
|
|
31
|
+
products: Array.isArray(input.products) ? input.products : [],
|
|
32
|
+
resources: Array.isArray(input.resources) ? input.resources : [],
|
|
33
|
+
externalEvents: Array.isArray(input.externalEvents) ? input.externalEvents : [],
|
|
34
|
+
slotDurationMinutes: input.slotDurationMinutes || DEFAULT_RESOURCE_PLANNER_CONTEXT.slotDurationMinutes,
|
|
35
|
+
businessStartTime: input.businessStartTime || DEFAULT_RESOURCE_PLANNER_CONTEXT.businessStartTime,
|
|
36
|
+
businessEndTime: input.businessEndTime || DEFAULT_RESOURCE_PLANNER_CONTEXT.businessEndTime
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function sameId(left, right) {
|
|
40
|
+
return String(left) === String(right);
|
|
41
|
+
}
|
|
42
|
+
function dateOf(value) {
|
|
43
|
+
return dayjs(value).format('YYYY-MM-DD');
|
|
44
|
+
}
|
|
45
|
+
function timeOf(value) {
|
|
46
|
+
return dayjs(value).format('HH:mm');
|
|
47
|
+
}
|
|
48
|
+
function toDateTime(date, time) {
|
|
49
|
+
if (/^\d{4}-\d{2}-\d{2}/.test(time)) return dayjs(time);
|
|
50
|
+
return dayjs("".concat(date, " ").concat(time.length === 5 ? "".concat(time, ":00") : time));
|
|
51
|
+
}
|
|
52
|
+
function overlaps(startA, endA, startB, endB) {
|
|
53
|
+
return startA.isBefore(endB) && endA.isAfter(startB);
|
|
54
|
+
}
|
|
55
|
+
function containsRange(outerStart, outerEnd, innerStart, innerEnd) {
|
|
56
|
+
return !innerStart.isBefore(outerStart) && !innerEnd.isAfter(outerEnd);
|
|
57
|
+
}
|
|
58
|
+
function maxDayjs(left, right) {
|
|
59
|
+
return left.isAfter(right) ? left : right;
|
|
60
|
+
}
|
|
61
|
+
function minDayjs(left, right) {
|
|
62
|
+
return left.isBefore(right) ? left : right;
|
|
63
|
+
}
|
|
64
|
+
function addDays(start, end) {
|
|
65
|
+
var result = [];
|
|
66
|
+
var cursor = dayjs(start);
|
|
67
|
+
var finalDay = dayjs(end);
|
|
68
|
+
while (!cursor.isAfter(finalDay, 'day')) {
|
|
69
|
+
result.push(cursor.format('YYYY-MM-DD'));
|
|
70
|
+
cursor = cursor.add(1, 'day');
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
function getQueryProducts(products, query) {
|
|
75
|
+
var _query$productIds;
|
|
76
|
+
if (!((_query$productIds = query.productIds) !== null && _query$productIds !== void 0 && _query$productIds.length)) return products;
|
|
77
|
+
return products.filter(function (product) {
|
|
78
|
+
return query.productIds.some(function (id) {
|
|
79
|
+
return sameId(id, product.id);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function getQueryResources(resources, query) {
|
|
84
|
+
var _query$resourceIds;
|
|
85
|
+
if (!((_query$resourceIds = query.resourceIds) !== null && _query$resourceIds !== void 0 && _query$resourceIds.length)) return resources;
|
|
86
|
+
return resources.filter(function (resource) {
|
|
87
|
+
return query.resourceIds.some(function (id) {
|
|
88
|
+
return sameId(id, resource.id);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function matchesResourceRequirement(resource, requirement) {
|
|
93
|
+
var _requirement$resource;
|
|
94
|
+
var isFormlessCandidate = resource.formId == null;
|
|
95
|
+
var formMatches = requirement.formId == null || isFormlessCandidate || sameId(requirement.formId, resource.formId);
|
|
96
|
+
var resourceMatches = !((_requirement$resource = requirement.resourceIds) !== null && _requirement$resource !== void 0 && _requirement$resource.length) || isFormlessCandidate || requirement.resourceIds.some(function (id) {
|
|
97
|
+
return sameId(id, resource.id);
|
|
98
|
+
});
|
|
99
|
+
return formMatches && resourceMatches;
|
|
100
|
+
}
|
|
101
|
+
function resolveProductTitle(product) {
|
|
102
|
+
var _product$raw, _product$raw2, _product$raw3;
|
|
103
|
+
var rawTitle = ((_product$raw = product.raw) === null || _product$raw === void 0 ? void 0 : _product$raw.title) || ((_product$raw2 = product.raw) === null || _product$raw2 === void 0 ? void 0 : _product$raw2.name) || ((_product$raw3 = product.raw) === null || _product$raw3 === void 0 ? void 0 : _product$raw3.product_title);
|
|
104
|
+
if (typeof product.title === 'string') return product.title;
|
|
105
|
+
if (typeof rawTitle === 'string') return rawTitle;
|
|
106
|
+
if (rawTitle && _typeof(rawTitle) === 'object') {
|
|
107
|
+
return rawTitle.en || rawTitle.zh || rawTitle.default || Object.values(rawTitle)[0];
|
|
108
|
+
}
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
export function buildDemandIntervals(products, query, context) {
|
|
112
|
+
var dates = query.date ? [query.date] : query.dateRange ? addDays(query.dateRange.start, query.dateRange.end) : [];
|
|
113
|
+
var selectedProducts = getQueryProducts(products, query);
|
|
114
|
+
var intervals = [];
|
|
115
|
+
var _iterator = _createForOfIteratorHelper(selectedProducts),
|
|
116
|
+
_step;
|
|
117
|
+
try {
|
|
118
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
119
|
+
var product = _step.value;
|
|
120
|
+
var quantity = Math.max(1, Number(product.quantity || 1));
|
|
121
|
+
var capacityRequired = Math.max(1, Number(query.pax || product.capacityRequired || 1));
|
|
122
|
+
var requirements = product.resourceRequirements || [];
|
|
123
|
+
if (product.kind === 'session' || product.kind === 'venue_slot') {
|
|
124
|
+
var schedules = product.schedule || [];
|
|
125
|
+
var _iterator2 = _createForOfIteratorHelper(schedules),
|
|
126
|
+
_step2;
|
|
127
|
+
try {
|
|
128
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
129
|
+
var schedule = _step2.value;
|
|
130
|
+
var scheduleDate = dateOf(schedule.start_at);
|
|
131
|
+
if (dates.length > 0 && !dates.includes(scheduleDate)) continue;
|
|
132
|
+
var start = dayjs(schedule.start_at);
|
|
133
|
+
var end = dayjs(schedule.end_at);
|
|
134
|
+
intervals.push({
|
|
135
|
+
id: "".concat(product.id, ":").concat(start.toISOString(), ":").concat(end.toISOString()),
|
|
136
|
+
productId: product.id,
|
|
137
|
+
source: product.kind,
|
|
138
|
+
date: dateOf(schedule.start_at),
|
|
139
|
+
start_at: start.toISOString(),
|
|
140
|
+
end_at: end.toISOString(),
|
|
141
|
+
durationMinutes: Math.max(1, end.diff(start, 'minute')),
|
|
142
|
+
quantity: quantity,
|
|
143
|
+
capacityRequired: capacityRequired,
|
|
144
|
+
resourceRequirements: requirements
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
} catch (err) {
|
|
148
|
+
_iterator2.e(err);
|
|
149
|
+
} finally {
|
|
150
|
+
_iterator2.f();
|
|
151
|
+
}
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
if (product.kind === 'duration') {
|
|
155
|
+
var duration = Math.max(1, Number(product.durationMinutes || 30));
|
|
156
|
+
var _iterator3 = _createForOfIteratorHelper(dates),
|
|
157
|
+
_step3;
|
|
158
|
+
try {
|
|
159
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
160
|
+
var currentDate = _step3.value;
|
|
161
|
+
var _start = query.startTime ? toDateTime(currentDate, query.startTime) : toDateTime(currentDate, (context === null || context === void 0 ? void 0 : context.businessStartTime) || DEFAULT_RESOURCE_PLANNER_CONTEXT.businessStartTime);
|
|
162
|
+
var _end = query.startTime && query.endTime ? toDateTime(currentDate, query.endTime) : query.startTime ? _start.add(duration, 'minute') : toDateTime(currentDate, (context === null || context === void 0 ? void 0 : context.businessEndTime) || DEFAULT_RESOURCE_PLANNER_CONTEXT.businessEndTime);
|
|
163
|
+
if (!_end.isAfter(_start)) _end = _end.add(1, 'day');
|
|
164
|
+
intervals.push({
|
|
165
|
+
id: "".concat(product.id, ":").concat(currentDate, ":").concat(query.startTime || 'range'),
|
|
166
|
+
productId: product.id,
|
|
167
|
+
source: 'duration',
|
|
168
|
+
date: currentDate,
|
|
169
|
+
start_at: _start.toISOString(),
|
|
170
|
+
end_at: _end.toISOString(),
|
|
171
|
+
durationMinutes: duration,
|
|
172
|
+
quantity: quantity,
|
|
173
|
+
capacityRequired: capacityRequired,
|
|
174
|
+
resourceRequirements: requirements
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
} catch (err) {
|
|
178
|
+
_iterator3.e(err);
|
|
179
|
+
} finally {
|
|
180
|
+
_iterator3.f();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
} catch (err) {
|
|
185
|
+
_iterator.e(err);
|
|
186
|
+
} finally {
|
|
187
|
+
_iterator.f();
|
|
188
|
+
}
|
|
189
|
+
return intervals;
|
|
190
|
+
}
|
|
191
|
+
function getEventsForResource(resource, contextEvents) {
|
|
192
|
+
var embeddedEvents = resource.times.flatMap(function (time) {
|
|
193
|
+
return time.event_list || [];
|
|
194
|
+
});
|
|
195
|
+
return [].concat(_toConsumableArray(embeddedEvents), _toConsumableArray(contextEvents.filter(function (event) {
|
|
196
|
+
var _event$resourceId;
|
|
197
|
+
return sameId((_event$resourceId = event.resourceId) !== null && _event$resourceId !== void 0 ? _event$resourceId : event.resource_id, resource.id);
|
|
198
|
+
}))).filter(Boolean);
|
|
199
|
+
}
|
|
200
|
+
function collectEventsByResource(resources, contextEvents) {
|
|
201
|
+
var eventsByResource = new Map();
|
|
202
|
+
resources.forEach(function (resource) {
|
|
203
|
+
eventsByResource.set(String(resource.id), getEventsForResource(resource, contextEvents));
|
|
204
|
+
});
|
|
205
|
+
return eventsByResource;
|
|
206
|
+
}
|
|
207
|
+
function getWorkingSegmentsForInterval(resource, interval) {
|
|
208
|
+
var intervalStart = dayjs(interval.start_at);
|
|
209
|
+
var intervalEnd = dayjs(interval.end_at);
|
|
210
|
+
return resource.times.map(function (time) {
|
|
211
|
+
var start = maxDayjs(dayjs(time.start_at), intervalStart);
|
|
212
|
+
var end = minDayjs(dayjs(time.end_at), intervalEnd);
|
|
213
|
+
return {
|
|
214
|
+
start: start,
|
|
215
|
+
end: end
|
|
216
|
+
};
|
|
217
|
+
}).filter(function (segment) {
|
|
218
|
+
return segment.end.isAfter(segment.start);
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
function mergeBusySegments(segments) {
|
|
222
|
+
var sorted = _toConsumableArray(segments).filter(function (segment) {
|
|
223
|
+
return segment.end.isAfter(segment.start);
|
|
224
|
+
}).sort(function (left, right) {
|
|
225
|
+
return left.start.valueOf() - right.start.valueOf();
|
|
226
|
+
});
|
|
227
|
+
var merged = [];
|
|
228
|
+
sorted.forEach(function (segment) {
|
|
229
|
+
var previous = merged[merged.length - 1];
|
|
230
|
+
if (previous && !segment.start.isAfter(previous.end)) {
|
|
231
|
+
previous.end = maxDayjs(previous.end, segment.end);
|
|
232
|
+
} else {
|
|
233
|
+
merged.push(_objectSpread({}, segment));
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
return merged;
|
|
237
|
+
}
|
|
238
|
+
function subtractBusyIntervals(workingSegments, events) {
|
|
239
|
+
var available = [];
|
|
240
|
+
workingSegments.forEach(function (working) {
|
|
241
|
+
var busySegments = mergeBusySegments(events.filter(function (event) {
|
|
242
|
+
return overlaps(working.start, working.end, dayjs(event.start_at), dayjs(event.end_at));
|
|
243
|
+
}).map(function (event) {
|
|
244
|
+
return {
|
|
245
|
+
start: maxDayjs(dayjs(event.start_at), working.start),
|
|
246
|
+
end: minDayjs(dayjs(event.end_at), working.end)
|
|
247
|
+
};
|
|
248
|
+
}));
|
|
249
|
+
var cursor = working.start;
|
|
250
|
+
busySegments.forEach(function (busy) {
|
|
251
|
+
if (busy.start.isAfter(cursor)) {
|
|
252
|
+
available.push({
|
|
253
|
+
start: cursor,
|
|
254
|
+
end: busy.start
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
if (busy.end.isAfter(cursor)) cursor = busy.end;
|
|
258
|
+
});
|
|
259
|
+
if (working.end.isAfter(cursor)) {
|
|
260
|
+
available.push({
|
|
261
|
+
start: cursor,
|
|
262
|
+
end: working.end
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
return available;
|
|
267
|
+
}
|
|
268
|
+
function buildCapacityRanges(params) {
|
|
269
|
+
var workingSegments = params.workingSegments,
|
|
270
|
+
events = params.events,
|
|
271
|
+
maxCapacity = params.maxCapacity,
|
|
272
|
+
requiredCapacity = params.requiredCapacity;
|
|
273
|
+
var ranges = [];
|
|
274
|
+
workingSegments.forEach(function (working) {
|
|
275
|
+
var boundaries = new Map([[working.start.valueOf(), working.start], [working.end.valueOf(), working.end]]);
|
|
276
|
+
events.forEach(function (event) {
|
|
277
|
+
var eventStart = dayjs(event.start_at);
|
|
278
|
+
var eventEnd = dayjs(event.end_at);
|
|
279
|
+
if (!overlaps(working.start, working.end, eventStart, eventEnd)) return;
|
|
280
|
+
var clippedStart = maxDayjs(eventStart, working.start);
|
|
281
|
+
var clippedEnd = minDayjs(eventEnd, working.end);
|
|
282
|
+
boundaries.set(clippedStart.valueOf(), clippedStart);
|
|
283
|
+
boundaries.set(clippedEnd.valueOf(), clippedEnd);
|
|
284
|
+
});
|
|
285
|
+
var points = Array.from(boundaries.values()).sort(function (left, right) {
|
|
286
|
+
return left.valueOf() - right.valueOf();
|
|
287
|
+
});
|
|
288
|
+
var _loop = function _loop() {
|
|
289
|
+
var start = points[index];
|
|
290
|
+
var end = points[index + 1];
|
|
291
|
+
if (!end.isAfter(start)) return 0; // continue
|
|
292
|
+
var usedCapacity = events.filter(function (event) {
|
|
293
|
+
return overlaps(start, end, dayjs(event.start_at), dayjs(event.end_at));
|
|
294
|
+
}).reduce(function (sum, event) {
|
|
295
|
+
return sum + Math.max(1, Number(event.pax || 1));
|
|
296
|
+
}, 0);
|
|
297
|
+
var remainingCapacity = Math.max(0, maxCapacity - usedCapacity);
|
|
298
|
+
if (remainingCapacity < requiredCapacity) return 0; // continue
|
|
299
|
+
var status = remainingCapacity < maxCapacity ? 'limited' : 'available';
|
|
300
|
+
var previous = ranges[ranges.length - 1];
|
|
301
|
+
if (previous && previous.end.isSame(start) && previous.remainingCapacity === remainingCapacity && previous.maxCapacity === maxCapacity && previous.status === status) {
|
|
302
|
+
previous.end = end;
|
|
303
|
+
} else {
|
|
304
|
+
ranges.push({
|
|
305
|
+
start: start,
|
|
306
|
+
end: end,
|
|
307
|
+
remainingCapacity: remainingCapacity,
|
|
308
|
+
maxCapacity: maxCapacity,
|
|
309
|
+
status: status
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
_ret;
|
|
314
|
+
for (var index = 0; index < points.length - 1; index += 1) {
|
|
315
|
+
_ret = _loop();
|
|
316
|
+
if (_ret === 0) continue;
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
return ranges;
|
|
320
|
+
}
|
|
321
|
+
function rangeFitsDuration(segment, durationMinutes) {
|
|
322
|
+
return segment.end.diff(segment.start, 'minute') >= durationMinutes;
|
|
323
|
+
}
|
|
324
|
+
function makeAvailabilityRangeCell(params) {
|
|
325
|
+
var _segment$remainingCap;
|
|
326
|
+
var interval = params.interval,
|
|
327
|
+
resource = params.resource,
|
|
328
|
+
segment = params.segment;
|
|
329
|
+
var maxCapacity = Math.max(1, Number(segment.maxCapacity || resource.capacity || 1));
|
|
330
|
+
var remainingCapacity = resource.resourceType === 'single' ? 1 : Math.max(0, Number((_segment$remainingCap = segment.remainingCapacity) !== null && _segment$remainingCap !== void 0 ? _segment$remainingCap : maxCapacity));
|
|
331
|
+
var status = resource.resourceType === 'single' ? 'available' : segment.status || (remainingCapacity < maxCapacity ? 'limited' : 'available');
|
|
332
|
+
return {
|
|
333
|
+
key: "".concat(interval.productId, ":").concat(resource.id, ":").concat(segment.start.toISOString(), ":").concat(segment.end.toISOString()),
|
|
334
|
+
productId: interval.productId,
|
|
335
|
+
resourceId: resource.id,
|
|
336
|
+
date: interval.date,
|
|
337
|
+
start_at: segment.start.toISOString(),
|
|
338
|
+
end_at: segment.end.toISOString(),
|
|
339
|
+
startTime: segment.start.format('HH:mm'),
|
|
340
|
+
endTime: segment.end.format('HH:mm'),
|
|
341
|
+
durationMinutes: interval.durationMinutes,
|
|
342
|
+
cellType: 'availability_range',
|
|
343
|
+
status: status,
|
|
344
|
+
remainingCapacity: remainingCapacity,
|
|
345
|
+
maxCapacity: maxCapacity,
|
|
346
|
+
reasonCodes: [],
|
|
347
|
+
conflicts: []
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
function buildAvailabilityCellsForResource(params) {
|
|
351
|
+
var resource = params.resource,
|
|
352
|
+
interval = params.interval,
|
|
353
|
+
events = params.events;
|
|
354
|
+
var requiredCapacity = Math.max(1, Number(interval.capacityRequired || 1));
|
|
355
|
+
var durationMinutes = Math.max(1, Number(interval.durationMinutes || 1));
|
|
356
|
+
var maxCapacity = Math.max(1, Number(resource.capacity || 1));
|
|
357
|
+
var workingSegments = getWorkingSegmentsForInterval(resource, interval);
|
|
358
|
+
var now = dayjs();
|
|
359
|
+
workingSegments = workingSegments.map(function (segment) {
|
|
360
|
+
return {
|
|
361
|
+
start: segment.end.isAfter(now) ? maxDayjs(segment.start, now) : segment.start,
|
|
362
|
+
end: segment.end
|
|
363
|
+
};
|
|
364
|
+
}).filter(function (segment) {
|
|
365
|
+
return segment.end.isAfter(segment.start);
|
|
366
|
+
});
|
|
367
|
+
var availableSegments = resource.resourceType === 'single' ? subtractBusyIntervals(workingSegments, events).map(function (segment) {
|
|
368
|
+
return _objectSpread(_objectSpread({}, segment), {}, {
|
|
369
|
+
remainingCapacity: 1,
|
|
370
|
+
maxCapacity: 1,
|
|
371
|
+
status: 'available'
|
|
372
|
+
});
|
|
373
|
+
}) : buildCapacityRanges({
|
|
374
|
+
workingSegments: workingSegments,
|
|
375
|
+
events: events,
|
|
376
|
+
maxCapacity: maxCapacity,
|
|
377
|
+
requiredCapacity: requiredCapacity
|
|
378
|
+
});
|
|
379
|
+
return availableSegments.filter(function (segment) {
|
|
380
|
+
return rangeFitsDuration(segment, durationMinutes);
|
|
381
|
+
}).map(function (segment) {
|
|
382
|
+
return makeAvailabilityRangeCell({
|
|
383
|
+
interval: interval,
|
|
384
|
+
resource: resource,
|
|
385
|
+
segment: segment
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
export function evaluateResourceForInterval(params) {
|
|
390
|
+
var resource = params.resource,
|
|
391
|
+
interval = params.interval,
|
|
392
|
+
context = params.context;
|
|
393
|
+
var start = dayjs(interval.start_at);
|
|
394
|
+
var end = dayjs(interval.end_at);
|
|
395
|
+
var conflicts = [];
|
|
396
|
+
var reasonCodes = [];
|
|
397
|
+
var maxCapacity = Math.max(1, Number(resource.capacity || 1));
|
|
398
|
+
var requiredCapacity = Math.max(1, Number(interval.capacityRequired || 1));
|
|
399
|
+
if (start.isBefore(dayjs())) {
|
|
400
|
+
reasonCodes.push('past');
|
|
401
|
+
conflicts.push({
|
|
402
|
+
type: 'past',
|
|
403
|
+
message: '时间已过期',
|
|
404
|
+
resourceId: resource.id,
|
|
405
|
+
productId: interval.productId
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
var insideResourceTime = resource.times.some(function (time) {
|
|
409
|
+
return containsRange(dayjs(time.start_at), dayjs(time.end_at), start, end);
|
|
410
|
+
});
|
|
411
|
+
if (!insideResourceTime) {
|
|
412
|
+
reasonCodes.push('outside_resource_time');
|
|
413
|
+
conflicts.push({
|
|
414
|
+
type: 'outside_resource_time',
|
|
415
|
+
message: '所选时间不在资源可用时间内',
|
|
416
|
+
resourceId: resource.id,
|
|
417
|
+
productId: interval.productId
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
var events = getEventsForResource(resource, context.externalEvents);
|
|
421
|
+
var overlapping = events.filter(function (event) {
|
|
422
|
+
return overlaps(start, end, dayjs(event.start_at), dayjs(event.end_at));
|
|
423
|
+
});
|
|
424
|
+
var usedCapacity = resource.resourceType === 'single' ? overlapping.length : overlapping.reduce(function (sum, event) {
|
|
425
|
+
return sum + Math.max(1, Number(event.pax || 1));
|
|
426
|
+
}, 0);
|
|
427
|
+
var remainingCapacity = resource.resourceType === 'single' ? overlapping.length > 0 ? 0 : 1 : Math.max(0, maxCapacity - usedCapacity);
|
|
428
|
+
if (overlapping.length > 0 && resource.resourceType === 'single') {
|
|
429
|
+
reasonCodes.push('remote_event_overlap');
|
|
430
|
+
conflicts.push.apply(conflicts, _toConsumableArray(overlapping.map(function (event) {
|
|
431
|
+
return {
|
|
432
|
+
type: 'remote_event_overlap',
|
|
433
|
+
message: '资源时间被已有预约占用',
|
|
434
|
+
event: event,
|
|
435
|
+
resourceId: resource.id,
|
|
436
|
+
productId: interval.productId
|
|
437
|
+
};
|
|
438
|
+
})));
|
|
439
|
+
}
|
|
440
|
+
if (resource.resourceType !== 'single' && remainingCapacity < requiredCapacity) {
|
|
441
|
+
reasonCodes.push('capacity_full');
|
|
442
|
+
conflicts.push({
|
|
443
|
+
type: 'capacity_full',
|
|
444
|
+
message: '资源剩余容量不足',
|
|
445
|
+
resourceId: resource.id,
|
|
446
|
+
productId: interval.productId
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
var status = 'available';
|
|
450
|
+
if (reasonCodes.includes('past')) status = 'past';else if (reasonCodes.includes('outside_resource_time')) status = 'unavailable';else if (reasonCodes.includes('remote_event_overlap') || reasonCodes.includes('capacity_full')) {
|
|
451
|
+
status = 'full';
|
|
452
|
+
} else if (remainingCapacity < maxCapacity) {
|
|
453
|
+
status = 'limited';
|
|
454
|
+
}
|
|
455
|
+
return {
|
|
456
|
+
key: "".concat(interval.productId, ":").concat(resource.id, ":").concat(interval.start_at, ":").concat(interval.end_at),
|
|
457
|
+
productId: interval.productId,
|
|
458
|
+
resourceId: resource.id,
|
|
459
|
+
date: interval.date,
|
|
460
|
+
start_at: interval.start_at,
|
|
461
|
+
end_at: interval.end_at,
|
|
462
|
+
startTime: timeOf(interval.start_at),
|
|
463
|
+
endTime: timeOf(interval.end_at),
|
|
464
|
+
durationMinutes: interval.durationMinutes,
|
|
465
|
+
cellType: status === 'available' || status === 'limited' ? 'fixed_interval' : 'unavailable',
|
|
466
|
+
status: status,
|
|
467
|
+
remainingCapacity: remainingCapacity,
|
|
468
|
+
maxCapacity: maxCapacity,
|
|
469
|
+
reasonCodes: reasonCodes,
|
|
470
|
+
conflicts: conflicts
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
function aggregateStatus(cells) {
|
|
474
|
+
if (!cells.length) return 'unavailable';
|
|
475
|
+
if (cells.some(function (cell) {
|
|
476
|
+
return cell.status === 'available';
|
|
477
|
+
})) return 'available';
|
|
478
|
+
if (cells.some(function (cell) {
|
|
479
|
+
return cell.status === 'limited';
|
|
480
|
+
})) return 'limited';
|
|
481
|
+
if (cells.some(function (cell) {
|
|
482
|
+
return cell.status === 'past';
|
|
483
|
+
})) return 'past';
|
|
484
|
+
if (cells.some(function (cell) {
|
|
485
|
+
return cell.status === 'full';
|
|
486
|
+
})) return 'full';
|
|
487
|
+
if (cells.some(function (cell) {
|
|
488
|
+
return cell.status === 'conflict';
|
|
489
|
+
})) return 'conflict';
|
|
490
|
+
return 'unavailable';
|
|
491
|
+
}
|
|
492
|
+
function uniqueReasonCodes(cells) {
|
|
493
|
+
return Array.from(new Set(cells.flatMap(function (cell) {
|
|
494
|
+
return cell.reasonCodes || [];
|
|
495
|
+
})));
|
|
496
|
+
}
|
|
497
|
+
function buildProductOptions(products, cells, query) {
|
|
498
|
+
var queryProducts = getQueryProducts(products, query);
|
|
499
|
+
return queryProducts.map(function (product) {
|
|
500
|
+
var productCells = cells.filter(function (cell) {
|
|
501
|
+
return sameId(cell.productId, product.id);
|
|
502
|
+
});
|
|
503
|
+
var status = product.kind === 'normal' ? 'available' : aggregateStatus(productCells);
|
|
504
|
+
return {
|
|
505
|
+
productId: product.id,
|
|
506
|
+
title: resolveProductTitle(product),
|
|
507
|
+
status: status,
|
|
508
|
+
reasonCodes: uniqueReasonCodes(productCells)
|
|
509
|
+
};
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
function buildResourceOptions(resources, cells, query) {
|
|
513
|
+
var queryResources = getQueryResources(resources, query);
|
|
514
|
+
return queryResources.map(function (resource) {
|
|
515
|
+
var resourceCells = cells.filter(function (cell) {
|
|
516
|
+
return cell.resourceId !== undefined && sameId(cell.resourceId, resource.id);
|
|
517
|
+
});
|
|
518
|
+
var bestCell = resourceCells.find(function (cell) {
|
|
519
|
+
return cell.status === 'available';
|
|
520
|
+
}) || resourceCells.find(function (cell) {
|
|
521
|
+
return cell.status === 'limited';
|
|
522
|
+
}) || resourceCells[0];
|
|
523
|
+
return {
|
|
524
|
+
resourceId: resource.id,
|
|
525
|
+
resourceName: resource.name,
|
|
526
|
+
resourceFormId: resource.formId,
|
|
527
|
+
resourceType: resource.resourceType,
|
|
528
|
+
status: resourceCells.length ? aggregateStatus(resourceCells) : 'unavailable',
|
|
529
|
+
remainingCapacity: bestCell === null || bestCell === void 0 ? void 0 : bestCell.remainingCapacity,
|
|
530
|
+
maxCapacity: (bestCell === null || bestCell === void 0 ? void 0 : bestCell.maxCapacity) || resource.capacity,
|
|
531
|
+
reasonCodes: uniqueReasonCodes(resourceCells)
|
|
532
|
+
};
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
function buildDateSummary(cells, query) {
|
|
536
|
+
var dates = query.date ? [query.date] : query.dateRange ? addDays(query.dateRange.start, query.dateRange.end) : Array.from(new Set(cells.map(function (cell) {
|
|
537
|
+
return cell.date;
|
|
538
|
+
}).filter(Boolean)));
|
|
539
|
+
return dates.map(function (date) {
|
|
540
|
+
var dateCells = cells.filter(function (cell) {
|
|
541
|
+
return cell.date === date;
|
|
542
|
+
});
|
|
543
|
+
var availableCount = dateCells.filter(function (cell) {
|
|
544
|
+
return cell.status === 'available' || cell.status === 'limited';
|
|
545
|
+
}).length;
|
|
546
|
+
return {
|
|
547
|
+
date: date,
|
|
548
|
+
status: dateCells.length ? aggregateStatus(dateCells) : 'unavailable',
|
|
549
|
+
availableCount: availableCount,
|
|
550
|
+
totalCount: dateCells.length
|
|
551
|
+
};
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
function buildTimeLabels(date, context, query) {
|
|
555
|
+
if (!date) return [];
|
|
556
|
+
var slotMinutes = query.slotDurationMinutes || context.slotDurationMinutes;
|
|
557
|
+
var labels = [];
|
|
558
|
+
var cursor = toDateTime(date, context.businessStartTime);
|
|
559
|
+
var end = toDateTime(date, context.businessEndTime);
|
|
560
|
+
if (!end.isAfter(cursor)) end = end.add(1, 'day');
|
|
561
|
+
while (cursor.isBefore(end)) {
|
|
562
|
+
labels.push(cursor.format('HH:mm'));
|
|
563
|
+
cursor = cursor.add(slotMinutes, 'minute');
|
|
564
|
+
}
|
|
565
|
+
return labels;
|
|
566
|
+
}
|
|
567
|
+
function buildGridSlotInterval(product, date, label, context, query) {
|
|
568
|
+
var slotMinutes = product.kind === 'duration' ? Math.max(1, Number(product.durationMinutes || query.slotDurationMinutes || context.slotDurationMinutes)) : query.slotDurationMinutes || context.slotDurationMinutes;
|
|
569
|
+
var start = toDateTime(date, label);
|
|
570
|
+
var end = start.add(slotMinutes, 'minute');
|
|
571
|
+
return {
|
|
572
|
+
id: "".concat(product.id, ":").concat(date, ":").concat(label),
|
|
573
|
+
productId: product.id,
|
|
574
|
+
source: product.kind === 'session' ? 'session' : product.kind === 'venue_slot' ? 'venue_slot' : 'duration',
|
|
575
|
+
date: date,
|
|
576
|
+
start_at: start.toISOString(),
|
|
577
|
+
end_at: end.toISOString(),
|
|
578
|
+
durationMinutes: slotMinutes,
|
|
579
|
+
quantity: Math.max(1, Number(product.quantity || 1)),
|
|
580
|
+
capacityRequired: Math.max(1, Number(query.pax || product.capacityRequired || 1)),
|
|
581
|
+
resourceRequirements: product.resourceRequirements || []
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
function buildTimeGrid(context, query, cells) {
|
|
585
|
+
var _query$dateRange;
|
|
586
|
+
var date = query.date || ((_query$dateRange = query.dateRange) === null || _query$dateRange === void 0 ? void 0 : _query$dateRange.start);
|
|
587
|
+
var products = getQueryProducts(context.products, query).filter(function (product) {
|
|
588
|
+
return product.kind !== 'normal';
|
|
589
|
+
});
|
|
590
|
+
var resources = getQueryResources(context.resources, query);
|
|
591
|
+
var timeLabels = buildTimeLabels(date, context, query);
|
|
592
|
+
if (!date || !products.length || !resources.length) {
|
|
593
|
+
return {
|
|
594
|
+
date: date,
|
|
595
|
+
timeLabels: timeLabels,
|
|
596
|
+
resources: []
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
var rows = resources.map(function (resource) {
|
|
600
|
+
var slots = timeLabels.map(function (label) {
|
|
601
|
+
var product = products[0];
|
|
602
|
+
var interval = buildGridSlotInterval(product, date, label, context, query);
|
|
603
|
+
var start = dayjs(interval.start_at);
|
|
604
|
+
var end = dayjs(interval.end_at);
|
|
605
|
+
var cell = cells.find(function (item) {
|
|
606
|
+
return sameId(item.productId, product.id) && sameId(item.resourceId, resource.id) && item.date === date && (item.status === 'available' || item.status === 'limited') && containsRange(dayjs(item.start_at), dayjs(item.end_at), start, end);
|
|
607
|
+
});
|
|
608
|
+
return {
|
|
609
|
+
startTime: label,
|
|
610
|
+
endTime: dayjs(interval.end_at).format('HH:mm'),
|
|
611
|
+
status: (cell === null || cell === void 0 ? void 0 : cell.status) || 'unavailable',
|
|
612
|
+
resourceId: resource.id,
|
|
613
|
+
productId: product.id,
|
|
614
|
+
remainingCapacity: cell === null || cell === void 0 ? void 0 : cell.remainingCapacity,
|
|
615
|
+
maxCapacity: (cell === null || cell === void 0 ? void 0 : cell.maxCapacity) || resource.capacity,
|
|
616
|
+
reasonCodes: (cell === null || cell === void 0 ? void 0 : cell.reasonCodes) || ['outside_available_range']
|
|
617
|
+
};
|
|
618
|
+
});
|
|
619
|
+
return {
|
|
620
|
+
resourceId: resource.id,
|
|
621
|
+
resourceName: resource.name,
|
|
622
|
+
resourceFormId: resource.formId,
|
|
623
|
+
slots: slots
|
|
624
|
+
};
|
|
625
|
+
});
|
|
626
|
+
return {
|
|
627
|
+
date: date,
|
|
628
|
+
timeLabels: timeLabels,
|
|
629
|
+
resources: rows
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
export function queryPlannerAvailability(contextInput) {
|
|
633
|
+
var query = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
634
|
+
var context = normalizePlannerContext(contextInput);
|
|
635
|
+
var intervals = buildDemandIntervals(context.products, query, context);
|
|
636
|
+
var resources = getQueryResources(context.resources, query);
|
|
637
|
+
var eventsByResource = collectEventsByResource(resources, context.externalEvents);
|
|
638
|
+
var cells = [];
|
|
639
|
+
var _iterator4 = _createForOfIteratorHelper(intervals),
|
|
640
|
+
_step4;
|
|
641
|
+
try {
|
|
642
|
+
var _loop2 = function _loop2() {
|
|
643
|
+
var interval = _step4.value;
|
|
644
|
+
var candidateResources = resources.filter(function (resource) {
|
|
645
|
+
var requirements = interval.resourceRequirements || [];
|
|
646
|
+
if (!requirements.length) return true;
|
|
647
|
+
return requirements.some(function (requirement) {
|
|
648
|
+
return matchesResourceRequirement(resource, requirement);
|
|
649
|
+
});
|
|
650
|
+
});
|
|
651
|
+
if (!candidateResources.length) {
|
|
652
|
+
cells.push({
|
|
653
|
+
key: "".concat(interval.productId, ":missing-resource:").concat(interval.start_at),
|
|
654
|
+
productId: interval.productId,
|
|
655
|
+
date: interval.date,
|
|
656
|
+
start_at: interval.start_at,
|
|
657
|
+
end_at: interval.end_at,
|
|
658
|
+
startTime: timeOf(interval.start_at),
|
|
659
|
+
endTime: timeOf(interval.end_at),
|
|
660
|
+
durationMinutes: interval.durationMinutes,
|
|
661
|
+
cellType: 'unavailable',
|
|
662
|
+
status: 'unavailable',
|
|
663
|
+
reasonCodes: ['missing_resource'],
|
|
664
|
+
conflicts: [{
|
|
665
|
+
type: 'missing_resource',
|
|
666
|
+
message: '没有匹配商品需求的资源',
|
|
667
|
+
productId: interval.productId
|
|
668
|
+
}]
|
|
669
|
+
});
|
|
670
|
+
return 1; // continue
|
|
671
|
+
}
|
|
672
|
+
candidateResources.forEach(function (resource) {
|
|
673
|
+
if (interval.source === 'duration' && !query.startTime) {
|
|
674
|
+
cells.push.apply(cells, _toConsumableArray(buildAvailabilityCellsForResource({
|
|
675
|
+
resource: resource,
|
|
676
|
+
interval: interval,
|
|
677
|
+
events: eventsByResource.get(String(resource.id)) || []
|
|
678
|
+
})));
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
cells.push(evaluateResourceForInterval({
|
|
682
|
+
resource: resource,
|
|
683
|
+
interval: interval,
|
|
684
|
+
context: context
|
|
685
|
+
}));
|
|
686
|
+
});
|
|
687
|
+
};
|
|
688
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
689
|
+
if (_loop2()) continue;
|
|
690
|
+
}
|
|
691
|
+
} catch (err) {
|
|
692
|
+
_iterator4.e(err);
|
|
693
|
+
} finally {
|
|
694
|
+
_iterator4.f();
|
|
695
|
+
}
|
|
696
|
+
return {
|
|
697
|
+
query: query,
|
|
698
|
+
demandIntervals: intervals,
|
|
699
|
+
productOptions: buildProductOptions(context.products, cells, query),
|
|
700
|
+
resourceOptions: buildResourceOptions(context.resources, cells, query),
|
|
701
|
+
dateSummary: buildDateSummary(cells, query),
|
|
702
|
+
timeGrid: buildTimeGrid(context, query, cells),
|
|
703
|
+
cells: cells
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
function getIntervalRequirements(interval) {
|
|
707
|
+
return interval.resourceRequirements.length ? interval.resourceRequirements : [{
|
|
708
|
+
capacityRequired: interval.capacityRequired,
|
|
709
|
+
required: true
|
|
710
|
+
}];
|
|
711
|
+
}
|
|
712
|
+
function buildAssignableCandidateGroups(params) {
|
|
713
|
+
var interval = params.interval,
|
|
714
|
+
cells = params.cells,
|
|
715
|
+
resources = params.resources;
|
|
716
|
+
var conflicts = [];
|
|
717
|
+
var groups = getIntervalRequirements(interval).map(function (requirement) {
|
|
718
|
+
var candidateCells = cells.filter(function (cell) {
|
|
719
|
+
if (!sameId(cell.productId, interval.productId)) return false;
|
|
720
|
+
if (cell.date !== interval.date) return false;
|
|
721
|
+
if (cell.resourceId === undefined) return false;
|
|
722
|
+
if (cell.status !== 'available' && cell.status !== 'limited') return false;
|
|
723
|
+
var cellStart = dayjs(cell.start_at);
|
|
724
|
+
var cellEnd = dayjs(cell.end_at);
|
|
725
|
+
var intervalStart = dayjs(interval.start_at);
|
|
726
|
+
var intervalEnd = dayjs(interval.end_at);
|
|
727
|
+
return containsRange(cellStart, cellEnd, intervalStart, intervalEnd) || interval.source === 'duration';
|
|
728
|
+
});
|
|
729
|
+
return candidateCells.flatMap(function (cell) {
|
|
730
|
+
var resource = resources.find(function (item) {
|
|
731
|
+
return sameId(item.id, cell.resourceId);
|
|
732
|
+
});
|
|
733
|
+
if (!resource || !matchesResourceRequirement(resource, requirement)) return [];
|
|
734
|
+
return [{
|
|
735
|
+
requirement: requirement,
|
|
736
|
+
resource: resource,
|
|
737
|
+
cell: cell
|
|
738
|
+
}];
|
|
739
|
+
});
|
|
740
|
+
});
|
|
741
|
+
groups.forEach(function (group, index) {
|
|
742
|
+
var _interval$resourceReq;
|
|
743
|
+
if (group.length) return;
|
|
744
|
+
conflicts.push({
|
|
745
|
+
type: 'missing_resource',
|
|
746
|
+
message: '没有匹配商品需求的可用资源',
|
|
747
|
+
productId: interval.productId,
|
|
748
|
+
resourceId: (_interval$resourceReq = interval.resourceRequirements[index]) === null || _interval$resourceReq === void 0 || (_interval$resourceReq = _interval$resourceReq.resourceIds) === null || _interval$resourceReq === void 0 ? void 0 : _interval$resourceReq[0]
|
|
749
|
+
});
|
|
750
|
+
});
|
|
751
|
+
return {
|
|
752
|
+
groups: groups,
|
|
753
|
+
conflicts: conflicts
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
function combineCandidateGroups(groups) {
|
|
757
|
+
if (!groups.length || groups.some(function (group) {
|
|
758
|
+
return group.length === 0;
|
|
759
|
+
})) return [];
|
|
760
|
+
return groups.reduce(function (combinations, group) {
|
|
761
|
+
return combinations.flatMap(function (combination) {
|
|
762
|
+
return group.map(function (candidate) {
|
|
763
|
+
return [].concat(_toConsumableArray(combination), [candidate]);
|
|
764
|
+
});
|
|
765
|
+
});
|
|
766
|
+
}, [[]]);
|
|
767
|
+
}
|
|
768
|
+
function buildSlotFromCandidates(params) {
|
|
769
|
+
var interval = params.interval,
|
|
770
|
+
candidates = params.candidates,
|
|
771
|
+
start = params.start,
|
|
772
|
+
end = params.end;
|
|
773
|
+
if (!end.isAfter(start)) return null;
|
|
774
|
+
var status = candidates.some(function (candidate) {
|
|
775
|
+
return candidate.cell.status === 'limited';
|
|
776
|
+
}) ? 'limited' : 'available';
|
|
777
|
+
var assignments = candidates.map(function (candidate) {
|
|
778
|
+
return {
|
|
779
|
+
productId: interval.productId,
|
|
780
|
+
resourceId: candidate.resource.id,
|
|
781
|
+
start_at: start.toISOString(),
|
|
782
|
+
end_at: end.toISOString(),
|
|
783
|
+
capacityRequired: Math.max(1, Number(candidate.requirement.capacityRequired || interval.capacityRequired || 1))
|
|
784
|
+
};
|
|
785
|
+
});
|
|
786
|
+
return {
|
|
787
|
+
key: [interval.productId, start.toISOString(), end.toISOString()].concat(_toConsumableArray(candidates.map(function (candidate) {
|
|
788
|
+
return candidate.resource.id;
|
|
789
|
+
}))).join(':'),
|
|
790
|
+
productId: interval.productId,
|
|
791
|
+
date: interval.date,
|
|
792
|
+
start_at: start.toISOString(),
|
|
793
|
+
end_at: end.toISOString(),
|
|
794
|
+
startTime: start.format('HH:mm'),
|
|
795
|
+
endTime: end.format('HH:mm'),
|
|
796
|
+
durationMinutes: Math.max(1, end.diff(start, 'minute')),
|
|
797
|
+
status: status,
|
|
798
|
+
resources: candidates.map(function (candidate) {
|
|
799
|
+
return {
|
|
800
|
+
resourceId: candidate.resource.id,
|
|
801
|
+
resourceName: candidate.resource.name,
|
|
802
|
+
resourceFormId: candidate.resource.formId,
|
|
803
|
+
resourceType: candidate.resource.resourceType,
|
|
804
|
+
capacityRequired: Math.max(1, Number(candidate.requirement.capacityRequired || interval.capacityRequired || 1)),
|
|
805
|
+
remainingCapacity: candidate.cell.remainingCapacity,
|
|
806
|
+
maxCapacity: candidate.cell.maxCapacity
|
|
807
|
+
};
|
|
808
|
+
}),
|
|
809
|
+
assignments: assignments,
|
|
810
|
+
conflicts: []
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
function buildSlotsForInterval(params) {
|
|
814
|
+
var interval = params.interval,
|
|
815
|
+
candidates = params.candidates,
|
|
816
|
+
query = params.query,
|
|
817
|
+
context = params.context;
|
|
818
|
+
var start = candidates.reduce(function (current, candidate) {
|
|
819
|
+
return maxDayjs(current, dayjs(candidate.cell.start_at));
|
|
820
|
+
}, dayjs(interval.start_at));
|
|
821
|
+
var end = candidates.reduce(function (current, candidate) {
|
|
822
|
+
return minDayjs(current, dayjs(candidate.cell.end_at));
|
|
823
|
+
}, dayjs(interval.end_at));
|
|
824
|
+
var durationMinutes = Math.max(1, Number(interval.durationMinutes || 1));
|
|
825
|
+
if (interval.source !== 'duration' || query.startTime) {
|
|
826
|
+
var fixedStart = dayjs(interval.start_at);
|
|
827
|
+
var fixedEnd = dayjs(interval.end_at);
|
|
828
|
+
if (containsRange(start, end, fixedStart, fixedEnd) || candidates.every(function (candidate) {
|
|
829
|
+
return candidate.cell.cellType === 'fixed_interval';
|
|
830
|
+
})) {
|
|
831
|
+
var slot = buildSlotFromCandidates({
|
|
832
|
+
interval: interval,
|
|
833
|
+
candidates: candidates,
|
|
834
|
+
start: fixedStart,
|
|
835
|
+
end: fixedEnd
|
|
836
|
+
});
|
|
837
|
+
return slot ? [slot] : [];
|
|
838
|
+
}
|
|
839
|
+
return [];
|
|
840
|
+
}
|
|
841
|
+
var stepMinutes = Math.max(1, Number(query.slotDurationMinutes || context.slotDurationMinutes || 30));
|
|
842
|
+
var slots = [];
|
|
843
|
+
var cursor = start;
|
|
844
|
+
while (!cursor.add(durationMinutes, 'minute').isAfter(end)) {
|
|
845
|
+
var slotEnd = cursor.add(durationMinutes, 'minute');
|
|
846
|
+
var _slot = buildSlotFromCandidates({
|
|
847
|
+
interval: interval,
|
|
848
|
+
candidates: candidates,
|
|
849
|
+
start: cursor,
|
|
850
|
+
end: slotEnd
|
|
851
|
+
});
|
|
852
|
+
if (_slot) slots.push(_slot);
|
|
853
|
+
cursor = cursor.add(stepMinutes, 'minute');
|
|
854
|
+
}
|
|
855
|
+
return slots;
|
|
856
|
+
}
|
|
857
|
+
export function resolveAssignableSlots(contextInput) {
|
|
858
|
+
var query = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
859
|
+
var context = normalizePlannerContext(contextInput);
|
|
860
|
+
var projection = queryPlannerAvailability(context, query);
|
|
861
|
+
var resources = getQueryResources(context.resources, query);
|
|
862
|
+
var slotsByKey = new Map();
|
|
863
|
+
var conflicts = [];
|
|
864
|
+
projection.demandIntervals.forEach(function (interval) {
|
|
865
|
+
var _buildAssignableCandi = buildAssignableCandidateGroups({
|
|
866
|
+
interval: interval,
|
|
867
|
+
cells: projection.cells,
|
|
868
|
+
resources: resources
|
|
869
|
+
}),
|
|
870
|
+
groups = _buildAssignableCandi.groups,
|
|
871
|
+
groupConflicts = _buildAssignableCandi.conflicts;
|
|
872
|
+
conflicts.push.apply(conflicts, _toConsumableArray(groupConflicts));
|
|
873
|
+
combineCandidateGroups(groups).forEach(function (candidates) {
|
|
874
|
+
buildSlotsForInterval({
|
|
875
|
+
interval: interval,
|
|
876
|
+
candidates: candidates,
|
|
877
|
+
query: query,
|
|
878
|
+
context: context
|
|
879
|
+
}).forEach(function (slot) {
|
|
880
|
+
if (!slotsByKey.has(slot.key)) slotsByKey.set(slot.key, slot);
|
|
881
|
+
});
|
|
882
|
+
});
|
|
883
|
+
});
|
|
884
|
+
return {
|
|
885
|
+
projection: projection,
|
|
886
|
+
slots: Array.from(slotsByKey.values()),
|
|
887
|
+
conflicts: conflicts
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
export function autoAssignResources(contextInput) {
|
|
891
|
+
var query = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
892
|
+
var baseContext = normalizePlannerContext(contextInput);
|
|
893
|
+
var projection = queryPlannerAvailability(baseContext, query);
|
|
894
|
+
var assignments = [];
|
|
895
|
+
var conflicts = [];
|
|
896
|
+
var missingTimeProductIds = new Set();
|
|
897
|
+
var _iterator5 = _createForOfIteratorHelper(projection.demandIntervals),
|
|
898
|
+
_step5;
|
|
899
|
+
try {
|
|
900
|
+
var _loop3 = function _loop3() {
|
|
901
|
+
var interval = _step5.value;
|
|
902
|
+
if (interval.source === 'duration' && !query.startTime) {
|
|
903
|
+
var productKey = String(interval.productId);
|
|
904
|
+
if (!missingTimeProductIds.has(productKey)) {
|
|
905
|
+
missingTimeProductIds.add(productKey);
|
|
906
|
+
conflicts.push({
|
|
907
|
+
type: 'missing_time',
|
|
908
|
+
message: 'duration 商品需要先确定开始时间后才能自动分配资源',
|
|
909
|
+
productId: interval.productId
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
return 0; // continue
|
|
913
|
+
}
|
|
914
|
+
var contextWithAssignments = withAssignmentEvents(baseContext, assignments);
|
|
915
|
+
var candidateResources = getQueryResources(contextWithAssignments.resources, query).filter(function (resource) {
|
|
916
|
+
var requirements = interval.resourceRequirements || [];
|
|
917
|
+
if (!requirements.length) return true;
|
|
918
|
+
return requirements.some(function (requirement) {
|
|
919
|
+
return matchesResourceRequirement(resource, requirement);
|
|
920
|
+
});
|
|
921
|
+
});
|
|
922
|
+
var availableCell = candidateResources.map(function (resource) {
|
|
923
|
+
return evaluateResourceForInterval({
|
|
924
|
+
resource: resource,
|
|
925
|
+
interval: interval,
|
|
926
|
+
context: contextWithAssignments
|
|
927
|
+
});
|
|
928
|
+
}).find(function (cell) {
|
|
929
|
+
return cell.status === 'available' || cell.status === 'limited';
|
|
930
|
+
});
|
|
931
|
+
if (!(availableCell !== null && availableCell !== void 0 && availableCell.resourceId)) {
|
|
932
|
+
conflicts.push({
|
|
933
|
+
type: 'missing_resource',
|
|
934
|
+
message: '无法为商品自动分配可用资源',
|
|
935
|
+
productId: interval.productId
|
|
936
|
+
});
|
|
937
|
+
return 0; // continue
|
|
938
|
+
}
|
|
939
|
+
assignments.push({
|
|
940
|
+
productId: interval.productId,
|
|
941
|
+
resourceId: availableCell.resourceId,
|
|
942
|
+
start_at: interval.start_at,
|
|
943
|
+
end_at: interval.end_at,
|
|
944
|
+
capacityRequired: interval.capacityRequired
|
|
945
|
+
});
|
|
946
|
+
},
|
|
947
|
+
_ret2;
|
|
948
|
+
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
949
|
+
_ret2 = _loop3();
|
|
950
|
+
if (_ret2 === 0) continue;
|
|
951
|
+
}
|
|
952
|
+
} catch (err) {
|
|
953
|
+
_iterator5.e(err);
|
|
954
|
+
} finally {
|
|
955
|
+
_iterator5.f();
|
|
956
|
+
}
|
|
957
|
+
return {
|
|
958
|
+
assignments: assignments,
|
|
959
|
+
conflicts: conflicts
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
function withAssignmentEvents(context, assignments) {
|
|
963
|
+
if (!assignments.length) return context;
|
|
964
|
+
return _objectSpread(_objectSpread({}, context), {}, {
|
|
965
|
+
externalEvents: [].concat(_toConsumableArray(context.externalEvents), _toConsumableArray(assignments.map(function (assignment) {
|
|
966
|
+
return {
|
|
967
|
+
resourceId: assignment.resourceId,
|
|
968
|
+
start_at: assignment.start_at,
|
|
969
|
+
end_at: assignment.end_at,
|
|
970
|
+
pax: assignment.capacityRequired || 1,
|
|
971
|
+
source: 'selection'
|
|
972
|
+
};
|
|
973
|
+
})))
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
export function validateAssignments(contextInput, selection) {
|
|
977
|
+
if (selection.assignments.length > 0) {
|
|
978
|
+
var context = normalizePlannerContext(contextInput);
|
|
979
|
+
var _conflicts = [];
|
|
980
|
+
var _loop4 = function _loop4() {
|
|
981
|
+
var assignment = selection.assignments[index];
|
|
982
|
+
var product = context.products.find(function (item) {
|
|
983
|
+
return sameId(item.id, assignment.productId);
|
|
984
|
+
});
|
|
985
|
+
var resource = context.resources.find(function (item) {
|
|
986
|
+
return sameId(item.id, assignment.resourceId);
|
|
987
|
+
});
|
|
988
|
+
if (!product) {
|
|
989
|
+
_conflicts.push({
|
|
990
|
+
type: 'missing_resource',
|
|
991
|
+
message: 'assignment 对应的商品不存在',
|
|
992
|
+
productId: assignment.productId
|
|
993
|
+
});
|
|
994
|
+
return 0; // continue
|
|
995
|
+
}
|
|
996
|
+
if (!resource) {
|
|
997
|
+
_conflicts.push({
|
|
998
|
+
type: 'missing_resource',
|
|
999
|
+
message: 'assignment 对应的资源不存在',
|
|
1000
|
+
productId: assignment.productId,
|
|
1001
|
+
resourceId: assignment.resourceId
|
|
1002
|
+
});
|
|
1003
|
+
return 0; // continue
|
|
1004
|
+
}
|
|
1005
|
+
var start = dayjs(assignment.start_at);
|
|
1006
|
+
var end = dayjs(assignment.end_at);
|
|
1007
|
+
var interval = {
|
|
1008
|
+
id: "".concat(assignment.productId, ":").concat(assignment.resourceId, ":").concat(assignment.start_at, ":").concat(assignment.end_at),
|
|
1009
|
+
productId: assignment.productId,
|
|
1010
|
+
source: product.kind === 'session' ? 'session' : product.kind === 'venue_slot' ? 'venue_slot' : 'duration',
|
|
1011
|
+
date: start.format('YYYY-MM-DD'),
|
|
1012
|
+
start_at: assignment.start_at,
|
|
1013
|
+
end_at: assignment.end_at,
|
|
1014
|
+
durationMinutes: Math.max(1, end.diff(start, 'minute')),
|
|
1015
|
+
quantity: Math.max(1, Number(product.quantity || 1)),
|
|
1016
|
+
capacityRequired: Math.max(1, Number(assignment.capacityRequired || product.capacityRequired || 1)),
|
|
1017
|
+
resourceRequirements: product.resourceRequirements || []
|
|
1018
|
+
};
|
|
1019
|
+
var cell = evaluateResourceForInterval({
|
|
1020
|
+
resource: resource,
|
|
1021
|
+
interval: interval,
|
|
1022
|
+
context: context
|
|
1023
|
+
});
|
|
1024
|
+
if (cell.status !== 'available' && cell.status !== 'limited') {
|
|
1025
|
+
_conflicts.push.apply(_conflicts, _toConsumableArray(cell.conflicts));
|
|
1026
|
+
}
|
|
1027
|
+
var priorContext = withAssignmentEvents(context, selection.assignments.slice(0, index));
|
|
1028
|
+
var selfConflictCell = evaluateResourceForInterval({
|
|
1029
|
+
resource: resource,
|
|
1030
|
+
interval: interval,
|
|
1031
|
+
context: priorContext
|
|
1032
|
+
});
|
|
1033
|
+
if (selfConflictCell.status !== 'available' && selfConflictCell.status !== 'limited') {
|
|
1034
|
+
_conflicts.push.apply(_conflicts, _toConsumableArray(selfConflictCell.conflicts.map(function (conflict) {
|
|
1035
|
+
return _objectSpread(_objectSpread({}, conflict), {}, {
|
|
1036
|
+
type: 'cart_overlap',
|
|
1037
|
+
message: '本次选择中存在资源时间冲突'
|
|
1038
|
+
});
|
|
1039
|
+
})));
|
|
1040
|
+
}
|
|
1041
|
+
},
|
|
1042
|
+
_ret3;
|
|
1043
|
+
for (var index = 0; index < selection.assignments.length; index += 1) {
|
|
1044
|
+
_ret3 = _loop4();
|
|
1045
|
+
if (_ret3 === 0) continue;
|
|
1046
|
+
}
|
|
1047
|
+
return {
|
|
1048
|
+
ok: _conflicts.length === 0,
|
|
1049
|
+
conflicts: _conflicts
|
|
1050
|
+
};
|
|
1051
|
+
}
|
|
1052
|
+
var projection = queryPlannerAvailability(contextInput, {
|
|
1053
|
+
productIds: selection.productIds,
|
|
1054
|
+
date: selection.date,
|
|
1055
|
+
startTime: selection.startTime,
|
|
1056
|
+
endTime: selection.endTime,
|
|
1057
|
+
resourceIds: selection.resourceIds,
|
|
1058
|
+
mode: selection.mode
|
|
1059
|
+
});
|
|
1060
|
+
var conflicts = projection.cells.filter(function (cell) {
|
|
1061
|
+
return cell.status !== 'available' && cell.status !== 'limited';
|
|
1062
|
+
}).flatMap(function (cell) {
|
|
1063
|
+
return cell.conflicts;
|
|
1064
|
+
});
|
|
1065
|
+
return {
|
|
1066
|
+
ok: conflicts.length === 0,
|
|
1067
|
+
conflicts: conflicts
|
|
1068
|
+
};
|
|
1069
|
+
}
|