@pisell/pisellos 2.1.163 → 2.1.165

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 +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/modules/Discount/index.d.ts +2 -5
  6. package/dist/modules/Discount/index.js +1 -21
  7. package/dist/modules/Discount/types.d.ts +0 -4
  8. package/dist/modules/Order/index.d.ts +0 -1
  9. package/dist/modules/Order/index.js +6 -18
  10. package/dist/modules/Order/types.d.ts +0 -2
  11. package/dist/modules/ProductList/index.d.ts +1 -3
  12. package/dist/modules/ProductList/index.js +11 -22
  13. package/dist/modules/Schedule/getDateIsInSchedule.js +0 -5
  14. package/dist/solution/BookingByStep/index.d.ts +2 -2
  15. package/dist/solution/ScanOrder/index.js +1 -1
  16. package/dist/solution/ShopDiscount/index.js +15 -16
  17. package/dist/solution/VenueBooking/index.d.ts +8 -23
  18. package/dist/solution/VenueBooking/index.js +476 -528
  19. package/dist/solution/VenueBooking/utils/dateSummary.d.ts +2 -2
  20. package/dist/solution/VenueBooking/utils/dateSummary.js +25 -12
  21. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +6 -0
  22. package/dist/solution/VenueBooking/utils/slotMerge.js +9 -3
  23. package/dist/solution/VenueBooking/utils/timeSlot.d.ts +0 -2
  24. package/dist/solution/VenueBooking/utils/timeSlot.js +4 -9
  25. package/lib/index.d.ts +0 -1
  26. package/lib/index.js +0 -3
  27. package/lib/model/strategy/adapter/index.d.ts +0 -4
  28. package/lib/model/strategy/adapter/index.js +2 -13
  29. package/lib/model/strategy/adapter/promotion/index.js +49 -0
  30. package/lib/modules/Discount/index.d.ts +2 -5
  31. package/lib/modules/Discount/index.js +1 -11
  32. package/lib/modules/Discount/types.d.ts +0 -4
  33. package/lib/modules/Order/index.d.ts +0 -1
  34. package/lib/modules/Order/index.js +1 -11
  35. package/lib/modules/Order/types.d.ts +0 -2
  36. package/lib/modules/ProductList/index.d.ts +1 -3
  37. package/lib/modules/ProductList/index.js +39 -45
  38. package/lib/modules/Schedule/getDateIsInSchedule.js +0 -4
  39. package/lib/solution/BookingByStep/index.d.ts +2 -2
  40. package/lib/solution/ScanOrder/index.js +1 -1
  41. package/lib/solution/ShopDiscount/index.js +2 -3
  42. package/lib/solution/VenueBooking/index.d.ts +8 -23
  43. package/lib/solution/VenueBooking/index.js +87 -164
  44. package/lib/solution/VenueBooking/utils/dateSummary.d.ts +2 -2
  45. package/lib/solution/VenueBooking/utils/dateSummary.js +10 -5
  46. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +6 -0
  47. package/lib/solution/VenueBooking/utils/slotMerge.js +4 -3
  48. package/lib/solution/VenueBooking/utils/timeSlot.d.ts +0 -2
  49. package/lib/solution/VenueBooking/utils/timeSlot.js +3 -7
  50. package/package.json +1 -1
  51. package/dist/model/strategy/adapter/dataVariant/adapter.d.ts +0 -50
  52. package/dist/model/strategy/adapter/dataVariant/adapter.js +0 -167
  53. package/dist/model/strategy/adapter/dataVariant/evaluator.d.ts +0 -89
  54. package/dist/model/strategy/adapter/dataVariant/evaluator.js +0 -780
  55. package/dist/model/strategy/adapter/dataVariant/examples.d.ts +0 -39
  56. package/dist/model/strategy/adapter/dataVariant/examples.js +0 -277
  57. package/dist/model/strategy/adapter/dataVariant/index.d.ts +0 -4
  58. package/dist/model/strategy/adapter/dataVariant/index.js +0 -4
  59. package/dist/model/strategy/adapter/dataVariant/type.d.ts +0 -148
  60. package/dist/model/strategy/adapter/dataVariant/type.js +0 -54
  61. package/dist/solution/VenueBooking/utils/smartPricing.d.ts +0 -70
  62. package/dist/solution/VenueBooking/utils/smartPricing.js +0 -233
  63. package/lib/model/strategy/adapter/dataVariant/adapter.d.ts +0 -50
  64. package/lib/model/strategy/adapter/dataVariant/adapter.js +0 -149
  65. package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +0 -89
  66. package/lib/model/strategy/adapter/dataVariant/evaluator.js +0 -583
  67. package/lib/model/strategy/adapter/dataVariant/examples.d.ts +0 -39
  68. package/lib/model/strategy/adapter/dataVariant/examples.js +0 -293
  69. package/lib/model/strategy/adapter/dataVariant/index.d.ts +0 -4
  70. package/lib/model/strategy/adapter/dataVariant/index.js +0 -38
  71. package/lib/model/strategy/adapter/dataVariant/type.d.ts +0 -148
  72. package/lib/model/strategy/adapter/dataVariant/type.js +0 -31
  73. package/lib/solution/VenueBooking/utils/smartPricing.d.ts +0 -70
  74. package/lib/solution/VenueBooking/utils/smartPricing.js +0 -180
