@pisell/pisellos 2.1.128 → 2.1.130
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/model/strategy/adapter/promotion/index.js +0 -9
- package/dist/modules/Order/index.d.ts +4 -0
- package/dist/modules/Order/index.js +18 -1
- package/dist/modules/Order/types.d.ts +9 -1
- package/dist/modules/Order/utils.d.ts +7 -0
- package/dist/modules/Order/utils.js +27 -11
- package/dist/solution/ScanOrder/index.d.ts +27 -3
- package/dist/solution/ScanOrder/index.js +865 -481
- package/dist/solution/ScanOrder/types.d.ts +34 -24
- package/dist/solution/ScanOrder/types.js +5 -1
- package/dist/solution/ScanOrder/utils.d.ts +13 -1
- package/dist/solution/ScanOrder/utils.js +45 -6
- package/dist/solution/VenueBooking/index.d.ts +28 -5
- package/dist/solution/VenueBooking/index.js +463 -227
- package/dist/solution/VenueBooking/types.d.ts +23 -0
- package/dist/solution/VenueBooking/utils/dateSummary.d.ts +1 -1
- package/dist/solution/VenueBooking/utils/dateSummary.js +1 -1
- package/dist/solution/VenueBooking/utils/resource.d.ts +11 -1
- package/dist/solution/VenueBooking/utils/resource.js +57 -21
- package/dist/solution/VenueBooking/utils/slotMerge.d.ts +5 -0
- package/dist/solution/VenueBooking/utils/slotMerge.js +33 -12
- package/dist/solution/VenueBooking/utils/timeSlot.d.ts +1 -1
- package/dist/solution/VenueBooking/utils/timeSlot.js +259 -62
- package/lib/model/strategy/adapter/promotion/index.js +49 -0
- package/lib/modules/Order/index.d.ts +4 -0
- package/lib/modules/Order/index.js +14 -1
- package/lib/modules/Order/types.d.ts +9 -1
- package/lib/modules/Order/utils.d.ts +7 -0
- package/lib/modules/Order/utils.js +22 -12
- package/lib/solution/ScanOrder/index.d.ts +27 -3
- package/lib/solution/ScanOrder/index.js +409 -114
- package/lib/solution/ScanOrder/types.d.ts +34 -24
- package/lib/solution/ScanOrder/utils.d.ts +13 -1
- package/lib/solution/ScanOrder/utils.js +37 -0
- package/lib/solution/VenueBooking/index.d.ts +28 -5
- package/lib/solution/VenueBooking/index.js +203 -58
- package/lib/solution/VenueBooking/types.d.ts +23 -0
- package/lib/solution/VenueBooking/utils/dateSummary.d.ts +1 -1
- package/lib/solution/VenueBooking/utils/dateSummary.js +1 -1
- package/lib/solution/VenueBooking/utils/resource.d.ts +11 -1
- package/lib/solution/VenueBooking/utils/resource.js +15 -4
- package/lib/solution/VenueBooking/utils/slotMerge.d.ts +5 -0
- package/lib/solution/VenueBooking/utils/slotMerge.js +29 -12
- package/lib/solution/VenueBooking/utils/timeSlot.d.ts +1 -1
- package/lib/solution/VenueBooking/utils/timeSlot.js +182 -43
- package/package.json +1 -1
|
@@ -38,6 +38,7 @@ __export(timeSlot_exports, {
|
|
|
38
38
|
});
|
|
39
39
|
module.exports = __toCommonJS(timeSlot_exports);
|
|
40
40
|
var import_dayjs = __toESM(require("dayjs"));
|
|
41
|
+
var import_decimal = __toESM(require("decimal.js"));
|
|
41
42
|
function isBusinessHoursCrossDay(config) {
|
|
42
43
|
const [startH, startM] = config.businessStartTime.split(":").map(Number);
|
|
43
44
|
const [endH, endM] = config.businessEndTime.split(":").map(Number);
|
|
@@ -122,64 +123,202 @@ function computeSlotStatus(params) {
|
|
|
122
123
|
return { status: "partially_occupied", remainingCapacity: remaining };
|
|
123
124
|
return { status: "available", remainingCapacity: remaining };
|
|
124
125
|
}
|
|
126
|
+
function mergeSubSlots(subSlots) {
|
|
127
|
+
const priority = {
|
|
128
|
+
available: 5,
|
|
129
|
+
partially_occupied: 4,
|
|
130
|
+
occupied: 3,
|
|
131
|
+
unavailable: 2,
|
|
132
|
+
past: 1
|
|
133
|
+
};
|
|
134
|
+
let best = subSlots[0];
|
|
135
|
+
for (const slot of subSlots) {
|
|
136
|
+
if ((priority[slot.status] ?? 0) > (priority[best.status] ?? 0))
|
|
137
|
+
best = slot;
|
|
138
|
+
}
|
|
139
|
+
let minPrice = null;
|
|
140
|
+
for (const slot of subSlots) {
|
|
141
|
+
if (slot.price == null)
|
|
142
|
+
continue;
|
|
143
|
+
const decimal = new import_decimal.default(slot.price || "0");
|
|
144
|
+
if (!minPrice || decimal.lt(minPrice))
|
|
145
|
+
minPrice = decimal;
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
startTime: best.startTime,
|
|
149
|
+
endTime: best.endTime,
|
|
150
|
+
status: best.status,
|
|
151
|
+
price: minPrice ? minPrice.toFixed(2) : null,
|
|
152
|
+
resourceId: best.resourceId,
|
|
153
|
+
resourceFormId: best.resourceFormId,
|
|
154
|
+
capacity: best.capacity,
|
|
155
|
+
remainingCapacity: best.remainingCapacity
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function buildProductSlots(params) {
|
|
159
|
+
const {
|
|
160
|
+
date,
|
|
161
|
+
config,
|
|
162
|
+
resource,
|
|
163
|
+
mapping,
|
|
164
|
+
timeLabels,
|
|
165
|
+
timesForDate,
|
|
166
|
+
events,
|
|
167
|
+
resCapacity,
|
|
168
|
+
now,
|
|
169
|
+
crossDay,
|
|
170
|
+
quotationPriceMap,
|
|
171
|
+
childRawResources,
|
|
172
|
+
childTimesCache,
|
|
173
|
+
childEventsCache,
|
|
174
|
+
config_businessStartHour
|
|
175
|
+
} = params;
|
|
176
|
+
const slots = [];
|
|
177
|
+
for (const label of timeLabels) {
|
|
178
|
+
const [h] = label.split(":").map(Number);
|
|
179
|
+
const isNextDay = crossDay && h < config_businessStartHour;
|
|
180
|
+
const slotDate = isNextDay ? (0, import_dayjs.default)(date).add(1, "day").format("YYYY-MM-DD") : date;
|
|
181
|
+
const slotStart = (0, import_dayjs.default)(`${slotDate} ${label}`);
|
|
182
|
+
const slotEnd = slotStart.add(config.slotDurationMinutes, "minute");
|
|
183
|
+
let status;
|
|
184
|
+
let remainingCapacity = null;
|
|
185
|
+
if (slotStart.isBefore(now)) {
|
|
186
|
+
status = "past";
|
|
187
|
+
} else if (!isSlotWithinResourceTimes(slotStart, slotEnd, timesForDate)) {
|
|
188
|
+
status = "unavailable";
|
|
189
|
+
} else {
|
|
190
|
+
const result = computeSlotStatus({
|
|
191
|
+
slotStart,
|
|
192
|
+
slotEnd,
|
|
193
|
+
events,
|
|
194
|
+
resourceType: mapping.resourceType,
|
|
195
|
+
capacity: resCapacity
|
|
196
|
+
});
|
|
197
|
+
status = result.status;
|
|
198
|
+
remainingCapacity = result.remainingCapacity;
|
|
199
|
+
if (status !== "occupied" && childRawResources && childRawResources.length) {
|
|
200
|
+
for (let i = 0; i < childRawResources.length; i++) {
|
|
201
|
+
const child = childRawResources[i];
|
|
202
|
+
const childTimes = (childTimesCache == null ? void 0 : childTimesCache[i]) ?? getResourceTimesForDate(child, date, config);
|
|
203
|
+
const childEvents = (childEventsCache == null ? void 0 : childEventsCache[i]) ?? collectEventsForDate(child, date, config);
|
|
204
|
+
if (!isSlotWithinResourceTimes(slotStart, slotEnd, childTimes)) {
|
|
205
|
+
status = "unavailable";
|
|
206
|
+
remainingCapacity = null;
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
const childType = child.type || "single";
|
|
210
|
+
const childResult = computeSlotStatus({
|
|
211
|
+
slotStart,
|
|
212
|
+
slotEnd,
|
|
213
|
+
events: childEvents,
|
|
214
|
+
resourceType: childType,
|
|
215
|
+
capacity: child.capacity ?? 1
|
|
216
|
+
});
|
|
217
|
+
if (childResult.status === "occupied") {
|
|
218
|
+
status = "occupied";
|
|
219
|
+
remainingCapacity = 0;
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
if (childResult.status === "partially_occupied" && status === "available") {
|
|
223
|
+
status = "partially_occupied";
|
|
224
|
+
remainingCapacity = Math.min(
|
|
225
|
+
remainingCapacity ?? childResult.remainingCapacity,
|
|
226
|
+
childResult.remainingCapacity
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
const isBookable = status === "available" || status === "partially_occupied";
|
|
233
|
+
const slotStartStr = slotStart.format("YYYY-MM-DD HH:mm");
|
|
234
|
+
slots.push({
|
|
235
|
+
startTime: slotStartStr,
|
|
236
|
+
endTime: slotEnd.format("YYYY-MM-DD HH:mm"),
|
|
237
|
+
status,
|
|
238
|
+
price: isBookable ? (quotationPriceMap == null ? void 0 : quotationPriceMap.get(`${mapping.productId}:${slotStartStr}`)) ?? mapping.price : null,
|
|
239
|
+
resourceId: resource.resourceId,
|
|
240
|
+
resourceFormId: resource.formId,
|
|
241
|
+
capacity: status === "past" || status === "unavailable" ? null : resCapacity,
|
|
242
|
+
remainingCapacity,
|
|
243
|
+
productId: mapping.productId
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
return slots;
|
|
247
|
+
}
|
|
125
248
|
function buildTimeSlotGrid(params) {
|
|
126
249
|
const { date, config, rawResources, resourceProductMap, quotationPriceMap } = params;
|
|
127
250
|
const timeLabels = generateTimeLabels(config);
|
|
128
251
|
const now = (0, import_dayjs.default)();
|
|
129
252
|
const crossDay = isBusinessHoursCrossDay(config);
|
|
253
|
+
const config_businessStartHour = Number(config.businessStartTime.split(":")[0]);
|
|
254
|
+
const rawResourceById = /* @__PURE__ */ new Map();
|
|
255
|
+
for (const item of rawResources)
|
|
256
|
+
rawResourceById.set(item.resourceId, item);
|
|
130
257
|
const resources = [];
|
|
131
258
|
for (const resource of rawResources) {
|
|
132
|
-
const
|
|
133
|
-
if (!
|
|
259
|
+
const mappings = resourceProductMap.get(resource.resourceId);
|
|
260
|
+
if (!mappings || !mappings.length)
|
|
134
261
|
continue;
|
|
135
262
|
const timesForDate = getResourceTimesForDate(resource, date, config);
|
|
136
263
|
const events = collectEventsForDate(resource, date, config);
|
|
137
264
|
const resCapacity = resource.capacity ?? 1;
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
remainingCapacity = result.remainingCapacity;
|
|
161
|
-
}
|
|
162
|
-
const isBookable = status === "available" || status === "partially_occupied";
|
|
163
|
-
const slotStartStr = slotStart.format("YYYY-MM-DD HH:mm");
|
|
164
|
-
slots.push({
|
|
165
|
-
startTime: slotStartStr,
|
|
166
|
-
endTime: slotEnd.format("YYYY-MM-DD HH:mm"),
|
|
167
|
-
status,
|
|
168
|
-
price: isBookable ? (quotationPriceMap == null ? void 0 : quotationPriceMap.get(`${mapping.productId}:${slotStartStr}`)) ?? mapping.price : null,
|
|
169
|
-
resourceId: resource.resourceId,
|
|
170
|
-
resourceFormId: resource.formId,
|
|
171
|
-
capacity: status === "past" || status === "unavailable" ? null : resCapacity,
|
|
172
|
-
remainingCapacity
|
|
265
|
+
const combined = resource.combined_resource;
|
|
266
|
+
const isCombined = !!(combined && combined.status === 1 && Array.isArray(combined.resource_ids) && combined.resource_ids.length);
|
|
267
|
+
const childRawResources = isCombined ? combined.resource_ids.map((id) => rawResourceById.get(id)).filter((r) => !!r) : void 0;
|
|
268
|
+
const childTimesCache = childRawResources == null ? void 0 : childRawResources.map((child) => getResourceTimesForDate(child, date, config));
|
|
269
|
+
const childEventsCache = childRawResources == null ? void 0 : childRawResources.map((child) => collectEventsForDate(child, date, config));
|
|
270
|
+
const subRows = mappings.map((mapping) => {
|
|
271
|
+
const productSlots = buildProductSlots({
|
|
272
|
+
date,
|
|
273
|
+
config,
|
|
274
|
+
resource,
|
|
275
|
+
mapping,
|
|
276
|
+
timeLabels,
|
|
277
|
+
timesForDate,
|
|
278
|
+
events,
|
|
279
|
+
resCapacity,
|
|
280
|
+
now,
|
|
281
|
+
crossDay,
|
|
282
|
+
quotationPriceMap,
|
|
283
|
+
childRawResources,
|
|
284
|
+
childTimesCache,
|
|
285
|
+
childEventsCache,
|
|
286
|
+
config_businessStartHour
|
|
173
287
|
});
|
|
288
|
+
return {
|
|
289
|
+
productId: mapping.productId,
|
|
290
|
+
productTitle: mapping.productTitle,
|
|
291
|
+
price: mapping.price,
|
|
292
|
+
slots: productSlots
|
|
293
|
+
};
|
|
294
|
+
});
|
|
295
|
+
const hasMultipleProducts = subRows.length > 1;
|
|
296
|
+
const primary = mappings[0];
|
|
297
|
+
let outerSlots;
|
|
298
|
+
if (hasMultipleProducts) {
|
|
299
|
+
outerSlots = timeLabels.map((_label, slotIndex) => {
|
|
300
|
+
const group = subRows.map((row2) => row2.slots[slotIndex]);
|
|
301
|
+
return mergeSubSlots(group);
|
|
302
|
+
});
|
|
303
|
+
} else {
|
|
304
|
+
outerSlots = subRows[0].slots.map((slot) => ({ ...slot, productId: void 0 }));
|
|
174
305
|
}
|
|
175
|
-
|
|
306
|
+
const row = {
|
|
176
307
|
resourceId: resource.resourceId,
|
|
177
308
|
resourceFormId: resource.formId,
|
|
178
|
-
resourceName: resource.main_field ||
|
|
179
|
-
productId:
|
|
180
|
-
productTitle:
|
|
181
|
-
slots
|
|
182
|
-
}
|
|
309
|
+
resourceName: resource.main_field || primary.resourceName,
|
|
310
|
+
productId: primary.productId,
|
|
311
|
+
productTitle: primary.productTitle,
|
|
312
|
+
slots: outerSlots
|
|
313
|
+
};
|
|
314
|
+
if (hasMultipleProducts) {
|
|
315
|
+
row.products = subRows;
|
|
316
|
+
row.hasMultipleProducts = true;
|
|
317
|
+
}
|
|
318
|
+
if (isCombined && combined) {
|
|
319
|
+
row.combinedResource = { resourceIds: [...combined.resource_ids] };
|
|
320
|
+
}
|
|
321
|
+
resources.push(row);
|
|
183
322
|
}
|
|
184
323
|
const productOrder = /* @__PURE__ */ new Map();
|
|
185
324
|
for (const row of resources) {
|