@pisell/pisellos 2.2.171 → 2.2.173

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 (160) hide show
  1. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  2. package/dist/modules/BookingContext/index.d.ts +37 -0
  3. package/dist/modules/BookingContext/index.js +436 -0
  4. package/dist/modules/BookingContext/types.d.ts +102 -0
  5. package/dist/modules/BookingContext/types.js +51 -0
  6. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.d.ts +16 -0
  7. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +193 -0
  8. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +8 -0
  9. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +137 -0
  10. package/dist/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +75 -0
  11. package/dist/modules/BookingContext/utils/cacheItemToBookingInput.js +215 -0
  12. package/dist/modules/BookingContext/utils/flexible.d.ts +28 -0
  13. package/dist/modules/BookingContext/utils/flexible.js +56 -0
  14. package/dist/modules/BookingContext/utils/formatResourceList.d.ts +8 -0
  15. package/dist/modules/BookingContext/utils/formatResourceList.js +38 -0
  16. package/dist/modules/BookingContext/utils/index.d.ts +11 -0
  17. package/dist/modules/BookingContext/utils/index.js +11 -0
  18. package/dist/modules/BookingContext/utils/noResource.d.ts +13 -0
  19. package/dist/modules/BookingContext/utils/noResource.js +77 -0
  20. package/dist/modules/BookingContext/utils/productExtend.d.ts +72 -0
  21. package/dist/modules/BookingContext/utils/productExtend.js +339 -0
  22. package/dist/modules/BookingContext/utils/resourceErrors.d.ts +41 -0
  23. package/dist/modules/BookingContext/utils/resourceErrors.js +74 -0
  24. package/dist/modules/BookingContext/utils/resourceSelection.d.ts +7 -0
  25. package/dist/modules/BookingContext/utils/resourceSelection.js +24 -0
  26. package/dist/modules/BookingContext/utils/resources.d.ts +80 -0
  27. package/dist/modules/BookingContext/utils/resources.js +486 -0
  28. package/dist/modules/BookingContext/utils/serviceTimes.d.ts +55 -0
  29. package/dist/modules/BookingContext/utils/serviceTimes.js +151 -0
  30. package/dist/modules/BookingContext/utils/timeSlices.d.ts +42 -0
  31. package/dist/modules/BookingContext/utils/timeSlices.js +100 -0
  32. package/dist/modules/Customer/index.d.ts +6 -0
  33. package/dist/modules/Customer/index.js +129 -83
  34. package/dist/modules/Customer/types.d.ts +2 -0
  35. package/dist/modules/Discount/index.d.ts +2 -4
  36. package/dist/modules/Discount/index.js +8 -93
  37. package/dist/modules/Discount/types.d.ts +1 -7
  38. package/dist/modules/Order/index.d.ts +33 -17
  39. package/dist/modules/Order/index.js +757 -395
  40. package/dist/modules/Order/types.d.ts +58 -17
  41. package/dist/modules/Order/types.js +2 -0
  42. package/dist/modules/Order/utils/manualProductDiscount.d.ts +106 -0
  43. package/dist/modules/Order/utils/manualProductDiscount.js +212 -0
  44. package/dist/modules/Order/utils.d.ts +39 -1
  45. package/dist/modules/Order/utils.js +219 -31
  46. package/dist/modules/Quotation/index.js +16 -5
  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/Schedule/index.js +6 -2
  51. package/dist/modules/index.d.ts +1 -0
  52. package/dist/modules/index.js +2 -1
  53. package/dist/server/index.js +10 -6
  54. package/dist/server/modules/order/utils/filterOrders.js +20 -6
  55. package/dist/server/modules/products/index.js +113 -94
  56. package/dist/server/modules/schedule/index.js +13 -6
  57. package/dist/solution/BaseSales/index.d.ts +53 -7
  58. package/dist/solution/BaseSales/index.js +1160 -339
  59. package/dist/solution/BaseSales/types.d.ts +67 -1
  60. package/dist/solution/BaseSales/types.js +3 -1
  61. package/dist/solution/BaseSales/utils/quotationPrice.d.ts +7 -0
  62. package/dist/solution/BaseSales/utils/quotationPrice.js +237 -0
  63. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +65 -15
  64. package/dist/solution/BaseSales/utils.js +46 -8
  65. package/dist/solution/BookingByStep/index.d.ts +1 -1
  66. package/dist/solution/BookingTicket/index.d.ts +134 -2
  67. package/dist/solution/BookingTicket/index.js +776 -175
  68. package/dist/solution/BookingTicket/types.d.ts +2 -0
  69. package/dist/solution/BookingTicket/types.js +3 -0
  70. package/dist/solution/BookingTicket/utils/addProductDecision.d.ts +113 -0
  71. package/dist/solution/BookingTicket/utils/addProductDecision.js +346 -0
  72. package/dist/solution/ScanOrder/index.d.ts +9 -3
  73. package/dist/solution/ScanOrder/index.js +231 -128
  74. package/dist/solution/ScanOrder/utils.js +46 -8
  75. package/dist/solution/ShopDiscount/index.d.ts +0 -1
  76. package/dist/solution/ShopDiscount/index.js +18 -23
  77. package/dist/solution/VenueBooking/index.d.ts +5 -9
  78. package/dist/solution/VenueBooking/index.js +103 -55
  79. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +4 -0
  80. package/dist/solution/VenueBooking/utils/slotMerge.js +10 -0
  81. package/lib/model/strategy/adapter/promotion/index.js +49 -0
  82. package/lib/modules/BookingContext/index.d.ts +37 -0
  83. package/lib/modules/BookingContext/index.js +297 -0
  84. package/lib/modules/BookingContext/types.d.ts +102 -0
  85. package/lib/modules/BookingContext/types.js +34 -0
  86. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.d.ts +16 -0
  87. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +207 -0
  88. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +8 -0
  89. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +141 -0
  90. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +75 -0
  91. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +198 -0
  92. package/lib/modules/BookingContext/utils/flexible.d.ts +28 -0
  93. package/lib/modules/BookingContext/utils/flexible.js +80 -0
  94. package/lib/modules/BookingContext/utils/formatResourceList.d.ts +8 -0
  95. package/lib/modules/BookingContext/utils/formatResourceList.js +50 -0
  96. package/lib/modules/BookingContext/utils/index.d.ts +11 -0
  97. package/lib/modules/BookingContext/utils/index.js +43 -0
  98. package/lib/modules/BookingContext/utils/noResource.d.ts +13 -0
  99. package/lib/modules/BookingContext/utils/noResource.js +90 -0
  100. package/lib/modules/BookingContext/utils/productExtend.d.ts +72 -0
  101. package/lib/modules/BookingContext/utils/productExtend.js +283 -0
  102. package/lib/modules/BookingContext/utils/resourceErrors.d.ts +41 -0
  103. package/lib/modules/BookingContext/utils/resourceErrors.js +80 -0
  104. package/lib/modules/BookingContext/utils/resourceSelection.d.ts +7 -0
  105. package/lib/modules/BookingContext/utils/resourceSelection.js +46 -0
  106. package/lib/modules/BookingContext/utils/resources.d.ts +80 -0
  107. package/lib/modules/BookingContext/utils/resources.js +377 -0
  108. package/lib/modules/BookingContext/utils/serviceTimes.d.ts +55 -0
  109. package/lib/modules/BookingContext/utils/serviceTimes.js +162 -0
  110. package/lib/modules/BookingContext/utils/timeSlices.d.ts +42 -0
  111. package/lib/modules/BookingContext/utils/timeSlices.js +124 -0
  112. package/lib/modules/Customer/index.d.ts +6 -0
  113. package/lib/modules/Customer/index.js +26 -11
  114. package/lib/modules/Customer/types.d.ts +2 -0
  115. package/lib/modules/Discount/index.d.ts +2 -4
  116. package/lib/modules/Discount/index.js +8 -63
  117. package/lib/modules/Discount/types.d.ts +1 -7
  118. package/lib/modules/Order/index.d.ts +33 -17
  119. package/lib/modules/Order/index.js +402 -148
  120. package/lib/modules/Order/types.d.ts +58 -17
  121. package/lib/modules/Order/utils/manualProductDiscount.d.ts +106 -0
  122. package/lib/modules/Order/utils/manualProductDiscount.js +207 -0
  123. package/lib/modules/Order/utils.d.ts +39 -1
  124. package/lib/modules/Order/utils.js +197 -22
  125. package/lib/modules/Quotation/index.js +17 -6
  126. package/lib/modules/Rules/index.d.ts +4 -0
  127. package/lib/modules/Rules/index.js +22 -14
  128. package/lib/modules/SalesSummary/index.js +4 -2
  129. package/lib/modules/Schedule/index.js +3 -1
  130. package/lib/modules/index.d.ts +1 -0
  131. package/lib/modules/index.js +3 -1
  132. package/lib/server/index.js +2 -0
  133. package/lib/server/modules/order/utils/filterOrders.js +12 -4
  134. package/lib/server/modules/products/index.js +23 -12
  135. package/lib/server/modules/schedule/index.js +2 -1
  136. package/lib/solution/BaseSales/index.d.ts +53 -7
  137. package/lib/solution/BaseSales/index.js +527 -20
  138. package/lib/solution/BaseSales/types.d.ts +67 -1
  139. package/lib/solution/BaseSales/types.js +3 -1
  140. package/lib/solution/BaseSales/utils/quotationPrice.d.ts +7 -0
  141. package/lib/solution/BaseSales/utils/quotationPrice.js +277 -0
  142. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +70 -11
  143. package/lib/solution/BaseSales/utils.js +46 -6
  144. package/lib/solution/BookingByStep/index.d.ts +1 -1
  145. package/lib/solution/BookingTicket/index.d.ts +134 -2
  146. package/lib/solution/BookingTicket/index.js +349 -8
  147. package/lib/solution/BookingTicket/types.d.ts +2 -0
  148. package/lib/solution/BookingTicket/types.js +6 -0
  149. package/lib/solution/BookingTicket/utils/addProductDecision.d.ts +113 -0
  150. package/lib/solution/BookingTicket/utils/addProductDecision.js +318 -0
  151. package/lib/solution/ScanOrder/index.d.ts +9 -3
  152. package/lib/solution/ScanOrder/index.js +147 -66
  153. package/lib/solution/ScanOrder/utils.js +46 -6
  154. package/lib/solution/ShopDiscount/index.d.ts +0 -1
  155. package/lib/solution/ShopDiscount/index.js +2 -4
  156. package/lib/solution/VenueBooking/index.d.ts +5 -9
  157. package/lib/solution/VenueBooking/index.js +50 -14
  158. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +4 -0
  159. package/lib/solution/VenueBooking/utils/slotMerge.js +10 -0
  160. package/package.json +2 -2
