@pisell/pisellos 2.1.166 → 2.1.168

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 (81) hide show
  1. package/dist/index.d.ts +0 -1
  2. package/dist/index.js +0 -3
  3. package/dist/model/strategy/adapter/index.d.ts +0 -4
  4. package/dist/model/strategy/adapter/index.js +1 -5
  5. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  6. package/dist/modules/Cart/utils/changePrice.js +16 -9
  7. package/dist/modules/Discount/index.d.ts +2 -5
  8. package/dist/modules/Discount/index.js +1 -21
  9. package/dist/modules/Discount/types.d.ts +0 -4
  10. package/dist/modules/Order/index.d.ts +0 -1
  11. package/dist/modules/Order/index.js +6 -18
  12. package/dist/modules/Order/types.d.ts +0 -2
  13. package/dist/modules/ProductList/index.d.ts +1 -3
  14. package/dist/modules/ProductList/index.js +11 -22
  15. package/dist/modules/Schedule/getDateIsInSchedule.js +0 -5
  16. package/dist/solution/BookingByStep/index.d.ts +2 -2
  17. package/dist/solution/ScanOrder/index.js +1 -1
  18. package/dist/solution/ShopDiscount/index.js +15 -16
  19. package/dist/solution/VenueBooking/index.d.ts +3 -40
  20. package/dist/solution/VenueBooking/index.js +261 -394
  21. package/dist/solution/VenueBooking/types.d.ts +1 -3
  22. package/dist/solution/VenueBooking/types.js +0 -1
  23. package/dist/solution/VenueBooking/utils/dateSummary.d.ts +2 -2
  24. package/dist/solution/VenueBooking/utils/dateSummary.js +25 -12
  25. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +6 -0
  26. package/dist/solution/VenueBooking/utils/slotMerge.js +9 -3
  27. package/dist/solution/VenueBooking/utils/timeSlot.d.ts +0 -2
  28. package/dist/solution/VenueBooking/utils/timeSlot.js +4 -9
  29. package/lib/index.d.ts +0 -1
  30. package/lib/index.js +0 -3
  31. package/lib/model/strategy/adapter/index.d.ts +0 -4
  32. package/lib/model/strategy/adapter/index.js +2 -13
  33. package/lib/model/strategy/adapter/promotion/index.js +0 -49
  34. package/lib/modules/Cart/utils/changePrice.js +13 -9
  35. package/lib/modules/Discount/index.d.ts +2 -5
  36. package/lib/modules/Discount/index.js +1 -11
  37. package/lib/modules/Discount/types.d.ts +0 -4
  38. package/lib/modules/Order/index.d.ts +0 -1
  39. package/lib/modules/Order/index.js +1 -11
  40. package/lib/modules/Order/types.d.ts +0 -2
  41. package/lib/modules/ProductList/index.d.ts +1 -3
  42. package/lib/modules/ProductList/index.js +39 -45
  43. package/lib/modules/Schedule/getDateIsInSchedule.js +0 -4
  44. package/lib/solution/BookingByStep/index.d.ts +2 -2
  45. package/lib/solution/ScanOrder/index.js +1 -1
  46. package/lib/solution/ShopDiscount/index.js +2 -3
  47. package/lib/solution/VenueBooking/index.d.ts +3 -40
  48. package/lib/solution/VenueBooking/index.js +111 -257
  49. package/lib/solution/VenueBooking/types.d.ts +1 -3
  50. package/lib/solution/VenueBooking/types.js +0 -1
  51. package/lib/solution/VenueBooking/utils/dateSummary.d.ts +2 -2
  52. package/lib/solution/VenueBooking/utils/dateSummary.js +10 -5
  53. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +6 -0
  54. package/lib/solution/VenueBooking/utils/slotMerge.js +4 -3
  55. package/lib/solution/VenueBooking/utils/timeSlot.d.ts +0 -2
  56. package/lib/solution/VenueBooking/utils/timeSlot.js +3 -7
  57. package/package.json +1 -1
  58. package/dist/model/strategy/adapter/dataVariant/adapter.d.ts +0 -50
  59. package/dist/model/strategy/adapter/dataVariant/adapter.js +0 -167
  60. package/dist/model/strategy/adapter/dataVariant/evaluator.d.ts +0 -89
  61. package/dist/model/strategy/adapter/dataVariant/evaluator.js +0 -780
  62. package/dist/model/strategy/adapter/dataVariant/examples.d.ts +0 -39
  63. package/dist/model/strategy/adapter/dataVariant/examples.js +0 -277
  64. package/dist/model/strategy/adapter/dataVariant/index.d.ts +0 -4
  65. package/dist/model/strategy/adapter/dataVariant/index.js +0 -4
  66. package/dist/model/strategy/adapter/dataVariant/type.d.ts +0 -148
  67. package/dist/model/strategy/adapter/dataVariant/type.js +0 -54
  68. package/dist/solution/VenueBooking/utils/smartPricing.d.ts +0 -70
  69. package/dist/solution/VenueBooking/utils/smartPricing.js +0 -233
  70. package/lib/model/strategy/adapter/dataVariant/adapter.d.ts +0 -50
  71. package/lib/model/strategy/adapter/dataVariant/adapter.js +0 -149
  72. package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +0 -89
  73. package/lib/model/strategy/adapter/dataVariant/evaluator.js +0 -583
  74. package/lib/model/strategy/adapter/dataVariant/examples.d.ts +0 -39
  75. package/lib/model/strategy/adapter/dataVariant/examples.js +0 -293
  76. package/lib/model/strategy/adapter/dataVariant/index.d.ts +0 -4
  77. package/lib/model/strategy/adapter/dataVariant/index.js +0 -38
  78. package/lib/model/strategy/adapter/dataVariant/type.d.ts +0 -148
  79. package/lib/model/strategy/adapter/dataVariant/type.js +0 -31
  80. package/lib/solution/VenueBooking/utils/smartPricing.d.ts +0 -70
  81. package/lib/solution/VenueBooking/utils/smartPricing.js +0 -180
