@pisell/pisellos 2.2.175 → 2.2.177

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 (176) 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 +86 -17
  38. package/dist/modules/Order/index.js +1303 -497
  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 +18 -5
  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/index.d.ts +23 -0
  56. package/dist/server/modules/order/index.js +123 -46
  57. package/dist/server/modules/order/utils/filterOrders.js +20 -6
  58. package/dist/server/modules/products/index.d.ts +1 -1
  59. package/dist/server/modules/products/index.js +130 -113
  60. package/dist/server/modules/schedule/index.js +13 -6
  61. package/dist/solution/BaseSales/index.d.ts +89 -7
  62. package/dist/solution/BaseSales/index.js +1484 -365
  63. package/dist/solution/BaseSales/types.d.ts +67 -1
  64. package/dist/solution/BaseSales/types.js +3 -1
  65. package/dist/solution/BaseSales/utils/cartPromotion.d.ts +275 -0
  66. package/dist/solution/BaseSales/utils/cartPromotion.js +1258 -0
  67. package/dist/solution/BaseSales/utils/quotationPrice.d.ts +7 -0
  68. package/dist/solution/BaseSales/utils/quotationPrice.js +237 -0
  69. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +68 -16
  70. package/dist/solution/BaseSales/utils.js +46 -8
  71. package/dist/solution/BookingByStep/index.d.ts +1 -1
  72. package/dist/solution/BookingTicket/index.d.ts +133 -1
  73. package/dist/solution/BookingTicket/index.js +780 -175
  74. package/dist/solution/BookingTicket/types.d.ts +2 -0
  75. package/dist/solution/BookingTicket/types.js +3 -0
  76. package/dist/solution/BookingTicket/utils/addProductDecision.d.ts +113 -0
  77. package/dist/solution/BookingTicket/utils/addProductDecision.js +346 -0
  78. package/dist/solution/BookingTicket/utils/cartView.js +4 -2
  79. package/dist/solution/ScanOrder/index.d.ts +9 -3
  80. package/dist/solution/ScanOrder/index.js +231 -128
  81. package/dist/solution/ScanOrder/utils.js +46 -8
  82. package/dist/solution/ShopDiscount/index.d.ts +0 -1
  83. package/dist/solution/ShopDiscount/index.js +18 -23
  84. package/dist/solution/VenueBooking/index.d.ts +5 -9
  85. package/dist/solution/VenueBooking/index.js +103 -55
  86. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +4 -0
  87. package/dist/solution/VenueBooking/utils/slotMerge.js +10 -0
  88. package/lib/model/strategy/adapter/promotion/index.js +0 -49
  89. package/lib/modules/BookingContext/index.d.ts +37 -0
  90. package/lib/modules/BookingContext/index.js +297 -0
  91. package/lib/modules/BookingContext/types.d.ts +102 -0
  92. package/lib/modules/BookingContext/types.js +34 -0
  93. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.d.ts +16 -0
  94. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +207 -0
  95. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +8 -0
  96. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +141 -0
  97. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +75 -0
  98. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +198 -0
  99. package/lib/modules/BookingContext/utils/flexible.d.ts +28 -0
  100. package/lib/modules/BookingContext/utils/flexible.js +80 -0
  101. package/lib/modules/BookingContext/utils/formatResourceList.d.ts +8 -0
  102. package/lib/modules/BookingContext/utils/formatResourceList.js +50 -0
  103. package/lib/modules/BookingContext/utils/index.d.ts +11 -0
  104. package/lib/modules/BookingContext/utils/index.js +43 -0
  105. package/lib/modules/BookingContext/utils/noResource.d.ts +13 -0
  106. package/lib/modules/BookingContext/utils/noResource.js +90 -0
  107. package/lib/modules/BookingContext/utils/productExtend.d.ts +72 -0
  108. package/lib/modules/BookingContext/utils/productExtend.js +283 -0
  109. package/lib/modules/BookingContext/utils/resourceErrors.d.ts +41 -0
  110. package/lib/modules/BookingContext/utils/resourceErrors.js +80 -0
  111. package/lib/modules/BookingContext/utils/resourceSelection.d.ts +7 -0
  112. package/lib/modules/BookingContext/utils/resourceSelection.js +46 -0
  113. package/lib/modules/BookingContext/utils/resources.d.ts +80 -0
  114. package/lib/modules/BookingContext/utils/resources.js +377 -0
  115. package/lib/modules/BookingContext/utils/serviceTimes.d.ts +55 -0
  116. package/lib/modules/BookingContext/utils/serviceTimes.js +162 -0
  117. package/lib/modules/BookingContext/utils/timeSlices.d.ts +42 -0
  118. package/lib/modules/BookingContext/utils/timeSlices.js +124 -0
  119. package/lib/modules/Customer/index.d.ts +6 -0
  120. package/lib/modules/Customer/index.js +26 -11
  121. package/lib/modules/Customer/types.d.ts +2 -0
  122. package/lib/modules/Discount/index.d.ts +2 -4
  123. package/lib/modules/Discount/index.js +8 -63
  124. package/lib/modules/Discount/types.d.ts +1 -7
  125. package/lib/modules/Order/index.d.ts +86 -17
  126. package/lib/modules/Order/index.js +633 -146
  127. package/lib/modules/Order/types.d.ts +198 -18
  128. package/lib/modules/Order/types.js +1 -0
  129. package/lib/modules/Order/utils/manualProductDiscount.d.ts +106 -0
  130. package/lib/modules/Order/utils/manualProductDiscount.js +207 -0
  131. package/lib/modules/Order/utils.d.ts +50 -1
  132. package/lib/modules/Order/utils.js +229 -21
  133. package/lib/modules/Quotation/index.d.ts +0 -1
  134. package/lib/modules/Quotation/index.js +18 -15
  135. package/lib/modules/Rules/index.d.ts +4 -0
  136. package/lib/modules/Rules/index.js +22 -14
  137. package/lib/modules/SalesSummary/index.js +4 -2
  138. package/lib/modules/SalesSummary/utils.js +18 -5
  139. package/lib/modules/Schedule/index.js +3 -1
  140. package/lib/modules/index.d.ts +1 -0
  141. package/lib/modules/index.js +3 -1
  142. package/lib/server/index.js +41 -4
  143. package/lib/server/modules/order/index.d.ts +23 -0
  144. package/lib/server/modules/order/index.js +46 -14
  145. package/lib/server/modules/order/utils/filterOrders.js +12 -4
  146. package/lib/server/modules/products/index.d.ts +1 -1
  147. package/lib/server/modules/products/index.js +30 -20
  148. package/lib/server/modules/schedule/index.js +2 -1
  149. package/lib/solution/BaseSales/index.d.ts +89 -7
  150. package/lib/solution/BaseSales/index.js +736 -22
  151. package/lib/solution/BaseSales/types.d.ts +67 -1
  152. package/lib/solution/BaseSales/types.js +3 -1
  153. package/lib/solution/BaseSales/utils/cartPromotion.d.ts +275 -0
  154. package/lib/solution/BaseSales/utils/cartPromotion.js +836 -0
  155. package/lib/solution/BaseSales/utils/quotationPrice.d.ts +7 -0
  156. package/lib/solution/BaseSales/utils/quotationPrice.js +277 -0
  157. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +71 -12
  158. package/lib/solution/BaseSales/utils.js +46 -6
  159. package/lib/solution/BookingByStep/index.d.ts +1 -1
  160. package/lib/solution/BookingTicket/index.d.ts +133 -1
  161. package/lib/solution/BookingTicket/index.js +352 -8
  162. package/lib/solution/BookingTicket/types.d.ts +2 -0
  163. package/lib/solution/BookingTicket/types.js +6 -0
  164. package/lib/solution/BookingTicket/utils/addProductDecision.d.ts +113 -0
  165. package/lib/solution/BookingTicket/utils/addProductDecision.js +318 -0
  166. package/lib/solution/BookingTicket/utils/cartView.js +4 -2
  167. package/lib/solution/ScanOrder/index.d.ts +9 -3
  168. package/lib/solution/ScanOrder/index.js +147 -66
  169. package/lib/solution/ScanOrder/utils.js +46 -6
  170. package/lib/solution/ShopDiscount/index.d.ts +0 -1
  171. package/lib/solution/ShopDiscount/index.js +2 -4
  172. package/lib/solution/VenueBooking/index.d.ts +5 -9
  173. package/lib/solution/VenueBooking/index.js +50 -14
  174. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +4 -0
  175. package/lib/solution/VenueBooking/utils/slotMerge.js +10 -0
  176. package/package.json +2 -2
