@pisell/pisellos 2.2.175 → 2.2.176

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 (172) hide show
  1. package/dist/modules/BookingContext/index.d.ts +37 -0
  2. package/dist/modules/BookingContext/index.js +436 -0
  3. package/dist/modules/BookingContext/types.d.ts +102 -0
  4. package/dist/modules/BookingContext/types.js +51 -0
  5. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.d.ts +16 -0
  6. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +193 -0
  7. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +8 -0
  8. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +137 -0
  9. package/dist/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +75 -0
  10. package/dist/modules/BookingContext/utils/cacheItemToBookingInput.js +215 -0
  11. package/dist/modules/BookingContext/utils/flexible.d.ts +28 -0
  12. package/dist/modules/BookingContext/utils/flexible.js +56 -0
  13. package/dist/modules/BookingContext/utils/formatResourceList.d.ts +8 -0
  14. package/dist/modules/BookingContext/utils/formatResourceList.js +38 -0
  15. package/dist/modules/BookingContext/utils/index.d.ts +11 -0
  16. package/dist/modules/BookingContext/utils/index.js +11 -0
  17. package/dist/modules/BookingContext/utils/noResource.d.ts +13 -0
  18. package/dist/modules/BookingContext/utils/noResource.js +77 -0
  19. package/dist/modules/BookingContext/utils/productExtend.d.ts +72 -0
  20. package/dist/modules/BookingContext/utils/productExtend.js +339 -0
  21. package/dist/modules/BookingContext/utils/resourceErrors.d.ts +41 -0
  22. package/dist/modules/BookingContext/utils/resourceErrors.js +74 -0
  23. package/dist/modules/BookingContext/utils/resourceSelection.d.ts +7 -0
  24. package/dist/modules/BookingContext/utils/resourceSelection.js +24 -0
  25. package/dist/modules/BookingContext/utils/resources.d.ts +80 -0
  26. package/dist/modules/BookingContext/utils/resources.js +486 -0
  27. package/dist/modules/BookingContext/utils/serviceTimes.d.ts +55 -0
  28. package/dist/modules/BookingContext/utils/serviceTimes.js +151 -0
  29. package/dist/modules/BookingContext/utils/timeSlices.d.ts +42 -0
  30. package/dist/modules/BookingContext/utils/timeSlices.js +100 -0
  31. package/dist/modules/Customer/index.d.ts +6 -0
  32. package/dist/modules/Customer/index.js +129 -83
  33. package/dist/modules/Customer/types.d.ts +2 -0
  34. package/dist/modules/Discount/index.d.ts +2 -4
  35. package/dist/modules/Discount/index.js +8 -93
  36. package/dist/modules/Discount/types.d.ts +1 -7
  37. package/dist/modules/Order/index.d.ts +84 -17
  38. package/dist/modules/Order/index.js +1239 -495
  39. package/dist/modules/Order/types.d.ts +198 -18
  40. package/dist/modules/Order/types.js +31 -0
  41. package/dist/modules/Order/utils/manualProductDiscount.d.ts +106 -0
  42. package/dist/modules/Order/utils/manualProductDiscount.js +212 -0
  43. package/dist/modules/Order/utils.d.ts +50 -1
  44. package/dist/modules/Order/utils.js +261 -31
  45. package/dist/modules/Quotation/index.d.ts +0 -1
  46. package/dist/modules/Quotation/index.js +23 -21
  47. package/dist/modules/Rules/index.d.ts +4 -0
  48. package/dist/modules/Rules/index.js +26 -10
  49. package/dist/modules/SalesSummary/index.js +4 -2
  50. package/dist/modules/SalesSummary/utils.js +3 -3
  51. package/dist/modules/Schedule/index.js +6 -2
  52. package/dist/modules/index.d.ts +1 -0
  53. package/dist/modules/index.js +2 -1
  54. package/dist/server/index.js +87 -29
  55. package/dist/server/modules/order/utils/filterOrders.js +20 -6
  56. package/dist/server/modules/products/index.d.ts +1 -1
  57. package/dist/server/modules/products/index.js +130 -113
  58. package/dist/server/modules/schedule/index.js +13 -6
  59. package/dist/solution/BaseSales/index.d.ts +89 -7
  60. package/dist/solution/BaseSales/index.js +1484 -365
  61. package/dist/solution/BaseSales/types.d.ts +67 -1
  62. package/dist/solution/BaseSales/types.js +3 -1
  63. package/dist/solution/BaseSales/utils/cartPromotion.d.ts +275 -0
  64. package/dist/solution/BaseSales/utils/cartPromotion.js +1258 -0
  65. package/dist/solution/BaseSales/utils/quotationPrice.d.ts +7 -0
  66. package/dist/solution/BaseSales/utils/quotationPrice.js +237 -0
  67. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +68 -16
  68. package/dist/solution/BaseSales/utils.js +46 -8
  69. package/dist/solution/BookingByStep/index.d.ts +1 -1
  70. package/dist/solution/BookingTicket/index.d.ts +133 -1
  71. package/dist/solution/BookingTicket/index.js +780 -175
  72. package/dist/solution/BookingTicket/types.d.ts +2 -0
  73. package/dist/solution/BookingTicket/types.js +3 -0
  74. package/dist/solution/BookingTicket/utils/addProductDecision.d.ts +113 -0
  75. package/dist/solution/BookingTicket/utils/addProductDecision.js +346 -0
  76. package/dist/solution/BookingTicket/utils/cartView.js +4 -2
  77. package/dist/solution/ScanOrder/index.d.ts +9 -3
  78. package/dist/solution/ScanOrder/index.js +231 -128
  79. package/dist/solution/ScanOrder/utils.js +46 -8
  80. package/dist/solution/ShopDiscount/index.d.ts +0 -1
  81. package/dist/solution/ShopDiscount/index.js +18 -23
  82. package/dist/solution/VenueBooking/index.d.ts +5 -9
  83. package/dist/solution/VenueBooking/index.js +103 -55
  84. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +4 -0
  85. package/dist/solution/VenueBooking/utils/slotMerge.js +10 -0
  86. package/lib/model/strategy/adapter/promotion/index.js +0 -49
  87. package/lib/modules/BookingContext/index.d.ts +37 -0
  88. package/lib/modules/BookingContext/index.js +297 -0
  89. package/lib/modules/BookingContext/types.d.ts +102 -0
  90. package/lib/modules/BookingContext/types.js +34 -0
  91. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.d.ts +16 -0
  92. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +207 -0
  93. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +8 -0
  94. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +141 -0
  95. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +75 -0
  96. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +198 -0
  97. package/lib/modules/BookingContext/utils/flexible.d.ts +28 -0
  98. package/lib/modules/BookingContext/utils/flexible.js +80 -0
  99. package/lib/modules/BookingContext/utils/formatResourceList.d.ts +8 -0
  100. package/lib/modules/BookingContext/utils/formatResourceList.js +50 -0
  101. package/lib/modules/BookingContext/utils/index.d.ts +11 -0
  102. package/lib/modules/BookingContext/utils/index.js +43 -0
  103. package/lib/modules/BookingContext/utils/noResource.d.ts +13 -0
  104. package/lib/modules/BookingContext/utils/noResource.js +90 -0
  105. package/lib/modules/BookingContext/utils/productExtend.d.ts +72 -0
  106. package/lib/modules/BookingContext/utils/productExtend.js +283 -0
  107. package/lib/modules/BookingContext/utils/resourceErrors.d.ts +41 -0
  108. package/lib/modules/BookingContext/utils/resourceErrors.js +80 -0
  109. package/lib/modules/BookingContext/utils/resourceSelection.d.ts +7 -0
  110. package/lib/modules/BookingContext/utils/resourceSelection.js +46 -0
  111. package/lib/modules/BookingContext/utils/resources.d.ts +80 -0
  112. package/lib/modules/BookingContext/utils/resources.js +377 -0
  113. package/lib/modules/BookingContext/utils/serviceTimes.d.ts +55 -0
  114. package/lib/modules/BookingContext/utils/serviceTimes.js +162 -0
  115. package/lib/modules/BookingContext/utils/timeSlices.d.ts +42 -0
  116. package/lib/modules/BookingContext/utils/timeSlices.js +124 -0
  117. package/lib/modules/Customer/index.d.ts +6 -0
  118. package/lib/modules/Customer/index.js +26 -11
  119. package/lib/modules/Customer/types.d.ts +2 -0
  120. package/lib/modules/Discount/index.d.ts +2 -4
  121. package/lib/modules/Discount/index.js +8 -63
  122. package/lib/modules/Discount/types.d.ts +1 -7
  123. package/lib/modules/Order/index.d.ts +84 -17
  124. package/lib/modules/Order/index.js +588 -145
  125. package/lib/modules/Order/types.d.ts +198 -18
  126. package/lib/modules/Order/types.js +1 -0
  127. package/lib/modules/Order/utils/manualProductDiscount.d.ts +106 -0
  128. package/lib/modules/Order/utils/manualProductDiscount.js +207 -0
  129. package/lib/modules/Order/utils.d.ts +50 -1
  130. package/lib/modules/Order/utils.js +229 -21
  131. package/lib/modules/Quotation/index.d.ts +0 -1
  132. package/lib/modules/Quotation/index.js +18 -15
  133. package/lib/modules/Rules/index.d.ts +4 -0
  134. package/lib/modules/Rules/index.js +22 -14
  135. package/lib/modules/SalesSummary/index.js +4 -2
  136. package/lib/modules/SalesSummary/utils.js +3 -3
  137. package/lib/modules/Schedule/index.js +3 -1
  138. package/lib/modules/index.d.ts +1 -0
  139. package/lib/modules/index.js +3 -1
  140. package/lib/server/index.js +41 -4
  141. package/lib/server/modules/order/utils/filterOrders.js +12 -4
  142. package/lib/server/modules/products/index.d.ts +1 -1
  143. package/lib/server/modules/products/index.js +30 -20
  144. package/lib/server/modules/schedule/index.js +2 -1
  145. package/lib/solution/BaseSales/index.d.ts +89 -7
  146. package/lib/solution/BaseSales/index.js +736 -22
  147. package/lib/solution/BaseSales/types.d.ts +67 -1
  148. package/lib/solution/BaseSales/types.js +3 -1
  149. package/lib/solution/BaseSales/utils/cartPromotion.d.ts +275 -0
  150. package/lib/solution/BaseSales/utils/cartPromotion.js +836 -0
  151. package/lib/solution/BaseSales/utils/quotationPrice.d.ts +7 -0
  152. package/lib/solution/BaseSales/utils/quotationPrice.js +277 -0
  153. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +71 -12
  154. package/lib/solution/BaseSales/utils.js +46 -6
  155. package/lib/solution/BookingByStep/index.d.ts +1 -1
  156. package/lib/solution/BookingTicket/index.d.ts +133 -1
  157. package/lib/solution/BookingTicket/index.js +352 -8
  158. package/lib/solution/BookingTicket/types.d.ts +2 -0
  159. package/lib/solution/BookingTicket/types.js +6 -0
  160. package/lib/solution/BookingTicket/utils/addProductDecision.d.ts +113 -0
  161. package/lib/solution/BookingTicket/utils/addProductDecision.js +318 -0
  162. package/lib/solution/BookingTicket/utils/cartView.js +4 -2
  163. package/lib/solution/ScanOrder/index.d.ts +9 -3
  164. package/lib/solution/ScanOrder/index.js +147 -66
  165. package/lib/solution/ScanOrder/utils.js +46 -6
  166. package/lib/solution/ShopDiscount/index.d.ts +0 -1
  167. package/lib/solution/ShopDiscount/index.js +2 -4
  168. package/lib/solution/VenueBooking/index.d.ts +5 -9
  169. package/lib/solution/VenueBooking/index.js +50 -14
  170. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +4 -0
  171. package/lib/solution/VenueBooking/utils/slotMerge.js +10 -0
  172. package/package.json +2 -2