@@ -3,7 +3,6 @@ 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';
7
6
  import type { OpenDataAvailabilityResult } from '../../modules/OpenData';
8
7
  import type { ProductData } from '../../modules/Product/types';
9
8
  import { type CartItemSummary, type PaxInfo, type QuantityCheckResult, type QuantityLimitResult } from '../../model/strategy/adapter/itemRule';
@@ -41,10 +40,6 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
41
40
  private productsLoaded;
42
41
  private loadOpenDataConfigInFlight;
43
42
  private static readonly OPEN_DATA_CACHE_TTL;
44
- /** 按日期缓存 slot 智能定价 Map,避免同周重复 resolveProducts */
45
- private slotPriceMapCache;
46
- /** loadProducts 后缓存的全量商品(venue + addon),供分段算价复用 */
47
- private smartPricingProductCatalog;
48
43
  private getLoggerContext;
49
44
  private safeStringify;
50
45
  private pickErrorMessage;
@@ -73,22 +68,6 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
73
68
  passed: boolean | null;
74
69
  failures: QuantityCheckResult[];
75
70
  };
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;
92
71
  loadAllProducts(): Promise<{
93
72
  venueProducts: ProductData[];
94
73
  addonProducts: ProductData[];
@@ -161,7 +140,8 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
161
140
  setSlotConfig(config: Partial<VenueBookingSlotConfig>): void;
162
141
  getSlotConfig(): VenueBookingSlotConfig;
163
142
  loadSchedules(): Promise<void>;
164
- getScheduleListByIds(ids: number[]): ScheduleItem[];
143
+ private injectScheduleResolverToQuotation;
144
+ getScheduleListByIds(ids: number[]): import("../../modules/Schedule/types").ScheduleItem[];
165
145
  getTempOrder(): import("./types").ScanOrderTempOrder | null;
166
146
  updateTempOrderNote(note: string): string;
167
147
  updateTempOrderContactsInfo(contactsInfo: any[]): any[];
@@ -169,7 +149,7 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
169
149
  onCustomerLogin(params: {
170
150
  customerId: number;
171
151
  }): Promise<void>;
172
- private recalculateOrderPricesFromSmartPricing;
152
+ private recalculateOrderPricesFromQuotation;
173
153
  scanCode(code: string, customerId?: number): Promise<{
174
154
  isAvailable: boolean;
175
155
  discountList: import("../../modules/Discount").Discount[];
@@ -188,6 +168,11 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
188
168
  getOrderProducts(): ScanOrderOrderProduct[];
189
169
  getSummary(): Promise<import("./types").ScanOrderSummary>;
190
170
  submitOrder<T = any>(): Promise<T>;
171
+ /**
172
+ * 0 元订单免费领取(非定金场景)
173
+ * 与 appointment getFreeProduct 同接口:POST /pay/order/free-pay/:id
174
+ */
175
+ submitFreeOrder(id: string | number): Promise<any>;
191
176
  addProductToOrder(product: Partial<ScanOrderOrderProduct> & ScanOrderOrderProductIdentity): Promise<ScanOrderOrderProduct[]>;
192
177
  updateProductInOrder(params: UpdateProductInOrderParams): Promise<ScanOrderOrderProduct[]>;
193
178
  removeProductFromOrder(identity: ScanOrderOrderProductIdentity): Promise<ScanOrderOrderProduct[]>;
@@ -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 {
@@ -303,11 +298,16 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
303
298
  }
304
299
  this.customerLoginRefreshIdInFlight = params.customerId;
305
300
  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();
306
308
  await this.store.order.loadDiscountConfig({
307
309
  customerId: params.customerId
308
310
  });
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;
329
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
330
330
  this.logMethodStart("initialize");
331
331
  this.core = core;
332
332
  this.initializeOptions = options || {};
@@ -462,6 +462,10 @@ 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
+ });
465
469
  }
