@pisell/pisellos 2.1.162 → 2.1.163

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.
Files changed (74) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.js +3 -0
  3. package/dist/model/strategy/adapter/dataVariant/adapter.d.ts +50 -0
  4. package/dist/model/strategy/adapter/dataVariant/adapter.js +167 -0
  5. package/dist/model/strategy/adapter/dataVariant/evaluator.d.ts +89 -0
  6. package/dist/model/strategy/adapter/dataVariant/evaluator.js +780 -0
  7. package/dist/model/strategy/adapter/dataVariant/examples.d.ts +39 -0
  8. package/dist/model/strategy/adapter/dataVariant/examples.js +277 -0
  9. package/dist/model/strategy/adapter/dataVariant/index.d.ts +4 -0
  10. package/dist/model/strategy/adapter/dataVariant/index.js +4 -0
  11. package/dist/model/strategy/adapter/dataVariant/type.d.ts +148 -0
  12. package/dist/model/strategy/adapter/dataVariant/type.js +54 -0
  13. package/dist/model/strategy/adapter/index.d.ts +4 -0
  14. package/dist/model/strategy/adapter/index.js +5 -1
  15. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  16. package/dist/modules/Discount/index.d.ts +5 -2
  17. package/dist/modules/Discount/index.js +21 -1
  18. package/dist/modules/Discount/types.d.ts +4 -0
  19. package/dist/modules/Order/index.d.ts +1 -0
  20. package/dist/modules/Order/index.js +18 -6
  21. package/dist/modules/Order/types.d.ts +2 -0
  22. package/dist/modules/ProductList/index.d.ts +3 -1
  23. package/dist/modules/ProductList/index.js +22 -11
  24. package/dist/modules/Schedule/getDateIsInSchedule.js +5 -0
  25. package/dist/solution/BookingByStep/index.d.ts +2 -2
  26. package/dist/solution/ScanOrder/index.js +1 -1
  27. package/dist/solution/ShopDiscount/index.js +16 -15
  28. package/dist/solution/VenueBooking/index.d.ts +23 -3
  29. package/dist/solution/VenueBooking/index.js +267 -168
  30. package/dist/solution/VenueBooking/utils/dateSummary.d.ts +2 -2
  31. package/dist/solution/VenueBooking/utils/dateSummary.js +12 -25
  32. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +0 -6
  33. package/dist/solution/VenueBooking/utils/slotMerge.js +3 -9
  34. package/dist/solution/VenueBooking/utils/smartPricing.d.ts +70 -0
  35. package/dist/solution/VenueBooking/utils/smartPricing.js +233 -0
  36. package/dist/solution/VenueBooking/utils/timeSlot.d.ts +2 -0
  37. package/dist/solution/VenueBooking/utils/timeSlot.js +9 -4
  38. package/lib/index.d.ts +1 -0
  39. package/lib/index.js +3 -0
  40. package/lib/model/strategy/adapter/dataVariant/adapter.d.ts +50 -0
  41. package/lib/model/strategy/adapter/dataVariant/adapter.js +149 -0
  42. package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +89 -0
  43. package/lib/model/strategy/adapter/dataVariant/evaluator.js +583 -0
  44. package/lib/model/strategy/adapter/dataVariant/examples.d.ts +39 -0
  45. package/lib/model/strategy/adapter/dataVariant/examples.js +293 -0
  46. package/lib/model/strategy/adapter/dataVariant/index.d.ts +4 -0
  47. package/lib/model/strategy/adapter/dataVariant/index.js +38 -0
  48. package/lib/model/strategy/adapter/dataVariant/type.d.ts +148 -0
  49. package/lib/model/strategy/adapter/dataVariant/type.js +31 -0
  50. package/lib/model/strategy/adapter/index.d.ts +4 -0
  51. package/lib/model/strategy/adapter/index.js +13 -2
  52. package/lib/modules/Discount/index.d.ts +5 -2
  53. package/lib/modules/Discount/index.js +11 -1
  54. package/lib/modules/Discount/types.d.ts +4 -0
  55. package/lib/modules/Order/index.d.ts +1 -0
  56. package/lib/modules/Order/index.js +11 -1
  57. package/lib/modules/Order/types.d.ts +2 -0
  58. package/lib/modules/ProductList/index.d.ts +3 -1
  59. package/lib/modules/ProductList/index.js +45 -39
  60. package/lib/modules/Schedule/getDateIsInSchedule.js +4 -0
  61. package/lib/solution/BookingByStep/index.d.ts +2 -2
  62. package/lib/solution/ScanOrder/index.js +1 -1
  63. package/lib/solution/ShopDiscount/index.js +3 -2
  64. package/lib/solution/VenueBooking/index.d.ts +23 -3
  65. package/lib/solution/VenueBooking/index.js +164 -69
  66. package/lib/solution/VenueBooking/utils/dateSummary.d.ts +2 -2
  67. package/lib/solution/VenueBooking/utils/dateSummary.js +5 -10
  68. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +0 -6
  69. package/lib/solution/VenueBooking/utils/slotMerge.js +3 -4
  70. package/lib/solution/VenueBooking/utils/smartPricing.d.ts +70 -0
  71. package/lib/solution/VenueBooking/utils/smartPricing.js +180 -0
  72. package/lib/solution/VenueBooking/utils/timeSlot.d.ts +2 -0
  73. package/lib/solution/VenueBooking/utils/timeSlot.js +7 -3
  74. package/package.json +1 -1