@@ -2,15 +2,117 @@ import { CartItem } from '../Cart/types';
2
2
  import type { DiscountModule } from '../Discount';
3
3
  import type { RulesModule } from '../Rules';
4
4
  import type { Discount } from '../Discount/types';
5
+ import type { UnavailableReason } from '../Rules/types';
5
6
  import type { SubmitPayloadEnhancer } from './utils';
6
7
  import type { PaymentItem } from '../Payment/types';
7
8
  import type { ICustomer } from '../AccountList/types';
9
+ import type { OrderProductDiscountItem } from '../../server/modules/order/types';
10
+ export type { OrderProductDiscountItem } from '../../server/modules/order/types';
8
11
  export declare enum OrderHooks {
9
12
  OnOrderCreate = "order:onOrderCreate",
10
13
  OnOrderUpdate = "order:onOrderUpdate",
11
14
  OnOrderCancel = "order:onOrderCancel",
12
15
  OnOrderStatusChange = "order:onOrderStatusChange",
13
- OnOrderCustomerChange = "order:onOrderCustomerChange"
16
+ OnOrderCustomerChange = "order:onOrderCustomerChange",
17
+ OnPromotionApplied = "order:onPromotionApplied"
18
+ }
19
+ /**
20
+ * 促销评估器协议(OS 与 PromotionEvaluator 之间的桥接接口)。
21
+ *
22
+ * 与 `pisell_os/src/model/strategy/adapter/promotion/evaluator.ts` 中的
23
+ * `PromotionEvaluator` 实例结构保持兼容。SalesSdkProvider 会从 `appHelper.utils.promotionEvaluator`
24
+ * 读取实例并通过 `setPromotionEvaluator` 注入到 OrderModule。
25
+ *
26
+ * 这里只声明 OrderModule 需要调用的子集,避免反向依赖具体 evaluator 实现。
27
+ */
28
+ export interface OrderPromotionEvaluator {
29
+ evaluateCartWithPricing(input: {
30
+ products: any[];
31
+ channel?: string;
32
+ }): any;
33
+ getProductsApplicableStrategies(input: {
34
+ products: any[];
35
+ channel?: string;
36
+ }, matchVariant?: boolean): any[];
37
+ }
38
+ /** 赠品解析回调 context(OS → SDK 的请求体) */
39
+ export interface OrderGiftSelectContext {
40
+ strategyId: string;
41
+ strategyName: string | Record<string, string>;
42
+ giftCount: number;
43
+ giftOptions: Array<{
44
+ product_id: number;
45
+ product_variant_id: number;
46
+ }>;
47
+ /** 触发此赠品的主商品 metadata.unique_identification_number 列表 */
48
+ sourceProductIds: string[];
49
+ }
50
+ /**
51
+ * 赠品解析回调签名(SDK → OS 的返回值)。
52
+ *
53
+ * - 单选项:SDK 内部自动构造商品,不弹窗
54
+ * - 多选项:SDK 弹窗等用户确认后构造
55
+ * - 用户取消:抛错或返回空数组(OS 视为放弃本次添加)
56
+ *
57
+ * 返回的 OrderProduct 必须是完整的购物车行(含 metadata._giftInfo 标记),OS 会直接 push 入 tempOrder.products。
58
+ */
59
+ export type OrderGiftSelectResolver = (ctx: OrderGiftSelectContext) => Promise<Partial<OrderProduct>[] | null>;
60
+ /** 未满足的促销策略(购物车底部 alert 渲染源) */
61
+ export interface OrderUnfulfilledPromotion {
62
+ strategyId: string;
63
+ strategyName: string | Record<string, string>;
64
+ actionType: string;
65
+ needQuantity: number;
66
+ currentQuantity: number;
67
+ requiredQuantity: number;
68
+ eligibleProducts: Array<{
69
+ product_id: number;
70
+ product_variant_id: number;
71
+ }>;
72
+ strategyMetadata?: any;
73
+ display?: {
74
+ text: string | Record<string, string>;
75
+ type: string;
76
+ };
77
+ }
78
+ /** 上一次 applyPromotion 计算出的赠品操作(仅供调试/读取使用) */
79
+ export interface OrderLastGiftActions {
80
+ toAdd: Array<{
81
+ strategyId: string;
82
+ strategyName: string | Record<string, string>;
83
+ giftCount: number;
84
+ giftOptions: Array<{
85
+ product_id: number;
86
+ product_variant_id: number;
87
+ }>;
88
+ sourceProductIds: string[];
89
+ }>;
90
+ toReduce: Array<{
91
+ strategyId: string;
92
+ items: Array<{
93
+ uid: string;
94
+ currentQuantity: number;
95
+ newQuantity: number;
96
+ }>;
97
+ }>;
98
+ toRemove: string[];
99
+ }
100
+ /** onPromotionApplied 事件 payload */
101
+ export interface OrderPromotionAppliedPayload {
102
+ unfulfilledPromotions: OrderUnfulfilledPromotion[];
103
+ giftActions: OrderLastGiftActions;
104
+ /** evaluator 返回的赠品摘要 */
105
+ gifts: Array<{
106
+ strategyId: string;
107
+ strategyName: string | Record<string, string>;
108
+ giftCount: number;
109
+ giftOptions: Array<{
110
+ product_id: number;
111
+ product_variant_id: number;
112
+ }>;
113
+ }>;
114
+ /** 处理后的商品列表 */
115
+ products: OrderProduct[];
14
116
  }