@@ -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,37 @@ 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;
88
+ /**
89
+ * 计算商品行「每单位有效折扣」:discount_list 合计 + 被 Rules 剥离但仍 inPromotion 的差额。
90
+ *
91
+ * Rules.calcDiscount 会把 type=promotion 从 discount_list 去掉,但 metadata._promotion 仍保留;
92
+ * applyProductDiscountPrices 必须回读 _promotion,否则抬价/降价都会在第二步被 source 原价覆盖。
93
+ *
94
+ * @example
95
+ * resolveEffectivePerUnitDiscount({ metadata: { _promotion: { inPromotion: true, originalPrice: 1, finalPrice: 5 } }, discount_list: [] });
96
+ * // => -4
97
+ */
98
+ export declare function resolveEffectivePerUnitDiscount(product: Record<string, any>): number;
68
99
  export declare function createDefaultOrderRulesHooks(): RulesParamsHooks;
69
100
  /**
70
101
  * 通过 session 类商品的开始时间结束时间生成商品的时长
@@ -140,4 +171,22 @@ export declare function formatV1Product(products: OrderSubmitProduct[]): {
140
171
  session: null;
141
172
  unique: string;
142
173
  }[];
174
+ /**
175
+ * 判断 holder_id 是否已分配(非空)。
176
+ *
177
+ * @example
178
+ * hasAssignedHolderId(12); // true
179
+ * hasAssignedHolderId([]); // false
180
+ */
181
+ export declare function hasAssignedHolderId(value: unknown): boolean;
182
+ /**
183
+ * 清空 tempOrder 购物车行上的 holder 分配(products / bookings / runtime origin)。
184
+ * 移除或更换下单客户时调用,与 booking 页换客户清 holder 行为对齐。
185
+ *
186
+ * @example
187
+ * clearTempOrderHolderAssignments(tempOrder);
188
+ */
189
+ export declare function clearTempOrderHolderAssignments(tempOrder: OrderTempOrder): boolean;
143
190
  export { createEmptySummary } from '../../solution/ScanOrder/utils';