@@ -11,7 +11,7 @@ export declare class ProductList extends BaseModule implements Module {
11
11
  constructor(name?: string, version?: string);
12
12
  initialize(core: PisellCore, options: any): Promise<void>;
13
13
  storeChange(path?: string, value?: any): Promise<void>;
14
- loadProducts({ category_ids, product_ids, collection, menu_list_ids, customer_id: paramsCustomerId, with_count, schedule_datetime, schedule_date, cacheId, with_schedule, }: {
14
+ loadProducts({ category_ids, product_ids, collection, menu_list_ids, customer_id: paramsCustomerId, with_count, schedule_datetime, schedule_date, cacheId, with_schedule, with_extra, }: {
15
15
  category_ids?: number[];
16
16
  product_ids?: number[];
17
17
  collection?: number | string[];
@@ -22,6 +22,8 @@ export declare class ProductList extends BaseModule implements Module {
22
22
  menu_list_ids?: number[];
23
23
  with_count?: string[];
24
24
  with_schedule?: number;
25
+ /** 追加到默认 with 字段(如 dataVariants) */
26
+ with_extra?: string[];
25
27
  }): Promise<any>;
26
28
  loadProductsPrice({ ids, customer_id, schedule_date, channel, }: {
27
29
  ids?: number[];
@@ -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
  }) {
64
65
  var _a;
65
66
  let userPlugin = this.core.getPlugin("user");
@@ -69,44 +70,49 @@ var ProductList = class extends import_BaseModule.BaseModule {
69
70
  } catch (error) {
70
71
  console.error(error);
71
72
  }
72
- const productsData = await this.request.post(
73
- `/product/query`,
74
- {
75
- open_quotation: 1,
76
- open_bundle: 0,
77
- exclude_extension_type: [
78
- "product_party",
79
- "product_event",
80
- "product_series_event",
81
- "product_package_ticket",
82
- "ticket",
83
- "event_item"
84
- ],
85
- with: ["category", "collection", "resourceRelation"],
86
- status: "published",
87
- num: 500,
88
- skip: 1,
89
- customer_id,
90
- category_ids,
91
- ids: product_ids,
92
- collection,
93
- front_end_cache_id: cacheId,
94
- menu_list_ids,
95
- with_count,
96
- // client_schedule_ids: schedule_ids,
97
- schedule_date,
98
- // application_code: this.otherParams?.channel === 'online_store' ? 'online-store' : this.otherParams?.channel,
99
- application_code: "online-store",
100
- with_schedule,
101
- schedule_datetime,
102
- is_eject: 1
103
- },
104
- { useCache: true, customToast: () => {
105
- } }
106
- );
107
- const sortedList = (productsData.data.list || []).slice().sort((a, b) => Number(b.sort) - Number(a.sort));
108
- this.addProduct(sortedList);
109
- return sortedList;
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
+ with_count,
97
+ // client_schedule_ids: schedule_ids,
98
+ schedule_date,
99
+ schedule_datetime,
100
+ // application_code: this.otherParams?.channel === 'online_store' ? 'online-store' : this.otherParams?.channel,
101
+ application_code: "online-store",
102
+ with_schedule,
103
+ is_eject: 1,
104
+ menu_list_ids,
105
+ open_deposit: 1
106
+ },
107
+ { 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
+ }
110
116
  }
111
117
  async loadProductsPrice({
112
118
  ids = [],
@@ -34,6 +34,10 @@ __export(getDateIsInSchedule_exports, {
34
34
  });
35
35
  module.exports = __toCommonJS(getDateIsInSchedule_exports);
36
36
  var import_dayjs = __toESM(require("dayjs"));
37
+ var import_isSameOrAfter = __toESM(require("dayjs/plugin/isSameOrAfter"));
38
+ var import_isSameOrBefore = __toESM(require("dayjs/plugin/isSameOrBefore"));
39
+ import_dayjs.default.extend(import_isSameOrAfter.default);
40
+ import_dayjs.default.extend(import_isSameOrBefore.default);
37
41
  var getDateIsInSchedule = (dateTime, scheduleList) => {
38
42
  if (!dateTime || !scheduleList || scheduleList.length === 0) {
39
43
  return false;
@@ -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 | 2 | 1 | 5 | 4 | 3 | 6;
313
+ weekNum: 0 | 1 | 5 | 4 | 2 | 3 | 6;
314
314
  }[]>;
315
315
  submitTimeSlot(timeSlots: TimeSliceItem): void;
316
316
  private getScheduleDataByIds;
@@ -329,7 +329,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
329
329
  count: number;
330
330
  left: number;
331
331
  summaryCount: number;
332
- status: "lots_of_space" | "filling_up_fast" | "sold_out";
332
+ status: "sold_out" | "lots_of_space" | "filling_up_fast";
333
333
  }[];
334
334
  /**
335
335
  * 找到多个资源的公共可用时间段
@@ -563,7 +563,7 @@ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
563
563
  ...tempOrder.metadata || {},
564
564
  shop_service_data: {
565
565
  ...(tempOrder.metadata || {}).shop_service_data || {},
566
- service_type: ((_a = this.otherParams) == null ? void 0 : _a.businessCode) === "dine_in" ? "dine_in" : "take_away",
566
+ service_type: ((_a = this.otherParams) == null ? void 0 : _a.businessCode) === "dine_in" ? "dine_in" : "",
567
567
  pickup_reference_mode: mode
568
568
  }
569
569
  };
@@ -511,7 +511,7 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
511
511
  try {
512
512
  const orderId = this.store.orderId;
513
513
  const customerId = params.customerId || ((_a = this.getCustomer()) == null ? void 0 : _a.id);
514
- const goodPassList = await ((_b = this.store.discount) == null ? void 0 : _b.loadPrepareConfig({
514
+ const prepareConfig = await ((_b = this.store.discount) == null ? void 0 : _b.loadPrepareConfig({
515
515
  customer_id: customerId,
516
516
  action: orderId ? "edit" : "create",
517
517
  with_good_pass: 1,
@@ -520,11 +520,12 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
520
520
  request_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
521
521
  ...orderId ? { order_id: orderId } : {}
522
522
  }));
523
+ const goodPassList = (prepareConfig == null ? void 0 : prepareConfig.discountList) || [];
523
524
  const scanDiscount = (_c = this.getDiscountList()) == null ? void 0 : _c.filter(
524
525
  (item) => item.isScan
525
526
  );
526
527
  const scanDiscountIds = scanDiscount.map((n) => n.id);
527
- const newGoodPassList = goodPassList == null ? void 0 : goodPassList.filter((n) => !scanDiscountIds.includes(n.id));
528
+ const newGoodPassList = goodPassList.filter((n) => !scanDiscountIds.includes(n.id));
528
529
  const newDiscountList = [...scanDiscount, ...newGoodPassList || []];
529
530
  this.store.originalDiscountList = newDiscountList;
530
531
  await ((_d = this.store.discount) == null ? void 0 : _d.setOriginalDiscountList(newDiscountList));
@@ -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';
@@ -40,6 +41,10 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
40
41
  private productsLoaded;
41
42
  private loadOpenDataConfigInFlight;
42
43
  private static readonly OPEN_DATA_CACHE_TTL;
44
+ /** 按日期缓存 slot 智能定价 Map,避免同周重复 resolveProducts */
45
+ private slotPriceMapCache;
46
+ /** loadProducts 后缓存的全量商品(venue + addon),供分段算价复用 */
47
+ private smartPricingProductCatalog;
43
48
  private getLoggerContext;
44
49
  private safeStringify;
45
50
  private pickErrorMessage;
@@ -68,6 +73,22 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
68
73
  passed: boolean | null;
69
74
  failures: QuantityCheckResult[];
70
75
  };
76
+ /** 清除 slot 价格分段缓存(商品重载 / 登录后 customerId 变化时调用) */
77
+ private clearSlotPriceMapCache;
78
+ /** 读取当前登录 customerId */
79
+ private resolveCustomerIdForSmartPricing;
80
+ private resolveAvailableWalletIdsForSmartPricing;
81
+ /** 读取 schedule 全量列表,供智能定价 schedule_match 使用 */
82
+ private getScheduleListForSmartPricing;
83
+ /** 构建智能定价上下文,对齐 OS Server buildProductFormatterContext */
84
+ private buildSmartPricingContext;
85
+ /** venue + addon 全量商品,供智能定价评估 */
86
+ private getAllProductsForSmartPricing;
87
+ private getSlotPriceMapCacheKey;
88
+ /**
89
+ * 按 schedule 分段构建 slot 价格 Map,带实例级缓存。
90
+ */
91
+ private buildSlotPriceMapForDate;
71
92
  loadAllProducts(): Promise<{
72
93
  venueProducts: ProductData[];
73
94
  addonProducts: ProductData[];
@@ -140,8 +161,7 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
140
161
  setSlotConfig(config: Partial<VenueBookingSlotConfig>): void;
141
162
  getSlotConfig(): VenueBookingSlotConfig;
142
163
  loadSchedules(): Promise<void>;
143
- private injectScheduleResolverToQuotation;
144
- getScheduleListByIds(ids: number[]): import("../../modules/Schedule/types").ScheduleItem[];
164
+ getScheduleListByIds(ids: number[]): ScheduleItem[];
145
165
  getTempOrder(): import("./types").ScanOrderTempOrder | null;
146
166
  updateTempOrderNote(note: string): string;
147
167
  updateTempOrderContactsInfo(contactsInfo: any[]): any[];
@@ -149,7 +169,7 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
149
169
  onCustomerLogin(params: {
150
170
  customerId: number;
151
171
  }): Promise<void>;
152
- private recalculateOrderPricesFromQuotation;
172
+ private recalculateOrderPricesFromSmartPricing;
153
173
  scanCode(code: string, customerId?: number): Promise<{
154
174
  isAvailable: boolean;
155
175
  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");
@@ -110,6 +111,10 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
110
111
  this.loadAllProductsInFlight = null;
111
112
  this.productsLoaded = false;
112
113
  this.loadOpenDataConfigInFlight = null;
114
+ /** 按日期缓存 slot 智能定价 Map,避免同周重复 resolveProducts */
115
+ this.slotPriceMapCache = /* @__PURE__ */ new Map();
116
+ /** loadProducts 后缓存的全量商品(venue + addon),供分段算价复用 */
117
+ this.smartPricingProductCatalog = [];
113
118
  }
114
119
  getLoggerContext() {
115
120
  return {
@@ -298,16 +303,11 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
298
303
  }
299
304
  this.customerLoginRefreshIdInFlight = params.customerId;
300
305
  const refreshTask = (async () => {
301
- var _a;
302
- if (this.store.quotation) {
303
- await this.store.quotation.loadQuotations({
304
- channel: (_a = this.otherParams) == null ? void 0 : _a.channel
305
- });
306
- }
307
- this.recalculateOrderPricesFromQuotation();
308
306
  await this.store.order.loadDiscountConfig({
309
307
  customerId: params.customerId
310
308
  });
309
+ this.clearSlotPriceMapCache();
310
+ this.recalculateOrderPricesFromSmartPricing();
311
311
  await this.store.order.recalculateSummary({ createIfMissing: true });
312
312
  this.store.order.persistTempOrder();
313
313
  await this.refreshItemRuleQuantityLimits();
@@ -326,7 +326,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
326
326
  }
327
327
  }
328
328
  async initialize(core, options = {}) {
329
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
329
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
330
330
  this.logMethodStart("initialize");
331
331
  this.core = core;
332
332
  this.initializeOptions = options || {};
@@ -462,10 +462,6 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
462
462
  await this.loadRuntimeConfigs();
463
463
  if (this.store.schedule) {
464
464
  await this.store.schedule.loadAllSchedule();
465
- this.injectScheduleResolverToQuotation();
466
- (_k = this.store.quotation) == null ? void 0 : _k.loadQuotations({
467
- channel: (_j = this.otherParams) == null ? void 0 : _j.channel
468
- });
469
465
  }
470
466
  await this.refreshItemRuleQuantityLimits();
471
467
  this.store.status = "ready";
@@ -541,6 +537,93 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
541
537
  getCartValidation() {
542
538
  return this.store.cartValidation || { passed: null, failures: [] };
543
539
  }
540
+ /** 清除 slot 价格分段缓存(商品重载 / 登录后 customerId 变化时调用) */
541
+ clearSlotPriceMapCache() {
542
+ this.slotPriceMapCache.clear();
543
+ }
544
+ /** 读取当前登录 customerId */
545
+ resolveCustomerIdForSmartPricing() {
546
+ var _a, _b, _c;
547
+ try {
548
+ const userPlugin = (_a = this.core) == null ? void 0 : _a.getPlugin("user");
549
+ const customerId = Number((_c = (_b = userPlugin == null ? void 0 : userPlugin.get) == null ? void 0 : _b.call(userPlugin)) == null ? void 0 : _c.id);
550
+ return Number.isFinite(customerId) && customerId > 0 ? customerId : void 0;
551
+ } catch {
552
+ return void 0;
553
+ }
554
+ }
555
+ resolveAvailableWalletIdsForSmartPricing() {
556
+ var _a, _b, _c, _d, _e, _f, _g, _h;
557
+ const orderWalletIds = (_b = (_a = this.store.order) == null ? void 0 : _a.getAvailableWalletIds) == null ? void 0 : _b.call(_a);
558
+ const fallbackWalletIds = ((_c = this.otherParams) == null ? void 0 : _c.available_wallet_ids) || ((_d = this.otherParams) == null ? void 0 : _d.availableWalletIds) || ((_f = (_e = this.otherParams) == null ? void 0 : _e.strategy_context) == null ? void 0 : _f.available_wallet_ids) || ((_h = (_g = this.otherParams) == null ? void 0 : _g.strategy_context) == null ? void 0 : _h.availableWalletIds);
559
+ const source = Array.isArray(orderWalletIds) && orderWalletIds.length ? orderWalletIds : fallbackWalletIds;
560
+ if (!Array.isArray(source))
561
+ return [];
562
+ const ids = source.map((item) => Number(item)).filter((item) => Number.isFinite(item) && item > 0);
563
+ return Array.from(new Set(ids));
564
+ }
565
+ /** 读取 schedule 全量列表,供智能定价 schedule_match 使用 */
566
+ getScheduleListForSmartPricing() {
567
+ var _a;
568
+ const scheduleModule = this.store.schedule;
569
+ const list = (_a = scheduleModule == null ? void 0 : scheduleModule.store) == null ? void 0 : _a.scheduleList;
570
+ return Array.isArray(list) ? list : [];
571
+ }
572
+ /** 构建智能定价上下文,对齐 OS Server buildProductFormatterContext */
573
+ buildSmartPricingContext(customerId) {
574
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
575
+ const evaluator = (_b = (_a = this.core) == null ? void 0 : _a.context) == null ? void 0 : _b.dataVariantEvaluator;
576
+ return {
577
+ evaluator,
578
+ scheduleList: this.getScheduleListForSmartPricing(),
579
+ menuList: ((_c = this.otherParams) == null ? void 0 : _c.menuList) || ((_e = (_d = this.otherParams) == null ? void 0 : _d.openData) == null ? void 0 : _e.menuList) || [],
580
+ customerId: customerId ?? this.resolveCustomerIdForSmartPricing(),
581
+ availableWalletIds: this.resolveAvailableWalletIdsForSmartPricing(),
582
+ channel: (_f = this.otherParams) == null ? void 0 : _f.channel,
583
+ businessCode: (_g = this.otherParams) == null ? void 0 : _g.businessCode,
584
+ orderType: ((_h = this.otherParams) == null ? void 0 : _h.orderType) || ((_i = this.otherParams) == null ? void 0 : _i.type),
585
+ strategy_context: (_j = this.otherParams) == null ? void 0 : _j.strategy_context
586
+ };
587
+ }
588
+ /** venue + addon 全量商品,供智能定价评估 */
589
+ getAllProductsForSmartPricing() {
590
+ if (this.smartPricingProductCatalog.length) {
591
+ return this.smartPricingProductCatalog;
592
+ }
593
+ const venueList = this.getVenueProducts();
594
+ const addonList = this.getAddonProductsList();
595
+ return [...venueList, ...addonList];
596
+ }
597
+ getSlotPriceMapCacheKey(date, context) {
598
+ return [
599
+ date,
600
+ context.customerId ?? "",
601
+ (context.availableWalletIds || []).join(","),
602
+ context.channel ?? "",
603
+ context.businessCode ?? ""
604
+ ].join("|");
605
+ }
606
+ /**
607
+ * 按 schedule 分段构建 slot 价格 Map,带实例级缓存。
608
+ */
609
+ buildSlotPriceMapForDate(date, config, productIds) {
610
+ const context = this.buildSmartPricingContext();
611
+ const cacheKey = this.getSlotPriceMapCacheKey(date, context);
612
+ const cached = this.slotPriceMapCache.get(cacheKey);
613
+ if (cached)
614
+ return cached;
615
+ const timeLabels = (0, import_timeSlot.generateTimeLabels)(config);
616
+ const slotPriceMap = (0, import_smartPricing.buildSlotPriceMapByScheduleSegments)({
617
+ products: this.getAllProductsForSmartPricing(),
618
+ productIds,
619
+ date,
620
+ timeLabels,
621
+ config,
622
+ context
623
+ });
624
+ this.slotPriceMapCache.set(cacheKey, slotPriceMap);
625
+ return slotPriceMap;
626
+ }
544
627
  // ─── 场地商品 & 附加商品 ───
545
628
  async loadAllProducts() {
546
629
  if (this.loadAllProductsInFlight)
@@ -569,9 +652,18 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
569
652
  menu_list_ids: menuListIds,
570
653
  cacheId: this.cacheId,
571
654
  schedule_date: (0, import_dayjs.default)().format("YYYY-MM-DD"),
572
- schedule_datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
655
+ schedule_datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss"),
656
+ with_extra: ["dataVariants"]
573
657
  });
574
- const list = Array.isArray(allProducts) ? allProducts : [];
658
+ const rawList = Array.isArray(allProducts) ? allProducts : [];
659
+ let list = rawList;
660
+ this.smartPricingProductCatalog = rawList.slice();
661
+ list = (0, import_smartPricing.formatProductsWithDataVariant)(
662
+ list,
663
+ this.buildSmartPricingContext(),
664
+ (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
665
+ );
666
+ this.clearSlotPriceMapCache();
575
667
  const venueList = list.filter((p) => p.duration != null);
576
668
  const addonList = list.filter((p) => p.duration == null);
577
669
  const venueStore = (_c = this.store.venueProducts) == null ? void 0 : _c.store;
@@ -752,29 +844,24 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
752
844
  config: this.baseSlotConfig,
753
845
  rawResources: this.store.rawResourceData,
754
846
  resourceProductMap: this.resourceProductMap,
755
- quotationModule: this.store.quotation,
756
- resolveConfig: (date) => this.resolveSlotConfigForDate(date)
847
+ resolveConfig: (date) => this.resolveSlotConfigForDate(date),
848
+ buildSlotPriceMap: (date, config, productIds) => this.buildSlotPriceMapForDate(date, config, productIds)
757
849
  });
758
850
  }
759
851
  getTimeSlotGrid(date) {
760
852
  const resolvedSlotConfig = this.syncOperatingHoursToSlotConfig(date);
761
- let quotationPriceMap;
762
- if (this.store.quotation) {
763
- const productIds = [
764
- ...new Set(
765
- [...this.resourceProductMap.values()].flat().map((m) => m.productId)
766
- )
767
- ];
768
- const timeLabels = (0, import_timeSlot.generateTimeLabels)(resolvedSlotConfig);
769
- const timePoints = timeLabels.map((label) => `${date} ${label}`);
770
- quotationPriceMap = this.store.quotation.buildProductPriceMap({ productIds, timePoints });
771
- }
853
+ const productIds = [
854
+ ...new Set(
855
+ [...this.resourceProductMap.values()].flat().map((m) => m.productId)
856
+ )
857
+ ];
858
+ const slotPriceMap = productIds.length ? this.buildSlotPriceMapForDate(date, resolvedSlotConfig, productIds) : void 0;
772
859
  return (0, import_timeSlot.buildTimeSlotGrid)({
773
860
  date,
774
861
  config: resolvedSlotConfig,
775
862
  rawResources: this.store.rawResourceData,
776
863
  resourceProductMap: this.resourceProductMap,
777
- quotationPriceMap
864
+ slotPriceMap
778
865
  });
779
866
  }
780
867
  // ─── 时间槽订单操作 ───
@@ -1059,8 +1146,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1059
1146
  booking_uid: bookingUuid,
1060
1147
  price_breakdown: (0, import_slotMerge.buildPriceBreakdown)({
1061
1148
  group,
1062
- productId: mapping.productId,
1063
- quotation: this.store.quotation
1149
+ productId: mapping.productId
1064
1150
  })
1065
1151
  },
1066
1152
  _origin: {
@@ -1153,20 +1239,12 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1153
1239
  if (!this.store.schedule)
1154
1240
  throw new Error("schedule 模块未初始化");
1155
1241
  await this.store.schedule.loadAllSchedule();
1156
- this.injectScheduleResolverToQuotation();
1157
1242
  this.logMethodSuccess("loadSchedules");
1158
1243
  } catch (error) {
1159
1244
  this.logMethodError("loadSchedules", error);
1160
1245
  throw error;
1161
1246
  }
1162
1247
  }
1163
- injectScheduleResolverToQuotation() {
1164
- if (this.store.quotation && this.store.schedule) {
1165
- this.store.quotation.setScheduleResolver(
1166
- (id) => this.store.schedule.getScheduleListByIds([id])[0]
1167
- );
1168
- }
1169
- }
1170
1248
  getScheduleListByIds(ids) {
1171
1249
  if (!this.store.schedule)
1172
1250
  return [];
@@ -1205,14 +1283,16 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1205
1283
  throw error;
1206
1284
  }
1207
1285
  }
1208
- recalculateOrderPricesFromQuotation() {
1286
+ recalculateOrderPricesFromSmartPricing() {
1209
1287
  var _a, _b;
1210
- if (!this.store.order || !this.store.quotation)
1288
+ if (!this.store.order)
1211
1289
  return;
1212
1290
  const tempOrder = this.store.order.getTempOrder();
1213
1291
  if (!((_a = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _a.length))
1214
1292
  return;
1215
1293
  const now = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
1294
+ const catalog = this.getAllProductsForSmartPricing();
1295
+ const context = this.buildSmartPricingContext();
1216
1296
  for (const product of tempOrder.products) {
1217
1297
  if ((_b = product.metadata) == null ? void 0 : _b.venue_booking) {
1218
1298
  const mappings = this.resourceProductMap.get(product.metadata.resource_id);
@@ -1225,34 +1305,49 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1225
1305
  product,
1226
1306
  this.store.slotConfig.slotDurationMinutes
1227
1307
  );
1228
- const updatedSlots = slots.map((slot) => ({
1229
- ...slot,
1230
- productId: mapping.productId,
1231
- price: this.store.quotation.getPriceForProduct({
1308
+ const uniqueDates = [
1309
+ ...new Set(slots.map((slot) => (0, import_dayjs.default)(slot.startTime).format("YYYY-MM-DD")))
1310
+ ];
1311
+ const slotPriceMaps = /* @__PURE__ */ new Map();
1312
+ for (const slotDate of uniqueDates) {
1313
+ slotPriceMaps.set(
1314
+ slotDate,
1315
+ this.buildSlotPriceMapForDate(slotDate, this.store.slotConfig, [mapping.productId])
1316
+ );
1317
+ }
1318
+ const updatedSlots = slots.map((slot) => {
1319
+ const slotDate = (0, import_dayjs.default)(slot.startTime).format("YYYY-MM-DD");
1320
+ const slotPriceMap = slotPriceMaps.get(slotDate);
1321
+ return {
1322
+ ...slot,
1232
1323
  productId: mapping.productId,
1233
- datetime: slot.startTime
1234
- }) ?? mapping.price
1235
- }));
1324
+ price: slotPriceMap ? (0, import_smartPricing.getSlotPriceFromMap)({
1325
+ slotPriceMap,
1326
+ productId: mapping.productId,
1327
+ slotStartTime: slot.startTime,
1328
+ fallbackPrice: mapping.price
1329
+ }) : mapping.price
1330
+ };
1331
+ });
1236
1332
  const merged = (0, import_slotMerge.mergeConsecutiveSlots)(updatedSlots);
1237
1333
  if (merged.length === 1) {
1238
1334
  product.selling_price = merged[0].totalPrice;
1239
1335
  product.original_price = merged[0].totalPrice;
1240
1336
  product.metadata.price_breakdown = (0, import_slotMerge.buildPriceBreakdown)({
1241
1337
  group: merged[0],
1242
- productId: mapping.productId,
1243
- quotation: this.store.quotation
1338
+ productId: mapping.productId
1244
1339
  });
1245
1340
  }
1246
1341
  } else if (product.product_id != null) {
1247
- const quotationPrice = this.store.quotation.getPriceForProduct({
1248
- productId: product.product_id,
1249
- variantId: product.product_variant_id ?? void 0,
1250
- datetime: now
1342
+ const smartPrice = (0, import_smartPricing.getPriceForProductAtDatetime)({
1343
+ products: catalog,
1344
+ context,
1345
+ productId: Number(product.product_id),
1346
+ datetime: now,
1347
+ fallbackPrice: product.selling_price
1251
1348
  });
1252
- if (quotationPrice !== null) {
1253
- product.selling_price = quotationPrice;
1254
- product.original_price = quotationPrice;
1255
- }
1349
+ product.selling_price = smartPrice;
1350
+ product.original_price = smartPrice;
1256
1351
  }
1257
1352
  }
1258
1353
  }
@@ -1438,7 +1533,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1438
1533
  }
1439
1534
  }
1440
1535
  async addProductToOrder(product) {
1441
- var _a;
1536
+ var _a, _b;
1442
1537
  this.logMethodStart("addProductToOrder", {
1443
1538
  product_id: product.product_id,
1444
1539
  product_variant_id: product.product_variant_id
@@ -1446,18 +1541,18 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1446
1541
  try {
1447
1542
  if (!this.store.order)
1448
1543
  throw new Error("order 模块未初始化");
1449
- if (!((_a = product.metadata) == null ? void 0 : _a.venue_booking) && this.store.quotation && product.product_id != null) {
1450
- const quotationPrice = this.store.quotation.getPriceForProduct({
1451
- productId: product.product_id,
1452
- variantId: product.product_variant_id ?? void 0,
1453
- datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
1544
+ if (!((_a = product.metadata) == null ? void 0 : _a.venue_booking) && product.product_id != null) {
1545
+ const smartPrice = (0, import_smartPricing.getPriceForProductAtDatetime)({
1546
+ products: this.getAllProductsForSmartPricing(),
1547
+ context: this.buildSmartPricingContext(),
1548
+ productId: Number(product.product_id),
1549
+ datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss"),
1550
+ fallbackPrice: product.selling_price
1454
1551
  });
1455
- if (quotationPrice !== null) {
1456
- product.selling_price = quotationPrice;
1457
- product.original_price = quotationPrice;
1458
- } else if (product.selling_price != null) {
1459
- product.original_price = product.selling_price;
1460
- }
1552
+ product.selling_price = smartPrice;
1553
+ product.original_price = smartPrice;
1554
+ } else if (product.selling_price != null && !((_b = product.metadata) == null ? void 0 : _b.venue_booking)) {
1555
+ product.original_price = product.selling_price;
1461
1556
  }
1462
1557
  const products = await this.store.order.addProductToOrder(product);
1463
1558
  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
- quotationModule,
45
- resolveConfig
44
+ resolveConfig,
45
+ buildSlotPriceMap
46
46
  } = params;
47
47
  const result = [];
48
- const productIds = quotationModule ? [...new Set([...resourceProductMap.values()].flat().map((m) => m.productId))] : [];
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
- let quotationPriceMap;
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
- quotationPriceMap
60
+ slotPriceMap
66
61
  });
67
62
  let totalSlots = 0;
68
63
  let availableSlots = 0;