@pisell/pisellos 2.2.152 → 2.2.154

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 (92) hide show
  1. package/dist/core/index.js +1 -0
  2. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  3. package/dist/modules/Cart/utils/cartProduct.js +1 -1
  4. package/dist/modules/Discount/index.d.ts +6 -2
  5. package/dist/modules/Discount/index.js +14 -8
  6. package/dist/modules/Order/index.d.ts +2 -0
  7. package/dist/modules/Order/index.js +234 -161
  8. package/dist/modules/Order/types.d.ts +19 -0
  9. package/dist/modules/Order/utils.js +7 -6
  10. package/dist/modules/Payment/index.d.ts +4 -0
  11. package/dist/modules/Payment/index.js +567 -505
  12. package/dist/modules/Payment/types.d.ts +29 -9
  13. package/dist/modules/SalesSummary/index.d.ts +7 -5
  14. package/dist/modules/SalesSummary/index.js +35 -11
  15. package/dist/plugins/app.d.ts +2 -0
  16. package/dist/server/index.d.ts +2 -5
  17. package/dist/server/index.js +58 -66
  18. package/dist/server/modules/index.d.ts +1 -1
  19. package/dist/server/modules/products/index.d.ts +12 -1
  20. package/dist/server/modules/products/index.js +169 -78
  21. package/dist/server/modules/products/types.d.ts +11 -0
  22. package/dist/server/modules/products/types.js +4 -0
  23. package/dist/server/utils/product.js +2 -2
  24. package/dist/solution/BaseSales/index.d.ts +26 -2
  25. package/dist/solution/BaseSales/index.js +342 -112
  26. package/dist/solution/BaseSales/types.d.ts +4 -4
  27. package/dist/solution/BaseSales/types.js +4 -4
  28. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +62 -0
  29. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +116 -0
  30. package/dist/solution/BaseSales/utils.js +3 -3
  31. package/dist/solution/BookingByStep/index.d.ts +1 -1
  32. package/dist/solution/BookingTicket/index.d.ts +11 -13
  33. package/dist/solution/BookingTicket/index.js +23 -37
  34. package/dist/solution/BookingTicket/types.d.ts +9 -6
  35. package/dist/solution/BookingTicket/types.js +6 -3
  36. package/dist/solution/BookingTicket/utils/cartView.d.ts +7 -12
  37. package/dist/solution/BookingTicket/utils/cartView.js +52 -14
  38. package/dist/solution/BookingTicket/utils/orderCustomer.d.ts +4 -0
  39. package/dist/solution/BookingTicket/utils/orderCustomer.js +31 -0
  40. package/dist/solution/Sales/index.d.ts +3 -0
  41. package/dist/solution/Sales/index.js +85 -43
  42. package/dist/solution/Sales/types.d.ts +3 -0
  43. package/dist/solution/ScanOrder/types.d.ts +4 -4
  44. package/dist/solution/ScanOrder/types.js +4 -4
  45. package/dist/solution/ScanOrder/utils.js +3 -3
  46. package/dist/solution/ShopDiscount/index.d.ts +2 -1
  47. package/dist/solution/ShopDiscount/index.js +32 -20
  48. package/dist/solution/ShopDiscount/types.d.ts +1 -0
  49. package/lib/core/index.js +1 -0
  50. package/lib/modules/Cart/utils/cartProduct.js +1 -1
  51. package/lib/modules/Discount/index.d.ts +6 -2
  52. package/lib/modules/Discount/index.js +3 -1
  53. package/lib/modules/Order/index.d.ts +2 -0
  54. package/lib/modules/Order/index.js +40 -8
  55. package/lib/modules/Order/types.d.ts +19 -0
  56. package/lib/modules/Order/utils.js +4 -2
  57. package/lib/modules/Payment/index.d.ts +4 -0
  58. package/lib/modules/Payment/index.js +26 -2
  59. package/lib/modules/Payment/types.d.ts +29 -9
  60. package/lib/modules/SalesSummary/index.d.ts +7 -5
  61. package/lib/modules/SalesSummary/index.js +29 -9
  62. package/lib/plugins/app.d.ts +2 -0
  63. package/lib/server/index.d.ts +2 -5
  64. package/lib/server/index.js +38 -58
  65. package/lib/server/modules/index.d.ts +1 -1
  66. package/lib/server/modules/products/index.d.ts +12 -1
  67. package/lib/server/modules/products/index.js +69 -9
  68. package/lib/server/modules/products/types.d.ts +11 -0
  69. package/lib/server/utils/product.js +2 -2
  70. package/lib/solution/BaseSales/index.d.ts +26 -2
  71. package/lib/solution/BaseSales/index.js +169 -3
  72. package/lib/solution/BaseSales/types.d.ts +4 -4
  73. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +62 -0
  74. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +155 -0
  75. package/lib/solution/BaseSales/utils.js +3 -3
  76. package/lib/solution/BookingByStep/index.d.ts +1 -1
  77. package/lib/solution/BookingTicket/index.d.ts +11 -13
  78. package/lib/solution/BookingTicket/index.js +17 -27
  79. package/lib/solution/BookingTicket/types.d.ts +9 -6
  80. package/lib/solution/BookingTicket/utils/cartView.d.ts +7 -12
  81. package/lib/solution/BookingTicket/utils/cartView.js +44 -18
  82. package/lib/solution/BookingTicket/utils/orderCustomer.d.ts +4 -0
  83. package/lib/solution/BookingTicket/utils/orderCustomer.js +58 -0
  84. package/lib/solution/Sales/index.d.ts +3 -0
  85. package/lib/solution/Sales/index.js +50 -15
  86. package/lib/solution/Sales/types.d.ts +3 -0
  87. package/lib/solution/ScanOrder/types.d.ts +4 -4
  88. package/lib/solution/ScanOrder/utils.js +3 -3
  89. package/lib/solution/ShopDiscount/index.d.ts +2 -1
  90. package/lib/solution/ShopDiscount/index.js +10 -4
  91. package/lib/solution/ShopDiscount/types.d.ts +1 -0
  92. package/package.json +1 -1