15
117
  /**
16
118
  * tempOrder 上的下单客户协议字段视图。
@@ -48,6 +150,13 @@ export interface OrderCustomerChangePayload {
48
150
  patch: OrderCustomerView;
49
151
  snapshot: ICustomer | null;
50
152
  }
153
+ export interface OrderScanCodeResult {
154
+ isAvailable: boolean;
155
+ discountList: Discount[];
156
+ scannedDiscountList: Discount[];
157
+ type: 'server' | 'clientCalc';
158
+ unavailableReason?: UnavailableReason;
159
+ }
51
160
  export interface OrderProductIdentity {
52
161
  product_id: number | null;
53
162
  product_variant_id: number;
@@ -66,7 +175,7 @@ export interface OrderProduct extends OrderProductIdentity {
66
175
  original_price: string;
67
176
  tax_fee: string;
68
177
  is_charge_tax: number;
69
- discount_list: any[];
178
+ discount_list: OrderProductDiscountItem[];
70
179
  product_bundle: any[];
71
180
  booking_uid?: string;
72
181
  metadata: Record<string, any>;
@@ -103,11 +212,11 @@ export interface OrderSummary {
103
212
  export interface OrderTempOrder {
104
213
  order_id: number | null;
105
214
  external_sale_number: string;
106
- order_number: string;
107
- shop_order_number: string;
108
- shop_full_order_number: string;
215
+ order_number: string | null;
216
+ shop_order_number: string | null;
217
+ shop_full_order_number: string | null;
109
218
  type: string;
110
- business_code: string;
219
+ business_code?: string;
111
220
  platform: string;
112
221
  sales_channel: string;
113
222
  order_sales_channel: string;
@@ -141,7 +250,7 @@ export interface OrderTempOrder {
141
250
  bookings: any[];
142
251
  payments: any[];
143
252
  surcharges: any[];
144
- discount_list: any[];
253
+ discount_list?: any[];
145
254
  relation_forms: any[];
146
255
  contacts: any[];
147
256
  contacts_info: Record<string, any> | null;
@@ -157,7 +266,7 @@ export interface OrderSubmitProduct extends Omit<OrderProduct, 'unique_identific
157
266
  payment_price: string;
158
267
  product_sku: Record<string, any>;
159
268
  }
160
- export interface OrderSubmitPayload extends Omit<OrderTempOrder, 'platform' | 'products' | '_extend' | 'customer' | 'shop_full_order_number'> {
269
+ export interface OrderSubmitPayload extends Omit<OrderTempOrder, 'platform' | 'products' | '_extend' | 'customer' | 'discount_list'> {
161
270
  platform: string;
162
271
  request_unique_idempotency_token?: string;
163
272
  form_record_ids?: Array<{
@@ -176,16 +285,32 @@ export interface OrderState {
176
285
  discount: DiscountModule | null;
177
286
  rules: RulesModule | null;
178
287
  }
288
+ export interface ReplaceTempOrderOptions {
289
+ recalculateSummary?: boolean;
290
+ persist?: boolean;
291
+ saveDraft?: boolean;
292
+ }
293
+ export type AddProductBookingInput = Record<string, any>;
179
294
  /** 更新购物车行:仅传 SKU 时命中同 SKU 第一行;多行同 SKU 须传 unique_identification_number / 选项指纹等 */