466
470
  await this.refreshItemRuleQuantityLimits();
467
471
  this.store.status = "ready";
@@ -537,93 +541,6 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
537
541
  getCartValidation() {
538
542
  return this.store.cartValidation || { passed: null, failures: [] };
539
543
  }
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
- }
627
544
  // ─── 场地商品 & 附加商品 ───
628
545
  async loadAllProducts() {
629
546
  if (this.loadAllProductsInFlight)
@@ -652,18 +569,9 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
652
569
  menu_list_ids: menuListIds,
653
570
  cacheId: this.cacheId,
654
571
  schedule_date: (0, import_dayjs.default)().format("YYYY-MM-DD"),
655
- schedule_datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss"),
656
- with_extra: ["dataVariants"]
572
+ schedule_datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
657
573
  });
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();
574
+ const list = Array.isArray(allProducts) ? allProducts : [];
667
575
  const venueList = list.filter((p) => p.duration != null);
668
576
  const addonList = list.filter((p) => p.duration == null);
669
577
  const venueStore = (_c = this.store.venueProducts) == null ? void 0 : _c.store;
@@ -844,24 +752,29 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
844
752
  config: this.baseSlotConfig,
845
753
  rawResources: this.store.rawResourceData,
846
754
  resourceProductMap: this.resourceProductMap,
847
- resolveConfig: (date) => this.resolveSlotConfigForDate(date),
848
- buildSlotPriceMap: (date, config, productIds) => this.buildSlotPriceMapForDate(date, config, productIds)
755
+ quotationModule: this.store.quotation,
756
+ resolveConfig: (date) => this.resolveSlotConfigForDate(date)
849
757
  });
850
758
  }
851
759
  getTimeSlotGrid(date) {
852
760
  const resolvedSlotConfig = this.syncOperatingHoursToSlotConfig(date);
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;
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
+ }
859
772
  return (0, import_timeSlot.buildTimeSlotGrid)({
860
773
  date,
861
774
  config: resolvedSlotConfig,
862
775
  rawResources: this.store.rawResourceData,
863
776
  resourceProductMap: this.resourceProductMap,
864
- slotPriceMap
777
+ quotationPriceMap
865
778
  });
866
779
  }
867
780
  // ─── 时间槽订单操作 ───
@@ -1146,7 +1059,8 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1146
1059
  booking_uid: bookingUuid,
1147
1060
  price_breakdown: (0, import_slotMerge.buildPriceBreakdown)({
1148
1061
  group,
1149
- productId: mapping.productId
1062
+ productId: mapping.productId,
1063
+ quotation: this.store.quotation
1150
1064
  })
1151
1065
  },
1152
1066
  _origin: {
@@ -1239,12 +1153,20 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1239
1153
  if (!this.store.schedule)
1240
1154
  throw new Error("schedule 模块未初始化");
1241
1155
  await this.store.schedule.loadAllSchedule();
1156
+ this.injectScheduleResolverToQuotation();
1242
1157
  this.logMethodSuccess("loadSchedules");
1243
1158
  } catch (error) {
1244
1159
  this.logMethodError("loadSchedules", error);
1245
1160
  throw error;
1246
1161
  }
1247
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
+ }
1248
1170
  getScheduleListByIds(ids) {
1249
1171
  if (!this.store.schedule)
1250
1172
  return [];
@@ -1283,16 +1205,14 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1283
1205
  throw error;
1284
1206
  }
1285
1207
  }