@@ -50,7 +50,6 @@ 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");
54
53
  var import_utils3 = require("../../modules/Order/utils");
55
54
  var import_Order = require("../../modules/Order");
56
55
  var import_types4 = require("../RegisterAndLogin/types");
@@ -111,10 +110,6 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
111
110
  this.loadAllProductsInFlight = null;
112
111
  this.productsLoaded = false;
113
112
  this.loadOpenDataConfigInFlight = null;
114
- /** 按日期缓存 slot 智能定价 Map,避免同周重复 resolveProducts */
115
- this.slotPriceMapCache = /* @__PURE__ */ new Map();
116
- /** loadProducts 后缓存的全量商品(venue + addon),供分段算价复用 */
117
- this.smartPricingProductCatalog = [];
118
113
  }
119
114
  getLoggerContext() {
120
115
  return {
@@ -277,16 +272,19 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
277
272
  });
278
273
  }
279
274
  registerCustomerLoginListeners() {
275
+ var _a, _b, _c, _d;
280
276
  this.clearLoginEffectListeners();
281
- const createHandleLogin = () => async (payload) => {
277
+ const accountModule = (_a = this.core) == null ? void 0 : _a.getModule("account");
278
+ const registerAndLoginModule = (_b = this.core) == null ? void 0 : _b.getModule("registerAndLogin");
279
+ const currentAccount = ((_c = accountModule == null ? void 0 : accountModule.getCurrentAccount) == null ? void 0 : _c.call(accountModule)) || ((_d = accountModule == null ? void 0 : accountModule.getAccount) == null ? void 0 : _d.call(accountModule)) || null;
280
+ const createHandleLogin = (eventName) => async (payload) => {
282
281
  const customerId = this.resolveCustomerIdFromLoginPayload(payload);
283
282
  if (!customerId)
284
283
  return;
285
284
  await this.refreshOrderMarketingAfterLogin({ customerId });
286
285
  };
287
- this.registerLoginEffect(_VenueBookingImpl.PISELL1_LOGIN_SUCCESS, createHandleLogin());
288
- this.registerLoginEffect(import_types3.AccountHooks.OnLogin, createHandleLogin());
289
- this.registerLoginEffect(import_types4.RegisterAndLoginHooks.onLoginSuccess, createHandleLogin());
286
+ this.registerLoginEffect(import_types3.AccountHooks.OnLogin, createHandleLogin(import_types3.AccountHooks.OnLogin));
287
+ this.registerLoginEffect(import_types4.RegisterAndLoginHooks.onLoginSuccess, createHandleLogin(import_types4.RegisterAndLoginHooks.onLoginSuccess));
290
288
  }
291
289
  async refreshOrderMarketingAfterLogin(params) {
292
290
  if (!this.store.order)
@@ -300,24 +298,20 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
300
298
  }
301
299
  this.customerLoginRefreshIdInFlight = params.customerId;
302
300
  const refreshTask = (async () => {
303
- var _a, _b, _c;
304
- this.smartPricingCustomerId = params.customerId;
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();
305
308
  await this.store.order.loadDiscountConfig({
306
309
  customerId: params.customerId
307
310
  });
308
- this.clearSlotPriceMapCache();
309
- this.recalculateOrderPricesFromSmartPricing();
310
- this.store.order.applyDiscount();
311
- this.normalizeDiscountedOrderPrices(
312
- this.store.order.getDiscountList()
313
- );
314
311
  await this.store.order.recalculateSummary({ createIfMissing: true });
315
312
  this.store.order.persistTempOrder();
316
313
  await this.refreshItemRuleQuantityLimits();
317
314
  await this.refreshCartValidationPassed();
318
- await ((_c = (_b = (_a = this.core) == null ? void 0 : _a.effects) == null ? void 0 : _b.emit) == null ? void 0 : _c.call(_b, import_types.VenueBookingHooks.onSmartPricingUpdated, {
319
- customerId: params.customerId
320
- }));
321
315
  })();
322
316
  this.customerLoginRefreshInFlight = refreshTask;
323
317
  try {
@@ -332,12 +326,11 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
332
326
  }
333
327
  }