@@ -2,7 +2,7 @@ import { Module, PisellCore } from '../../../types';
2
2
  import { BaseModule } from '../../../modules/BaseModule';
3
3
  import { ProductData } from '../../../modules/Product/types';
4
4
  import type { RouteDefinition } from '../../types';
5
- import { ProductFormatter, ProductFormatterContext } from './types';
5
+ import { ProductIdScope, ProductFormatter, ProductFormatterContext } from './types';
6
6
  /**
7
7
  * Products 模块 - 用于获取和管理完整的商品详细数据
8
8
  * 相比 ProductList 模块,Products 会获取所有详细信息并缓存
@@ -80,10 +80,12 @@ export declare class ProductsModule extends BaseModule implements Module {
80
80
  * @param extraContext 额外的上下文数据(可选,由 Server 层传入)
81
81
  * @param options 可选参数
82
82
  * @param options.changedIds 变更的商品 IDs,非空时仅对这些商品增量执行 prepare 并更新缓存
83
+ * @param options.productIds 指定商品 IDs,仅对这些商品执行价格计算;不传则处理全量
83
84
  * @returns 应用了价格的商品列表
84
85
  */
85
86
  getProductsWithPrice(schedule_date: string, extraContext?: Partial<ProductFormatterContext>, options?: {
86
87
  changedIds?: number[];
88
+ productIds?: number[];
87
89
  }): Promise<ProductData[]>;
88
90
  /**
89
91
  * 准备带价格的商品数据(通过格式化器流程处理)
@@ -96,6 +98,11 @@ export declare class ProductsModule extends BaseModule implements Module {
96
98
  */
97
99
  private prepareProductsWithPrice;
98
100
  private getProductsPriceCacheKey;
101
+ private normalizeProductIds;
102
+ /**
103
+ * 按轻量范围返回商品 ID,不做 structuredClone。
104
+ */
105
+ getProductIdsByScope(scope: ProductIdScope): number[];
99
106
  /**
100
107
  * 应用所有已注册的格式化器
101
108
  * @param products 商品列表
@@ -173,6 +180,10 @@ export declare class ProductsModule extends BaseModule implements Module {
173
180
  * 仅供内部 formatter 流程使用,因为 formatter 会创建新对象
174
181
  */
175
182
  private getProductsRef;
183
+ /**
184
+ * 按 ID 从 Map 取商品引用,供内部 formatter 流程使用。
185
+ */
186
+ private getProductsRefByIds;
176
187
  /**
177
188
  * 根据ID获取单个商品(从内存缓存)
178
189
  * 使用 Map 快速查询,时间复杂度 O(1)
@@ -326,12 +326,16 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
326
326
  * @param extraContext 额外的上下文数据(可选,由 Server 层传入)
327
327
  * @param options 可选参数
328
328
  * @param options.changedIds 变更的商品 IDs,非空时仅对这些商品增量执行 prepare 并更新缓存
329
+ * @param options.productIds 指定商品 IDs,仅对这些商品执行价格计算;不传则处理全量
329
330
  * @returns 应用了价格的商品列表
330
331
  */