191
+ export { buildManualProductDiscountItem, ensureManualProductDiscountList, findManualProductDiscountItem, mergeManualProductDiscountIntoList, resolveManualDiscountMessage, resolveManualDiscountOriginTotal, resolveManualDiscountReasonFromSources, resolveSafeProductNum, shouldBuildManualProductDiscount, syncManualProductDiscountProductNum, stripManualProductDiscountItems, } from './utils/manualProductDiscount';
192
+ export type { ManualProductDiscountItem } from './utils/manualProductDiscount';
@@ -29,32 +29,50 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  // src/modules/Order/utils.ts
30
30
  var utils_exports = {};
31
31
  __export(utils_exports, {
32
+ buildManualProductDiscountItem: () => import_manualProductDiscount.buildManualProductDiscountItem,
32
33
  buildSubmitPayload: () => buildSubmitPayload,
34
+ clearTempOrderHolderAssignments: () => clearTempOrderHolderAssignments,
33
35
  composeLinePrice: () => composeLinePrice,
34
36
  createDefaultOrderRulesHooks: () => createDefaultOrderRulesHooks,
35
37
  createDefaultTempOrder: () => createDefaultTempOrder,
36
38
  createEmptySummary: () => import_utils2.createEmptySummary,
37
39
  createUuidV4: () => createUuidV4,
40
+ ensureManualProductDiscountList: () => import_manualProductDiscount.ensureManualProductDiscountList,
41
+ findManualProductDiscountItem: () => import_manualProductDiscount.findManualProductDiscountItem,
38
42
  formatDateTime: () => formatDateTime,
39
43
  formatV1Product: () => formatV1Product,
40
44
  generateDuration: () => generateDuration,
41
45
  getAllDiscountList: () => getAllDiscountList,
46
+ hasAssignedHolderId: () => hasAssignedHolderId,
42
47
  isTempOrder: () => isTempOrder,
43
48
  mapPaymentItemToOrderPayment: () => mapPaymentItemToOrderPayment,
44
49
  mapPaymentItemsToOrderPayments: () => mapPaymentItemsToOrderPayments,
50
+ mergeManualProductDiscountIntoList: () => import_manualProductDiscount.mergeManualProductDiscountIntoList,
45
51
  mergeRelationForms: () => mergeRelationForms,
46
52
  normalizeBookingIsAll: () => normalizeBookingIsAll,
47
53
  normalizeBookingSubType: () => normalizeBookingSubType,
54
+ normalizeOrderProductDiscountList: () => normalizeOrderProductDiscountList,
48
55
  normalizeSubmitBooking: () => normalizeSubmitBooking,
49
56
  normalizeSubmitCollectPaxValue: () => normalizeSubmitCollectPaxValue,
57
+ resolveEffectivePerUnitDiscount: () => resolveEffectivePerUnitDiscount,
58
+ resolveManualDiscountMessage: () => import_manualProductDiscount.resolveManualDiscountMessage,
59
+ resolveManualDiscountOriginTotal: () => import_manualProductDiscount.resolveManualDiscountOriginTotal,
60
+ resolveManualDiscountReasonFromSources: () => import_manualProductDiscount.resolveManualDiscountReasonFromSources,
61
+ resolveManualOverrideLineOriginalPrice: () => resolveManualOverrideLineOriginalPrice,
62
+ resolveRulesManualDiscountFlag: () => resolveRulesManualDiscountFlag,
63
+ resolveSafeProductNum: () => import_manualProductDiscount.resolveSafeProductNum,
50
64
  resolveSubmitCollectPax: () => resolveSubmitCollectPax,
51
- sumOptionUnitPrice: () => sumOptionUnitPrice
65
+ shouldBuildManualProductDiscount: () => import_manualProductDiscount.shouldBuildManualProductDiscount,
66
+ stripManualProductDiscountItems: () => import_manualProductDiscount.stripManualProductDiscountItems,
67
+ sumOptionUnitPrice: () => sumOptionUnitPrice,
68
+ syncManualProductDiscountProductNum: () => import_manualProductDiscount.syncManualProductDiscountProductNum
52
69
  });