@@ -2,9 +2,12 @@ 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",
@@ -48,6 +51,13 @@ export interface OrderCustomerChangePayload {
48
51
  patch: OrderCustomerView;
49
52
  snapshot: ICustomer | null;
50
53
  }
54
+ export interface OrderScanCodeResult {
55
+ isAvailable: boolean;
56
+ discountList: Discount[];
57
+ scannedDiscountList: Discount[];
58
+ type: 'server' | 'clientCalc';
59
+ unavailableReason?: UnavailableReason;
60
+ }
51
61
  export interface OrderProductIdentity {
52
62
  product_id: number | null;
53
63
  product_variant_id: number;
@@ -66,7 +76,7 @@ export interface OrderProduct extends OrderProductIdentity {
66
76
  original_price: string;
67
77
  tax_fee: string;
68
78
  is_charge_tax: number;
69
- discount_list: any[];
79
+ discount_list: OrderProductDiscountItem[];
70
80
  product_bundle: any[];
71
81
  booking_uid?: string;
72
82
  metadata: Record<string, any>;
@@ -103,11 +113,11 @@ export interface OrderSummary {
103
113
  export interface OrderTempOrder {
104
114
  order_id: number | null;
105
115
  external_sale_number: string;
106
- order_number: string;
107
- shop_order_number: string;
108
- shop_full_order_number: string;
116
+ order_number: string | null;
117
+ shop_order_number: string | null;
118
+ shop_full_order_number: string | null;
109
119
  type: string;
110
- business_code: string;
120
+ business_code?: string;
111
121
  platform: string;
112
122
  sales_channel: string;
113
123
  order_sales_channel: string;
@@ -141,7 +151,7 @@ export interface OrderTempOrder {
141
151
  bookings: any[];
142
152
  payments: any[];
143
153
  surcharges: any[];
144
- discount_list: any[];
154
+ discount_list?: any[];
145
155
  relation_forms: any[];
146
156
  contacts: any[];
147
157
  contacts_info: Record<string, any> | null;
@@ -157,7 +167,7 @@ export interface OrderSubmitProduct extends Omit<OrderProduct, 'unique_identific
157
167
  payment_price: string;
158
168
  product_sku: Record<string, any>;
159
169
  }
160
- export interface OrderSubmitPayload extends Omit<OrderTempOrder, 'platform' | 'products' | '_extend' | 'customer' | 'shop_full_order_number'> {
170
+ export interface OrderSubmitPayload extends Omit<OrderTempOrder, 'platform' | 'products' | '_extend' | 'customer' | 'discount_list'> {
161
171
  platform: string;
162
172
  request_unique_idempotency_token?: string;
163
173
  form_record_ids?: Array<{
@@ -176,16 +186,32 @@ export interface OrderState {
176
186
  discount: DiscountModule | null;
177
187
  rules: RulesModule | null;
178
188
  }
189
+ export interface ReplaceTempOrderOptions {
190
+ recalculateSummary?: boolean;
191
+ persist?: boolean;
192
+ saveDraft?: boolean;
193
+ }
194
+ export type AddProductBookingInput = Record<string, any>;
179
195
  /** 更新购物车行:仅传 SKU 时命中同 SKU 第一行;多行同 SKU 须传 unique_identification_number / 选项指纹等 */
180
- export interface UpdateProductInOrderParams {
196
+ export interface UpdateOrderProductParams {
181
197
  product_id: number | null;
182
198
  product_variant_id: number;
183
199
  updates: Partial<OrderProduct>;
184
200
  unique_identification_number?: string;
201
+ identity_key?: string;
185
202
  product_option_item?: any[];
186
203
  product_bundle?: any[];
204
+ booking?: AddProductBookingInput;
205
+ }
206
+ /** 仅更新购物车行数量;行定位语义与 updateOrderProduct / removeProductFromOrder 保持一致 */
207
+ export interface UpdateOrderProductQuantityParams extends OrderProductIdentity {
208
+ num: number;
209
+ identity_key?: string;
210
+ }
211
+ export interface UpdateOrderBookingParams {
212
+ unique_identification_number: string;
213
+ updates: AddProductBookingInput;
187
214
  }
188
- export type AddProductBookingInput = Record<string, any>;
189
215
  export interface OrderProductMergeDecisionContext {
190
216
  incomingProduct: Partial<OrderProduct> & OrderProductIdentity;
191
217
  normalizedIncoming: OrderProduct;
@@ -236,10 +262,11 @@ export interface SubmitSalesOrderParams {
236
262
  query: {
237
263
  order_id: number | null;
238
264
  external_sale_number: string;
239
- order_number: string;
240
- shop_order_number: string;
265
+ order_number: string | null;
266
+ shop_order_number: string | null;
267
+ shop_full_order_number: string | null;
241
268
  type: string;
242
- business_code: string;
269
+ business_code?: string;
243
270
  platform: string;
244
271
  request_unique_idempotency_token?: string;
245
272
  sales_channel: string;
@@ -271,7 +298,6 @@ export interface SubmitSalesOrderParams {
271
298
  bookings: OrderSubmitBooking[];
272
299
  payments: any[];
273
300
  surcharges?: any[];
274
- discount_list: any[];
275
301
  relation_forms: any[];
276
302
  form_record_ids?: OrderSubmitFormRecord[];
277
303
  contacts: any[];
@@ -350,6 +376,7 @@ export interface SyncPaymentsToOrderParams {
350
376
  paymentStatus?: SubmitSalesOrderParams['query']['payment_status'];
351
377
  submitWhenPaid?: boolean;
352
378
  smallTicketDataFlag?: number;
379
+ channel?: string;
353
380
  }
354
381
  export interface SyncPaymentsToOrderResult<T = any> {
355
382
  isFullyPaid: boolean;
@@ -446,6 +473,7 @@ export interface OrderModuleAPI {
446
473
  }) => void;
447
474
  getTempOrder: () => OrderTempOrder | null;
448
475
  ensureTempOrder: () => OrderTempOrder;
476
+ replaceTempOrder: (tempOrder: OrderTempOrder, options?: ReplaceTempOrderOptions) => Promise<OrderTempOrder>;
449
477
  addNewOrder: () => Promise<OrderTempOrder>;
450
478
  restoreOrder: () => OrderTempOrder;
451
479
  getOrderProducts: () => OrderProduct[];
@@ -458,15 +486,26 @@ export interface OrderModuleAPI {
458
486
  getOrderSyncState: () => OrderSyncState;
459
487
  getOrderAmountSnapshot: () => OrderAmountSnapshot | null;
460
488
  getTempOrderNote: () => string;
461
- updateTempOrderNote: (note: string) => string;
489
+ updateTempOrderNote: {
490
+ (note: string): string;
491
+ (note: string, sync: true): Promise<string>;
492
+ (note: string, sync: boolean): string | Promise<string>;
493
+ };
462
494
  updateTempOrderShopDiscount: (amount: string | number) => string;
463
495
  updateTempOrderCustomer: (customer: UpdateTempOrderCustomerInput) => OrderSnapshot['customer'];
464
496
  updateTempOrderBuzzer: (buzzer: string) => string;
465
497
  updateTempOrderContactsInfo: (contactsInfo: Record<string, any> | null) => Record<string, any> | null;
466
498
  addProductToOrder: (product: Partial<OrderProduct> & OrderProductIdentity, booking?: AddProductBookingInput) => Promise<OrderProduct[]>;
467
- updateProductInOrder: (params: UpdateProductInOrderParams) => Promise<OrderProduct[]>;
499
+ updateOrderProduct: (params: UpdateOrderProductParams) => Promise<OrderProduct[]>;
500
+ updateOrderProductQuantity: (params: UpdateOrderProductQuantityParams) => Promise<OrderProduct[]>;
501
+ updateOrderBooking: (params: UpdateOrderBookingParams) => any[];
468
502
  removeProductFromOrder: (identity: OrderProductIdentity) => Promise<OrderProduct[]>;
503
+ /** @deprecated no-op;OrderModule 不再负责 tempOrder localStorage 持久化。 */
469
504
  persistTempOrder: () => void;
505
+ /** @deprecated no-op;OrderModule 不再负责 tempOrder localStorage 持久化。 */
506
+ setEnableTempOrderPersist: (enabled: boolean) => void;
507
+ /** @deprecated 固定返回 false;OrderModule 不再负责 tempOrder localStorage 持久化。 */
508
+ isTempOrderPersistEnabled: () => boolean;
470
509
  submitTempOrder: <T = any>(params?: {
471
510
  cacheId?: string;
472
511
  platform?: string;
@@ -516,8 +555,10 @@ export interface OrderModuleAPI {
516
555
  clearOrderCustomer: () => void;
517
556
  loadDiscountConfig: (params: {
518
557
  customerId: number;
519
- action?: 'create';
520
- }) => Promise<void>;
558
+ action?: 'create' | 'edit';
559
+ orderId?: number;
560
+ apply?: boolean;
561
+ }) => Promise<Discount[]>;
521
562
  getDiscountList: () => Discount[];
522
563
  applyDiscount: () => void;
523
564
  /**
@@ -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
+ });
@@ -1,6 +1,6 @@
1
1
  import Decimal from 'decimal.js';
2
2
  import { CartItem } from "../Cart";
3
- import type { OrderSubmitPayload, OrderSubmitProduct, OrderSummary, OrderTempOrder } from './types';
3
+ import type { OrderProductDiscountItem, OrderSubmitPayload, OrderSubmitProduct, OrderSummary, OrderTempOrder } from './types';
4
4
  import type { RulesParamsHooks } from '../Rules/types';
5
5
  import type { MapOrderPaymentsOptions, OrderPaymentData, OrderPaymentSource } from './types';
6
6
  /**
@@ -65,6 +65,26 @@ export declare function sumOptionUnitPrice(options?: Array<{
65
65
  *
66
66
  * 导出为纯函数方便单测直接驱动钩子,不依赖 OrderModule 实例。
67
67
  */
68
+ /** Rules calcDiscount 用手动价标记;undefined 表示交给 Rules 用 total/origin_total 推断 */
69
+ export declare function resolveRulesManualDiscountFlag(metadata: Record<string, any> | null | undefined): boolean | undefined;
70
+ /**
71
+ * 商品行折扣只保留后端 OrderProductDiscountItem 协议字段。
72
+ * Rules/券计算过程中的 `_num`、`config` 等运行态字段不应进入 tempOrder 或提交 payload。
73
+ */
74
+ export declare function normalizeOrderProductDiscountList(discountList?: unknown[] | null): OrderProductDiscountItem[];
75
+ /**
76
+ * 手动改价(price_override)时行级 original_price(composite 单价):
77
+ * 购物车划线价应对齐 metadata.origin._extend.origin_total(改价前单价 composite,如 40),
78
+ * 而非 bundle 子项 catalog 原价合成的 composedOriginalPrice(如 30)。
79
+ *
80
+ * origin_total 与 SkuDetailModal / cacheItem._extend 一致,为单价语义,不再除以 num。
81
+ */
82
+ export declare function resolveManualOverrideLineOriginalPrice(params: {
83
+ num?: number;
84
+ metadata?: Record<string, any> | null;
85
+ /** 已有行级 original_price(origin 被裁剪时兜底划线价) */
86
+ lineOriginalPrice?: string | number | null;
87
+ }, fallbackCompositeOriginal: string): string;
68
88
  export declare function createDefaultOrderRulesHooks(): RulesParamsHooks;
69
89
  /**
70
90
  * 通过 session 类商品的开始时间结束时间生成商品的时长
@@ -140,4 +160,22 @@ export declare function formatV1Product(products: OrderSubmitProduct[]): {
140
160
  session: null;
141
161
  unique: string;
142
162
  }[];
163
+ /**
164
+ * 判断 holder_id 是否已分配(非空)。
165
+ *
166
+ * @example
167
+ * hasAssignedHolderId(12); // true
168
+ * hasAssignedHolderId([]); // false
169
+ */
170
+ export declare function hasAssignedHolderId(value: unknown): boolean;
171
+ /**
172
+ * 清空 tempOrder 购物车行上的 holder 分配(products / bookings / runtime origin)。
173
+ * 移除或更换下单客户时调用,与 booking 页换客户清 holder 行为对齐。
174
+ *
175
+ * @example
176
+ * clearTempOrderHolderAssignments(tempOrder);
177
+ */
178
+ export declare function clearTempOrderHolderAssignments(tempOrder: OrderTempOrder): boolean;
143
179
  export { createEmptySummary } from '../../solution/ScanOrder/utils';
180
+ export { buildManualProductDiscountItem, ensureManualProductDiscountList, findManualProductDiscountItem, mergeManualProductDiscountIntoList, resolveManualDiscountMessage, resolveManualDiscountOriginTotal, resolveManualDiscountReasonFromSources, resolveSafeProductNum, shouldBuildManualProductDiscount, syncManualProductDiscountProductNum, stripManualProductDiscountItems, } from './utils/manualProductDiscount';
181
+ export type { ManualProductDiscountItem } from './utils/manualProductDiscount';