331
332
  async getProductsWithPrice(schedule_date, extraContext, options) {
333
+ var _a;
332
334
  const t0 = performance.now();
333
- const cacheKey = this.getProductsPriceCacheKey(schedule_date, extraContext);
334
- const changedIds = options == null ? void 0 : options.changedIds;
335
+ const scopedProductIds = this.normalizeProductIds(options == null ? void 0 : options.productIds);
336
+ const cacheKey = this.getProductsPriceCacheKey(schedule_date, extraContext, scopedProductIds);
337
+ const scopedProductIdSet = scopedProductIds ? new Set(scopedProductIds) : void 0;
338
+ const changedIds = scopedProductIdSet ? (_a = options == null ? void 0 : options.changedIds) == null ? void 0 : _a.filter((id) => scopedProductIdSet.has(id)) : options == null ? void 0 : options.changedIds;
335
339
  if (this.productsPriceCache.has(cacheKey)) {
336
340
  const cachedProducts = this.productsPriceCache.get(cacheKey);
337
341
  if (changedIds && changedIds.length > 0) {
@@ -398,8 +402,15 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
398
402
  });
399
403
  return cachedProducts;
400
404
  }
401
- this.logInfo("商品价格缓存未命中,准备获取", { cacheKey });
402
- const result = await this.prepareProductsWithPrice(schedule_date, extraContext);
405
+ this.logInfo("商品价格缓存未命中,准备获取", {
406
+ cacheKey,
407
+ scopedProductCount: scopedProductIds == null ? void 0 : scopedProductIds.length
408
+ });
409
+ const result = await this.prepareProductsWithPrice(
410
+ schedule_date,
411
+ extraContext,
412
+ scopedProductIds ? { productIds: scopedProductIds } : void 0
413
+ );
403
414
  this.productsPriceCache.set(cacheKey, result);