53
70
  module.exports = __toCommonJS(utils_exports);
54
71
  var import_dayjs = __toESM(require("dayjs"));
55
72
  var import_decimal = __toESM(require("decimal.js"));
56
73
  var import_utils = require("../../solution/ScanOrder/utils");
57
74
  var import_utils2 = require("../../solution/ScanOrder/utils");
75
+ var import_manualProductDiscount = require("./utils/manualProductDiscount");
58
76
  function composeLinePrice(params) {
59
77
  const { mainPrice, bundle, useOriginalBundle } = params;
60
78
  let total = new import_decimal.default(Number(mainPrice) || 0);
@@ -80,6 +98,105 @@ function sumOptionUnitPrice(options) {
80
98
  }
81
99
  return total;
82
100
  }
101
+ function resolveRulesManualDiscountFlag(metadata) {
102
+ if (!metadata)
103
+ return void 0;
104
+ if (metadata.is_manual_discount === true || metadata.is_manual_discount === 1) {
105
+ return true;
106
+ }
107
+ const priceOverride = metadata.price_override;
108
+ if (priceOverride !== void 0 && priceOverride !== null && priceOverride !== "") {
109
+ return true;
110
+ }
111
+ return void 0;
112
+ }
113
+ function normalizeOrderProductDiscountAmount(amount) {
114
+ if (amount === void 0 || amount === null)
115
+ return void 0;
116
+ return String(amount);
117
+ }
118
+ function normalizeOrderProductDiscountList(discountList) {
119
+ if (!Array.isArray(discountList))
120
+ return [];
121
+ return discountList.filter((item) => !!item && typeof item === "object").map((item) => {
122
+ const normalized = {
123
+ discount_id: Number.isFinite(Number(item.discount_id)) ? Number(item.discount_id) : 0
124
+ };
125
+ if (item.order_discount_id === null) {
126
+ normalized.order_discount_id = null;
127
+ } else if (item.order_discount_id !== void 0) {
128
+ const orderDiscountId = Number(item.order_discount_id);
129
+ if (Number.isFinite(orderDiscountId)) {
130
+ normalized.order_discount_id = orderDiscountId;
131
+ }
132
+ }
133
+ if (item.type !== void 0)
134
+ normalized.type = item.type;
135
+ const amount = normalizeOrderProductDiscountAmount(item.amount);
136
+ if (amount !== void 0)
137
+ normalized.amount = amount;
138
+ if (item.discount && typeof item.discount === "object") {
139
+ normalized.discount = { ...item.discount };
140
+ }
141
+ if (item.metadata === null) {
142
+ normalized.metadata = null;
143
+ } else if (item.metadata && typeof item.metadata === "object") {
144
+ normalized.metadata = { ...item.metadata };
145
+ }
146
+ return normalized;
147
+ });
148
+ }
149
+ function resolveManualOverrideLineOriginalPrice(params, fallbackCompositeOriginal) {
150
+ var _a, _b;
151
+ const metadata = params.metadata || {};
152
+ const priceOverride = metadata.price_override;
153
+ if (priceOverride === void 0 || priceOverride === null || priceOverride === "") {
154
+ return fallbackCompositeOriginal;
155
+ }
156
+ const refTotal = (_b = (_a = metadata.origin) == null ? void 0 : _a._extend) == null ? void 0 : _b.origin_total;
157
+ if (refTotal !== void 0 && refTotal !== null && refTotal !== "") {
158
+ const parsed = Number(refTotal);
159
+ if (Number.isFinite(parsed)) {
160
+ return new import_decimal.default(parsed).toDecimalPlaces(2).toFixed(2);
161
+ }
162
+ }
163
+ const lineOriginal = params.lineOriginalPrice;
164
+ if (lineOriginal !== void 0 && lineOriginal !== null && lineOriginal !== "") {
165
+ const parsedLine = Number(lineOriginal);
166
+ const parsedFallback = Number(fallbackCompositeOriginal);
167
+ if (Number.isFinite(parsedLine) && Number.isFinite(parsedFallback) && parsedLine > parsedFallback) {
168
+ return new import_decimal.default(parsedLine).toDecimalPlaces(2).toFixed(2);
169
+ }
170
+ }
171
+ return fallbackCompositeOriginal;
172
+ }
173
+ function resolveEffectivePerUnitDiscount(product) {
174
+ const discountList = Array.isArray(product == null ? void 0 : product.discount_list) ? product.discount_list : [];
175
+ const fromList = discountList.reduce(
176
+ (sum, discount) => sum + Number((discount == null ? void 0 : discount.amount) || 0),
177
+ 0
178
+ );
179
+ const hasPromoDiscountItem = discountList.some((item) => (item == null ? void 0 : item.type) === "promotion");
180
+ if (hasPromoDiscountItem)
181
+ return fromList;
182
+ const metadata = (product == null ? void 0 : product.metadata) || {};
183
+ const optionSum = sumOptionUnitPrice(product == null ? void 0 : product.product_option_item).toNumber();
184
+ if (metadata.source_product_price != null && metadata.main_product_selling_price != null) {
185
+ const source = Number(metadata.source_product_price);
186
+ const selling = Number(metadata.main_product_selling_price) - optionSum;
187
+ if (Number.isFinite(source) && Number.isFinite(selling) && source !== selling) {
188
+ return fromList + (source - selling);
189
+ }
190
+ }
191
+ const promo = metadata._promotion;
192
+ if ((promo == null ? void 0 : promo.inPromotion) !== true)
193
+ return fromList;
194
+ const originalPrice = Number(promo.originalPrice);
195
+ const finalPrice = Number(promo.finalPrice);
196
+ if (!Number.isFinite(originalPrice) || !Number.isFinite(finalPrice))
197
+ return fromList;
198
+ return fromList + (originalPrice - finalPrice);
199
+ }
83
200
  function createDefaultOrderRulesHooks() {
84
201
  const toUnitPriceString = (totalLike, num) => {
85
202
  const effectiveNum = Number(num) > 0 ? Number(num) : 1;
@@ -114,7 +231,7 @@ function createDefaultOrderRulesHooks() {
114
231
  id: product.product_id,
115
232
  // Rules 引擎用 _id 作为 processedProductsMap 键;必须与购物车行级 identity 一致,
116
233
  // 否则同 SKU 不同小料会在 calcDiscount 重组时互相覆盖。
117
- // 不透明 identity 契约下,normalizeOrderProduct / restoreTempOrderFromStorage 已保证唯一值存在;
234
+ // 不透明 identity 契约下,normalizeOrderProduct / hydrate 已保证唯一值存在;
118
235
  // 留 fingerprint 分支仅作 Rules 单测里直接传裸 product 时的兜底。
119
236
  _id: ((_a = product.metadata) == null ? void 0 : _a.unique_identification_number) ? `${product.product_id}_${product.product_variant_id}_${product.metadata.unique_identification_number}` : `${product.product_id}_${product.product_variant_id}_${(0, import_utils.buildProductLineFingerprint)(
120
237
  product.product_option_item,
@@ -135,9 +252,14 @@ function createDefaultOrderRulesHooks() {
135
252
  bundle: product.product_bundle || [],
136
253
  booking_id: ((_b = product.metadata) == null ? void 0 : _b.booking_id) || null,
137
254
  isClient: false,
138
- isManualDiscount: ((_c = product.metadata) == null ? void 0 : _c.is_manual_discount) || false,
139
- holder_id: (_d = product.metadata) == null ? void 0 : _d.holder_id,
140
- startDate: ((_e = product.metadata) == null ? void 0 : _e.start_date) || ((_f = product.metadata) == null ? void 0 : _f.startDate)
255
+ // 勿写死 false:否则 Rules 不会走 total≠origin_total 的手动价推断,
256
+ // 无券时会把 bundle 价还原成 original_price(手动改价套餐会从 20 回到 30)。
257
+ isManualDiscount: resolveRulesManualDiscountFlag(metadataAny),
258
+ holder_id: (_c = product.metadata) == null ? void 0 : _c.holder_id,
259
+ startDate: ((_d = product.metadata) == null ? void 0 : _d.start_date) || ((_e = product.metadata) == null ? void 0 : _e.startDate),
260
+ main_product_selling_price: metadataAny.main_product_selling_price !== void 0 ? new import_decimal.default(Number(metadataAny.main_product_selling_price) || 0).minus(optionSum).toDecimalPlaces(2).toString() : void 0,
261
+ inPromotion: ((_f = metadataAny._promotion) == null ? void 0 : _f.inPromotion) === true,
262
+ _promotion: metadataAny._promotion
141
263
  };
142
264
  },
143
265
  setProduct: (product, values) => {
@@ -160,10 +282,14 @@ function createDefaultOrderRulesHooks() {
160
282
  bundle: nextBundle,
161
283
  useOriginalBundle: true
162
284
  });
285
+ const finalOriginalPrice = resolveManualOverrideLineOriginalPrice(
286
+ { num: nextNum, metadata: metadataAny, lineOriginalPrice: product.original_price },
287
+ composedOriginalPrice
288
+ );
163
289
  return {
164
290
  ...product,
165
291
  selling_price: composedSellingPrice,
166
- original_price: composedOriginalPrice,
292
+ original_price: finalOriginalPrice,
167
293
  discount_list: values.discount_list ?? product.discount_list,
168
294
  num: values.quantity ?? product.num,
169
295
  product_bundle: nextBundle,
@@ -321,6 +447,11 @@ function normalizeSubmitProduct(product) {
321
447
  num,
322
448
  product_option_item: productOptionItem,
323
449
  surcharge_fee: _productSurchargeFee,
450
+ discount_amount: _deprecatedDiscountAmount,
451
+ discount_type: _deprecatedDiscountType,
452
+ discountway: _deprecatedDiscountway,
453
+ product_discount_reason: _deprecatedProductDiscountReason,
454
+ discount_per: _deprecatedDiscountPer,
324
455
  ...productRest
325
456
  } = submitProduct;
326
457
  const rawMetadata = submitProduct.metadata || {};
@@ -365,7 +496,7 @@ function normalizeSubmitProduct(product) {
365
496
  ...bookingUid ? { booking_uid: bookingUid } : {},
366
497
  product_quantity: toBundleNumber(num ?? submitProduct.product_quantity, 1),
367
498
  product_sku: productSku,
368
- discount_list: submitProduct.discount_list || [],
499
+ discount_list: normalizeOrderProductDiscountList(submitProduct.discount_list),
369
500
  product_bundle: formatSubmitBundleItems(submitProduct.product_bundle),
370
501
  metadata: cleanMetadata,
371
502
  // 出站兼容:后端消费 payment_price 字段,这里从 selling_price 直接派生。
@@ -425,22 +556,23 @@ function createDefaultTempOrder(params) {
425
556
  return {
426
557
  order_id: null,
427
558
  external_sale_number: "",
428
- order_number: "",
429
- shop_order_number: "",
430
- shop_full_order_number: "",
431
- type: "appointment_booking",
432
- business_code: "appointment_booking",
559
+ order_number: null,
560
+ shop_order_number: null,
561
+ shop_full_order_number: null,
562
+ type: "",
563
+ business_code: void 0,
433
564
  platform: "h5",
434
565
  sales_channel: "my_pisel",
435
566
  order_sales_channel: "online_store",
436
567
  status: "normal",
437
568
  payment_status: "payment_processing",
438
569
  shipping_status: "unfulfilled",
439
- customer_id: null,
570
+ customer_id: 0,
440
571
  customer_name: "",
441
572
  country_calling_code: "",
442
573
  phone: "",
443
574
  email: "",
575
+ customer: null,
444
576
  is_price_include_tax: 1,
445
577
  tax_title: "",
446
578
  tax_country_code: "",
@@ -459,7 +591,6 @@ function createDefaultTempOrder(params) {
459
591
  bookings: [],
460
592
  payments: [],
461
593
  surcharges: [],
462
- discount_list: [],
463
594
  relation_forms: [],
464
595
  contacts: [],
465
596
  contacts_info: null,
@@ -471,6 +602,7 @@ function createDefaultTempOrder(params) {
471
602
  };
472
603
  }
473
604
  function buildSubmitPayload(params) {
605
+ var _a;
474
606
  const {
475
607
  tempOrder,
476
608
  cacheId,
@@ -496,7 +628,7 @@ function buildSubmitPayload(params) {
496
628
  shop_service_type: _shopServiceType,
497
629
  start_time: _startTime,
498
630
  customer: _customer,
499
- shop_full_order_number: _shopFullOrderNumber,
631
+ discount_list: _discountList,
500
632
  tax_fee: _rootTaxFee,
501
633
  total_amount: _totalAmount,
502
634
  total_refund_amount: _totalRefundAmount,
@@ -504,12 +636,25 @@ function buildSubmitPayload(params) {
504
636
  holder_id: _holderId,
505
637
  ...tempOrderRest
506
638
  } = tempOrder;
639
+ let submitType = type ?? tempOrder.type;
640
+ if (!submitType) {
641
+ if ((_a = tempOrder == null ? void 0 : tempOrder.bookings) == null ? void 0 : _a.length) {
642
+ submitType = "appointment_booking";
643
+ } else {
644
+ submitType = "virtual";
645
+ }
646
+ }
507
647
  const payload = {
508
648
  ...tempOrderRest,
649
+ customer_id: tempOrder.customer_id ?? 1,
650
+ customer_name: tempOrder.customer_name || "Select a customer",
651
+ order_number: null,
652
+ shop_order_number: null,
653
+ shop_full_order_number: null,
509
654
  platform: normalizeSubmitPlatform(platform),
510
655
  request_unique_idempotency_token: tempOrder.request_unique_idempotency_token || `${tempOrder.external_sale_number}_${now.getTime()}`,
511
- type: type ?? tempOrder.type ?? "table-order",
512
- business_code: businessCode ?? tempOrder.business_code ?? "table-order",
656
+ type: submitType,
657
+ business_code: businessCode ?? tempOrder.business_code,
513
658
  sales_channel: tempOrder.sales_channel || "my_pisel",
514
659
  order_sales_channel: channel ?? tempOrder.order_sales_channel ?? "online_store",
515
660
  status: tempOrder.status || "normal",
@@ -524,12 +669,11 @@ function buildSubmitPayload(params) {
524
669
  note: tempOrder.note || "",
525
670
  delivery_type: tempOrder.delivery_type || "nil",
526
671
  schedule_date: scheduleDate,
527
- created_at: tempOrder.created_at || formatDateTime(now),
672
+ // created_at: tempOrder.created_at || formatDateTime(now), 和后端协定这个字段先不提交到接口
528
673
  bookings: (tempOrder.bookings || []).filter(
529
- (booking) => Number(booking.parent_id ?? 0) !== 0
674
+ (booking) => Number(booking.parent_id) !== 0
530
675
  ).map((booking) => normalizeSubmitBooking(booking)),
531
676
  payments: tempOrder.payments || [],
532
- // discount_list: tempOrder.discount_list || [],
533
677
  relation_forms: tempOrder.relation_forms || [],
534
678
  // contacts: tempOrder.contacts || [],
535
679
  contacts_info: tempOrder.contacts_info && !Array.isArray(tempOrder.contacts_info) ? tempOrder.contacts_info : null,
@@ -610,26 +754,90 @@ function formatV1Product(products) {
610
754
  };
611
755
  });
612
756
  }
757
+ function hasAssignedHolderId(value) {
758
+ if (value === void 0 || value === null || value === "")
759
+ return false;
760
+ if (Array.isArray(value))
761
+ return value.length > 0;
762
+ return true;
763
+ }
764
+ function clearTempOrderHolderAssignments(tempOrder) {
765
+ var _a;
766
+ let changed = false;
767
+ const resetHolderField = (target, key = "holder_id") => {
768
+ if (!hasAssignedHolderId(target[key]))
769
+ return;
770
+ target[key] = null;
771
+ changed = true;
772
+ };
773
+ for (const product of tempOrder.products || []) {
774
+ if (product.metadata && typeof product.metadata === "object") {
775
+ resetHolderField(product.metadata);
776
+ }
777
+ }
778
+ for (const booking of tempOrder.bookings || []) {
779
+ const bookingRecord = booking;
780
+ if (booking.metadata && typeof booking.metadata === "object") {
781
+ resetHolderField(booking.metadata);
782
+ }
783
+ if (bookingRecord.holder !== void 0 && bookingRecord.holder !== null) {
784
+ delete bookingRecord.holder;
785
+ changed = true;
786
+ }
787
+ }
788
+ const productsByUid = (_a = tempOrder._extend) == null ? void 0 : _a.productsByUid;
789
+ if (productsByUid && typeof productsByUid === "object") {
790
+ for (const entry of Object.values(productsByUid)) {
791
+ const origin = entry == null ? void 0 : entry.origin;
792
+ if (!origin || typeof origin !== "object")
793
+ continue;
794
+ if (origin.metadata && typeof origin.metadata === "object") {
795
+ resetHolderField(origin.metadata);
796
+ }
797
+ if (origin._extend && typeof origin._extend === "object") {
798
+ resetHolderField(origin._extend);
799
+ }
800
+ }
801
+ }
802
+ return changed;
803
+ }
613
804
  // Annotate the CommonJS export names for ESM import in node:
614
805
  0 && (module.exports = {
806
+ buildManualProductDiscountItem,
615
807
  buildSubmitPayload,
808
+ clearTempOrderHolderAssignments,
616
809
  composeLinePrice,
617
810
  createDefaultOrderRulesHooks,
618
811
  createDefaultTempOrder,
619
812
  createEmptySummary,
620
813
  createUuidV4,
814
+ ensureManualProductDiscountList,
815
+ findManualProductDiscountItem,
621
816
  formatDateTime,
622
817
  formatV1Product,
623
818
  generateDuration,
624
819
  getAllDiscountList,
820
+ hasAssignedHolderId,
625
821
  isTempOrder,
626
822
  mapPaymentItemToOrderPayment,
627
823
  mapPaymentItemsToOrderPayments,
824
+ mergeManualProductDiscountIntoList,
628
825
  mergeRelationForms,
629
826
  normalizeBookingIsAll,
630
827
  normalizeBookingSubType,
828
+ normalizeOrderProductDiscountList,
631
829
  normalizeSubmitBooking,
632
830
  normalizeSubmitCollectPaxValue,
831
+ resolveEffectivePerUnitDiscount,
832
+ resolveManualDiscountMessage,
833
+ resolveManualDiscountOriginTotal,
834
+ resolveManualDiscountReasonFromSources,
835
+ resolveManualOverrideLineOriginalPrice,
836
+ resolveRulesManualDiscountFlag,
837
+ resolveSafeProductNum,
633
838
  resolveSubmitCollectPax,
634
- sumOptionUnitPrice
839
+ shouldBuildManualProductDiscount,
840
+ stripManualProductDiscountItems,
841
+ sumOptionUnitPrice,
842
+ syncManualProductDiscountProductNum
635
843
  });
@@ -47,7 +47,6 @@ export declare class QuotationModule extends BaseModule implements Module {
47
47
  customer_id?: number | string;
48
48
  }): Map<string, string | null>;
49
49
  setScheduleResolver(resolver: (id: number) => ScheduleItem | undefined): void;
50
- private filterQuotationsByCustomer;
51
50
  private isQuotationVisibleForCustomer;
52
51
  private hasValidCustomerId;
53
52
  private isQuotationActiveAt;
@@ -43,8 +43,6 @@ var QuotationModule = class extends import_BaseModule.BaseModule {
43
43
  const query = {};
44
44
  if (params == null ? void 0 : params.channel)
45
45
  query.channel = params.channel;
46
- if (params == null ? void 0 : params.customer_id)
47
- query.customer_id = String(params.customer_id);
48
46
  if ((params == null ? void 0 : params.channel) === "online_store") {
49
47
  query.channel = "online-store";
50
48
  }
@@ -53,10 +51,7 @@ var QuotationModule = class extends import_BaseModule.BaseModule {
53
51
  query,
54
52
  { useCache: false }
55
53
  );
56
- const list = this.filterQuotationsByCustomer(
57
- ((_a = res == null ? void 0 : res.data) == null ? void 0 : _a.list) || (res == null ? void 0 : res.list) || [],
58
- params == null ? void 0 : params.customer_id
59
- );
54
+ const list = ((_a = res == null ? void 0 : res.data) == null ? void 0 : _a.list) || (res == null ? void 0 : res.list) || [];
60
55
  list.sort((a, b) => a.sort - b.sort);
61
56
  this.store.list = list;
62
57
  }
@@ -74,9 +69,11 @@ var QuotationModule = class extends import_BaseModule.BaseModule {
74
69
  getPriceForProduct(params) {
75
70
  const { productId, variantId, datetime, customer_id } = params;
76
71
  for (const quotation of this.store.list) {
77
- if (!this.isQuotationVisibleForCustomer(quotation, customer_id))
72
+ const visible = this.isQuotationVisibleForCustomer(quotation, customer_id);
73
+ if (!visible)
78
74
  continue;
79
- if (!this.isQuotationActiveAt(quotation, datetime))
75
+ const active = this.isQuotationActiveAt(quotation, datetime);
76
+ if (!active)
80
77
  continue;
81
78
  const match = this.findProductData(quotation.product_data, productId, variantId);
82
79
  if (!match)
@@ -128,9 +125,6 @@ var QuotationModule = class extends import_BaseModule.BaseModule {
128
125
  setScheduleResolver(resolver) {
129
126
  this.scheduleResolver = resolver;
130
127
  }
131
- filterQuotationsByCustomer(list, customerId) {
132
- return list.filter((quotation) => this.isQuotationVisibleForCustomer(quotation, customerId));
133
- }
134
128
  isQuotationVisibleForCustomer(quotation, customerId) {
135
129
  const customers = quotation.customer || [];
136
130
  if (customers.length === 0)
@@ -148,18 +142,27 @@ var QuotationModule = class extends import_BaseModule.BaseModule {
148
142
  var _a;
149
143
  if (!((_a = quotation.schedule) == null ? void 0 : _a.length))
150
144
  return false;
151
- const scheduleItems = quotation.schedule.map((s) => {
145
+ const scheduleItems = [];
146
+ quotation.schedule.forEach((s) => {
152
147
  var _a2;
153
148
  const full = (_a2 = this.scheduleResolver) == null ? void 0 : _a2.call(this, s.id);
154
- if (full)
155
- return full;
156
- return {
149
+ if (full) {
150
+ scheduleItems.push(full);
151
+ return;
152
+ }
153
+ if (this.scheduleResolver) {
154
+ return;
155
+ }
156
+ const fallbackSchedule = {
157
157
  ...s,
158
158
  repeat_type: s.repeat_type || "none",
159
159
  repeat_rule: s.repeat_rule || null,
160
160
  time_slot: s.time_slot || []
161
161
  };
162
+ scheduleItems.push(fallbackSchedule);
162
163
  });
164
+ if (!scheduleItems.length)
165
+ return false;
163
166
  return (0, import_getDateIsInSchedule.getDateIsInSchedule)(datetime, scheduleItems);
164
167
  }
165
168
  findProductData(productData, productId, variantId) {
@@ -32,6 +32,10 @@ export declare class RulesModule extends BaseModule implements Module, RulesModu
32
32
  unavailableReason?: UnavailableReason;
33
33
  };
34
34
  filterDiscountListByType(discountList: Discount[], type: string): Discount[];
35
+ /** 剔除指定 type/tag 的折扣项,保留手动改价(type=product) / 券等 */
36
+ excludeDiscountListByType(discountList: Discount[], type: string): Discount[];
37
+ /** 手动改价场景:去掉 promotion,保留 type=product 等行内折扣 */
38
+ resolveDiscountListForManualOverride(discountList: Discount[]): Discount[];
35
39
  private getUnavailableReason;
36
40
  calcDiscount({ discountList, productList, holders, isFormSubject, orderTotalAmount }: {
37
41
  discountList: Discount[];