334
328
  async initialize(core, options = {}) {
335
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
329
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
336
330
  this.logMethodStart("initialize");
337
331
  this.core = core;
338
332
  this.initializeOptions = options || {};
339
333
  this.store = { ...this.store, ...options.store };
340
- this.smartPricingCustomerId = void 0;
341
334
  this.store.entryContext = ((_a = options.otherParams) == null ? void 0 : _a.entryContext) || this.store.entryContext;
342
335
  this.store.status = "initializing";
343
336
  this.store.error = null;
@@ -469,6 +462,10 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
469
462
  await this.loadRuntimeConfigs();
470
463
  if (this.store.schedule) {
471
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
+ });
472
469
  }
473
470
  await this.refreshItemRuleQuantityLimits();
474
471
  this.store.status = "ready";
@@ -544,95 +541,6 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
544
541
  getCartValidation() {
545
542
  return this.store.cartValidation || { passed: null, failures: [] };
546
543
  }
547
- /** 清除 slot 价格分段缓存(商品重载 / 登录后 customerId 变化时调用) */
548
- clearSlotPriceMapCache() {
549
- this.slotPriceMapCache.clear();
550
- }
551
- /** 读取当前登录 customerId */
552
- resolveCustomerIdForSmartPricing() {
553
- var _a, _b, _c;
554
- if (this.smartPricingCustomerId)
555
- return this.smartPricingCustomerId;
556
- try {
557
- const userPlugin = (_a = this.core) == null ? void 0 : _a.getPlugin("user");
558
- const customerId = Number((_c = (_b = userPlugin == null ? void 0 : userPlugin.get) == null ? void 0 : _b.call(userPlugin)) == null ? void 0 : _c.id);
559
- return Number.isFinite(customerId) && customerId > 0 ? customerId : void 0;
560
- } catch {
561
- return void 0;
562
- }
563
- }
564
- resolveAvailableWalletIdsForSmartPricing() {
565
- var _a, _b, _c, _d, _e, _f, _g, _h;
566
- const orderWalletIds = (_b = (_a = this.store.order) == null ? void 0 : _a.getAvailableWalletIds) == null ? void 0 : _b.call(_a);
567
- 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);
568
- const source = Array.isArray(orderWalletIds) && orderWalletIds.length ? orderWalletIds : fallbackWalletIds;
569
- if (!Array.isArray(source))
570
- return [];
571
- const ids = source.map((item) => Number(item)).filter((item) => Number.isFinite(item) && item > 0);
572
- return Array.from(new Set(ids));
573
- }
574
- /** 读取 schedule 全量列表,供智能定价 schedule_match 使用 */
575
- getScheduleListForSmartPricing() {
576
- var _a;
577
- const scheduleModule = this.store.schedule;
578
- const list = (_a = scheduleModule == null ? void 0 : scheduleModule.store) == null ? void 0 : _a.scheduleList;
579
- return Array.isArray(list) ? list : [];
580
- }
581
- /** 构建智能定价上下文,对齐 OS Server buildProductFormatterContext */
582
- buildSmartPricingContext(customerId) {
583
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
584
- const evaluator = (_b = (_a = this.core) == null ? void 0 : _a.context) == null ? void 0 : _b.dataVariantEvaluator;
585
- return {
586
- evaluator,
587
- scheduleList: this.getScheduleListForSmartPricing(),
588
- menuList: ((_c = this.otherParams) == null ? void 0 : _c.menuList) || ((_e = (_d = this.otherParams) == null ? void 0 : _d.openData) == null ? void 0 : _e.menuList) || [],
589
- customerId: customerId ?? this.resolveCustomerIdForSmartPricing(),
590
- availableWalletIds: this.resolveAvailableWalletIdsForSmartPricing(),
591
- channel: (_f = this.otherParams) == null ? void 0 : _f.channel,
592
- businessCode: (_g = this.otherParams) == null ? void 0 : _g.businessCode,
593
- orderType: ((_h = this.otherParams) == null ? void 0 : _h.orderType) || ((_i = this.otherParams) == null ? void 0 : _i.type),
594
- strategy_context: (_j = this.otherParams) == null ? void 0 : _j.strategy_context
595
- };
596
- }
597
- /** venue + addon 全量商品,供智能定价评估 */
598
- getAllProductsForSmartPricing() {
599
- if (this.smartPricingProductCatalog.length) {
600
- return this.smartPricingProductCatalog;
601
- }
602
- const venueList = this.getVenueProducts();
603
- const addonList = this.getAddonProductsList();
604
- return [...venueList, ...addonList];
605
- }
606
- getSlotPriceMapCacheKey(date, context) {
607
- return [
608
- date,
609
- context.customerId ?? "",
610
- (context.availableWalletIds || []).join(","),
611
- context.channel ?? "",
612
- context.businessCode ?? ""
613
- ].join("|");
614
- }
615
- /**
616
- * 按 schedule 分段构建 slot 价格 Map,带实例级缓存。
617
- */
618
- buildSlotPriceMapForDate(date, config, productIds) {
619
- const context = this.buildSmartPricingContext();
620
- const cacheKey = this.getSlotPriceMapCacheKey(date, context);
621
- const cached = this.slotPriceMapCache.get(cacheKey);
622
- if (cached)
623
- return cached;
624
- const timeLabels = (0, import_timeSlot.generateTimeLabels)(config);
625
- const slotPriceMap = (0, import_smartPricing.buildSlotPriceMapByScheduleSegments)({
626
- products: this.getAllProductsForSmartPricing(),
627
- productIds,
628
- date,
629
- timeLabels,
630
- config,
631
- context
632
- });
633
- this.slotPriceMapCache.set(cacheKey, slotPriceMap);
634
- return slotPriceMap;
635
- }
636
544
  // ─── 场地商品 & 附加商品 ───
