@pisell/pisellos 2.1.125 → 2.1.126
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/itemRule/adapter.d.ts +8 -0
- package/dist/model/strategy/adapter/itemRule/adapter.js +46 -6
- package/dist/model/strategy/adapter/itemRule/type.d.ts +11 -1
- package/dist/modules/Order/index.js +2 -2
- package/dist/modules/Schedule/utils.d.ts +1 -1
- package/dist/solution/BookingByStep/index.d.ts +2 -2
- package/dist/solution/ScanOrder/index.js +36 -12
- package/dist/solution/ScanOrder/utils.d.ts +1 -0
- package/dist/solution/ScanOrder/utils.js +5 -0
- package/dist/solution/VenueBooking/index.d.ts +4 -0
- package/dist/solution/VenueBooking/index.js +181 -99
- package/dist/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
- package/dist/solution/VenueBooking/utils/dateSummary.js +6 -4
- package/lib/model/strategy/adapter/itemRule/adapter.d.ts +8 -0
- package/lib/model/strategy/adapter/itemRule/adapter.js +31 -0
- package/lib/model/strategy/adapter/itemRule/type.d.ts +11 -1
- package/lib/model/strategy/adapter/promotion/index.js +49 -0
- package/lib/modules/Order/index.js +2 -2
- package/lib/modules/Schedule/utils.d.ts +1 -1
- package/lib/solution/BookingByStep/index.d.ts +2 -2
- package/lib/solution/ScanOrder/index.js +22 -3
- package/lib/solution/ScanOrder/utils.d.ts +1 -0
- package/lib/solution/ScanOrder/utils.js +5 -0
- package/lib/solution/VenueBooking/index.d.ts +4 -0
- package/lib/solution/VenueBooking/index.js +75 -9
- package/lib/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
- package/lib/solution/VenueBooking/utils/dateSummary.js +13 -4
- package/package.json +1 -1
|
@@ -283,17 +283,48 @@ var ItemRuleAdapter = class {
|
|
|
283
283
|
}
|
|
284
284
|
}
|
|
285
285
|
}
|
|
286
|
+
const remainingMax = this.calculateRemainingMax(
|
|
287
|
+
scope,
|
|
288
|
+
requiredMax,
|
|
289
|
+
targets,
|
|
290
|
+
businessData
|
|
291
|
+
);
|
|
286
292
|
return {
|
|
287
293
|
ruleId: action.id,
|
|
288
294
|
targetType,
|
|
289
295
|
targets,
|
|
290
296
|
requiredMin,
|
|
291
297
|
requiredMax,
|
|
298
|
+
remainingMax,
|
|
292
299
|
requiredExact,
|
|
293
300
|
mustInclude,
|
|
294
301
|
scope
|
|
295
302
|
};
|
|
296
303
|
}
|
|
304
|
+
/**
|
|
305
|
+
* 计算当前提交剩余可选的最大数量。
|
|
306
|
+
*
|
|
307
|
+
* 仅在 scope='cumulative' 且存在 requiredMax 时生效:
|
|
308
|
+
* 用 requiredMax 减去 historicalItems 中目标商品的累计数量,保底 0。
|
|
309
|
+
* 其余场景返回 undefined,保持向后兼容。
|
|
310
|
+
*/
|
|
311
|
+
calculateRemainingMax(scope, requiredMax, targets, businessData) {
|
|
312
|
+
if (scope !== "cumulative" || typeof requiredMax !== "number") {
|
|
313
|
+
return void 0;
|
|
314
|
+
}
|
|
315
|
+
const historicalItems = businessData.historicalItems;
|
|
316
|
+
if (!(historicalItems == null ? void 0 : historicalItems.length)) {
|
|
317
|
+
return Math.max(0, requiredMax);
|
|
318
|
+
}
|
|
319
|
+
const targetIds = new Set(targets.map((t) => t.product_id));
|
|
320
|
+
let historicalQty = 0;
|
|
321
|
+
for (const item of historicalItems) {
|
|
322
|
+
if (targetIds.has(item.product_id)) {
|
|
323
|
+
historicalQty += item.quantity;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return Math.max(0, requiredMax - historicalQty);
|
|
327
|
+
}
|
|
297
328
|
// ============================================
|
|
298
329
|
// Prefill Cart 处理
|
|
299
330
|
// ============================================
|
|
@@ -180,8 +180,18 @@ export interface QuantityLimitResult {
|
|
|
180
180
|
targets: TargetItem[];
|
|
181
181
|
/** 要求的最小数量 */
|
|
182
182
|
requiredMin?: number;
|
|
183
|
-
/**
|
|
183
|
+
/** 要求的最大数量(规则配置的原始上限,用于 UI 文案展示) */
|
|
184
184
|
requiredMax?: number;
|
|
185
|
+
/**
|
|
186
|
+
* 当前提交剩余可选的最大数量。
|
|
187
|
+
*
|
|
188
|
+
* 仅在 scope='cumulative' 且存在 requiredMax 时计算:
|
|
189
|
+
* remainingMax = max(0, requiredMax - historicalItems 中目标商品累计数量)
|
|
190
|
+
*
|
|
191
|
+
* 非 cumulative 场景不设置此字段;调用方用于限制加购上限时,
|
|
192
|
+
* 应优先读取本字段,未定义时回退到 requiredMax。
|
|
193
|
+
*/
|
|
194
|
+
remainingMax?: number;
|
|
185
195
|
/** 要求的精确数量 */
|
|
186
196
|
requiredExact?: number;
|
|
187
197
|
/** 是否必须包含 */
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
|
|
29
|
+
// src/model/strategy/adapter/promotion/index.ts
|
|
30
|
+
var promotion_exports = {};
|
|
31
|
+
__export(promotion_exports, {
|
|
32
|
+
BUY_X_GET_Y_FREE_STRATEGY: () => import_examples.BUY_X_GET_Y_FREE_STRATEGY,
|
|
33
|
+
PromotionAdapter: () => import_adapter.PromotionAdapter,
|
|
34
|
+
PromotionEvaluator: () => import_evaluator.PromotionEvaluator,
|
|
35
|
+
X_ITEMS_FOR_Y_PRICE_STRATEGY: () => import_examples.X_ITEMS_FOR_Y_PRICE_STRATEGY,
|
|
36
|
+
default: () => import_adapter2.default
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(promotion_exports);
|
|
39
|
+
var import_evaluator = require("./evaluator");
|
|
40
|
+
var import_adapter = require("./adapter");
|
|
41
|
+
var import_adapter2 = __toESM(require("./adapter"));
|
|
42
|
+
var import_examples = require("./examples");
|
|
43
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
44
|
+
0 && (module.exports = {
|
|
45
|
+
BUY_X_GET_Y_FREE_STRATEGY,
|
|
46
|
+
PromotionAdapter,
|
|
47
|
+
PromotionEvaluator,
|
|
48
|
+
X_ITEMS_FOR_Y_PRICE_STRATEGY
|
|
49
|
+
});
|
|
@@ -737,8 +737,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
737
737
|
const res = await this.request.get(`/order/sales/${order_id}`, {
|
|
738
738
|
with: ["products", "scheduleEvents"]
|
|
739
739
|
});
|
|
740
|
-
if (res.
|
|
741
|
-
this.store.tempOrder.lastOrderInfo = res.data
|
|
740
|
+
if (res.code === 200 && this.store.tempOrder) {
|
|
741
|
+
this.store.tempOrder.lastOrderInfo = res.data;
|
|
742
742
|
}
|
|
743
743
|
}
|
|
744
744
|
getLastOrderInfo() {
|
|
@@ -46,7 +46,7 @@ export declare const formatScheduleResult: (schedule: ScheduleItem) => {
|
|
|
46
46
|
};
|
|
47
47
|
export declare const calcScheduleDateRange: (schedule: ScheduleItem) => any[];
|
|
48
48
|
export declare const calcCalendarDataBySchedules: (schedules: ScheduleItem[]) => unknown[];
|
|
49
|
-
export declare const calcMinTimeMaxTimeBySchedules: (schedules: ScheduleItem[], scheduleAllMap?: ScheduleAllMap, selectDate?: string) =>
|
|
49
|
+
export declare const calcMinTimeMaxTimeBySchedules: (schedules: ScheduleItem[], scheduleAllMap?: ScheduleAllMap, selectDate?: string) => ScheduleAllMap;
|
|
50
50
|
/**
|
|
51
51
|
* @title: 格式化日程数据
|
|
52
52
|
* @description:
|
|
@@ -310,7 +310,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
310
310
|
date: string;
|
|
311
311
|
status: string;
|
|
312
312
|
week: string;
|
|
313
|
-
weekNum: 0 |
|
|
313
|
+
weekNum: 0 | 1 | 2 | 5 | 4 | 3 | 6;
|
|
314
314
|
}[]>;
|
|
315
315
|
submitTimeSlot(timeSlots: TimeSliceItem): void;
|
|
316
316
|
private getScheduleDataByIds;
|
|
@@ -357,7 +357,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
357
357
|
};
|
|
358
358
|
setOtherData(key: string, value: any): void;
|
|
359
359
|
getOtherData(key: string): any;
|
|
360
|
-
getProductTypeById(id: number): Promise<"
|
|
360
|
+
getProductTypeById(id: number): Promise<"duration" | "session" | "normal">;
|
|
361
361
|
/**
|
|
362
362
|
* 提供给 UI 的方法,减轻 UI 层的计算压力,UI 层只需要传递 cartItemId 和 resourceCode 即返回对应的 renderList
|
|
363
363
|
*
|
|
@@ -765,6 +765,10 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
765
765
|
});
|
|
766
766
|
}
|
|
767
767
|
async applyItemRulePrefill() {
|
|
768
|
+
var _a, _b;
|
|
769
|
+
if ((_b = (_a = this.store.order) == null ? void 0 : _a.getLastOrderInfo) == null ? void 0 : _b.call(_a)) {
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
768
772
|
this.logMethodStart("applyItemRulePrefill");
|
|
769
773
|
await this.applyPrefillByItemRule();
|
|
770
774
|
await this.refreshItemRuleQuantityLimits();
|
|
@@ -950,7 +954,7 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
950
954
|
// 通过 resource_id + 店铺配置
|
|
951
955
|
// hasOrderId 表示 url 上是否有 orderid,如果是的话,后续的流程会走加单
|
|
952
956
|
async checkResourceAvailable(resourceId, hasOrderId) {
|
|
953
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
957
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
954
958
|
this.logMethodStart("checkResourceAvailable", {
|
|
955
959
|
resourceId
|
|
956
960
|
});
|
|
@@ -1063,8 +1067,23 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1063
1067
|
if (tempOrder.order_id) {
|
|
1064
1068
|
await ((_g = this.store.order) == null ? void 0 : _g.getOrderInfoByRemote(tempOrder.order_id));
|
|
1065
1069
|
}
|
|
1066
|
-
|
|
1067
|
-
|
|
1070
|
+
const lastOrderInfo = (_i = (_h = this.store.order) == null ? void 0 : _h.getLastOrderInfo) == null ? void 0 : _i.call(_h);
|
|
1071
|
+
const historicalItems = hasOrderId && Array.isArray(lastOrderInfo == null ? void 0 : lastOrderInfo.products) ? lastOrderInfo.products.reduce((acc, p) => {
|
|
1072
|
+
if (typeof (p == null ? void 0 : p.product_id) !== "number")
|
|
1073
|
+
return acc;
|
|
1074
|
+
acc.push({
|
|
1075
|
+
product_id: p.product_id,
|
|
1076
|
+
quantity: Number(p.product_quantity) || 0,
|
|
1077
|
+
...typeof p.product_variant_id === "number" ? { product_variant_id: p.product_variant_id } : {}
|
|
1078
|
+
});
|
|
1079
|
+
return acc;
|
|
1080
|
+
}, []) : [];
|
|
1081
|
+
await this.setItemRuleRuntimeConfig({
|
|
1082
|
+
pax: { total: 2, adult: 2, child: 0 },
|
|
1083
|
+
serviceType: "dine-in",
|
|
1084
|
+
submissionIndex: hasOrderId ? 1 : 0,
|
|
1085
|
+
historicalItems
|
|
1086
|
+
});
|
|
1068
1087
|
this.logMethodSuccess("checkResourceAvailable", {
|
|
1069
1088
|
resourceId,
|
|
1070
1089
|
mode: availabilityInfo.mode,
|
|
@@ -59,6 +59,7 @@ export declare function resolveSkuMatchedQuantityLimits(params: {
|
|
|
59
59
|
export declare function aggregateItemRuleLimit(matchedLimits: QuantityLimitResult[]): {
|
|
60
60
|
min: number | undefined;
|
|
61
61
|
max: number | undefined;
|
|
62
|
+
remainingMax: number | undefined;
|
|
62
63
|
exact: number | undefined;
|
|
63
64
|
mustInclude: boolean;
|
|
64
65
|
} | null;
|
|
@@ -195,6 +195,7 @@ function aggregateItemRuleLimit(matchedLimits) {
|
|
|
195
195
|
return null;
|
|
196
196
|
let min;
|
|
197
197
|
let max;
|
|
198
|
+
let remainingMax;
|
|
198
199
|
let exact;
|
|
199
200
|
let mustInclude = false;
|
|
200
201
|
for (const limit of matchedLimits) {
|
|
@@ -204,6 +205,9 @@ function aggregateItemRuleLimit(matchedLimits) {
|
|
|
204
205
|
if (typeof limit.requiredMax === "number" && Number.isFinite(limit.requiredMax)) {
|
|
205
206
|
max = max === void 0 ? limit.requiredMax : Math.min(max, limit.requiredMax);
|
|
206
207
|
}
|
|
208
|
+
if (typeof limit.remainingMax === "number" && Number.isFinite(limit.remainingMax)) {
|
|
209
|
+
remainingMax = remainingMax === void 0 ? limit.remainingMax : Math.min(remainingMax, limit.remainingMax);
|
|
210
|
+
}
|
|
207
211
|
if (typeof limit.requiredExact === "number" && Number.isFinite(limit.requiredExact)) {
|
|
208
212
|
exact = limit.requiredExact;
|
|
209
213
|
}
|
|
@@ -216,6 +220,7 @@ function aggregateItemRuleLimit(matchedLimits) {
|
|
|
216
220
|
return {
|
|
217
221
|
min,
|
|
218
222
|
max,
|
|
223
|
+
remainingMax,
|
|
219
224
|
exact,
|
|
220
225
|
mustInclude
|
|
221
226
|
};
|
|
@@ -25,6 +25,7 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
|
|
|
25
25
|
private cacheId;
|
|
26
26
|
private window;
|
|
27
27
|
private request;
|
|
28
|
+
private baseSlotConfig;
|
|
28
29
|
private itemRuleEvaluator;
|
|
29
30
|
private itemRuleConfigs;
|
|
30
31
|
private itemRuleConfigsPromise;
|
|
@@ -80,6 +81,9 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
|
|
|
80
81
|
startDate: string;
|
|
81
82
|
endDate: string;
|
|
82
83
|
}): Promise<void>;
|
|
84
|
+
private getOperatingHoursScheduleIds;
|
|
85
|
+
private resolveSlotConfigForDate;
|
|
86
|
+
private syncOperatingHoursToSlotConfig;
|
|
83
87
|
getDateRangeSummary(params: {
|
|
84
88
|
startDate: string;
|
|
85
89
|
endDate: string;
|
|
@@ -40,6 +40,7 @@ var import_types2 = require("../BookingByStep/types");
|
|
|
40
40
|
var import_ProductList = require("../../modules/ProductList");
|
|
41
41
|
var import_Date = require("../../modules/Date");
|
|
42
42
|
var import_Schedule = require("../../modules/Schedule");
|
|
43
|
+
var import_utils2 = require("../../modules/Schedule/utils");
|
|
43
44
|
var import_Quotation = require("../../modules/Quotation");
|
|
44
45
|
var import_OpenData = require("../../modules/OpenData");
|
|
45
46
|
var import_types3 = require("../../modules/Account/types");
|
|
@@ -49,7 +50,7 @@ var import_resource = require("./utils/resource");
|
|
|
49
50
|
var import_timeSlot = require("./utils/timeSlot");
|
|
50
51
|
var import_dateSummary = require("./utils/dateSummary");
|
|
51
52
|
var import_slotMerge = require("./utils/slotMerge");
|
|
52
|
-
var
|
|
53
|
+
var import_utils3 = require("../../modules/Order/utils");
|
|
53
54
|
var import_Order = require("../../modules/Order");
|
|
54
55
|
var import_types4 = require("../RegisterAndLogin/types");
|
|
55
56
|
var import_decimal = __toESM(require("decimal.js"));
|
|
@@ -96,6 +97,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
96
97
|
}
|
|
97
98
|
};
|
|
98
99
|
this.otherParams = {};
|
|
100
|
+
this.baseSlotConfig = { ...import_types.DEFAULT_SLOT_CONFIG };
|
|
99
101
|
this.itemRuleEvaluator = new import_itemRule.ItemRuleEvaluator();
|
|
100
102
|
this.itemRuleConfigs = [];
|
|
101
103
|
this.itemRuleConfigsPromise = null;
|
|
@@ -301,10 +303,11 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
301
303
|
this.store.status = "initializing";
|
|
302
304
|
this.store.error = null;
|
|
303
305
|
this.store.rawResourceData = [];
|
|
304
|
-
this.
|
|
306
|
+
this.baseSlotConfig = {
|
|
305
307
|
...import_types.DEFAULT_SLOT_CONFIG,
|
|
306
308
|
...((_b = options.otherParams) == null ? void 0 : _b.slotConfig) || {}
|
|
307
309
|
};
|
|
310
|
+
this.store.slotConfig = { ...this.baseSlotConfig };
|
|
308
311
|
this.otherParams = options.otherParams || {};
|
|
309
312
|
this.cacheId = (_c = this.otherParams) == null ? void 0 : _c.cacheId;
|
|
310
313
|
this.itemRuleRuntimeConfig = ((_d = this.otherParams) == null ? void 0 : _d.venueBookingItemRule) || ((_e = this.otherParams) == null ? void 0 : _e.itemRule) || {};
|
|
@@ -645,27 +648,87 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
645
648
|
}
|
|
646
649
|
}
|
|
647
650
|
// ─── 日期概览 & 时间槽矩阵(纯计算,不发请求) ───
|
|
651
|
+
getOperatingHoursScheduleIds() {
|
|
652
|
+
var _a, _b;
|
|
653
|
+
const openData = this.otherParams.openData || ((_b = (_a = this.store.openData) == null ? void 0 : _a.getOpenData) == null ? void 0 : _b.call(_a)) || null;
|
|
654
|
+
const rawIds = openData == null ? void 0 : openData["availability.operating_hours"];
|
|
655
|
+
if (!Array.isArray(rawIds))
|
|
656
|
+
return [];
|
|
657
|
+
return [...new Set(
|
|
658
|
+
rawIds.map((id) => Number(id)).filter((id) => Number.isFinite(id) && id > 0).map((id) => Math.floor(id))
|
|
659
|
+
)];
|
|
660
|
+
}
|
|
661
|
+
resolveSlotConfigForDate(date) {
|
|
662
|
+
var _a;
|
|
663
|
+
const nextSlotConfig = { ...this.baseSlotConfig };
|
|
664
|
+
if (!date || !this.store.schedule)
|
|
665
|
+
return nextSlotConfig;
|
|
666
|
+
const operatingHoursScheduleIds = this.getOperatingHoursScheduleIds();
|
|
667
|
+
if (!operatingHoursScheduleIds.length)
|
|
668
|
+
return nextSlotConfig;
|
|
669
|
+
const scheduleList = this.store.schedule.getScheduleListByIds(
|
|
670
|
+
operatingHoursScheduleIds
|
|
671
|
+
);
|
|
672
|
+
if (!scheduleList.length)
|
|
673
|
+
return nextSlotConfig;
|
|
674
|
+
const timeRangeMap = (0, import_utils2.calcMinTimeMaxTimeBySchedules)(
|
|
675
|
+
scheduleList,
|
|
676
|
+
void 0,
|
|
677
|
+
date
|
|
678
|
+
);
|
|
679
|
+
let earliestStart = null;
|
|
680
|
+
let latestEnd = null;
|
|
681
|
+
for (const schedule of scheduleList) {
|
|
682
|
+
const dateRangeList = ((_a = timeRangeMap == null ? void 0 : timeRangeMap[schedule.id]) == null ? void 0 : _a.dateRangeFormat) || [];
|
|
683
|
+
for (const range of dateRangeList) {
|
|
684
|
+
const start = (0, import_dayjs.default)(range == null ? void 0 : range.start);
|
|
685
|
+
const end = (0, import_dayjs.default)(range == null ? void 0 : range.end);
|
|
686
|
+
if (!start.isValid() || !end.isValid())
|
|
687
|
+
continue;
|
|
688
|
+
if (!earliestStart || start.isBefore(earliestStart)) {
|
|
689
|
+
earliestStart = start;
|
|
690
|
+
}
|
|
691
|
+
if (!latestEnd || end.isAfter(latestEnd)) {
|
|
692
|
+
latestEnd = end;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
if (!earliestStart || !latestEnd)
|
|
697
|
+
return nextSlotConfig;
|
|
698
|
+
return {
|
|
699
|
+
...nextSlotConfig,
|
|
700
|
+
businessStartTime: earliestStart.format("HH:mm"),
|
|
701
|
+
businessEndTime: latestEnd.format("HH:mm")
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
syncOperatingHoursToSlotConfig(date) {
|
|
705
|
+
const resolvedSlotConfig = this.resolveSlotConfigForDate(date);
|
|
706
|
+
this.store.slotConfig = resolvedSlotConfig;
|
|
707
|
+
return resolvedSlotConfig;
|
|
708
|
+
}
|
|
648
709
|
getDateRangeSummary(params) {
|
|
649
710
|
return (0, import_dateSummary.buildDateRangeSummary)({
|
|
650
711
|
startDate: params.startDate,
|
|
651
712
|
endDate: params.endDate,
|
|
652
|
-
config: this.
|
|
713
|
+
config: this.baseSlotConfig,
|
|
653
714
|
rawResources: this.store.rawResourceData,
|
|
654
715
|
resourceProductMap: this.resourceProductMap,
|
|
655
|
-
quotationModule: this.store.quotation
|
|
716
|
+
quotationModule: this.store.quotation,
|
|
717
|
+
resolveConfig: (date) => this.resolveSlotConfigForDate(date)
|
|
656
718
|
});
|
|
657
719
|
}
|
|
658
720
|
getTimeSlotGrid(date) {
|
|
721
|
+
const resolvedSlotConfig = this.syncOperatingHoursToSlotConfig(date);
|
|
659
722
|
let quotationPriceMap;
|
|
660
723
|
if (this.store.quotation) {
|
|
661
724
|
const productIds = [...new Set([...this.resourceProductMap.values()].map((m) => m.productId))];
|
|
662
|
-
const timeLabels = (0, import_timeSlot.generateTimeLabels)(
|
|
725
|
+
const timeLabels = (0, import_timeSlot.generateTimeLabels)(resolvedSlotConfig);
|
|
663
726
|
const timePoints = timeLabels.map((label) => `${date} ${label}`);
|
|
664
727
|
quotationPriceMap = this.store.quotation.buildProductPriceMap({ productIds, timePoints });
|
|
665
728
|
}
|
|
666
729
|
return (0, import_timeSlot.buildTimeSlotGrid)({
|
|
667
730
|
date,
|
|
668
|
-
config:
|
|
731
|
+
config: resolvedSlotConfig,
|
|
669
732
|
rawResources: this.store.rawResourceData,
|
|
670
733
|
resourceProductMap: this.resourceProductMap,
|
|
671
734
|
quotationPriceMap
|
|
@@ -800,7 +863,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
800
863
|
for (let i = 0; i < merged.length; i++) {
|
|
801
864
|
const group = merged[i];
|
|
802
865
|
const identityKey = (0, import_slotMerge.buildVenueIdentityKey)(resourceId, i);
|
|
803
|
-
const bookingUuid = (0,
|
|
866
|
+
const bookingUuid = (0, import_utils3.createUuidV4)();
|
|
804
867
|
const startMoment = (0, import_dayjs.default)(group.startTime, "YYYY-MM-DD HH:mm");
|
|
805
868
|
const endMoment = (0, import_dayjs.default)(group.endTime, "YYYY-MM-DD HH:mm");
|
|
806
869
|
const duration = endMoment.diff(startMoment, "minute");
|
|
@@ -892,10 +955,13 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
892
955
|
}
|
|
893
956
|
// ─── 配置 ───
|
|
894
957
|
setSlotConfig(config) {
|
|
895
|
-
this.
|
|
896
|
-
...this.
|
|
958
|
+
this.baseSlotConfig = {
|
|
959
|
+
...this.baseSlotConfig,
|
|
897
960
|
...config
|
|
898
961
|
};
|
|
962
|
+
this.store.slotConfig = {
|
|
963
|
+
...this.baseSlotConfig
|
|
964
|
+
};
|
|
899
965
|
}
|
|
900
966
|
getSlotConfig() {
|
|
901
967
|
return { ...this.store.slotConfig };
|
|
@@ -7,4 +7,5 @@ export declare function buildDateRangeSummary(params: {
|
|
|
7
7
|
rawResources: VenueResourceRawData[];
|
|
8
8
|
resourceProductMap: Map<number | string, ResourceProductMapping>;
|
|
9
9
|
quotationModule?: QuotationModule;
|
|
10
|
+
resolveConfig?: (date: string) => VenueBookingSlotConfig;
|
|
10
11
|
}): VenueDateSummaryItem[];
|
|
@@ -35,22 +35,31 @@ module.exports = __toCommonJS(dateSummary_exports);
|
|
|
35
35
|
var import_dayjs = __toESM(require("dayjs"));
|
|
36
36
|
var import_timeSlot = require("./timeSlot");
|
|
37
37
|
function buildDateRangeSummary(params) {
|
|
38
|
-
const {
|
|
38
|
+
const {
|
|
39
|
+
startDate,
|
|
40
|
+
endDate,
|
|
41
|
+
config,
|
|
42
|
+
rawResources,
|
|
43
|
+
resourceProductMap,
|
|
44
|
+
quotationModule,
|
|
45
|
+
resolveConfig
|
|
46
|
+
} = params;
|
|
39
47
|
const result = [];
|
|
40
48
|
const productIds = quotationModule ? [...new Set([...resourceProductMap.values()].map((m) => m.productId))] : [];
|
|
41
49
|
let cursor = (0, import_dayjs.default)(startDate);
|
|
42
50
|
const end = (0, import_dayjs.default)(endDate);
|
|
43
51
|
while (!cursor.isAfter(end)) {
|
|
44
52
|
const date = cursor.format("YYYY-MM-DD");
|
|
53
|
+
const effectiveConfig = (resolveConfig == null ? void 0 : resolveConfig(date)) || config;
|
|
45
54
|
let quotationPriceMap;
|
|
46
55
|
if (quotationModule && productIds.length) {
|
|
47
|
-
const timeLabels = (0, import_timeSlot.generateTimeLabels)(
|
|
56
|
+
const timeLabels = (0, import_timeSlot.generateTimeLabels)(effectiveConfig);
|
|
48
57
|
const timePoints = timeLabels.map((label) => `${date} ${label}`);
|
|
49
58
|
quotationPriceMap = quotationModule.buildProductPriceMap({ productIds, timePoints });
|
|
50
59
|
}
|
|
51
60
|
const grid = (0, import_timeSlot.buildTimeSlotGrid)({
|
|
52
61
|
date,
|
|
53
|
-
config,
|
|
62
|
+
config: effectiveConfig,
|
|
54
63
|
rawResources,
|
|
55
64
|
resourceProductMap,
|
|
56
65
|
quotationPriceMap
|
|
@@ -79,7 +88,7 @@ function buildDateRangeSummary(params) {
|
|
|
79
88
|
status = "unavailable";
|
|
80
89
|
} else if (availableSlots === 0) {
|
|
81
90
|
status = "sold_out";
|
|
82
|
-
} else if ((totalSlots - availableSlots) / totalSlots >=
|
|
91
|
+
} else if ((totalSlots - availableSlots) / totalSlots >= effectiveConfig.fewLeftThreshold) {
|
|
83
92
|
status = "few_left";
|
|
84
93
|
} else {
|
|
85
94
|
status = "available";
|