404
415
  this.logInfo("商品价格已缓存", {
405
416
  cacheKey,
@@ -425,7 +436,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
425
436
  var _a, _b;
426
437
  const tTotal = performance.now();
427
438
  const targetIds = options == null ? void 0 : options.productIds;
428
- const isIncremental = targetIds && targetIds.length > 0;
439
+ const isIncremental = Array.isArray(targetIds);
429
440
  this.logInfo("prepareProductsWithPrice 开始处理", {
430
441
  schedule_date,
431
442
  mode: isIncremental ? "incremental" : "full",
@@ -435,8 +446,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
435
446
  let products;
436
447
  let ids;
437
448
  if (isIncremental) {
438
- const idSet = new Set(targetIds);
439
- products = this.getProductsRef().filter((p) => idSet.has(p.id));
449
+ products = this.getProductsRefByIds(targetIds);
440
450
  ids = products.map((p) => p.id);
441
451
  } else {
442
452
  products = this.getProductsRef();
@@ -499,9 +509,47 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
499
509
  }
500
510
  return [];
501
511
  }
502
- getProductsPriceCacheKey(schedule_date, extraContext) {
512
+ getProductsPriceCacheKey(schedule_date, extraContext, productIds) {
503
513
  const datetime = (extraContext == null ? void 0 : extraContext.schedule_datetime) || schedule_date;
504
- return `${datetime}:customer:${(extraContext == null ? void 0 : extraContext.customer_id) ?? ""}`;
514
+ const productScope = productIds ? `:products:${productIds.join(",")}` : "";
515
+ return `${datetime}:customer:${(extraContext == null ? void 0 : extraContext.customer_id) ?? ""}${productScope}`;
516
+ }
517
+ normalizeProductIds(productIds) {
518
+ if (!Array.isArray(productIds))
519
+ return void 0;
520
+ return Array.from(new Set(
521
+ productIds.map((id) => Number(id)).filter((id) => Number.isFinite(id))
522
+ )).sort((a, b) => a - b);
523
+ }
524
+ /**
525
+ * 按轻量范围返回商品 ID,不做 structuredClone。
526
+ */
527
+ getProductIdsByScope(scope) {
528
+ const productIds = this.normalizeProductIds(scope.productIds) || [];
529
+ const collectionIds = this.normalizeProductIds(scope.collectionIds) || [];
530
+ if (scope.isAllProducts) {
531
+ return this.getProductsRef().map((product) => product.id);
532
+ }
533
+ if (productIds.length === 0 && collectionIds.length === 0)
534
+ return [];
535
+ const result = /* @__PURE__ */ new Set();
536
+ for (const id of productIds) {
537
+ if (this.store.map.has(id))
538
+ result.add(id);
539
+ }
540
+ if (collectionIds.length === 0)
541
+ return Array.from(result);
542
+ const collectionIdSet = new Set(collectionIds);
543
+ for (const product of this.getProductsRef()) {
544
+ if (result.has(product.id))
545
+ continue;
546
+ if (!Array.isArray(product.collection))
547
+ continue;
548
+ const isInCollection = product.collection.some((collection) => collectionIdSet.has(collection.id));
549
+ if (isInCollection)
550
+ result.add(product.id);
551
+ }
552
+ return Array.from(result);
505
553
  }
506
554
  /**
507
555
  * 应用所有已注册的格式化器
@@ -776,6 +824,18 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
776
824
  getProductsRef() {
777
825
  return this.store.list;
778
826
  }
827
+ /**
828
+ * 按 ID 从 Map 取商品引用,供内部 formatter 流程使用。
829
+ */
830
+ getProductsRefByIds(ids) {
831
+ const products = [];
832
+ for (const id of ids) {
833
+ const product = this.store.map.get(id);
834
+ if (product)
835
+ products.push(product);
836
+ }
837
+ return products;
838
+ }
779
839
  /**
780
840
  * 根据ID获取单个商品(从内存缓存)
781
841
  * 使用 Map 快速查询,时间复杂度 O(1)
@@ -17,6 +17,17 @@ export interface FormattedProductData extends ProductData {
17
17
  /** 购物车详情值 */
18
18
  cartDetailValue?: any;
19
19
  }
20
+ /**
21
+ * 商品轻量查询范围
22
+ */
23
+ export interface ProductIdScope {
24
+ /** 是否返回全部商品 ID */
25
+ isAllProducts?: boolean;
26
+ /** 指定商品 ID */
27
+ productIds?: number[];
28
+ /** 指定商品集合 ID */
29
+ collectionIds?: number[];
30
+ }
20
31
  /**
21
32
  * 加载报价单商品价格参数
22
33
  */
@@ -195,7 +195,7 @@ var formatDataKey = (data) => {
195
195
  }
196
196
  if ((_a = _data == null ? void 0 : _data.option) == null ? void 0 : _a.length) {
197
197
  for (const item of _data.option) {
198
- let str = `_${item.option_group_id}_${item.product_option_item_id}`;
198
+ let str = `_${item.option_group_id}_${item.option_group_item_id}`;
199
199
  key += str;
200
200
  rowKey += `${str}_${item.quantity || item.num}`;
201
201
  }
@@ -207,7 +207,7 @@ var formatDataKey = (data) => {
207
207
  rowKey += `${str}_${item.quantity || item.num}`;
208
208
  if (item == null ? void 0 : item.option) {
209
209
  for (const opt of item.option) {
210
- let str2 = `_${opt.option_group_id}_${opt.product_option_item_id}`;
210
+ let str2 = `_${opt.option_group_id}_${opt.option_group_item_id}`;
211
211
  key += str2;
212
212
  rowKey += `${str2}_${opt.quantity || opt.num}`;
213
213
  }
@@ -8,12 +8,15 @@ import type { Discount } from '../../modules/Discount/types';
8
8
  import { RequestPlugin, WindowPlugin } from '../../plugins';
9
9
  export * from './types';
10
10
  import { ProductList } from '../../modules/ProductList';
11
+ import { PaymentModule } from '../../modules/Payment';
11
12
  import type { SalesSummaryModule } from '../../modules/SalesSummary';
12
13
  import type { ScheduleModule } from '../../modules/Schedule';
13
14
  import type { ISalesDetail, ISalesDetailHeader, ISalesBooking, ISalesPayment, ISalesSurcharge } from './utils/parseSalesResponse';
15
+ import { type TransformBaseProductToOrderProductParams } from './utils/transformBaseProductToOrderProduct';
14
16
  export interface BaseSalesState {
15
17
  order?: OrderModule;
16
18
  products?: ProductList;
19
+ payment?: PaymentModule;
17
20
  salesSummary?: SalesSummaryModule;
18
21
  schedule?: ScheduleModule;
19
22
  }
@@ -22,6 +25,7 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
22
25
  protected defaultVersion: string;
23
26
  isSolution: boolean;
24
27
  protected initializeOptions: ModuleOptions;
28
+ private logger;
25
29
  protected store: BaseSalesState;
26
30
  protected otherParams: Record<string, any>;
27
31
  protected cacheId: string | undefined;
@@ -35,15 +39,29 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
35
39
  constructor(name?: string, version?: string);
36
40
  /**
37
41
  * 子类可覆盖此方法以追加/收敛要注册的子模块。
38
- * 默认包含通用销售模块:products / order / salesSummary / schedule。
42
+ * 默认包含通用销售模块:products / order / salesSummary / schedule / payment
39
43
  */
40
44
  protected getRegisteredModuleNames(): readonly string[];
45
+ /**
46
+ * 记录信息日志
47
+ */
48
+ private logInfo;
49
+ /**
50
+ * 记录警告日志
51
+ */
52
+ private logWarning;
53
+ /**
54
+ * 记录错误日志
55
+ */
56
+ private logError;
57
+ get payment(): PaymentModule | undefined;
41
58
  /**
42
59
  * 工厂入口:根据子模块名实例化对应模块。
43
60
  * 默认使用 BookingByStep 公共 `createModule`。子类若需引入额外类型(如 customer),
44
61
  * 可覆盖此方法并把未识别的 name 委托给 `super.createSubModule(name)`。
45
62
  */
46
63
  protected createSubModule(moduleName: string): Module | null;
64
+ protected getSubModuleHooks(moduleName: string): any;
47
65
  /**
48
66
  * 读取 sessionStorage[this.name][cacheId],作为子模块 initialState 的来源。
49
67
  * sessionStorage 损坏时静默忽略,按空状态注册。
@@ -80,7 +98,8 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
80
98
  getOrderAmountSnapshot(): import("../../modules/Order/types").OrderAmountSnapshot | null;
81
99
  getTempOrderNote(): string;
82
100
  updateTempOrderNote(note: string): string;
83
- updateOrderShopDiscount(amount: string | number): string;
101
+ updateTempOrderShopDiscount(amount: string | number): string;
102
+ updateTempOrderContactsInfo(contactsInfo: Record<string, any> | null): Record<string, any> | null;
84
103
  private ensureTempOrder;
85
104
  addNewOrder(): Promise<import("../../modules/Order/types").OrderTempOrder>;
86
105
  saveDraft(): Promise<void>;
@@ -124,6 +143,10 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
124
143
  deleteOrderPayment(paymentIdentity: string | number): OrderPaymentData[];
125
144
  /** 覆盖 wallet pass 支付项,同时保留普通支付项。 */
126
145
  updateVoucherOrderPayments(payments: OrderPaymentSource[]): OrderPaymentData[];
146
+ private getWalletProductList;
147
+ initWalletData(params?: {
148
+ order_wait_pay_amount?: number;
149
+ }): Promise<import("../../modules/Payment").WalletInitializationResult>;
127
150
  /**
128
151
  * 更新当前订单客户字段。
129
152
  *
@@ -159,6 +182,7 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
159
182
  order_ids?: Array<number | string>;
160
183
  submitBeforeSend?: boolean;
161
184
  }): Promise<T>;
185
+ transformBaseProductToOrderProduct(params: TransformBaseProductToOrderProductParams): import("./utils/transformBaseProductToOrderProduct").BaseProductOrderProductInput | null;
162
186
  addProductToOrder(product: Partial<BaseSalesOrderProduct> & BaseSalesOrderProductIdentity, booking?: AddProductBookingInput): Promise<import("../../modules/Order/types").OrderProduct[]>;
163
187
  updateProductInOrder(params: UpdateProductInOrderParams): Promise<import("../../modules/Order/types").OrderProduct[]>;
164
188
  /**
@@ -40,6 +40,7 @@ var import_types = require("../BookingByStep/types");
40
40
  var import_utils = require("../../modules/Order/utils");
41
41
  var import_dayjs = __toESM(require("dayjs"));
42
42
  __reExport(BaseSales_exports, require("./types"), module.exports);
43
+ var import_transformBaseProductToOrderProduct = require("./utils/transformBaseProductToOrderProduct");
43
44
  var BaseSalesImpl = class extends import_BaseModule.BaseModule {
44
45
  constructor(name, version) {
45
46
  super(name, version);
@@ -47,6 +48,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
47
48
  this.defaultVersion = "1.0.0";
48
49
  this.isSolution = true;
49
50
  this.initializeOptions = {};
51
+ // LoggerManager 实例
50
52
  this.store = {
51
53
  order: void 0
52
54
  };
@@ -56,10 +58,52 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
56
58
  }
57
59
  /**
58
60
  * 子类可覆盖此方法以追加/收敛要注册的子模块。
59
- * 默认包含通用销售模块:products / order / salesSummary / schedule。
61
+ * 默认包含通用销售模块:products / order / salesSummary / schedule / payment
60
62
  */
61
63
  getRegisteredModuleNames() {
62
- return ["products", "order", "salesSummary", "schedule"];
64
+ return ["products", "order", "salesSummary", "schedule", "payment"];
65
+ }
66
+ /**
67
+ * 记录信息日志
68
+ */
69
+ logInfo(title, metadata) {
70
+ if (this.logger) {
71
+ const tempOrder = this.getTempOrder();
72
+ this.logger.addLog({
73
+ type: "info",
74
+ title: `[BaseSales] ${tempOrder == null ? void 0 : tempOrder.order_id} ${tempOrder == null ? void 0 : tempOrder.external_sale_number} ${title}`,
75
+ metadata: metadata || {}
76
+ });
77
+ }
78
+ }
79
+ /**
80
+ * 记录警告日志
81
+ */
82
+ logWarning(title, metadata) {
83
+ if (this.logger) {
84
+ const tempOrder = this.getTempOrder();
85
+ this.logger.addLog({
86
+ type: "warning",
87
+ title: `[BaseSales] ${tempOrder == null ? void 0 : tempOrder.order_id} ${tempOrder == null ? void 0 : tempOrder.external_sale_number} ${title}`,
88
+ metadata: metadata || {}
89
+ });
90
+ }
91
+ }
92
+ /**
93
+ * 记录错误日志
94
+ */
95
+ logError(title, metadata) {
96
+ if (this.logger) {
97
+ const tempOrder = this.getTempOrder();
98
+ this.logger.addLog({
99
+ type: "error",
100
+ title: `[BaseSales] ${tempOrder == null ? void 0 : tempOrder.order_id} ${tempOrder == null ? void 0 : tempOrder.external_sale_number} ${title}`,
101
+ metadata: metadata || {}
102
+ });
103
+ }
104
+ }
105
+ get payment() {
106
+ return this.store.payment;
63
107
  }
64
108
  /**
65
109
  * 工厂入口:根据子模块名实例化对应模块。
@@ -69,6 +113,16 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
69
113
  createSubModule(moduleName) {
70
114
  return (0, import_types.createModule)(moduleName, this.name);
71
115
  }
116
+ getSubModuleHooks(moduleName) {
117
+ var _a, _b;
118
+ const optionHooks = this.initializeOptions.hooks || {};
119
+ const otherHooks = this.otherParams.hooks || {};
120
+ if (moduleName === "order") {
121
+ const directOrderHooks = optionHooks;
122
+ return optionHooks.order || ((_a = this.otherParams.order) == null ? void 0 : _a.hooks) || otherHooks.order || (directOrderHooks.onBeforeMergeProductToOrder ? directOrderHooks : void 0);
123
+ }
124
+ return optionHooks[moduleName] || ((_b = this.otherParams[moduleName]) == null ? void 0 : _b.hooks) || otherHooks[moduleName];
125
+ }
72
126
  /**
73
127
  * 读取 sessionStorage[this.name][cacheId],作为子模块 initialState 的来源。
74
128
  * sessionStorage 损坏时静默忽略,按空状态注册。
@@ -94,6 +148,12 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
94
148
  this.cacheId = (_a = this.otherParams) == null ? void 0 : _a.cacheId;
95
149
  this.window = core.getPlugin("window");
96
150
  this.request = core.getPlugin("request");
151
+ const appPlugin = core.getPlugin("app");
152
+ if (!appPlugin) {
153
+ throw new Error("Checkout 解决方案需要 app 插件支持");
154
+ }
155
+ const app = appPlugin.getApp();
156
+ this.logger = app.logger;
97
157
  const targetCacheData = this.readSessionCacheData();
98
158
  const moduleNames = this.getRegisteredModuleNames();
99
159
  moduleNames.forEach((step) => {
@@ -101,9 +161,11 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
101
161
  if (!targetModule) {
102
162
  throw new Error(`模块 ${step} 不存在`);
103
163
  }
164
+ const hooks = this.getSubModuleHooks(step);
104
165
  this.store[step] = targetModule;
105
166
  this.core.registerModule(targetModule, {
106
167
  initialState: (targetCacheData == null ? void 0 : targetCacheData[targetModule.name]) || {},
168
+ ...hooks ? { hooks } : {},
107
169
  otherParams: {
108
170
  ...this.otherParams,
109
171
  salesSummaryModuleName: `${this.name}_salesSummary`,
@@ -259,11 +321,16 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
259
321
  throw error;
260
322
  }
261
323
  }
262
- updateOrderShopDiscount(amount) {
324
+ updateTempOrderShopDiscount(amount) {
263
325
  if (!this.store.order)
264
326
  throw new Error("order 模块未初始化");
265
327
  return this.store.order.updateTempOrderShopDiscount(amount);
266
328
  }
329
+ updateTempOrderContactsInfo(contactsInfo) {
330
+ if (!this.store.order)
331
+ throw new Error("order 模块未初始化");
332
+ return this.store.order.updateTempOrderContactsInfo(contactsInfo);
333
+ }
267
334
  ensureTempOrder() {
268
335
  if (!this.store.order)
269
336
  throw new Error("order 模块未初始化");
@@ -496,6 +563,99 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
496
563
  throw new Error("order 模块未初始化");
497
564
  return this.store.order.updateVoucherOrderPayments(payments);
498
565
  }
566
+ getWalletProductList() {
567
+ var _a, _b;
568
+ const tempOrder = (_a = this.store.order) == null ? void 0 : _a.getTempOrder();
569
+ if (!((_b = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _b.length))
570
+ return [];
571
+ return tempOrder.products.map((product) => {
572
+ const metadata = product.metadata || {};
573
+ return {
574
+ product_id: product.product_id,
575
+ product_variant_id: String(product.product_variant_id ?? ""),
576
+ quantity: product.num || 1,
577
+ is_price_include_tax: tempOrder.is_price_include_tax,
578
+ is_charge_tax: product.is_charge_tax ?? 0,
579
+ tax_fee: product.tax_fee,
580
+ selling_price: Number(product.selling_price || 0),
581
+ holder_id: product.holder_id ?? metadata.holder_id,
582
+ original_price: product.original_price,
583
+ main_product_original_price: metadata.main_product_original_price ?? product.original_price,
584
+ main_product_selling_price: metadata.main_product_selling_price ?? product.selling_price,
585
+ metadata: {
586
+ main_product_attached_bundle_tax_fee: metadata.main_product_attached_bundle_tax_fee,
587
+ main_product_attached_bundle_surcharge_fee: metadata.main_product_attached_bundle_surcharge_fee,
588
+ surcharge_rounding_remainder: metadata.surcharge_rounding_remainder
589
+ },
590
+ product_bundle: (product.product_bundle || []).map((bundle) => {
591
+ const bundleMetadata = bundle.metadata || {};
592
+ return {
593
+ is_price_include_tax: tempOrder.is_price_include_tax,
594
+ bundle_id: bundle.bundle_id,
595
+ bundle_product_id: bundle.bundle_product_id,
596
+ bundle_variant_id: bundle.bundle_variant_id,
597
+ price_type: bundle.price_type,
598
+ price_type_ext: bundle.price_type_ext,
599
+ bundle_sum_price: bundle.bundle_sum_price,
600
+ bundle_selling_price: bundle.bundle_selling_price,
601
+ num: bundle.num,
602
+ is_charge_tax: bundle.is_charge_tax,
603
+ tax_fee: bundle.tax_fee,
604
+ metadata: {
605
+ surcharge_fee: bundleMetadata.surcharge_fee,
606
+ surcharge_rounding_remainder: bundleMetadata.surcharge_rounding_remainder
607
+ }
608
+ };
609
+ })
610
+ };
611
+ });
612
+ }
613
+ async initWalletData(params) {
614
+ if (!this.store.order)
615
+ throw new Error("order 模块未初始化");
616
+ if (!this.store.payment)
617
+ throw new Error("payment 模块未初始化");
618
+ const snapshot = this.store.order.getOrderSnapshot();
619
+ const tempOrder = snapshot == null ? void 0 : snapshot.tempOrder;
620
+ const amount = snapshot == null ? void 0 : snapshot.amount;
621
+ if (!tempOrder || !amount) {
622
+ return {
623
+ walletRecommendList: [],
624
+ userIdentificationCodes: [],
625
+ transformList: [],
626
+ noApplicableVoucher: [],
627
+ products: []
628
+ };
629
+ }
630
+ const walletBusinessData = {
631
+ customer_id: tempOrder.customer_id ? Number(tempOrder.customer_id) : void 0,
632
+ holder: tempOrder.holder,
633
+ amountInfo: {
634
+ totalAmount: amount.totalAmount,
635
+ subTotal: amount.summary.product_amount || amount.summary.product_expect_amount || amount.totalAmount,
636
+ depositAmount: amount.depositAmount,
637
+ isDeposit: tempOrder.is_deposit
638
+ },
639
+ products: this.getWalletProductList(),
640
+ order_wait_pay_amount: (params == null ? void 0 : params.order_wait_pay_amount) ?? Number(amount.amountGap || 0),
641
+ is_price_include_tax: tempOrder.is_price_include_tax ?? this.otherParams.is_price_include_tax ?? 1,
642
+ ...snapshot.identity.orderId ? { payment_order_id: String(snapshot.identity.orderId) } : {}
643
+ };
644
+ const result = await this.store.payment.wallet.initializeWalletDataFromBusinessAsync(
645
+ walletBusinessData
646
+ );
647
+ await this.core.effects.emit(`${this.name}:onWalletDataInitialized`, {
648
+ orderId: snapshot.identity.orderId,
649
+ customerId: walletBusinessData.customer_id,
650
+ walletBusinessData: {
651
+ customer_id: walletBusinessData.customer_id,
652
+ amountInfo: walletBusinessData.amountInfo,
653
+ order_wait_pay_amount: walletBusinessData.order_wait_pay_amount
654
+ },
655
+ timestamp: Date.now()
656
+ });
657
+ return result;
658
+ }
499
659
  /**
500
660
  * 更新当前订单客户字段。
501
661
  *
@@ -512,6 +672,9 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
512
672
  }
513
673
  /** 获取可用支付方式列表,供 PaymentModal 渲染支付选项。 */
514
674
  async getPaymentMethodsAsync() {
675
+ if (this.store.payment) {
676
+ return this.store.payment.getPayMethodListAsync();
677
+ }
515
678
  const response = await this.request.get("/pay/custom-payment/all");
516
679
  return (response == null ? void 0 : response.data) || [];
517
680
  }
@@ -565,6 +728,9 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
565
728
  order_ids: orderIds
566
729
  });
567
730
  }
731
+ transformBaseProductToOrderProduct(params) {
732
+ return (0, import_transformBaseProductToOrderProduct.transformBaseProductToOrderProduct)(params);
733
+ }
568
734
  async addProductToOrder(product, booking) {
569
735
  try {
570
736
  if (!this.store.order)
@@ -91,13 +91,13 @@ export interface BaseSalesOrderProduct extends BaseSalesOrderProductIdentity {
91
91
  * 出站 payload 版本的商品行。
92
92
  *
93
93
  * 与 tempOrder 内部 `BaseSalesOrderProduct` 的字段差异:
94
- * - `product_option_item[*]`:内部为 `{ product_option_item_id, option_group_id, num, price, ... }`,
95
- * 出站由 `normalizeSubmitProduct` 重命名为 `{ option_group_item_id, option_group_id, num }`
94
+ * - `product_option_item[*]`:内部为 `{ option_group_item_id, option_group_id, num, price, ... }`,
95
+ * 出站保留 `{ option_group_item_id, option_group_id, num }`
96
96
  * (后端 checkout 协议;丢弃 `price` 等运行时辅助字段)。
97
97
  * - `product_bundle[*].option[*]`:同上重命名规则。
98
98
  *
99
- * 运行时(UI 显示、加购合并、指纹、持久化)全部消费内部字段名 `product_option_item_id`,
100
- * 仅在 SDK 提交边界做一次出站映射,不影响 opaque identity 契约。
99
+ * 运行时(UI 显示、加购合并、指纹、持久化)与提交边界统一消费字段名
100
+ * `option_group_item_id`,保持 tempOrder 与后端协议一致。
101
101
  */
102
102
  export interface BaseSalesSubmitProduct extends Omit<BaseSalesOrderProduct, '_origin' | 'identity_key'> {
103
103
  /**
@@ -0,0 +1,62 @@
1
+ import type { OrderProduct, OrderProductIdentity } from '../../../modules/Order/types';
2
+ import type { ProductData } from '../../../modules/Product/types';
3
+ export interface BaseProductDetailOptionItem {
4
+ option_group_item_id?: number | string;
5
+ option_group_id?: number | string;
6
+ num?: number | string;
7
+ quantity?: number | string;
8
+ price?: number | string;
9
+ add_price?: number | string;
10
+ [key: string]: any;
11
+ }
12
+ export interface BaseProductDetailBundleItem {
13
+ option?: BaseProductDetailOptionItem[];
14
+ [key: string]: any;
15
+ }
16
+ export interface BaseProductDetailPayload {
17
+ id?: number | string | null;
18
+ product_id?: number | string | null;
19
+ variant_id?: number | string | null;
20
+ product_variant_id?: number | string | null;
21
+ quantity?: number | string;
22
+ num?: number | string;
23
+ option?: BaseProductDetailOptionItem[];
24
+ options?: BaseProductDetailOptionItem[];
25
+ product_option_item?: BaseProductDetailOptionItem[];
26
+ bundle?: BaseProductDetailBundleItem[];
27
+ product_bundle?: BaseProductDetailBundleItem[];
28
+ unique?: string;
29
+ unique_identification_number?: string;
30
+ session?: any;
31
+ form?: any;
32
+ service_times?: any;
33
+ machine_code?: string;
34
+ schedule_id?: number[];
35
+ duration?: number;
36
+ policy_id?: number;
37
+ source_shop_id?: number;
38
+ origin?: Record<string, any>;
39
+ _origin?: Record<string, any>;
40
+ price?: number | string;
41
+ selling_price?: number | string;
42
+ original_price?: number | string;
43
+ tax_fee?: number | string;
44
+ is_charge_tax?: number;
45
+ note?: string;
46
+ [key: string]: any;
47
+ }
48
+ export interface TransformBaseProductToOrderProductParams {
49
+ payload: BaseProductDetailPayload;
50
+ fallbackProductId?: number | string | null;
51
+ sourceProduct?: ProductData | Record<string, any> | null;
52
+ sourceItem?: ProductData | Record<string, any> | null;
53
+ }
54
+ export type BaseProductOrderProductInput = Partial<OrderProduct> & OrderProductIdentity & {
55
+ _origin?: Record<string, any>;
56
+ };
57
+ /**
58
+ * 将商品列表原始数据 + 商品详情选择回调转换成 OrderModule.addProductToOrder 入参。
59
+ *
60
+ * 注意:这里不生成 identity,缺省时由 OrderModule 自动补齐。
61
+ */
62
+ export declare function transformBaseProductToOrderProduct(params: TransformBaseProductToOrderProductParams): BaseProductOrderProductInput | null;