637
545
  async loadAllProducts() {
638
546
  if (this.loadAllProductsInFlight)
@@ -661,18 +569,9 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
661
569
  menu_list_ids: menuListIds,
662
570
  cacheId: this.cacheId,
663
571
  schedule_date: (0, import_dayjs.default)().format("YYYY-MM-DD"),
664
- schedule_datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss"),
665
- with_extra: ["dataVariants"]
572
+ schedule_datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
666
573
  });
667
- const rawList = Array.isArray(allProducts) ? allProducts : [];
668
- let list = rawList;
669
- this.smartPricingProductCatalog = rawList.slice();
670
- list = (0, import_smartPricing.formatProductsWithDataVariant)(
671
- list,
672
- this.buildSmartPricingContext(),
673
- (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
674
- );
675
- this.clearSlotPriceMapCache();
574
+ const list = Array.isArray(allProducts) ? allProducts : [];
676
575
  const venueList = list.filter((p) => p.duration != null);
677
576
  const addonList = list.filter((p) => p.duration == null);
678
577
  const venueStore = (_c = this.store.venueProducts) == null ? void 0 : _c.store;
@@ -853,24 +752,29 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
853
752
  config: this.baseSlotConfig,
854
753
  rawResources: this.store.rawResourceData,
855
754
  resourceProductMap: this.resourceProductMap,
856
- resolveConfig: (date) => this.resolveSlotConfigForDate(date),
857
- buildSlotPriceMap: (date, config, productIds) => this.buildSlotPriceMapForDate(date, config, productIds)
755
+ quotationModule: this.store.quotation,
756
+ resolveConfig: (date) => this.resolveSlotConfigForDate(date)
858
757
  });
859
758
  }
860
759
  getTimeSlotGrid(date) {
861
760
  const resolvedSlotConfig = this.syncOperatingHoursToSlotConfig(date);
862
- const productIds = [
863
- ...new Set(
864
- [...this.resourceProductMap.values()].flat().map((m) => m.productId)
865
- )
866
- ];
867
- const slotPriceMap = productIds.length ? this.buildSlotPriceMapForDate(date, resolvedSlotConfig, productIds) : void 0;
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
+ }
868
772
  return (0, import_timeSlot.buildTimeSlotGrid)({
869
773
  date,
870
774
  config: resolvedSlotConfig,
871
775
  rawResources: this.store.rawResourceData,
872
776
  resourceProductMap: this.resourceProductMap,
873
- slotPriceMap
777
+ quotationPriceMap
874
778
  });
875
779
  }
876
780
  // ─── 时间槽订单操作 ───
@@ -1155,7 +1059,8 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1155
1059
  booking_uid: bookingUuid,
1156
1060
  price_breakdown: (0, import_slotMerge.buildPriceBreakdown)({
1157
1061
  group,
1158
- productId: mapping.productId
1062
+ productId: mapping.productId,
1063
+ quotation: this.store.quotation
1159
1064
  })
1160
1065
  },
1161
1066
  _origin: {
@@ -1248,12 +1153,20 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1248
1153
  if (!this.store.schedule)
1249
1154
  throw new Error("schedule 模块未初始化");
1250
1155
  await this.store.schedule.loadAllSchedule();
1156
+ this.injectScheduleResolverToQuotation();
1251
1157
  this.logMethodSuccess("loadSchedules");
1252
1158
  } catch (error) {
1253
1159
  this.logMethodError("loadSchedules", error);
1254
1160
  throw error;
1255
1161
  }