1286
- recalculateOrderPricesFromSmartPricing() {
1208
+ recalculateOrderPricesFromQuotation() {
1287
1209
  var _a, _b;
1288
- if (!this.store.order)
1210
+ if (!this.store.order || !this.store.quotation)
1289
1211
  return;
1290
1212
  const tempOrder = this.store.order.getTempOrder();
1291
1213
  if (!((_a = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _a.length))
1292
1214
  return;
1293
1215
  const now = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
1294
- const catalog = this.getAllProductsForSmartPricing();
1295
- const context = this.buildSmartPricingContext();
1296
1216
  for (const product of tempOrder.products) {
1297
1217
  if ((_b = product.metadata) == null ? void 0 : _b.venue_booking) {
1298
1218
  const mappings = this.resourceProductMap.get(product.metadata.resource_id);
@@ -1305,49 +1225,34 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1305
1225
  product,
1306
1226
  this.store.slotConfig.slotDurationMinutes
1307
1227
  );
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,
1228
+ const updatedSlots = slots.map((slot) => ({
1229
+ ...slot,
1230
+ productId: mapping.productId,
1231
+ price: this.store.quotation.getPriceForProduct({
1323
1232
  productId: mapping.productId,
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
- });
1233
+ datetime: slot.startTime
1234
+ }) ?? mapping.price
1235
+ }));
1332
1236
  const merged = (0, import_slotMerge.mergeConsecutiveSlots)(updatedSlots);
1333
1237
  if (merged.length === 1) {
1334
1238
  product.selling_price = merged[0].totalPrice;
1335
1239
  product.original_price = merged[0].totalPrice;
1336
1240
  product.metadata.price_breakdown = (0, import_slotMerge.buildPriceBreakdown)({
1337
1241
  group: merged[0],
1338
- productId: mapping.productId
1242
+ productId: mapping.productId,
1243
+ quotation: this.store.quotation
1339
1244
  });
1340
1245
  }
1341
1246
  } else if (product.product_id != null) {
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
1247
+ const quotationPrice = this.store.quotation.getPriceForProduct({
1248
+ productId: product.product_id,
1249
+ variantId: product.product_variant_id ?? void 0,
1250
+ datetime: now
1348
1251
  });
1349
- product.selling_price = smartPrice;
1350
- product.original_price = smartPrice;
1252
+ if (quotationPrice !== null) {
1253
+ product.selling_price = quotationPrice;
1254
+ product.original_price = quotationPrice;
1255
+ }
1351
1256
  }
1352
1257
  }
1353
1258
  }
@@ -1532,8 +1437,26 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1532
1437
  throw error;
1533
1438
  }
1534
1439
  }
1440
+ /**
1441
+ * 0 元订单免费领取(非定金场景)
1442
+ * 与 appointment getFreeProduct 同接口:POST /pay/order/free-pay/:id
1443
+ */
1444
+ async submitFreeOrder(id) {
1445
+ this.logMethodStart("submitFreeOrder", { id });
1446
+ try {
1447
+ if (!id) {
1448
+ throw new Error("订单 ID 不能为空");
1449
+ }
1450
+ const res = await this.request.post(`/pay/order/free-pay/${id}`);
1451
+ this.logMethodSuccess("submitFreeOrder", { id, status: res == null ? void 0 : res.status });
1452
+ return res;
1453
+ } catch (error) {
1454
+ this.logMethodError("submitFreeOrder", error);
1455
+ throw error;
1456
+ }
1457
+ }
1535
1458
  async addProductToOrder(product) {
1536
- var _a, _b;
1459
+ var _a;
1537
1460
  this.logMethodStart("addProductToOrder", {
1538
1461
  product_id: product.product_id,
1539
1462
  product_variant_id: product.product_variant_id
@@ -1541,18 +1464,18 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1541
1464
  try {
1542
1465
  if (!this.store.order)
1543
1466
  throw new Error("order 模块未初始化");
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
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")
1551
1472
  });
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;
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
+ }
1556
1479
  }
1557
1480
  const products = await this.store.order.addProductToOrder(product);
1558
1481
  await this.refreshItemRuleQuantityLimits();
@@ -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
  }
@@ -27,8 +27,6 @@ export declare function buildTimeSlotGrid(params: {
27
27
  config: VenueBookingSlotConfig;
28
28
  rawResources: VenueResourceRawData[];
29
29
  resourceProductMap: Map<number | string, ResourceProductMapping[]>;
30
- /** @deprecated 使用 slotPriceMap */
31
30
  quotationPriceMap?: Map<string, string | null>;
32
- slotPriceMap?: Map<string, string | null>;
33
31
  }): VenueTimeSlotGrid;
34
32
  export {};