180
- export interface UpdateProductInOrderParams {
295
+ export interface UpdateOrderProductParams {
181
296
  product_id: number | null;
182
297
  product_variant_id: number;
183
298
  updates: Partial<OrderProduct>;
184
299
  unique_identification_number?: string;
300
+ identity_key?: string;
185
301
  product_option_item?: any[];
186
302
  product_bundle?: any[];
303
+ booking?: AddProductBookingInput;
304
+ }
305
+ /** 仅更新购物车行数量;行定位语义与 updateOrderProduct / removeProductFromOrder 保持一致 */
306
+ export interface UpdateOrderProductQuantityParams extends OrderProductIdentity {
307
+ num: number;
308
+ identity_key?: string;
309
+ }
310
+ export interface UpdateOrderBookingParams {
311
+ unique_identification_number: string;
312
+ updates: AddProductBookingInput;
187
313
  }
188
- export type AddProductBookingInput = Record<string, any>;
189
314
  export interface OrderProductMergeDecisionContext {
190
315
  incomingProduct: Partial<OrderProduct> & OrderProductIdentity;
191
316
  normalizedIncoming: OrderProduct;
@@ -236,10 +361,11 @@ export interface SubmitSalesOrderParams {
236
361
  query: {
237
362
  order_id: number | null;
238
363
  external_sale_number: string;
239
- order_number: string;
240
- shop_order_number: string;
364
+ order_number: string | null;
365
+ shop_order_number: string | null;
366
+ shop_full_order_number: string | null;
241
367
  type: string;
242
- business_code: string;
368
+ business_code?: string;
243
369
  platform: string;
244
370
  request_unique_idempotency_token?: string;
245
371
  sales_channel: string;
@@ -271,7 +397,6 @@ export interface SubmitSalesOrderParams {
271
397
  bookings: OrderSubmitBooking[];
272
398
  payments: any[];
273
399
  surcharges?: any[];
274
- discount_list: any[];
275
400
  relation_forms: any[];
276
401
  form_record_ids?: OrderSubmitFormRecord[];
277
402
  contacts: any[];
@@ -350,6 +475,7 @@ export interface SyncPaymentsToOrderParams {
350
475
  paymentStatus?: SubmitSalesOrderParams['query']['payment_status'];
351
476
  submitWhenPaid?: boolean;
352
477
  smallTicketDataFlag?: number;
478
+ channel?: string;
353
479
  }
354
480
  export interface SyncPaymentsToOrderResult<T = any> {
355
481
  isFullyPaid: boolean;
@@ -446,6 +572,7 @@ export interface OrderModuleAPI {
446
572
  }) => void;
447
573
  getTempOrder: () => OrderTempOrder | null;
448
574
  ensureTempOrder: () => OrderTempOrder;
575
+ replaceTempOrder: (tempOrder: OrderTempOrder, options?: ReplaceTempOrderOptions) => Promise<OrderTempOrder>;
449
576
  addNewOrder: () => Promise<OrderTempOrder>;
450
577
  restoreOrder: () => OrderTempOrder;
451
578
  getOrderProducts: () => OrderProduct[];
@@ -458,15 +585,26 @@ export interface OrderModuleAPI {
458
585
  getOrderSyncState: () => OrderSyncState;
459
586
  getOrderAmountSnapshot: () => OrderAmountSnapshot | null;
460
587
  getTempOrderNote: () => string;
461
- updateTempOrderNote: (note: string) => string;
588
+ updateTempOrderNote: {
589
+ (note: string): string;
590
+ (note: string, sync: true): Promise<string>;
591
+ (note: string, sync: boolean): string | Promise<string>;
592
+ };
462
593
  updateTempOrderShopDiscount: (amount: string | number) => string;
463
594
  updateTempOrderCustomer: (customer: UpdateTempOrderCustomerInput) => OrderSnapshot['customer'];
464
595
  updateTempOrderBuzzer: (buzzer: string) => string;
465
596
  updateTempOrderContactsInfo: (contactsInfo: Record<string, any> | null) => Record<string, any> | null;
466
597
  addProductToOrder: (product: Partial<OrderProduct> & OrderProductIdentity, booking?: AddProductBookingInput) => Promise<OrderProduct[]>;
467
- updateProductInOrder: (params: UpdateProductInOrderParams) => Promise<OrderProduct[]>;
598
+ updateOrderProduct: (params: UpdateOrderProductParams) => Promise<OrderProduct[]>;
599
+ updateOrderProductQuantity: (params: UpdateOrderProductQuantityParams) => Promise<OrderProduct[]>;
600
+ updateOrderBooking: (params: UpdateOrderBookingParams) => any[];
468
601
  removeProductFromOrder: (identity: OrderProductIdentity) => Promise<OrderProduct[]>;
602
+ /** @deprecated no-op;OrderModule 不再负责 tempOrder localStorage 持久化。 */
469
603
  persistTempOrder: () => void;
604
+ /** @deprecated no-op;OrderModule 不再负责 tempOrder localStorage 持久化。 */
605
+ setEnableTempOrderPersist: (enabled: boolean) => void;
606
+ /** @deprecated 固定返回 false;OrderModule 不再负责 tempOrder localStorage 持久化。 */
607
+ isTempOrderPersistEnabled: () => boolean;
470
608
  submitTempOrder: <T = any>(params?: {
471
609
  cacheId?: string;
472
610
  platform?: string;
@@ -516,10 +654,52 @@ export interface OrderModuleAPI {
516
654
  clearOrderCustomer: () => void;
517
655
  loadDiscountConfig: (params: {
518
656
  customerId: number;
519
- action?: 'create';
520
- }) => Promise<void>;
657
+ action?: 'create' | 'edit';
658
+ orderId?: number;
659
+ apply?: boolean;
660
+ }) => Promise<Discount[]>;
521
661
  getDiscountList: () => Discount[];
522
662
  applyDiscount: () => void;
663
+ /**
664
+ * 注入促销评估器。
665
+ *
666
+ * SalesSdkProvider 在初始化 bookingTicket 后会自动从 `appHelper.utils.promotionEvaluator`
667
+ * 读取实例并调用本方法注入。host 透明,业务 UI 不感知。
668
+ *
669
+ * @example
670
+ * order.setPromotionEvaluator(appHelper.utils.promotionEvaluator);
671
+ */
672
+ setPromotionEvaluator: (evaluator: OrderPromotionEvaluator | null) => void;
673
+ /**
674
+ * 注入赠品选择 resolver。OS 在 applyPromotion 内部当需要新增赠品时会 await 调用 resolver。
675
+ *
676
+ * 缺省时 OS 会 `console.warn` 并跳过新增(既有赠品的 reduce/remove 仍会执行)。
677
+ *
678
+ * @example
679
+ * order.setGiftSelectResolver((ctx) => giftSelectBridge.request(ctx));
680
+ */
681
+ setGiftSelectResolver: (resolver: OrderGiftSelectResolver | null) => void;
682
+ /**
683
+ * 为商品目录追加促销标签。
684
+ *
685
+ * @example
686
+ * const taggedProducts = order.appendPromotionTags(products);
687
+ */
688
+ appendPromotionTags: <T extends Record<string, any>>(products: T[]) => T[];
689
+ /**
690
+ * 应用购物车促销(评估 → 差异化赠品 → 写回 tempOrder.products → emit onPromotionApplied)。
691
+ *
692
+ * 自动在 addProductToOrder / updateOrderProductQuantity / removeProductFromOrder /
693
+ * clearOrderCartLines / setOrderCustomer 等写路径末尾触发,业务一般无需手动调用。
694
+ *
695
+ * 多选项赠品依赖 giftSelectResolver;如未注入则跳过且 console.warn。
696
+ * 内部以 `_isApplyingPromotion` flag 防递归。
697
+ */
698
+ applyPromotion: () => Promise<void>;
699
+ /** 读取上次 applyPromotion 产出的未满足促销提示 */
700
+ getUnfulfilledPromotions: () => OrderUnfulfilledPromotion[];
701
+ /** 读取上次 applyPromotion 产出的赠品操作 diff(toAdd / toReduce / toRemove) */
702
+ getLastGiftActions: () => OrderLastGiftActions | null;
523
703
  /**
524
704
  * 取消订单
525
705
  * @param params 取消订单参数
@@ -28,6 +28,7 @@ var OrderHooks = /* @__PURE__ */ ((OrderHooks2) => {
28
28
  OrderHooks2["OnOrderCancel"] = "order:onOrderCancel";
29
29
  OrderHooks2["OnOrderStatusChange"] = "order:onOrderStatusChange";
30
30
  OrderHooks2["OnOrderCustomerChange"] = "order:onOrderCustomerChange";
31
+ OrderHooks2["OnPromotionApplied"] = "order:onPromotionApplied";
31
32
  return OrderHooks2;
32
33
  })(OrderHooks || {});
33
34
  // Annotate the CommonJS export names for ESM import in node:
@@ -0,0 +1,106 @@
1
+ /** 解析商品行数量(checkout 协议 product_num 语义 = 当前行 num) */
2
+ export declare function resolveSafeProductNum(num?: number | null): number;
3
+ /**
4
+ * 将 discount_list 中 type=product 项的 product_num 同步为当前商品数量。
5
+ *
6
+ * @example
7
+ * syncManualProductDiscountProductNum(line.discount_list, line.num);
8
+ */
9
+ export declare function syncManualProductDiscountProductNum(discountList: any[] | undefined | null, productNum?: number | null): any[];
10
+ /** 从多源解析改价前行总价(与 cacheItem._extend.origin_total 语义一致) */
11
+ export declare function resolveManualDiscountOriginTotal(sources: {
12
+ originTotal?: unknown;
13
+ extendOriginTotal?: unknown;
14
+ originExtendOriginTotal?: unknown;
15
+ sourceExtendOriginTotal?: unknown;
16
+ catalogUnitPrice?: unknown;
17
+ quantity?: number;
18
+ }): number;
19
+ /** 从 payload / extend / origin 解析手动折扣原因 */
20
+ export declare function resolveManualDiscountReasonFromSources(sources: {
21
+ discountReason?: unknown;
22
+ extendDiscountReason?: unknown;
23
+ originExtendDiscountReason?: unknown;
24
+ }): string;
25
+ /** 是否带手动改价标记(price_override / is_manual_discount) */
26
+ export declare function hasManualProductDiscountFlag(metadata?: Record<string, any> | null): boolean;
27
+ /**
28
+ * normalize 兜底:手动改价但 discount_list 缺 type=product 时,按行级原价/折后价补写。
29
+ *
30
+ * @example
31
+ * ensureManualProductDiscountList({
32
+ * discountList: [],
33
+ * metadata: { price_override: '5', is_manual_discount: 1 },
34
+ * originalPrice: '11.00',
35
+ * sellingPrice: '5.00',
36
+ * quantity: 1,
37
+ * });
38
+ */
39
+ export declare function ensureManualProductDiscountList(params: {
40
+ discountList?: any[] | null;
41
+ metadata?: Record<string, any> | null;
42
+ originalPrice: string | number;
43
+ sellingPrice: string | number;
44
+ quantity?: number;
45
+ }): any[];
46
+ /** 商品手动折扣 discount_list 项(checkout 协议,type = product) */
47
+ export interface ManualProductDiscountItem {
48
+ amount: number;
49
+ type: 'product';
50
+ discount: {
51
+ message: string;
52
+ discountway: string;
53
+ product_num: number;
54
+ discount_per: string;
55
+ discount_type: 'discount' | 'change_price';
56
+ };
57
+ }
58
+ /**
59
+ * 从 discount_list 中取手动改价项(type = product)。
60
+ *
61
+ * @example
62
+ * const manual = findManualProductDiscountItem(product.discount_list);
63
+ * manual?.discount.message; // 折扣原因
64
+ */
65
+ export declare function findManualProductDiscountItem(discountList?: any[] | null): ManualProductDiscountItem | undefined;
66
+ /**
67
+ * 解析折扣原因:优先 discount_list[type=product].discount.message。
68
+ *
69
+ * @example
70
+ * resolveManualDiscountMessage(line.discount_list, line.metadata?.legacy_reason);
71
+ */
72
+ export declare function resolveManualDiscountMessage(discountList?: any[] | null, fallback?: string): string;
73
+ /** 去掉 discount_list 中已有的手动改价项,避免重复叠加 */
74
+ export declare function stripManualProductDiscountItems(discountList?: any[] | null): any[];
75
+ /**
76
+ * 由改价前后行总价构建手动折扣项;amount = |originTotal - sellingTotal|(行级差额)。
77
+ *
78
+ * @example
79
+ * buildManualProductDiscountItem({
80
+ * originTotal: 11,
81
+ * sellingTotal: 4,
82
+ * quantity: 1,
83
+ * message: 'VIP',
84
+ * });
85
+ */
86
+ export declare function buildManualProductDiscountItem(params: {
87
+ originTotal: number;
88
+ sellingTotal: number;
89
+ quantity?: number;
90
+ message?: string;
91
+ discountway?: string;
92
+ discount_per?: string;
93
+ }): ManualProductDiscountItem;
94
+ /**
95
+ * 将手动改价项合并进 discount_list(替换已有 type=product 项)。
96
+ *
97
+ * @example
98
+ * mergeManualProductDiscountIntoList(coupons, manualItem);
99
+ */
100
+ export declare function mergeManualProductDiscountIntoList(discountList: any[] | undefined | null, manualItem: ManualProductDiscountItem | null | undefined): any[];
101
+ /** 是否应写入手动改价 discount_list 项 */
102
+ export declare function shouldBuildManualProductDiscount(params: {
103
+ hasPriceOverride?: boolean;
104
+ originTotal?: number;
105
+ sellingTotal?: number;
106
+ }): boolean;
@@ -0,0 +1,207 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // src/modules/Order/utils/manualProductDiscount.ts
30
+ var manualProductDiscount_exports = {};
31
+ __export(manualProductDiscount_exports, {
32
+ buildManualProductDiscountItem: () => buildManualProductDiscountItem,
33
+ ensureManualProductDiscountList: () => ensureManualProductDiscountList,
34
+ findManualProductDiscountItem: () => findManualProductDiscountItem,
35
+ hasManualProductDiscountFlag: () => hasManualProductDiscountFlag,
36
+ mergeManualProductDiscountIntoList: () => mergeManualProductDiscountIntoList,
37
+ resolveManualDiscountMessage: () => resolveManualDiscountMessage,
38
+ resolveManualDiscountOriginTotal: () => resolveManualDiscountOriginTotal,
39
+ resolveManualDiscountReasonFromSources: () => resolveManualDiscountReasonFromSources,
40
+ resolveSafeProductNum: () => resolveSafeProductNum,
41
+ shouldBuildManualProductDiscount: () => shouldBuildManualProductDiscount,
42
+ stripManualProductDiscountItems: () => stripManualProductDiscountItems,
43
+ syncManualProductDiscountProductNum: () => syncManualProductDiscountProductNum
44
+ });
45
+ module.exports = __toCommonJS(manualProductDiscount_exports);
46
+ var import_decimal = __toESM(require("decimal.js"));
47
+ function resolveSafeProductNum(num) {
48
+ const parsed = Number(num);
49
+ if (!Number.isFinite(parsed) || parsed <= 0)
50
+ return 1;
51
+ return Math.floor(parsed);
52
+ }
53
+ function syncManualProductDiscountProductNum(discountList, productNum) {
54
+ const quantity = resolveSafeProductNum(productNum);
55
+ return (discountList || []).map((item) => {
56
+ if ((item == null ? void 0 : item.type) !== "product")
57
+ return item;
58
+ return {
59
+ ...item,
60
+ discount: {
61
+ ...item.discount || {},
62
+ product_num: quantity
63
+ }
64
+ };
65
+ });
66
+ }
67
+ function resolveManualDiscountOriginTotal(sources) {
68
+ const candidates = [
69
+ sources.originTotal,
70
+ sources.extendOriginTotal,
71
+ sources.originExtendOriginTotal,
72
+ sources.sourceExtendOriginTotal
73
+ ];
74
+ for (const candidate of candidates) {
75
+ if (candidate === void 0 || candidate === null || candidate === "")
76
+ continue;
77
+ const parsed = Number(candidate);
78
+ if (Number.isFinite(parsed))
79
+ return parsed;
80
+ }
81
+ const unit = Number(sources.catalogUnitPrice);
82
+ const quantity = sources.quantity ?? 1;
83
+ if (Number.isFinite(unit) && unit > 0) {
84
+ return new import_decimal.default(unit).mul(quantity).toNumber();
85
+ }
86
+ return NaN;
87
+ }
88
+ function resolveManualDiscountReasonFromSources(sources) {
89
+ for (const candidate of [
90
+ sources.discountReason,
91
+ sources.extendDiscountReason,
92
+ sources.originExtendDiscountReason
93
+ ]) {
94
+ if (candidate != null && String(candidate).trim() !== "") {
95
+ return String(candidate);
96
+ }
97
+ }
98
+ return "";
99
+ }
100
+ function hasManualProductDiscountFlag(metadata) {
101
+ if (!metadata)
102
+ return false;
103
+ const override = metadata.price_override;
104
+ if (override !== void 0 && override !== null && override !== "") {
105
+ return true;
106
+ }
107
+ return metadata.is_manual_discount === 1 || metadata.is_manual_discount === true;
108
+ }
109
+ function ensureManualProductDiscountList(params) {
110
+ var _a, _b, _c, _d, _e, _f, _g, _h;
111
+ const list = params.discountList || [];
112
+ const quantity = resolveSafeProductNum(params.quantity);
113
+ if (findManualProductDiscountItem(list)) {
114
+ return syncManualProductDiscountProductNum(list, quantity);
115
+ }
116
+ const metadata = params.metadata || {};
117
+ const originalNum = Number(params.originalPrice);
118
+ const sellingNum = Number(params.sellingPrice);
119
+ const shouldBuild = hasManualProductDiscountFlag(metadata) || shouldBuildManualProductDiscount({ originTotal: originalNum, sellingTotal: sellingNum });
120
+ if (!shouldBuild) {
121
+ return list;
122
+ }
123
+ if (!Number.isFinite(originalNum) || !Number.isFinite(sellingNum) || originalNum === sellingNum) {
124
+ return list;
125
+ }
126
+ const message = resolveManualDiscountMessage(
127
+ list,
128
+ resolveManualDiscountReasonFromSources({
129
+ extendDiscountReason: (_b = (_a = metadata.origin) == null ? void 0 : _a._extend) == null ? void 0 : _b.discount_reason,
130
+ originExtendDiscountReason: (_d = (_c = metadata.origin) == null ? void 0 : _c._extend) == null ? void 0 : _d.discount_reason
131
+ })
132
+ );
133
+ return mergeManualProductDiscountIntoList(
134
+ list,
135
+ buildManualProductDiscountItem({
136
+ originTotal: originalNum,
137
+ sellingTotal: sellingNum,
138
+ quantity,
139
+ message,
140
+ discountway: (_f = (_e = metadata.origin) == null ? void 0 : _e._extend) == null ? void 0 : _f.discountway,
141
+ discount_per: (_h = (_g = metadata.origin) == null ? void 0 : _g._extend) == null ? void 0 : _h.discount_per
142
+ })
143
+ );
144
+ }
145
+ function findManualProductDiscountItem(discountList) {
146
+ return (discountList || []).find((item) => (item == null ? void 0 : item.type) === "product");
147
+ }
148
+ function resolveManualDiscountMessage(discountList, fallback) {
149
+ var _a, _b;
150
+ const message = (_b = (_a = findManualProductDiscountItem(discountList)) == null ? void 0 : _a.discount) == null ? void 0 : _b.message;
151
+ if (message != null && String(message).trim() !== "") {
152
+ return String(message);
153
+ }
154
+ return fallback ?? "";
155
+ }
156
+ function stripManualProductDiscountItems(discountList) {
157
+ return (discountList || []).filter((item) => (item == null ? void 0 : item.type) !== "product");
158
+ }
159
+ function buildManualProductDiscountItem(params) {
160
+ const origin = new import_decimal.default(Number(params.originTotal) || 0);
161
+ const selling = new import_decimal.default(Number(params.sellingTotal) || 0);
162
+ const diff = origin.minus(selling);
163
+ const quantity = resolveSafeProductNum(params.quantity);
164
+ return {
165
+ amount: diff.abs().toDecimalPlaces(2).toNumber(),
166
+ type: "product",
167
+ discount: {
168
+ message: params.message ?? "",
169
+ discountway: params.discountway ?? "num",
170
+ product_num: quantity,
171
+ discount_per: params.discount_per ?? "",
172
+ discount_type: diff.isNegative() ? "change_price" : "discount"
173
+ }
174
+ };
175
+ }
176
+ function mergeManualProductDiscountIntoList(discountList, manualItem) {
177
+ const base = stripManualProductDiscountItems(discountList);
178
+ if (!manualItem)
179
+ return base;
180
+ if (manualItem.amount === 0 && !manualItem.discount.message)
181
+ return base;
182
+ return [...base, manualItem];
183
+ }
184
+ function shouldBuildManualProductDiscount(params) {
185
+ if (params.hasPriceOverride)
186
+ return true;
187
+ const origin = Number(params.originTotal);
188
+ const selling = Number(params.sellingTotal);
189
+ if (!Number.isFinite(origin) || !Number.isFinite(selling))
190
+ return false;
191
+ return origin !== selling;
192
+ }
193
+ // Annotate the CommonJS export names for ESM import in node:
194
+ 0 && (module.exports = {
195
+ buildManualProductDiscountItem,
196
+ ensureManualProductDiscountList,
197
+ findManualProductDiscountItem,
198
+ hasManualProductDiscountFlag,
199
+ mergeManualProductDiscountIntoList,
200
+ resolveManualDiscountMessage,
201
+ resolveManualDiscountOriginTotal,
202
+ resolveManualDiscountReasonFromSources,
203
+ resolveSafeProductNum,
204
+ shouldBuildManualProductDiscount,
205
+ stripManualProductDiscountItems,
206
+ syncManualProductDiscountProductNum
207
+ });