1256
1162
  }
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
+ }
1257
1170
  getScheduleListByIds(ids) {
1258
1171
  if (!this.store.schedule)
1259
1172
  return [];
@@ -1292,16 +1205,14 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1292
1205
  throw error;
1293
1206
  }
1294
1207
  }
1295
- recalculateOrderPricesFromSmartPricing() {
1208
+ recalculateOrderPricesFromQuotation() {
1296
1209
  var _a, _b;
1297
- if (!this.store.order)
1210
+ if (!this.store.order || !this.store.quotation)
1298
1211
  return;
1299
1212
  const tempOrder = this.store.order.getTempOrder();
1300
1213
  if (!((_a = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _a.length))
1301
1214
  return;
1302
1215
  const now = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
1303
- const catalog = this.getAllProductsForSmartPricing();
1304
- const context = this.buildSmartPricingContext();
1305
1216
  for (const product of tempOrder.products) {
1306
1217
  if ((_b = product.metadata) == null ? void 0 : _b.venue_booking) {
1307
1218
  const mappings = this.resourceProductMap.get(product.metadata.resource_id);
@@ -1314,75 +1225,37 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1314
1225
  product,
1315
1226
  this.store.slotConfig.slotDurationMinutes
1316
1227
  );
1317
- const uniqueDates = [
1318
- ...new Set(slots.map((slot) => (0, import_dayjs.default)(slot.startTime).format("YYYY-MM-DD")))
1319
- ];
1320
- const slotPriceMaps = /* @__PURE__ */ new Map();
1321
- for (const slotDate of uniqueDates) {
1322
- slotPriceMaps.set(
1323
- slotDate,
1324
- this.buildSlotPriceMapForDate(slotDate, this.store.slotConfig, [mapping.productId])
1325
- );
1326
- }
1327
- const updatedSlots = slots.map((slot) => {
1328
- const slotDate = (0, import_dayjs.default)(slot.startTime).format("YYYY-MM-DD");
1329
- const slotPriceMap = slotPriceMaps.get(slotDate);
1330
- return {
1331
- ...slot,
1228
+ const updatedSlots = slots.map((slot) => ({
1229
+ ...slot,
1230
+ productId: mapping.productId,
1231
+ price: this.store.quotation.getPriceForProduct({
1332
1232
  productId: mapping.productId,
1333
- price: slotPriceMap ? (0, import_smartPricing.getSlotPriceFromMap)({
1334
- slotPriceMap,
1335
- productId: mapping.productId,
1336
- slotStartTime: slot.startTime,
1337
- fallbackPrice: mapping.price
1338
- }) : mapping.price
1339
- };
1340
- });
1233
+ datetime: slot.startTime
1234
+ }) ?? mapping.price
1235
+ }));
1341
1236
  const merged = (0, import_slotMerge.mergeConsecutiveSlots)(updatedSlots);
1342
1237
  if (merged.length === 1) {
1343
- this.resetProductPriceForSmartPricing({
1344
- product,
1345
- price: merged[0].totalPrice,
1346
- priceBreakdown: (0, import_slotMerge.buildPriceBreakdown)({
1347
- group: merged[0],
1348
- productId: mapping.productId
1349
- })
1238
+ product.selling_price = merged[0].totalPrice;
1239
+ product.original_price = merged[0].totalPrice;
1240
+ product.metadata.price_breakdown = (0, import_slotMerge.buildPriceBreakdown)({
1241
+ group: merged[0],
1242
+ productId: mapping.productId,
1243
+ quotation: this.store.quotation
1350
1244
  });
1351
1245
  }
1352
1246
  } else if (product.product_id != null) {
1353
- const smartPrice = (0, import_smartPricing.getPriceForProductAtDatetime)({
1354
- products: catalog,
1355
- context,
1356
- productId: Number(product.product_id),
1357
- datetime: now,
1358
- fallbackPrice: product.selling_price
1359
- });
1360
- this.resetProductPriceForSmartPricing({
1361
- product,
1362
- price: smartPrice
1247
+ const quotationPrice = this.store.quotation.getPriceForProduct({
1248
+ productId: product.product_id,
1249
+ variantId: product.product_variant_id ?? void 0,
1250
+ datetime: now
1363
1251
  });
1252
+ if (quotationPrice !== null) {
1253
+ product.selling_price = quotationPrice;
1254
+ product.original_price = quotationPrice;
1255
+ }
1364
1256
  }
1365
1257
  }
1366
1258
  }
1367
- /**
1368
- * DataVariant 重算价格后,同步刷新订单展示、Rules 与 Summary 共用的价格口径。
1369
- * Rules 会在本轮结束后根据当前客户的 discountList 重新写入实际折扣。
1370
- */
1371
- resetProductPriceForSmartPricing(params) {
1372
- const { product, price, priceBreakdown } = params;
1373
- const metadata = product.metadata || {};
1374
- product.selling_price = price;
1375
- product.original_price = price;
1376
- product.discount_list = [];
1377
- product.metadata = {
1378
- ...metadata,
1379
- ...priceBreakdown ? { price_breakdown: priceBreakdown } : {},
1380
- source_product_price: price,
1381
- main_product_original_price: price,
1382
- main_product_selling_price: price,
1383
- price_schema_version: 2
1384
- };
1385
- }
1386
1259
  async scanCode(code, customerId) {
1387
1260
  this.logMethodStart("scanCode", { code });
1388
1261
  try {
@@ -1408,7 +1281,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1408
1281
  }
1409
1282
  /** 勾选/取消勾选某张折扣券,重新计算折扣并持久化 */
1410
1283
  async setDiscountSelected(params) {
1411
- var _a, _b, _c, _d, _e;
1284
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1412
1285
  this.logMethodStart("setDiscountSelected", params);
1413
1286
  try {
1414
1287
  if (!this.store.order)
@@ -1460,15 +1333,42 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1460
1333
  }
1461
1334
  }
1462
1335
  }
1463
- this.normalizeDiscountedOrderPrices(nextDiscountList);
1336
+ const selectedResourceIds = new Set(
1337
+ nextDiscountList.filter((d) => d.isSelected).map((d) => d.id)
1338
+ );
1339
+ for (const product of tempOrder.products) {
1340
+ if ((_c = product._origin) == null ? void 0 : _c.isManualDiscount)
1341
+ continue;
1342
+ product.discount_list = (product.discount_list || []).filter((pd) => {
1343
+ var _a2;
1344
+ const rid = ((_a2 = pd.discount) == null ? void 0 : _a2.resource_id) ?? pd.id;
1345
+ return rid != null && selectedResourceIds.has(rid);
1346
+ });
1347
+ const totalPerUnitDiscount = (product.discount_list || []).reduce(
1348
+ (sum, pd) => sum + (pd.amount || 0),
1349
+ 0
1350
+ );
1351
+ const optionSum = (0, import_utils3.sumOptionUnitPrice)(product.product_option_item);
1352
+ const sourcePrice = ((_d = product.metadata) == null ? void 0 : _d.source_product_price) ?? (((_e = product.metadata) == null ? void 0 : _e.main_product_original_price) != null ? new import_decimal.default(Number(product.metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? "0");
1353
+ const newSourceSellingPrice = new import_decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount).toDecimalPlaces(2).toString();
1354
+ const newMainSellingPrice = new import_decimal.default(Number(newSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
1355
+ if (product.metadata) {
1356
+ product.metadata.main_product_selling_price = newMainSellingPrice;
1357
+ product.metadata.price_schema_version = 2;
1358
+ }
1359
+ product.selling_price = (0, import_utils3.composeLinePrice)({
1360
+ mainPrice: newMainSellingPrice,
1361
+ bundle: product.product_bundle
1362
+ });
1363
+ }
1464
1364
  import_Order.OrderModule.populateSavedAmounts(tempOrder.products, nextDiscountList);
1465
1365
  await (discountModule == null ? void 0 : discountModule.setDiscountList(nextDiscountList));
1466
1366
  tempOrder.discount_list = (nextDiscountList || []).filter((d) => d.isSelected);
1467
1367
  const afterApplyTarget = this.store.order.getDiscountList().find((d) => d.id === params.discountId) || null;
1468
1368
  await this.store.order.recalculateSummary({ createIfMissing: true });
1469
1369
  this.store.order.persistTempOrder();
1470
- const finalSummary = ((_c = this.store.order.getTempOrder()) == null ? void 0 : _c.summary) || null;
1471
- const finalProduct = ((_e = (_d = this.store.order.getTempOrder()) == null ? void 0 : _d.products) == null ? void 0 : _e[0]) || null;
1370
+ const finalSummary = ((_f = this.store.order.getTempOrder()) == null ? void 0 : _f.summary) || null;
1371
+ const finalProduct = ((_h = (_g = this.store.order.getTempOrder()) == null ? void 0 : _g.products) == null ? void 0 : _h[0]) || null;
1472
1372
  this.logMethodSuccess("setDiscountSelected", params);
1473
1373
  const finalTarget = this.store.order.getDiscountList().find((d) => d.id === params.discountId) || null;
1474
1374
  return this.store.order.getDiscountList();
@@ -1477,51 +1377,6 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1477
1377
  throw error;
1478
1378
  }
1479
1379
  }
1480
- /**
1481
- * 统一 VenueBooking 折扣后的订单行价。
1482
- *
1483
- * Rules 的 `discount_list.amount` 是已经按适用规则计算出的每件优惠额;它是这里唯一
1484
- * 的折扣金额来源。使用智能定价写入的 source_product_price 减去该金额,再同步
1485
- * selling_price 与 Summary 使用的 main_product_selling_price,避免 UI 的购物车行价、
1486
- * 小计和提交订单各自读取到不同的价格字段。
1487
- */
1488
- normalizeDiscountedOrderPrices(discountList) {
1489
- var _a;
1490
- const order = this.store.order;
1491
- if (!order)
1492
- return;
1493
- const tempOrder = order.ensureTempOrder();
1494
- const selectedResourceIds = new Set(
1495
- (discountList || []).filter((discount) => discount.isSelected).map((discount) => discount.id)
1496
- );
1497
- for (const product of tempOrder.products) {
1498
- if ((_a = product._origin) == null ? void 0 : _a.isManualDiscount)
1499
- continue;
1500
- product.discount_list = (product.discount_list || []).filter((detail) => {
1501
- var _a2;
1502
- const resourceId = ((_a2 = detail.discount) == null ? void 0 : _a2.resource_id) ?? detail.id;
1503
- return resourceId != null && selectedResourceIds.has(resourceId);
1504
- });
1505
- const totalPerUnitDiscount = (product.discount_list || []).reduce(
1506
- (total, detail) => total.plus(detail.amount || 0),
1507
- new import_decimal.default(0)
1508
- );
1509
- const metadata = product.metadata || (product.metadata = {});
1510
- const optionSum = (0, import_utils3.sumOptionUnitPrice)(product.product_option_item);
1511
- const sourcePrice = metadata.source_product_price ?? (metadata.main_product_original_price != null ? new import_decimal.default(Number(metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? "0");
1512
- const nextSourceSellingPrice = import_decimal.default.max(
1513
- 0,
1514
- new import_decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount)
1515
- ).toDecimalPlaces(2).toString();
1516
- const nextMainSellingPrice = new import_decimal.default(Number(nextSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
1517
- metadata.main_product_selling_price = nextMainSellingPrice;
1518
- metadata.price_schema_version = 2;
1519
- product.selling_price = (0, import_utils3.composeLinePrice)({
1520
- mainPrice: nextMainSellingPrice,
1521
- bundle: product.product_bundle
1522
- });
1523
- }
1524
- }
1525
1380
  async addNewOrder() {
1526
1381
  this.logMethodStart("addNewOrder");
1527
1382
  try {
@@ -1601,7 +1456,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1601
1456
  }
1602
1457
  }
1603
1458
  async addProductToOrder(product) {
1604
- var _a, _b;
1459
+ var _a;
1605
1460
  this.logMethodStart("addProductToOrder", {
1606
1461
  product_id: product.product_id,
1607
1462
  product_variant_id: product.product_variant_id
@@ -1609,18 +1464,18 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1609
1464
  try {
1610
1465
  if (!this.store.order)
1611
1466
  throw new Error("order 模块未初始化");
1612
- if (!((_a = product.metadata) == null ? void 0 : _a.venue_booking) && product.product_id != null) {
1613
- const smartPrice = (0, import_smartPricing.getPriceForProductAtDatetime)({
1614
- products: this.getAllProductsForSmartPricing(),
1615
- context: this.buildSmartPricingContext(),
1616
- productId: Number(product.product_id),
1617
- datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss"),
1618
- fallbackPrice: product.selling_price
1467
+ if (!((_a = product.metadata) == null ? void 0 : _a.venue_booking) && this.store.quotation && product.product_id != null) {
1468
+ const quotationPrice = this.store.quotation.getPriceForProduct({
1469
+ productId: product.product_id,
1470
+ variantId: product.product_variant_id ?? void 0,
1471
+ datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
1619
1472
  });
1620
- product.selling_price = smartPrice;
1621
- product.original_price = smartPrice;
1622
- } else if (product.selling_price != null && !((_b = product.metadata) == null ? void 0 : _b.venue_booking)) {
1623
- product.original_price = product.selling_price;
1473
+ if (quotationPrice !== null) {
1474
+ product.selling_price = quotationPrice;
1475
+ product.original_price = quotationPrice;
1476
+ } else if (product.selling_price != null) {
1477
+ product.original_price = product.selling_price;
1478
+ }
1624
1479
  }
1625
1480
  const products = await this.store.order.addProductToOrder(product);
1626
1481
  await this.refreshItemRuleQuantityLimits();
@@ -2087,7 +1942,6 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
2087
1942
  };
2088
1943
  var VenueBookingImpl = _VenueBookingImpl;
2089
1944
  VenueBookingImpl.OPEN_DATA_CACHE_TTL = 5 * 60 * 1e3;
2090
- VenueBookingImpl.PISELL1_LOGIN_SUCCESS = "pisell1.login.success";
2091
1945
  // ─── UI 状态缓存(按 cacheId 分桶,sessionStorage) ───
2092
1946
  //
2093
1947
  // 用于物料层持久化 UI 层面的轻量状态(如当前步骤、登录回跳意图等)。
@@ -6,9 +6,7 @@ export declare enum VenueBookingHooks {
6
6
  onDestroy = "venueBooking:onDestroy",
7
7
  onRetryInit = "venueBooking:onRetryInit",
8
8
  onRefresh = "venueBooking:onRefresh",
9
- onCartValidationChanged = "venueBooking:onCartValidationChanged",
10
- /** 登录客户的智能定价、营销配置与订单汇总已完成刷新 */
11
- onSmartPricingUpdated = "venueBooking:onSmartPricingUpdated"
9
+ onCartValidationChanged = "venueBooking:onCartValidationChanged"
12
10
  }
13
11
  export type VenueBookingStatus = 'idle' | 'initializing' | 'ready' | 'error';
14
12
  export interface VenueBookingEntryContext {
@@ -29,7 +29,6 @@ var VenueBookingHooks = /* @__PURE__ */ ((VenueBookingHooks2) => {
29
29
  VenueBookingHooks2["onRetryInit"] = "venueBooking:onRetryInit";
30
30
  VenueBookingHooks2["onRefresh"] = "venueBooking:onRefresh";
31
31
  VenueBookingHooks2["onCartValidationChanged"] = "venueBooking:onCartValidationChanged";
32
- VenueBookingHooks2["onSmartPricingUpdated"] = "venueBooking:onSmartPricingUpdated";
33
32
  return VenueBookingHooks2;
34
33
  })(VenueBookingHooks || {});
35
34
  var DEFAULT_SLOT_CONFIG = {
@@ -1,11 +1,11 @@
1
1
  import type { VenueBookingSlotConfig, VenueResourceRawData, VenueDateSummaryItem, ResourceProductMapping } from '../types';
2
+ import type { QuotationModule } from '../../../modules/Quotation';
2
3
  export declare function buildDateRangeSummary(params: {
3
4
  startDate: string;
4
5
  endDate: string;
5
6
  config: VenueBookingSlotConfig;
6
7
  rawResources: VenueResourceRawData[];
7
8
  resourceProductMap: Map<number | string, ResourceProductMapping[]>;
9
+ quotationModule?: QuotationModule;
8
10
  resolveConfig?: (date: string) => VenueBookingSlotConfig;
9
- /** 按日期构建 slot 智能定价 Map */
10
- buildSlotPriceMap?: (date: string, config: VenueBookingSlotConfig, productIds: number[]) => Map<string, string | null>;
11
11
  }): VenueDateSummaryItem[];
@@ -41,23 +41,28 @@ function buildDateRangeSummary(params) {
41
41
  config,
42
42
  rawResources,
43
43
  resourceProductMap,
44
- resolveConfig,
45
- buildSlotPriceMap
44
+ quotationModule,
45
+ resolveConfig
46
46
  } = params;
47
47
  const result = [];
48
- const productIds = buildSlotPriceMap ? [...new Set([...resourceProductMap.values()].flat().map((m) => m.productId))] : [];
48
+ const productIds = quotationModule ? [...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
- const slotPriceMap = buildSlotPriceMap && productIds.length ? buildSlotPriceMap(date, effectiveConfig, productIds) : void 0;
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
+ }
55
60
  const grid = (0, import_timeSlot.buildTimeSlotGrid)({
56
61
  date,
57
62
  config: effectiveConfig,
58
63
  rawResources,
59
64
  resourceProductMap,
60
- slotPriceMap
65
+ quotationPriceMap
61
66
  });
62
67
  let totalSlots = 0;
63
68
  let availableSlots = 0;
@@ -5,6 +5,12 @@ 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
+ };
8
14
  }): PriceBreakdownEntry[];
9
15
  export interface BuildVenueBookingParams {
10
16
  group: MergedSlotGroup;
@@ -82,16 +82,17 @@ function mergeConsecutiveSlots(slots) {
82
82
  return groups;
83
83
  }
84
84
  function buildPriceBreakdown(params) {
85
- const { group } = params;
85
+ const { group, productId, quotation } = 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;
91
92
  const startHm = (0, import_dayjs.default)(slot.startTime, "YYYY-MM-DD HH:mm").format("YYYY-MM-DD HH:mm");
92
93
  const endHm = (0, import_dayjs.default)(slot.endTime, "YYYY-MM-DD HH:mm").format("YYYY-MM-DD HH:mm");
93
94
  const last = entries[entries.length - 1];
94
- if (last && last.unit_price === unitPrice && last.quotation_shelf_id === 0 && last.end_time === startHm) {
95
+ if (last && last.unit_price === unitPrice && last.quotation_shelf_id === shelfId && last.end_time === startHm) {
95
96
  last.end_time = endHm;
96
97
  last.quantity += 1;
97
98
  } else {
@@ -99,7 +100,7 @@ function buildPriceBreakdown(params) {
99
100
  start_time: startHm,
100
101
  end_time: endHm,
101
102
  unit_price: unitPrice,
102
- quotation_shelf_id: 0,
103
+ quotation_shelf_id: shelfId,
103
104
  quantity: 1
104
105
  });
105
106
  }