@pisell/pisellos 0.0.557 → 0.0.558
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/model/strategy/adapter/dataVariant/adapter.d.ts +49 -0
- package/dist/model/strategy/adapter/dataVariant/adapter.js +152 -0
- package/dist/model/strategy/adapter/dataVariant/evaluator.d.ts +87 -0
- package/dist/model/strategy/adapter/dataVariant/evaluator.js +755 -0
- package/dist/model/strategy/adapter/dataVariant/examples.d.ts +39 -0
- package/dist/model/strategy/adapter/dataVariant/examples.js +277 -0
- package/dist/model/strategy/adapter/dataVariant/index.d.ts +4 -0
- package/dist/model/strategy/adapter/dataVariant/index.js +4 -0
- package/dist/model/strategy/adapter/dataVariant/type.d.ts +146 -0
- package/dist/model/strategy/adapter/dataVariant/type.js +54 -0
- package/dist/model/strategy/adapter/index.d.ts +4 -0
- package/dist/model/strategy/adapter/index.js +5 -1
- package/dist/modules/Product/index.d.ts +1 -1
- package/dist/modules/ProductList/index.d.ts +2 -1
- package/dist/modules/ProductList/index.js +21 -11
- package/dist/solution/BookingByStep/index.d.ts +2 -2
- package/dist/solution/BookingTicket/index.d.ts +1 -1
- package/dist/solution/ScanOrder/index.d.ts +1 -1
- package/dist/solution/ScanOrder/index.js +33 -32
- package/dist/solution/VenueBooking/index.d.ts +22 -3
- package/dist/solution/VenueBooking/index.js +259 -166
- package/dist/solution/VenueBooking/utils/dateSummary.d.ts +2 -2
- package/dist/solution/VenueBooking/utils/dateSummary.js +12 -25
- package/dist/solution/VenueBooking/utils/slotMerge.d.ts +0 -6
- package/dist/solution/VenueBooking/utils/slotMerge.js +3 -9
- package/dist/solution/VenueBooking/utils/smartPricing.d.ts +69 -0
- package/dist/solution/VenueBooking/utils/smartPricing.js +233 -0
- package/dist/solution/VenueBooking/utils/timeSlot.d.ts +2 -0
- package/dist/solution/VenueBooking/utils/timeSlot.js +9 -4
- package/lib/index.d.ts +1 -0
- package/lib/index.js +3 -0
- package/lib/model/strategy/adapter/dataVariant/adapter.d.ts +49 -0
- package/lib/model/strategy/adapter/dataVariant/adapter.js +139 -0
- package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +87 -0
- package/lib/model/strategy/adapter/dataVariant/evaluator.js +564 -0
- package/lib/model/strategy/adapter/dataVariant/examples.d.ts +39 -0
- package/lib/model/strategy/adapter/dataVariant/examples.js +293 -0
- package/lib/model/strategy/adapter/dataVariant/index.d.ts +4 -0
- package/lib/model/strategy/adapter/dataVariant/index.js +38 -0
- package/lib/model/strategy/adapter/dataVariant/type.d.ts +146 -0
- package/lib/model/strategy/adapter/dataVariant/type.js +31 -0
- package/lib/model/strategy/adapter/index.d.ts +4 -0
- package/lib/model/strategy/adapter/index.js +13 -2
- package/lib/model/strategy/adapter/promotion/index.js +49 -0
- package/lib/modules/Product/index.d.ts +1 -1
- package/lib/modules/ProductList/index.d.ts +2 -1
- package/lib/modules/ProductList/index.js +45 -40
- package/lib/solution/BookingByStep/index.d.ts +2 -2
- package/lib/solution/BookingTicket/index.d.ts +1 -1
- package/lib/solution/ScanOrder/index.d.ts +1 -1
- package/lib/solution/ScanOrder/index.js +2 -1
- package/lib/solution/VenueBooking/index.d.ts +22 -3
- package/lib/solution/VenueBooking/index.js +151 -63
- package/lib/solution/VenueBooking/utils/dateSummary.d.ts +2 -2
- package/lib/solution/VenueBooking/utils/dateSummary.js +5 -10
- package/lib/solution/VenueBooking/utils/slotMerge.d.ts +0 -6
- package/lib/solution/VenueBooking/utils/slotMerge.js +3 -4
- package/lib/solution/VenueBooking/utils/smartPricing.d.ts +69 -0
- package/lib/solution/VenueBooking/utils/smartPricing.js +180 -0
- package/lib/solution/VenueBooking/utils/timeSlot.d.ts +2 -0
- package/lib/solution/VenueBooking/utils/timeSlot.js +7 -3
- package/package.json +1 -1
|
@@ -59,7 +59,8 @@ var ProductList = class extends import_BaseModule.BaseModule {
|
|
|
59
59
|
schedule_datetime,
|
|
60
60
|
schedule_date,
|
|
61
61
|
cacheId,
|
|
62
|
-
with_schedule
|
|
62
|
+
with_schedule,
|
|
63
|
+
with_extra = []
|
|
63
64
|
}, options) {
|
|
64
65
|
var _a;
|
|
65
66
|
let userPlugin = this.core.getPlugin("user");
|
|
@@ -69,45 +70,49 @@ var ProductList = class extends import_BaseModule.BaseModule {
|
|
|
69
70
|
} catch (error) {
|
|
70
71
|
console.error(error);
|
|
71
72
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
73
|
+
try {
|
|
74
|
+
const productsData = await this.request.post(
|
|
75
|
+
`/product/query`,
|
|
76
|
+
{
|
|
77
|
+
open_quotation: 1,
|
|
78
|
+
open_bundle: 0,
|
|
79
|
+
exclude_extension_type: [
|
|
80
|
+
"product_party",
|
|
81
|
+
"product_event",
|
|
82
|
+
"product_series_event",
|
|
83
|
+
"product_package_ticket",
|
|
84
|
+
"ticket",
|
|
85
|
+
"event_item"
|
|
86
|
+
],
|
|
87
|
+
with: ["category", "collection", "resourceRelation", ...with_extra],
|
|
88
|
+
status: "published",
|
|
89
|
+
num: 500,
|
|
90
|
+
skip: 1,
|
|
91
|
+
customer_id,
|
|
92
|
+
category_ids,
|
|
93
|
+
ids: product_ids,
|
|
94
|
+
collection,
|
|
95
|
+
front_end_cache_id: cacheId,
|
|
96
|
+
menu_list_ids,
|
|
97
|
+
with_count,
|
|
98
|
+
// client_schedule_ids: schedule_ids,
|
|
99
|
+
schedule_date,
|
|
100
|
+
schedule_datetime,
|
|
101
|
+
// application_code: this.otherParams?.channel === 'online_store' ? 'online-store' : this.otherParams?.channel,
|
|
102
|
+
application_code: "online-store",
|
|
103
|
+
with_schedule,
|
|
104
|
+
is_eject: 1,
|
|
105
|
+
open_deposit: 1
|
|
106
|
+
},
|
|
107
|
+
{ osServer: true, callback: options == null ? void 0 : options.callback, subscriberId: options == null ? void 0 : options.subscriberId, useCache: true, customToast: () => {
|
|
108
|
+
} }
|
|
109
|
+
);
|
|
110
|
+
const sortedList = (productsData.data.list || []).slice().sort((a, b) => Number(b.sort) - Number(a.sort));
|
|
111
|
+
this.addProduct(sortedList);
|
|
112
|
+
return sortedList;
|
|
113
|
+
} catch (error) {
|
|
114
|
+
return error;
|
|
115
|
+
}
|
|
111
116
|
}
|
|
112
117
|
async loadProductsPrice({
|
|
113
118
|
ids = [],
|
|
@@ -326,7 +326,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
326
326
|
date: string;
|
|
327
327
|
status: string;
|
|
328
328
|
week: string;
|
|
329
|
-
weekNum: 0 | 2 | 1 | 3 |
|
|
329
|
+
weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
|
|
330
330
|
}[]>;
|
|
331
331
|
submitTimeSlot(timeSlots: TimeSliceItem): void;
|
|
332
332
|
private getScheduleDataByIds;
|
|
@@ -373,7 +373,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
373
373
|
};
|
|
374
374
|
setOtherData(key: string, value: any): void;
|
|
375
375
|
getOtherData(key: string): any;
|
|
376
|
-
getProductTypeById(id: number): Promise<"
|
|
376
|
+
getProductTypeById(id: number): Promise<"duration" | "session" | "normal">;
|
|
377
377
|
/**
|
|
378
378
|
* 提供给 UI 的方法,减轻 UI 层的计算压力,UI 层只需要传递 cartItemId 和 resourceCode 即返回对应的 renderList
|
|
379
379
|
*
|
|
@@ -131,7 +131,7 @@ export declare class BookingTicketImpl extends BaseModule implements Module {
|
|
|
131
131
|
* 获取当前的客户搜索条件
|
|
132
132
|
* @returns 当前搜索条件
|
|
133
133
|
*/
|
|
134
|
-
getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "
|
|
134
|
+
getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "num" | "skip">;
|
|
135
135
|
/**
|
|
136
136
|
* 获取客户列表状态(包含滚动加载相关状态)
|
|
137
137
|
* @returns 客户状态
|
|
@@ -72,7 +72,7 @@ export declare class ScanOrderImpl extends BaseModule implements Module {
|
|
|
72
72
|
getTempOrder(): ScanOrderTempOrder | null;
|
|
73
73
|
updateTempOrderNote(note: string): string;
|
|
74
74
|
setPickupReferenceMode(mode: 'counter_pickup' | 'table_service'): {
|
|
75
|
-
service_type: 'dine_in';
|
|
75
|
+
service_type: 'dine_in' | '';
|
|
76
76
|
pickup_reference_mode: 'counter_pickup' | 'table_service';
|
|
77
77
|
};
|
|
78
78
|
setPickupRef(buzzer: string): string;
|
|
@@ -553,6 +553,7 @@ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
553
553
|
// 存储 UI 层选择的取餐方式到 tempOrder.metadata.shop_service_data
|
|
554
554
|
// service_type 在扫码点餐场景固定为 dine_in
|
|
555
555
|
setPickupReferenceMode(mode) {
|
|
556
|
+
var _a;
|
|
556
557
|
this.logMethodStart("setPickupReferenceMode", { mode });
|
|
557
558
|
try {
|
|
558
559
|
if (!this.store.order)
|
|
@@ -562,7 +563,7 @@ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
562
563
|
...tempOrder.metadata || {},
|
|
563
564
|
shop_service_data: {
|
|
564
565
|
...(tempOrder.metadata || {}).shop_service_data || {},
|
|
565
|
-
service_type: "dine_in",
|
|
566
|
+
service_type: ((_a = this.otherParams) == null ? void 0 : _a.businessCode) === "dine_in" ? "dine_in" : "",
|
|
566
567
|
pickup_reference_mode: mode
|
|
567
568
|
}
|
|
568
569
|
};
|
|
@@ -3,6 +3,7 @@ import { BaseModule } from '../../modules/BaseModule';
|
|
|
3
3
|
import { VenueBookingAddLogParams, VenueBookingSlotConfig, VenueDateSummaryItem, VenueSlotSelection, VenueTimeSlotGrid } from './types';
|
|
4
4
|
import type { ScanOrderOrderProduct, ScanOrderOrderProductIdentity } from '../ScanOrder/types';
|
|
5
5
|
import type { UpdateProductInOrderParams } from '../../modules/Order/types';
|
|
6
|
+
import type { ScheduleItem } from '../../modules/Schedule/types';
|
|
6
7
|
import type { OpenDataAvailabilityResult } from '../../modules/OpenData';
|
|
7
8
|
import type { ProductData } from '../../modules/Product/types';
|
|
8
9
|
import { type CartItemSummary, type PaxInfo, type QuantityCheckResult, type QuantityLimitResult } from '../../model/strategy/adapter/itemRule';
|
|
@@ -41,6 +42,10 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
|
|
|
41
42
|
private productsLoaded;
|
|
42
43
|
private loadOpenDataConfigInFlight;
|
|
43
44
|
private static readonly OPEN_DATA_CACHE_TTL;
|
|
45
|
+
/** 按日期缓存 slot 智能定价 Map,避免同周重复 resolveProducts */
|
|
46
|
+
private slotPriceMapCache;
|
|
47
|
+
/** loadProducts 后缓存的全量商品(venue + addon),供分段算价复用 */
|
|
48
|
+
private smartPricingProductCatalog;
|
|
44
49
|
private getLoggerContext;
|
|
45
50
|
private safeStringify;
|
|
46
51
|
private pickErrorMessage;
|
|
@@ -75,6 +80,21 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
|
|
|
75
80
|
passed: boolean | null;
|
|
76
81
|
failures: QuantityCheckResult[];
|
|
77
82
|
};
|
|
83
|
+
/** 清除 slot 价格分段缓存(商品重载 / 登录后 customerId 变化时调用) */
|
|
84
|
+
private clearSlotPriceMapCache;
|
|
85
|
+
/** 读取当前登录 customerId */
|
|
86
|
+
private resolveCustomerIdForSmartPricing;
|
|
87
|
+
/** 读取 schedule 全量列表,供智能定价 schedule_match 使用 */
|
|
88
|
+
private getScheduleListForSmartPricing;
|
|
89
|
+
/** 构建智能定价上下文,对齐 OS Server buildProductFormatterContext */
|
|
90
|
+
private buildSmartPricingContext;
|
|
91
|
+
/** venue + addon 全量商品,供智能定价评估 */
|
|
92
|
+
private getAllProductsForSmartPricing;
|
|
93
|
+
private getSlotPriceMapCacheKey;
|
|
94
|
+
/**
|
|
95
|
+
* 按 schedule 分段构建 slot 价格 Map,带实例级缓存。
|
|
96
|
+
*/
|
|
97
|
+
private buildSlotPriceMapForDate;
|
|
78
98
|
loadAllProducts(): Promise<{
|
|
79
99
|
venueProducts: ProductData[];
|
|
80
100
|
addonProducts: ProductData[];
|
|
@@ -147,8 +167,7 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
|
|
|
147
167
|
setSlotConfig(config: Partial<VenueBookingSlotConfig>): void;
|
|
148
168
|
getSlotConfig(): VenueBookingSlotConfig;
|
|
149
169
|
loadSchedules(): Promise<void>;
|
|
150
|
-
|
|
151
|
-
getScheduleListByIds(ids: number[]): import("../../server").ScheduleItem[];
|
|
170
|
+
getScheduleListByIds(ids: number[]): ScheduleItem[];
|
|
152
171
|
getTempOrder(): import("./types").ScanOrderTempOrder | null;
|
|
153
172
|
updateTempOrderNote(note: string): string;
|
|
154
173
|
updateTempOrderContactsInfo(contactsInfo: any[]): any[];
|
|
@@ -156,7 +175,7 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
|
|
|
156
175
|
onCustomerLogin(params: {
|
|
157
176
|
customerId: number;
|
|
158
177
|
}): Promise<void>;
|
|
159
|
-
private
|
|
178
|
+
private recalculateOrderPricesFromSmartPricing;
|
|
160
179
|
scanCode(code: string, customerId?: number): Promise<{
|
|
161
180
|
isAvailable: boolean;
|
|
162
181
|
discountList: import("../../modules/Discount").Discount[];
|
|
@@ -50,6 +50,7 @@ var import_resource = require("./utils/resource");
|
|
|
50
50
|
var import_timeSlot = require("./utils/timeSlot");
|
|
51
51
|
var import_dateSummary = require("./utils/dateSummary");
|
|
52
52
|
var import_slotMerge = require("./utils/slotMerge");
|
|
53
|
+
var import_smartPricing = require("./utils/smartPricing");
|
|
53
54
|
var import_utils3 = require("../../modules/Order/utils");
|
|
54
55
|
var import_Order = require("../../modules/Order");
|
|
55
56
|
var import_types4 = require("../RegisterAndLogin/types");
|
|
@@ -112,6 +113,10 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
112
113
|
this.loadAllProductsInFlight = null;
|
|
113
114
|
this.productsLoaded = false;
|
|
114
115
|
this.loadOpenDataConfigInFlight = null;
|
|
116
|
+
/** 按日期缓存 slot 智能定价 Map,避免同周重复 resolveProducts */
|
|
117
|
+
this.slotPriceMapCache = /* @__PURE__ */ new Map();
|
|
118
|
+
/** loadProducts 后缓存的全量商品(venue + addon),供分段算价复用 */
|
|
119
|
+
this.smartPricingProductCatalog = [];
|
|
115
120
|
}
|
|
116
121
|
getLoggerContext() {
|
|
117
122
|
return {
|
|
@@ -337,6 +342,8 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
337
342
|
this.customerLoginRefreshIdInFlight = params.customerId;
|
|
338
343
|
const refreshTask = (async () => {
|
|
339
344
|
var _a;
|
|
345
|
+
this.clearSlotPriceMapCache();
|
|
346
|
+
this.recalculateOrderPricesFromSmartPricing();
|
|
340
347
|
if (this.store.holder) {
|
|
341
348
|
await this.store.holder.refreshAllFormRecords({
|
|
342
349
|
customer_id: params.customerId,
|
|
@@ -348,7 +355,6 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
348
355
|
channel: (_a = this.otherParams) == null ? void 0 : _a.channel
|
|
349
356
|
});
|
|
350
357
|
}
|
|
351
|
-
this.recalculateOrderPricesFromQuotation();
|
|
352
358
|
await this.store.order.loadDiscountConfig({
|
|
353
359
|
customerId: params.customerId
|
|
354
360
|
});
|
|
@@ -370,7 +376,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
370
376
|
}
|
|
371
377
|
}
|
|
372
378
|
async initialize(core, options = {}) {
|
|
373
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m
|
|
379
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
374
380
|
this.logMethodStart("initialize");
|
|
375
381
|
this.core = core;
|
|
376
382
|
this.initializeOptions = options || {};
|
|
@@ -528,10 +534,6 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
528
534
|
await this.loadRuntimeConfigs();
|
|
529
535
|
if (this.store.schedule) {
|
|
530
536
|
await this.store.schedule.loadAllSchedule();
|
|
531
|
-
this.injectScheduleResolverToQuotation();
|
|
532
|
-
(_o = this.store.quotation) == null ? void 0 : _o.loadQuotations({
|
|
533
|
-
channel: (_n = this.otherParams) == null ? void 0 : _n.channel
|
|
534
|
-
});
|
|
535
537
|
}
|
|
536
538
|
await this.refreshItemRuleQuantityLimits();
|
|
537
539
|
this.store.status = "ready";
|
|
@@ -607,6 +609,81 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
607
609
|
getCartValidation() {
|
|
608
610
|
return this.store.cartValidation || { passed: null, failures: [] };
|
|
609
611
|
}
|
|
612
|
+
/** 清除 slot 价格分段缓存(商品重载 / 登录后 customerId 变化时调用) */
|
|
613
|
+
clearSlotPriceMapCache() {
|
|
614
|
+
this.slotPriceMapCache.clear();
|
|
615
|
+
}
|
|
616
|
+
/** 读取当前登录 customerId */
|
|
617
|
+
resolveCustomerIdForSmartPricing() {
|
|
618
|
+
var _a, _b, _c;
|
|
619
|
+
try {
|
|
620
|
+
const userPlugin = (_a = this.core) == null ? void 0 : _a.getPlugin("user");
|
|
621
|
+
const customerId = Number((_c = (_b = userPlugin == null ? void 0 : userPlugin.get) == null ? void 0 : _b.call(userPlugin)) == null ? void 0 : _c.id);
|
|
622
|
+
return Number.isFinite(customerId) && customerId > 0 ? customerId : void 0;
|
|
623
|
+
} catch {
|
|
624
|
+
return void 0;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
/** 读取 schedule 全量列表,供智能定价 schedule_match 使用 */
|
|
628
|
+
getScheduleListForSmartPricing() {
|
|
629
|
+
var _a;
|
|
630
|
+
const scheduleModule = this.store.schedule;
|
|
631
|
+
const list = (_a = scheduleModule == null ? void 0 : scheduleModule.store) == null ? void 0 : _a.scheduleList;
|
|
632
|
+
return Array.isArray(list) ? list : [];
|
|
633
|
+
}
|
|
634
|
+
/** 构建智能定价上下文,对齐 OS Server buildProductFormatterContext */
|
|
635
|
+
buildSmartPricingContext(customerId) {
|
|
636
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
637
|
+
const evaluator = (_b = (_a = this.core) == null ? void 0 : _a.context) == null ? void 0 : _b.dataVariantEvaluator;
|
|
638
|
+
return {
|
|
639
|
+
evaluator,
|
|
640
|
+
scheduleList: this.getScheduleListForSmartPricing(),
|
|
641
|
+
menuList: ((_c = this.otherParams) == null ? void 0 : _c.menuList) || ((_e = (_d = this.otherParams) == null ? void 0 : _d.openData) == null ? void 0 : _e.menuList) || [],
|
|
642
|
+
customerId: customerId ?? this.resolveCustomerIdForSmartPricing(),
|
|
643
|
+
channel: (_f = this.otherParams) == null ? void 0 : _f.channel,
|
|
644
|
+
businessCode: (_g = this.otherParams) == null ? void 0 : _g.businessCode,
|
|
645
|
+
orderType: ((_h = this.otherParams) == null ? void 0 : _h.orderType) || ((_i = this.otherParams) == null ? void 0 : _i.type),
|
|
646
|
+
strategy_context: (_j = this.otherParams) == null ? void 0 : _j.strategy_context
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
/** venue + addon 全量商品,供智能定价评估 */
|
|
650
|
+
getAllProductsForSmartPricing() {
|
|
651
|
+
if (this.smartPricingProductCatalog.length) {
|
|
652
|
+
return this.smartPricingProductCatalog;
|
|
653
|
+
}
|
|
654
|
+
const venueList = this.getVenueProducts();
|
|
655
|
+
const addonList = this.getAddonProductsList();
|
|
656
|
+
return [...venueList, ...addonList];
|
|
657
|
+
}
|
|
658
|
+
getSlotPriceMapCacheKey(date, context) {
|
|
659
|
+
return [
|
|
660
|
+
date,
|
|
661
|
+
context.customerId ?? "",
|
|
662
|
+
context.channel ?? "",
|
|
663
|
+
context.businessCode ?? ""
|
|
664
|
+
].join("|");
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* 按 schedule 分段构建 slot 价格 Map,带实例级缓存。
|
|
668
|
+
*/
|
|
669
|
+
buildSlotPriceMapForDate(date, config, productIds) {
|
|
670
|
+
const context = this.buildSmartPricingContext();
|
|
671
|
+
const cacheKey = this.getSlotPriceMapCacheKey(date, context);
|
|
672
|
+
const cached = this.slotPriceMapCache.get(cacheKey);
|
|
673
|
+
if (cached)
|
|
674
|
+
return cached;
|
|
675
|
+
const timeLabels = (0, import_timeSlot.generateTimeLabels)(config);
|
|
676
|
+
const slotPriceMap = (0, import_smartPricing.buildSlotPriceMapByScheduleSegments)({
|
|
677
|
+
products: this.getAllProductsForSmartPricing(),
|
|
678
|
+
productIds,
|
|
679
|
+
date,
|
|
680
|
+
timeLabels,
|
|
681
|
+
config,
|
|
682
|
+
context
|
|
683
|
+
});
|
|
684
|
+
this.slotPriceMapCache.set(cacheKey, slotPriceMap);
|
|
685
|
+
return slotPriceMap;
|
|
686
|
+
}
|
|
610
687
|
// ─── 场地商品 & 附加商品 ───
|
|
611
688
|
async loadAllProducts() {
|
|
612
689
|
if (this.loadAllProductsInFlight)
|
|
@@ -635,9 +712,17 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
635
712
|
menu_list_ids: menuListIds,
|
|
636
713
|
cacheId: this.cacheId,
|
|
637
714
|
schedule_date: (0, import_dayjs.default)().format("YYYY-MM-DD"),
|
|
638
|
-
schedule_datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
|
|
715
|
+
schedule_datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss"),
|
|
716
|
+
with_extra: ["dataVariants"]
|
|
639
717
|
});
|
|
640
|
-
|
|
718
|
+
let list = Array.isArray(allProducts) ? allProducts : [];
|
|
719
|
+
list = (0, import_smartPricing.formatProductsWithDataVariant)(
|
|
720
|
+
list,
|
|
721
|
+
this.buildSmartPricingContext(),
|
|
722
|
+
(0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
|
|
723
|
+
);
|
|
724
|
+
this.smartPricingProductCatalog = list.slice();
|
|
725
|
+
this.clearSlotPriceMapCache();
|
|
641
726
|
const venueList = list.filter((p) => p.duration != null);
|
|
642
727
|
const addonList = list.filter((p) => p.duration == null);
|
|
643
728
|
const venueStore = (_c = this.store.venueProducts) == null ? void 0 : _c.store;
|
|
@@ -822,29 +907,24 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
822
907
|
config: this.baseSlotConfig,
|
|
823
908
|
rawResources: this.store.rawResourceData,
|
|
824
909
|
resourceProductMap: this.resourceProductMap,
|
|
825
|
-
|
|
826
|
-
|
|
910
|
+
resolveConfig: (date) => this.resolveSlotConfigForDate(date),
|
|
911
|
+
buildSlotPriceMap: (date, config, productIds) => this.buildSlotPriceMapForDate(date, config, productIds)
|
|
827
912
|
});
|
|
828
913
|
}
|
|
829
914
|
getTimeSlotGrid(date) {
|
|
830
915
|
const resolvedSlotConfig = this.syncOperatingHoursToSlotConfig(date);
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
];
|
|
838
|
-
const timeLabels = (0, import_timeSlot.generateTimeLabels)(resolvedSlotConfig);
|
|
839
|
-
const timePoints = timeLabels.map((label) => `${date} ${label}`);
|
|
840
|
-
quotationPriceMap = this.store.quotation.buildProductPriceMap({ productIds, timePoints });
|
|
841
|
-
}
|
|
916
|
+
const productIds = [
|
|
917
|
+
...new Set(
|
|
918
|
+
[...this.resourceProductMap.values()].flat().map((m) => m.productId)
|
|
919
|
+
)
|
|
920
|
+
];
|
|
921
|
+
const slotPriceMap = productIds.length ? this.buildSlotPriceMapForDate(date, resolvedSlotConfig, productIds) : void 0;
|
|
842
922
|
return (0, import_timeSlot.buildTimeSlotGrid)({
|
|
843
923
|
date,
|
|
844
924
|
config: resolvedSlotConfig,
|
|
845
925
|
rawResources: this.store.rawResourceData,
|
|
846
926
|
resourceProductMap: this.resourceProductMap,
|
|
847
|
-
|
|
927
|
+
slotPriceMap
|
|
848
928
|
});
|
|
849
929
|
}
|
|
850
930
|
// ─── 时间槽订单操作 ───
|
|
@@ -1130,8 +1210,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1130
1210
|
booking_uid: bookingUuid,
|
|
1131
1211
|
price_breakdown: (0, import_slotMerge.buildPriceBreakdown)({
|
|
1132
1212
|
group,
|
|
1133
|
-
productId: mapping.productId
|
|
1134
|
-
quotation: this.store.quotation
|
|
1213
|
+
productId: mapping.productId
|
|
1135
1214
|
})
|
|
1136
1215
|
},
|
|
1137
1216
|
_origin: {
|
|
@@ -1229,20 +1308,12 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1229
1308
|
if (!this.store.schedule)
|
|
1230
1309
|
throw new Error("schedule 模块未初始化");
|
|
1231
1310
|
await this.store.schedule.loadAllSchedule();
|
|
1232
|
-
this.injectScheduleResolverToQuotation();
|
|
1233
1311
|
this.logMethodSuccess("loadSchedules");
|
|
1234
1312
|
} catch (error) {
|
|
1235
1313
|
this.logMethodError("loadSchedules", error);
|
|
1236
1314
|
throw error;
|
|
1237
1315
|
}
|
|
1238
1316
|
}
|
|
1239
|
-
injectScheduleResolverToQuotation() {
|
|
1240
|
-
if (this.store.quotation && this.store.schedule) {
|
|
1241
|
-
this.store.quotation.setScheduleResolver(
|
|
1242
|
-
(id) => this.store.schedule.getScheduleListByIds([id])[0]
|
|
1243
|
-
);
|
|
1244
|
-
}
|
|
1245
|
-
}
|
|
1246
1317
|
getScheduleListByIds(ids) {
|
|
1247
1318
|
if (!this.store.schedule)
|
|
1248
1319
|
return [];
|
|
@@ -1281,14 +1352,16 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1281
1352
|
throw error;
|
|
1282
1353
|
}
|
|
1283
1354
|
}
|
|
1284
|
-
|
|
1355
|
+
recalculateOrderPricesFromSmartPricing() {
|
|
1285
1356
|
var _a, _b;
|
|
1286
|
-
if (!this.store.order
|
|
1357
|
+
if (!this.store.order)
|
|
1287
1358
|
return;
|
|
1288
1359
|
const tempOrder = this.store.order.getTempOrder();
|
|
1289
1360
|
if (!((_a = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _a.length))
|
|
1290
1361
|
return;
|
|
1291
1362
|
const now = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
|
|
1363
|
+
const catalog = this.getAllProductsForSmartPricing();
|
|
1364
|
+
const context = this.buildSmartPricingContext();
|
|
1292
1365
|
for (const product of tempOrder.products) {
|
|
1293
1366
|
if ((_b = product.metadata) == null ? void 0 : _b.venue_booking) {
|
|
1294
1367
|
const mappings = this.resourceProductMap.get(product.metadata.resource_id);
|
|
@@ -1301,34 +1374,49 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1301
1374
|
product,
|
|
1302
1375
|
this.store.slotConfig.slotDurationMinutes
|
|
1303
1376
|
);
|
|
1304
|
-
const
|
|
1305
|
-
...slot,
|
|
1306
|
-
|
|
1307
|
-
|
|
1377
|
+
const uniqueDates = [
|
|
1378
|
+
...new Set(slots.map((slot) => (0, import_dayjs.default)(slot.startTime).format("YYYY-MM-DD")))
|
|
1379
|
+
];
|
|
1380
|
+
const slotPriceMaps = /* @__PURE__ */ new Map();
|
|
1381
|
+
for (const slotDate of uniqueDates) {
|
|
1382
|
+
slotPriceMaps.set(
|
|
1383
|
+
slotDate,
|
|
1384
|
+
this.buildSlotPriceMapForDate(slotDate, this.store.slotConfig, [mapping.productId])
|
|
1385
|
+
);
|
|
1386
|
+
}
|
|
1387
|
+
const updatedSlots = slots.map((slot) => {
|
|
1388
|
+
const slotDate = (0, import_dayjs.default)(slot.startTime).format("YYYY-MM-DD");
|
|
1389
|
+
const slotPriceMap = slotPriceMaps.get(slotDate);
|
|
1390
|
+
return {
|
|
1391
|
+
...slot,
|
|
1308
1392
|
productId: mapping.productId,
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1393
|
+
price: slotPriceMap ? (0, import_smartPricing.getSlotPriceFromMap)({
|
|
1394
|
+
slotPriceMap,
|
|
1395
|
+
productId: mapping.productId,
|
|
1396
|
+
slotStartTime: slot.startTime,
|
|
1397
|
+
fallbackPrice: mapping.price
|
|
1398
|
+
}) : mapping.price
|
|
1399
|
+
};
|
|
1400
|
+
});
|
|
1312
1401
|
const merged = (0, import_slotMerge.mergeConsecutiveSlots)(updatedSlots);
|
|
1313
1402
|
if (merged.length === 1) {
|
|
1314
1403
|
product.selling_price = merged[0].totalPrice;
|
|
1315
1404
|
product.original_price = merged[0].totalPrice;
|
|
1316
1405
|
product.metadata.price_breakdown = (0, import_slotMerge.buildPriceBreakdown)({
|
|
1317
1406
|
group: merged[0],
|
|
1318
|
-
productId: mapping.productId
|
|
1319
|
-
quotation: this.store.quotation
|
|
1407
|
+
productId: mapping.productId
|
|
1320
1408
|
});
|
|
1321
1409
|
}
|
|
1322
1410
|
} else if (product.product_id != null) {
|
|
1323
|
-
const
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1411
|
+
const smartPrice = (0, import_smartPricing.getPriceForProductAtDatetime)({
|
|
1412
|
+
products: catalog,
|
|
1413
|
+
context,
|
|
1414
|
+
productId: Number(product.product_id),
|
|
1415
|
+
datetime: now,
|
|
1416
|
+
fallbackPrice: product.selling_price
|
|
1327
1417
|
});
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
product.original_price = quotationPrice;
|
|
1331
|
-
}
|
|
1418
|
+
product.selling_price = smartPrice;
|
|
1419
|
+
product.original_price = smartPrice;
|
|
1332
1420
|
}
|
|
1333
1421
|
}
|
|
1334
1422
|
}
|
|
@@ -1514,7 +1602,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1514
1602
|
}
|
|
1515
1603
|
}
|
|
1516
1604
|
async addProductToOrder(product) {
|
|
1517
|
-
var _a;
|
|
1605
|
+
var _a, _b;
|
|
1518
1606
|
this.logMethodStart("addProductToOrder", {
|
|
1519
1607
|
product_id: product.product_id,
|
|
1520
1608
|
product_variant_id: product.product_variant_id
|
|
@@ -1522,18 +1610,18 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1522
1610
|
try {
|
|
1523
1611
|
if (!this.store.order)
|
|
1524
1612
|
throw new Error("order 模块未初始化");
|
|
1525
|
-
if (!((_a = product.metadata) == null ? void 0 : _a.venue_booking) &&
|
|
1526
|
-
const
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1613
|
+
if (!((_a = product.metadata) == null ? void 0 : _a.venue_booking) && product.product_id != null) {
|
|
1614
|
+
const smartPrice = (0, import_smartPricing.getPriceForProductAtDatetime)({
|
|
1615
|
+
products: this.getAllProductsForSmartPricing(),
|
|
1616
|
+
context: this.buildSmartPricingContext(),
|
|
1617
|
+
productId: Number(product.product_id),
|
|
1618
|
+
datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss"),
|
|
1619
|
+
fallbackPrice: product.selling_price
|
|
1530
1620
|
});
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
product.original_price = product.selling_price;
|
|
1536
|
-
}
|
|
1621
|
+
product.selling_price = smartPrice;
|
|
1622
|
+
product.original_price = smartPrice;
|
|
1623
|
+
} else if (product.selling_price != null && !((_b = product.metadata) == null ? void 0 : _b.venue_booking)) {
|
|
1624
|
+
product.original_price = product.selling_price;
|
|
1537
1625
|
}
|
|
1538
1626
|
const products = await this.store.order.addProductToOrder(product);
|
|
1539
1627
|
await this.refreshItemRuleQuantityLimits();
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { VenueBookingSlotConfig, VenueResourceRawData, VenueDateSummaryItem, ResourceProductMapping } from '../types';
|
|
2
|
-
import type { QuotationModule } from '../../../modules/Quotation';
|
|
3
2
|
export declare function buildDateRangeSummary(params: {
|
|
4
3
|
startDate: string;
|
|
5
4
|
endDate: string;
|
|
6
5
|
config: VenueBookingSlotConfig;
|
|
7
6
|
rawResources: VenueResourceRawData[];
|
|
8
7
|
resourceProductMap: Map<number | string, ResourceProductMapping[]>;
|
|
9
|
-
quotationModule?: QuotationModule;
|
|
10
8
|
resolveConfig?: (date: string) => VenueBookingSlotConfig;
|
|
9
|
+
/** 按日期构建 slot 智能定价 Map */
|
|
10
|
+
buildSlotPriceMap?: (date: string, config: VenueBookingSlotConfig, productIds: number[]) => Map<string, string | null>;
|
|
11
11
|
}): VenueDateSummaryItem[];
|
|
@@ -41,28 +41,23 @@ function buildDateRangeSummary(params) {
|
|
|
41
41
|
config,
|
|
42
42
|
rawResources,
|
|
43
43
|
resourceProductMap,
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
resolveConfig,
|
|
45
|
+
buildSlotPriceMap
|
|
46
46
|
} = params;
|
|
47
47
|
const result = [];
|
|
48
|
-
const productIds =
|
|
48
|
+
const productIds = buildSlotPriceMap ? [...new Set([...resourceProductMap.values()].flat().map((m) => m.productId))] : [];
|
|
49
49
|
let cursor = (0, import_dayjs.default)(startDate);
|
|
50
50
|
const end = (0, import_dayjs.default)(endDate);
|
|
51
51
|
while (!cursor.isAfter(end)) {
|
|
52
52
|
const date = cursor.format("YYYY-MM-DD");
|
|
53
53
|
const effectiveConfig = (resolveConfig == null ? void 0 : resolveConfig(date)) || config;
|
|
54
|
-
|
|
55
|
-
if (quotationModule && productIds.length) {
|
|
56
|
-
const timeLabels = (0, import_timeSlot.generateTimeLabels)(effectiveConfig);
|
|
57
|
-
const timePoints = timeLabels.map((label) => `${date} ${label}`);
|
|
58
|
-
quotationPriceMap = quotationModule.buildProductPriceMap({ productIds, timePoints });
|
|
59
|
-
}
|
|
54
|
+
const slotPriceMap = buildSlotPriceMap && productIds.length ? buildSlotPriceMap(date, effectiveConfig, productIds) : void 0;
|
|
60
55
|
const grid = (0, import_timeSlot.buildTimeSlotGrid)({
|
|
61
56
|
date,
|
|
62
57
|
config: effectiveConfig,
|
|
63
58
|
rawResources,
|
|
64
59
|
resourceProductMap,
|
|
65
|
-
|
|
60
|
+
slotPriceMap
|
|
66
61
|
});
|
|
67
62
|
let totalSlots = 0;
|
|
68
63
|
let availableSlots = 0;
|
|
@@ -5,12 +5,6 @@ export declare function mergeConsecutiveSlots(slots: VenueSlotSelection[]): Merg
|
|
|
5
5
|
export declare function buildPriceBreakdown(params: {
|
|
6
6
|
group: MergedSlotGroup;
|
|
7
7
|
productId: number;
|
|
8
|
-
quotation?: {
|
|
9
|
-
getQuotationShelfId: (p: {
|
|
10
|
-
productId: number;
|
|
11
|
-
datetime: string;
|
|
12
|
-
}) => number;
|
|
13
|
-
};
|
|
14
8
|
}): PriceBreakdownEntry[];
|
|
15
9
|
export interface BuildVenueBookingParams {
|
|
16
10
|
group: MergedSlotGroup;
|
|
@@ -82,17 +82,16 @@ function mergeConsecutiveSlots(slots) {
|
|
|
82
82
|
return groups;
|
|
83
83
|
}
|
|
84
84
|
function buildPriceBreakdown(params) {
|
|
85
|
-
const { group
|
|
85
|
+
const { group } = params;
|
|
86
86
|
if (!group.slots.length)
|
|
87
87
|
return [];
|
|
88
88
|
const entries = [];
|
|
89
89
|
for (const slot of group.slots) {
|
|
90
90
|
const unitPrice = Number(slot.price || "0");
|
|
91
|
-
const shelfId = quotation ? quotation.getQuotationShelfId({ productId, datetime: slot.startTime }) : 0;
|
|
92
91
|
const startHm = (0, import_dayjs.default)(slot.startTime, "YYYY-MM-DD HH:mm").format("YYYY-MM-DD HH:mm");
|
|
93
92
|
const endHm = (0, import_dayjs.default)(slot.endTime, "YYYY-MM-DD HH:mm").format("YYYY-MM-DD HH:mm");
|
|
94
93
|
const last = entries[entries.length - 1];
|
|
95
|
-
if (last && last.unit_price === unitPrice && last.quotation_shelf_id ===
|
|
94
|
+
if (last && last.unit_price === unitPrice && last.quotation_shelf_id === 0 && last.end_time === startHm) {
|
|
96
95
|
last.end_time = endHm;
|
|
97
96
|
last.quantity += 1;
|
|
98
97
|
} else {
|
|
@@ -100,7 +99,7 @@ function buildPriceBreakdown(params) {
|
|
|
100
99
|
start_time: startHm,
|
|
101
100
|
end_time: endHm,
|
|
102
101
|
unit_price: unitPrice,
|
|
103
|
-
quotation_shelf_id:
|
|
102
|
+
quotation_shelf_id: 0,
|
|
104
103
|
quantity: 1
|
|
105
104
|
});
|
|
106
105
|
}
|