@@ -168,7 +168,6 @@ function buildProductSlots(params) {
168
168
  now,
169
169
  crossDay,
170
170
  quotationPriceMap,
171
- slotPriceMap,
172
171
  childRawResources,
173
172
  childTimesCache,
174
173
  childEventsCache,
@@ -232,12 +231,11 @@ function buildProductSlots(params) {
232
231
  }
233
232
  const isBookable = status === "available" || status === "partially_occupied";
234
233
  const slotStartStr = slotStart.format("YYYY-MM-DD HH:mm");
235
- const resolvedPriceMap = slotPriceMap ?? quotationPriceMap;
236
234
  slots.push({
237
235
  startTime: slotStartStr,
238
236
  endTime: slotEnd.format("YYYY-MM-DD HH:mm"),
239
237
  status,
240
- price: isBookable ? (resolvedPriceMap == null ? void 0 : resolvedPriceMap.get(`${mapping.productId}:${slotStartStr}`)) ?? mapping.price : null,
238
+ price: isBookable ? (quotationPriceMap == null ? void 0 : quotationPriceMap.get(`${mapping.productId}:${slotStartStr}`)) ?? mapping.price : null,
241
239
  resourceId: resource.resourceId,
242
240
  resourceFormId: resource.formId,
243
241
  capacity: status === "past" || status === "unavailable" ? null : resCapacity,
@@ -248,8 +246,7 @@ function buildProductSlots(params) {
248
246
  return slots;
249
247
  }
250
248
  function buildTimeSlotGrid(params) {
251
- const { date, config, rawResources, resourceProductMap, quotationPriceMap, slotPriceMap } = params;
252
- const resolvedPriceMap = slotPriceMap ?? quotationPriceMap;
249
+ const { date, config, rawResources, resourceProductMap, quotationPriceMap } = params;
253
250
  const timeLabels = generateTimeLabels(config);
254
251
  const now = (0, import_dayjs.default)();
255
252
  const crossDay = isBusinessHoursCrossDay(config);
@@ -282,8 +279,7 @@ function buildTimeSlotGrid(params) {
282
279
  resCapacity,
283
280
  now,
284
281
  crossDay,
285
- quotationPriceMap: resolvedPriceMap,
286
- slotPriceMap: resolvedPriceMap,
282
+ quotationPriceMap,
287
283
  childRawResources,
288
284
  childTimesCache,
289
285
  childEventsCache,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "2.1.163",
4
+ "version": "2.1.165",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -1,50 +0,0 @@
1
- import type { EvaluationResult, RuntimeContext } from '../../type';
2
- import type { BusinessAdapter } from '../type';
3
- import type { DataVariantBusinessData, DataVariantProduct } from './type';
4
- /**
5
- * Data Variant 适配器。
6
- *
7
- * 负责把智能定价运行态数据转换为 StrategyEngine 能识别的 attributes。
8
- */
9
- export declare class DataVariantAdapter implements BusinessAdapter {
10
- name: string;
11
- version: string;
12
- /**
13
- * 准备批量全局上下文。
14
- *
15
- * 这里只放不依赖单个商品的字段,用于预计算 schedule/channel/orderType 等条件。
16
- */
17
- prepareContext(businessData: DataVariantBusinessData): RuntimeContext;
18
- /**
19
- * 准备全局预计算上下文。
20
- */
21
- prepareGlobalContext(businessData: DataVariantBusinessData): RuntimeContext;
22
- /**
23
- * 准备单商品上下文。
24
- *
25
- * 商品级条件只在当前商品 data_variants 引用到对应规则后才评估。
26
- */
27
- prepareProductContext(businessData: DataVariantBusinessData, product: DataVariantProduct): RuntimeContext;
28
- transformResult(result: EvaluationResult): EvaluationResult;
29
- formatConfig(result: EvaluationResult, businessData?: DataVariantBusinessData): {
30
- result: EvaluationResult;
31
- businessData?: DataVariantBusinessData;
32
- };
33
- /**
34
- * 构建 menu_match 使用的轻量商品对象。
35
- *
36
- * collection_ids 来自商品 collection 字段,避免 operator 读取复杂商品对象。
37
- */
38
- buildProductValue(product: DataVariantProduct): {
39
- id: number;
40
- product_variant_id: number;
41
- collection_ids: number[];
42
- };
43
- private toNumber;
44
- /**
45
- * 归一化客户 id:无效值返回 undefined,有效值统一为 number。
46
- */
47
- private normalizeCustomerId;
48
- private normalizeNumberArray;
49
- }
50
- export default DataVariantAdapter;