@pisell/pisellos 2.3.74 → 2.3.75

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 (276) hide show
  1. package/dist/core/index.js +6 -10
  2. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  3. package/dist/model/strategy/adapter/walletPass/example.js +3 -26
  4. package/dist/model/strategy/strategy-example.js +5 -19
  5. package/dist/modules/Cart/index.js +0 -3
  6. package/dist/modules/Cart/utils/cartProduct.js +0 -1
  7. package/dist/modules/Date/index.js +1 -5
  8. package/dist/modules/Discount/index.js +2 -4
  9. package/dist/modules/OpenData/index.js +0 -2
  10. package/dist/modules/Order/index.js +36 -64
  11. package/dist/modules/Payment/index.js +97 -162
  12. package/dist/modules/Rules/index.js +1 -4
  13. package/dist/modules/Schedule/index.js +0 -1
  14. package/dist/modules/Schedule/utils.js +0 -1
  15. package/dist/modules/Step/index.js +0 -1
  16. package/dist/plugins/request.js +1 -4
  17. package/dist/plugins/window.js +2 -6
  18. package/dist/server/index.js +97 -129
  19. package/dist/server/modules/menu/index.js +32 -41
  20. package/dist/server/modules/order/index.js +2 -4
  21. package/dist/server/modules/products/index.js +24 -42
  22. package/dist/server/modules/quotation/index.js +29 -38
  23. package/dist/server/modules/resource/index.js +3 -4
  24. package/dist/server/modules/schedule/index.js +27 -35
  25. package/dist/server/utils/product.js +0 -1
  26. package/dist/solution/BaseSales/index.js +38 -41
  27. package/dist/solution/BookingByStep/index.js +7 -59
  28. package/dist/solution/BookingByStep/utils/capacity.js +1 -11
  29. package/dist/solution/BookingByStep/utils/resources.js +1 -3
  30. package/dist/solution/BookingByStep/utils/timeslots.js +2 -43
  31. package/dist/solution/BookingTicket/index.js +0 -2
  32. package/dist/solution/BookingTicket/utils/scan/cloudSearch.js +6 -7
  33. package/dist/solution/BookingTicket/utils/scan/handleScan.js +25 -31
  34. package/dist/solution/BookingTicket/utils/scan/index.js +6 -10
  35. package/dist/solution/BuyTickets/index.js +9 -12
  36. package/dist/solution/Checkout/index.js +177 -252
  37. package/dist/solution/Checkout/utils/index.js +4 -16
  38. package/dist/solution/RegisterAndLogin/index.js +30 -76
  39. package/dist/solution/ScanOrder/index.js +50 -60
  40. package/dist/solution/ShopDiscount/index.js +2 -7
  41. package/dist/solution/VenueBooking/index.js +45 -55
  42. package/dist/utils/task.js +15 -18
  43. package/dist/utils/watch.js +0 -1
  44. package/lib/apis/picoding.js +2 -0
  45. package/lib/core/index.js +134 -134
  46. package/lib/effects/index.js +46 -57
  47. package/lib/index.js +82 -49
  48. package/lib/model/index.js +14 -21
  49. package/lib/model/strategy/adapter/dataVariant/adapter.js +38 -50
  50. package/lib/model/strategy/adapter/dataVariant/evaluator.js +162 -236
  51. package/lib/model/strategy/adapter/dataVariant/examples.js +229 -237
  52. package/lib/model/strategy/adapter/dataVariant/index.js +39 -34
  53. package/lib/model/strategy/adapter/dataVariant/type.js +57 -28
  54. package/lib/model/strategy/adapter/index.js +100 -64
  55. package/lib/model/strategy/adapter/itemRule/adapter.js +156 -144
  56. package/lib/model/strategy/adapter/itemRule/evaluator.js +36 -48
  57. package/lib/model/strategy/adapter/itemRule/examples.js +295 -225
  58. package/lib/model/strategy/adapter/itemRule/index.js +83 -57
  59. package/lib/model/strategy/adapter/itemRule/type.js +97 -36
  60. package/lib/model/strategy/adapter/promotion/adapter.js +91 -69
  61. package/lib/model/strategy/adapter/promotion/evaluator.js +444 -310
  62. package/lib/model/strategy/adapter/promotion/examples.js +222 -234
  63. package/lib/model/strategy/adapter/promotion/index.js +1 -0
  64. package/lib/model/strategy/adapter/promotion/type.js +243 -36
  65. package/lib/model/strategy/adapter/type.js +4 -16
  66. package/lib/model/strategy/adapter/walletPass/evaluator.js +180 -150
  67. package/lib/model/strategy/adapter/walletPass/example.js +217 -190
  68. package/lib/model/strategy/adapter/walletPass/index.js +75 -51
  69. package/lib/model/strategy/adapter/walletPass/locales.js +36 -58
  70. package/lib/model/strategy/adapter/walletPass/type.js +4 -16
  71. package/lib/model/strategy/adapter/walletPass/utils.js +588 -378
  72. package/lib/model/strategy/engine.js +270 -168
  73. package/lib/model/strategy/index.js +49 -34
  74. package/lib/model/strategy/strategy-example.js +243 -239
  75. package/lib/model/strategy/type.js +100 -40
  76. package/lib/modules/Account/index.js +39 -53
  77. package/lib/modules/Account/types.js +20 -33
  78. package/lib/modules/AccountList/index.js +116 -154
  79. package/lib/modules/AccountList/types.js +30 -31
  80. package/lib/modules/AccountList/utils.js +18 -30
  81. package/lib/modules/BaseModule.js +23 -42
  82. package/lib/modules/BookingContext/index.js +158 -136
  83. package/lib/modules/BookingContext/types.js +46 -32
  84. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +138 -146
  85. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +78 -83
  86. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +170 -150
  87. package/lib/modules/BookingContext/utils/flexible.js +38 -55
  88. package/lib/modules/BookingContext/utils/formatResourceList.js +19 -34
  89. package/lib/modules/BookingContext/utils/index.js +124 -41
  90. package/lib/modules/BookingContext/utils/noResource.js +58 -70
  91. package/lib/modules/BookingContext/utils/orderLineDisplay.js +14 -41
  92. package/lib/modules/BookingContext/utils/productExtend.js +202 -155
  93. package/lib/modules/BookingContext/utils/resourceErrors.js +53 -53
  94. package/lib/modules/BookingContext/utils/resourceSelection.js +19 -41
  95. package/lib/modules/BookingContext/utils/resources.js +209 -167
  96. package/lib/modules/BookingContext/utils/serviceTimes.js +115 -116
  97. package/lib/modules/BookingContext/utils/timeSlices.js +76 -86
  98. package/lib/modules/Cart/index.js +170 -124
  99. package/lib/modules/Cart/types.js +46 -51
  100. package/lib/modules/Cart/utils/cartAccount.js +40 -39
  101. package/lib/modules/Cart/utils/cartDate.js +56 -61
  102. package/lib/modules/Cart/utils/cartDiscount.js +28 -33
  103. package/lib/modules/Cart/utils/cartNote.js +27 -32
  104. package/lib/modules/Cart/utils/cartProduct.js +321 -251
  105. package/lib/modules/Cart/utils/cartRelationForms.js +29 -35
  106. package/lib/modules/Cart/utils/cartResource.js +70 -78
  107. package/lib/modules/Cart/utils/changePrice.js +22 -50
  108. package/lib/modules/Cart/utils/index.js +106 -48
  109. package/lib/modules/Customer/constants.js +13 -34
  110. package/lib/modules/Customer/index.js +235 -172
  111. package/lib/modules/Customer/types.js +38 -35
  112. package/lib/modules/Date/index.js +116 -115
  113. package/lib/modules/Date/types.js +16 -28
  114. package/lib/modules/Date/utils.js +174 -123
  115. package/lib/modules/Discount/index.js +122 -127
  116. package/lib/modules/Discount/types.js +9 -31
  117. package/lib/modules/Guests/index.js +30 -56
  118. package/lib/modules/Guests/types.js +23 -33
  119. package/lib/modules/Holder/index.js +209 -189
  120. package/lib/modules/Holder/types.js +4 -16
  121. package/lib/modules/Holder/utils.js +20 -49
  122. package/lib/modules/OpenData/index.js +70 -76
  123. package/lib/modules/OpenData/types.js +4 -16
  124. package/lib/modules/OpenData/utils.js +44 -78
  125. package/lib/modules/Order/index.js +1713 -2118
  126. package/lib/modules/Order/payment-utils.js +77 -120
  127. package/lib/modules/Order/types.js +88 -35
  128. package/lib/modules/Order/utils/bundleDiscountHydration.js +41 -74
  129. package/lib/modules/Order/utils/discountProductLineIdentity.js +142 -100
  130. package/lib/modules/Order/utils/manualProductDiscount.js +124 -123
  131. package/lib/modules/Order/utils/orderCollectionIdentity.js +184 -244
  132. package/lib/modules/Order/utils.js +814 -647
  133. package/lib/modules/Payment/cash.js +20 -33
  134. package/lib/modules/Payment/cashRecommendationAlgorithm.js +145 -76
  135. package/lib/modules/Payment/eftpos.js +16 -30
  136. package/lib/modules/Payment/index.js +532 -399
  137. package/lib/modules/Payment/mx51.js +1 -0
  138. package/lib/modules/Payment/types.js +230 -108
  139. package/lib/modules/Payment/utils.js +52 -51
  140. package/lib/modules/Payment/walletpass.js +485 -660
  141. package/lib/modules/Product/index.js +51 -46
  142. package/lib/modules/Product/types.js +4 -16
  143. package/lib/modules/Product/utils.js +32 -33
  144. package/lib/modules/ProductList/index.js +113 -123
  145. package/lib/modules/ProductList/types.js +9 -31
  146. package/lib/modules/Quotation/index.js +81 -118
  147. package/lib/modules/Quotation/types.js +4 -16
  148. package/lib/modules/Resource/index.js +27 -59
  149. package/lib/modules/Resource/types.js +22 -32
  150. package/lib/modules/Resource/utils.js +30 -38
  151. package/lib/modules/ResourcePlanner/index.js +25 -23
  152. package/lib/modules/ResourcePlanner/localClock.js +54 -119
  153. package/lib/modules/ResourcePlanner/planner.js +589 -770
  154. package/lib/modules/ResourcePlanner/types.js +10 -29
  155. package/lib/modules/Rules/index.js +1218 -959
  156. package/lib/modules/Rules/types.js +17 -40
  157. package/lib/modules/SalesSummary/index.js +85 -90
  158. package/lib/modules/SalesSummary/types.js +4 -16
  159. package/lib/modules/SalesSummary/utils.js +355 -430
  160. package/lib/modules/ScanOrderLogger/index.js +59 -79
  161. package/lib/modules/ScanOrderLogger/providers/feishu.js +54 -78
  162. package/lib/modules/ScanOrderLogger/providers/grafana.js +13 -36
  163. package/lib/modules/ScanOrderLogger/types.js +4 -16
  164. package/lib/modules/Schedule/getDateIsInSchedule.js +334 -163
  165. package/lib/modules/Schedule/index.js +100 -114
  166. package/lib/modules/Schedule/type.js +4 -16
  167. package/lib/modules/Schedule/types.js +4 -16
  168. package/lib/modules/Schedule/utils.js +433 -291
  169. package/lib/modules/Step/index.js +40 -52
  170. package/lib/modules/Step/tyeps.js +4 -16
  171. package/lib/modules/Summary/index.js +66 -71
  172. package/lib/modules/Summary/types.js +4 -16
  173. package/lib/modules/Summary/utils.js +773 -418
  174. package/lib/modules/SurchargeList/index.js +46 -60
  175. package/lib/modules/SurchargeList/types.js +4 -16
  176. package/lib/modules/index.js +245 -63
  177. package/lib/plugins/app.js +4 -16
  178. package/lib/plugins/index.js +36 -25
  179. package/lib/plugins/request.js +137 -126
  180. package/lib/plugins/shopStore.js +4 -16
  181. package/lib/plugins/user.js +4 -16
  182. package/lib/plugins/window.js +171 -179
  183. package/lib/server/index.js +3050 -2665
  184. package/lib/server/modules/floor-plan/index.js +118 -134
  185. package/lib/server/modules/floor-plan/types.js +15 -30
  186. package/lib/server/modules/index.js +106 -68
  187. package/lib/server/modules/menu/index.js +142 -122
  188. package/lib/server/modules/menu/types.js +18 -31
  189. package/lib/server/modules/order/index.js +784 -1002
  190. package/lib/server/modules/order/types.js +122 -33
  191. package/lib/server/modules/order/utils/filterBookings.js +219 -194
  192. package/lib/server/modules/order/utils/filterOrders.js +118 -92
  193. package/lib/server/modules/payment/index.js +59 -83
  194. package/lib/server/modules/payment/types.js +4 -16
  195. package/lib/server/modules/products/index.js +583 -471
  196. package/lib/server/modules/products/types.js +44 -34
  197. package/lib/server/modules/quotation/index.js +137 -172
  198. package/lib/server/modules/quotation/types.js +21 -31
  199. package/lib/server/modules/resource/index.js +220 -186
  200. package/lib/server/modules/resource/types.js +42 -33
  201. package/lib/server/modules/schedule/index.js +135 -123
  202. package/lib/server/modules/schedule/types.js +14 -21
  203. package/lib/server/modules/schedule/utils.js +334 -163
  204. package/lib/server/types.js +4 -16
  205. package/lib/server/utils/index.js +25 -23
  206. package/lib/server/utils/product.js +196 -139
  207. package/lib/server/utils/schedule.js +34 -41
  208. package/lib/server/utils/small-ticket.js +479 -456
  209. package/lib/server/utils/time.js +40 -49
  210. package/lib/solution/BaseSales/index.js +1186 -1410
  211. package/lib/solution/BaseSales/types.js +42 -38
  212. package/lib/solution/BaseSales/utils/cartPromotion.js +642 -498
  213. package/lib/solution/BaseSales/utils/parseSalesResponse.js +85 -105
  214. package/lib/solution/BaseSales/utils/quotationPrice.js +56 -114
  215. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +108 -145
  216. package/lib/solution/BaseSales/utils.js +158 -143
  217. package/lib/solution/BookingByStep/index.js +1527 -1340
  218. package/lib/solution/BookingByStep/types.js +40 -99
  219. package/lib/solution/BookingByStep/utils/capacity.js +192 -160
  220. package/lib/solution/BookingByStep/utils/products.js +42 -52
  221. package/lib/solution/BookingByStep/utils/resources.js +527 -330
  222. package/lib/solution/BookingByStep/utils/stock.js +65 -44
  223. package/lib/solution/BookingByStep/utils/timeslots.js +129 -131
  224. package/lib/solution/BookingTicket/index.js +607 -522
  225. package/lib/solution/BookingTicket/types.js +99 -77
  226. package/lib/solution/BookingTicket/utils/addProductDecision.js +226 -189
  227. package/lib/solution/BookingTicket/utils/addTimeAvailability.js +58 -89
  228. package/lib/solution/BookingTicket/utils/bookingStatus.js +107 -78
  229. package/lib/solution/BookingTicket/utils/cartView.js +114 -99
  230. package/lib/solution/BookingTicket/utils/exampleData.js +185 -0
  231. package/lib/solution/BookingTicket/utils/orderCustomer.js +18 -41
  232. package/lib/solution/BookingTicket/utils/resolveBestAddTimePlan.js +219 -86
  233. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +168 -116
  234. package/lib/solution/BookingTicket/utils/scan/cloudSearch.js +79 -91
  235. package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.js +54 -41
  236. package/lib/solution/BookingTicket/utils/scan/handleScan.js +84 -81
  237. package/lib/solution/BookingTicket/utils/scan/index.js +98 -104
  238. package/lib/solution/BookingTicket/utils/scan/scanCache.js +90 -43
  239. package/lib/solution/BookingTicket/utils/scan/scanProductValues.js +52 -64
  240. package/lib/solution/BookingTicket/utils/sessionCatalogStale.js +56 -58
  241. package/lib/solution/BookingTicket/utils/weighingProductSku.js +34 -48
  242. package/lib/solution/BuyTickets/index.js +67 -70
  243. package/lib/solution/BuyTickets/types.js +22 -38
  244. package/lib/solution/Checkout/index.js +1451 -1158
  245. package/lib/solution/Checkout/types.js +91 -61
  246. package/lib/solution/Checkout/utils/index.js +228 -156
  247. package/lib/solution/PlaceOrder/index.js +55 -0
  248. package/lib/solution/RegisterAndLogin/config.js +493 -460
  249. package/lib/solution/RegisterAndLogin/index.js +633 -630
  250. package/lib/solution/RegisterAndLogin/types.js +189 -76
  251. package/lib/solution/RegisterAndLogin/utils.js +183 -125
  252. package/lib/solution/Sales/index.js +328 -324
  253. package/lib/solution/Sales/types.js +27 -33
  254. package/lib/solution/ScanOrder/index.js +832 -864
  255. package/lib/solution/ScanOrder/types.js +33 -34
  256. package/lib/solution/ScanOrder/utils.js +409 -374
  257. package/lib/solution/ShopDiscount/index.js +226 -232
  258. package/lib/solution/ShopDiscount/types.js +15 -37
  259. package/lib/solution/ShopDiscount/utils.js +300 -172
  260. package/lib/solution/UnifiedBookingSales/index.js +1035 -1201
  261. package/lib/solution/UnifiedBookingSales/remoteOccupancyCache.js +99 -159
  262. package/lib/solution/UnifiedBookingSales/types.js +10 -32
  263. package/lib/solution/VenueBooking/index.js +811 -879
  264. package/lib/solution/VenueBooking/types.js +19 -39
  265. package/lib/solution/VenueBooking/utils/dateSummary.js +27 -56
  266. package/lib/solution/VenueBooking/utils/resource.js +31 -54
  267. package/lib/solution/VenueBooking/utils/slotMerge.js +94 -107
  268. package/lib/solution/VenueBooking/utils/timeSlot.js +132 -132
  269. package/lib/solution/VenueBooking/utils.js +130 -67
  270. package/lib/solution/index.js +124 -41
  271. package/lib/store/createStore.js +32 -29
  272. package/lib/types/index.js +4 -16
  273. package/lib/utils/payment-number.js +26 -46
  274. package/lib/utils/task.js +36 -36
  275. package/lib/utils/watch.js +81 -47
  276. package/package.json +2 -1
@@ -1,170 +1,212 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
- var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __export = (target, all) => {
6
- for (var name in all)
7
- __defProp(target, name, { get: all[name], enumerable: true });
8
- };
9
- var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") {
11
- for (let key of __getOwnPropNames(from))
12
- if (!__hasOwnProp.call(to, key) && key !== except)
13
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
- }
15
- return to;
16
- };
17
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
1
+ "use strict";
18
2
 
19
- // src/modules/Order/utils/discountProductLineIdentity.ts
20
- var discountProductLineIdentity_exports = {};
21
- __export(discountProductLineIdentity_exports, {
22
- DISCOUNT_SPLIT_ORIGIN_UID_KEY: () => DISCOUNT_SPLIT_ORIGIN_UID_KEY,
23
- consolidateDiscountFreeProductLines: () => consolidateDiscountFreeProductLines,
24
- ensureUniqueProductLineUids: () => ensureUniqueProductLineUids
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
25
5
  });
26
- module.exports = __toCommonJS(discountProductLineIdentity_exports);
27
- var import_lodash_es = require("lodash-es");
28
- var import_utils = require("../../../solution/ScanOrder/utils");
29
- var import_orderCollectionIdentity = require("./orderCollectionIdentity");
30
- var DISCOUNT_SPLIT_ORIGIN_UID_KEY = "discountSplitOriginUid";
6
+ exports.DISCOUNT_SPLIT_ORIGIN_UID_KEY = void 0;
7
+ exports.consolidateDiscountFreeProductLines = consolidateDiscountFreeProductLines;
8
+ exports.ensureUniqueProductLineUids = ensureUniqueProductLineUids;
9
+ var _lodashEs = require("lodash-es");
10
+ var _utils = require("../../../solution/ScanOrder/utils");
11
+ var _orderCollectionIdentity = require("./orderCollectionIdentity");
12
+ /**
13
+ * 商品券拆行的身份与回并工具。
14
+ *
15
+ * 背景:
16
+ * Rules.calcDiscount 应用 good_pass 时,会把一个数量行拆成若干「用券行」和
17
+ * 「普通余量行」。Rules 返回的拆分行可能复制同一份
18
+ * metadata.unique_identification_number,进而造成:
19
+ * - 按 UID 删除时同时命中多行;
20
+ * - UI 把不同券行视为同一个商品;
21
+ * - 后续商品更新无法准确定位目标行。
22
+ *
23
+ * 处理原则:
24
+ * 1. 拆分后每一行必须拥有独立 UID;
25
+ * 2. 原始拆分来源仅记录在 tempOrder._extend.productsByUid 的运行态索引中,
26
+ * 不写入商品 metadata,不污染提交协议;
27
+ * 3. 券被移除后,只回并被本工具确认来自同一折扣拆分源的行;
28
+ * 4. 预约、赠品、促销、手动折扣、备注、称重、holder 和已落库行均为硬边界。
29
+ *
30
+ * 两个导出函数都会原地更新 tempOrder。调用顺序必须是:
31
+ * ensureUniqueProductLineUids -> consolidateDiscountFreeProductLines。
32
+ */
33
+
34
+ /** productsByUid 运行态记录中用于关联同一次折扣拆分的字段。 */
35
+ const DISCOUNT_SPLIT_ORIGIN_UID_KEY = exports.DISCOUNT_SPLIT_ORIGIN_UID_KEY = 'discountSplitOriginUid';
36
+
37
+ // 这里只保留本模块所需的最小读取逻辑,避免反向依赖体量较大的 Order/utils.ts
38
+ // 并形成 utils.ts -> 本文件 -> utils.ts 的循环引用。
31
39
  function getProductLineUid(product) {
32
- var _a;
33
- if (!product || typeof product !== "object")
34
- return null;
35
- const uid = ((_a = product.metadata) == null ? void 0 : _a.unique_identification_number) ?? product.unique_identification_number;
36
- if (uid === void 0 || uid === null || uid === "")
37
- return null;
40
+ if (!product || typeof product !== 'object') return null;
41
+ const uid = product.metadata?.unique_identification_number ?? product.unique_identification_number;
42
+ if (uid === undefined || uid === null || uid === '') return null;
38
43
  return String(uid);
39
44
  }
40
45
  function getProductSkuOptions(product) {
41
- var _a;
42
- return Array.isArray((_a = product.product_sku) == null ? void 0 : _a.option) ? product.product_sku.option : [];
46
+ return Array.isArray(product.product_sku?.option) ? product.product_sku.option : [];
43
47
  }
44
48
  function hasProductLineNote(product) {
45
- return typeof product.note === "string" && product.note.trim().length > 0;
49
+ return typeof product.note === 'string' && product.note.trim().length > 0;
46
50
  }
47
51
  function isManualProductDiscountLine(product) {
48
- var _a, _b;
49
- return ((_a = product.metadata) == null ? void 0 : _a.is_manual_discount) === true || ((_b = product.metadata) == null ? void 0 : _b.is_manual_discount) === 1 || (product.discount_list || []).some((item) => (item == null ? void 0 : item.type) === "product");
52
+ return product.metadata?.is_manual_discount === true || product.metadata?.is_manual_discount === 1 || (product.discount_list || []).some(item => item?.type === 'product');
50
53
  }
51
54
  function ensureProductsByUid(tempOrder) {
52
- if (!tempOrder._extend || typeof tempOrder._extend !== "object") {
53
- tempOrder._extend = { productsByUid: {} };
55
+ if (!tempOrder._extend || typeof tempOrder._extend !== 'object') {
56
+ tempOrder._extend = {
57
+ productsByUid: {}
58
+ };
54
59
  }
55
60
  if (!tempOrder._extend.productsByUid) {
56
61
  tempOrder._extend.productsByUid = {};
57
62
  }
58
63
  return tempOrder._extend.productsByUid;
59
64
  }
65
+
66
+ /**
67
+ * 修复 Rules 折扣拆行复制 UID 的问题,并为拆分行记录共同来源。
68
+ *
69
+ * 第一条商品保留原 UID,后续重复行生成新 UUID;对应的 productsByUid.runtime
70
+ * 会复制原行 runtime(包括 origin),以保证删除、编辑及展示字段回读仍可工作。
71
+ *
72
+ * 没有 UID 的裸商品不会被补写 UID。这是为了兼容 Rules/mock 的历史协议形状;
73
+ * 正常 Order 写路径会在 normalize 阶段提前创建 UID。
74
+ */
60
75
  function ensureUniqueProductLineUids(tempOrder) {
61
- const usedUids = /* @__PURE__ */ new Set();
76
+ // usedUids 只描述本次 Rules 返回的商品集合,不能直接依赖 productsByUid:
77
+ // productsByUid 可能还保留已删除行的历史 runtime,历史 UID 不应导致当前行被改号。
78
+ const usedUids = new Set();
62
79
  const productsByUid = ensureProductsByUid(tempOrder);
63
- tempOrder.products = (tempOrder.products || []).map((product) => {
80
+ tempOrder.products = (tempOrder.products || []).map(product => {
64
81
  const sourceUid = getProductLineUid(product);
65
- if (!sourceUid)
66
- return product;
82
+ // 单测 mock 或兼容旧 Rules 时可能返回没有 UID 的裸商品。
83
+ // 这里不主动补 UID,避免一个“校验重复”的工具意外改变旧协议对象形状。
84
+ if (!sourceUid) return product;
85
+
86
+ // 实际场景:可乐 ×5 首次进入 Rules 时只有一行。
87
+ // 使用三张券后 Rules 可能返回「可乐 ×2 + 三条可乐 ×1」,但四条都复制原 UID。
88
+ // 第一条继续使用原 UID,可保留购物车已有引用、runtime origin 和删除定位的稳定性。
67
89
  if (!usedUids.has(sourceUid)) {
68
90
  usedUids.add(sourceUid);
69
91
  return product;
70
92
  }
71
- let splitUid = (0, import_orderCollectionIdentity.createUuidV4)();
93
+
94
+ // 从第二条重复 UID 开始生成真正的行级身份。
95
+ // 这样点击任意一条“可乐 ×1”时,只会删除该行,不会把所有同 UID 行一起删除。
96
+ let splitUid = (0, _orderCollectionIdentity.createUuidV4)();
72
97
  while (usedUids.has(splitUid)) {
73
- splitUid = (0, import_orderCollectionIdentity.createUuidV4)();
98
+ splitUid = (0, _orderCollectionIdentity.createUuidV4)();
74
99
  }
75
100
  product.metadata = {
76
- ...product.metadata || {},
101
+ ...(product.metadata || {}),
77
102
  unique_identification_number: splitUid
78
103
  };
79
104
  const sourceRuntime = productsByUid[sourceUid] || {};
80
- const discountSplitOriginUid = String(
81
- sourceRuntime[DISCOUNT_SPLIT_ORIGIN_UID_KEY] || sourceUid
82
- );
105
+ // 如果当前行已经是上一轮拆分出来的子行,继续沿用最初的拆分来源。
106
+ // 例如删除一条券行后,空出的券再次把「可乐 ×2」拆成两条 ×1,
107
+ // 新行仍应归属于最初那条可乐,而不是形成一个无法回并的新分组。
108
+ const discountSplitOriginUid = String(sourceRuntime[DISCOUNT_SPLIT_ORIGIN_UID_KEY] || sourceUid);
109
+
110
+ // 来源只写入 _extend.productsByUid:
111
+ // - metadata.unique_identification_number 是对外的行身份,必须各不相同;
112
+ // - discountSplitOriginUid 是内部回并依据,不能进入提交给后端的商品 metadata。
83
113
  productsByUid[sourceUid] = {
84
114
  ...sourceRuntime,
85
115
  [DISCOUNT_SPLIT_ORIGIN_UID_KEY]: discountSplitOriginUid
86
116
  };
117
+ // 克隆 origin 等 runtime 数据,保证新拆分行仍能正确展示标题、封面等商品信息。
87
118
  productsByUid[splitUid] = {
88
- ...(0, import_lodash_es.cloneDeep)(sourceRuntime),
119
+ ...(0, _lodashEs.cloneDeep)(sourceRuntime),
89
120
  [DISCOUNT_SPLIT_ORIGIN_UID_KEY]: discountSplitOriginUid
90
121
  };
91
122
  usedUids.add(splitUid);
92
123
  return product;
93
124
  });
94
125
  }
126
+
127
+ /**
128
+ * 把券移除后已经恢复原价的同源折扣拆分行重新合并。
129
+ *
130
+ * 此函数刻意不执行通用的「同 SKU 合并」:没有 discountSplitOriginUid 的普通行
131
+ * 可能是业务 hook、导入订单或其它流程主动拆开的,不能在折扣重算时擅自合并。
132
+ *
133
+ * payment_price、tax_fee、surcharge_fee 属于 summary 计算层的派生值。券行与普通行
134
+ * 在回并前可能暂时不同,因此它们不参与 mergeKey;原始价格、SKU/option/bundle
135
+ * 结构以及税务/商品类型配置仍参与比较,防止不同商品语义被误合并。
136
+ */
95
137
  function consolidateDiscountFreeProductLines(tempOrder) {
96
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
138
+ // 实际目标场景:
139
+ // 选择客户后「可乐 ×5」被三张商品券拆成「×2、×1、×1、×1」;
140
+ // 清除客户/商品券后,四行都恢复为无折扣状态,应在本轮重算中立即回并为「可乐 ×5」。
97
141
  const consolidatedProducts = [];
98
- const productIndexByKey = /* @__PURE__ */ new Map();
142
+ const productIndexByKey = new Map();
99
143
  for (const product of tempOrder.products || []) {
100
144
  const productBundle = Array.isArray(product.product_bundle) ? product.product_bundle : [];
101
- const hasDiscount = (product.discount_list || []).length > 0 || productBundle.some((bundle) => ((bundle == null ? void 0 : bundle.discount_list) || []).length > 0);
102
- const bookingUid = product.booking_uid ?? ((_a = product.metadata) == null ? void 0 : _a.booking_uid);
103
- const bookingId = product.booking_id ?? ((_b = product.metadata) == null ? void 0 : _b.booking_id);
145
+ const hasDiscount = (product.discount_list || []).length > 0 || productBundle.some(bundle => (bundle?.discount_list || []).length > 0);
146
+ const bookingUid = product.booking_uid ?? product.metadata?.booking_uid;
147
+ const bookingId = product.booking_id ?? product.metadata?.booking_id;
104
148
  const orderDetailId = product.order_detail_id ?? product.orderDetailId;
105
- const holderId = product.holder_id ?? ((_c = product.metadata) == null ? void 0 : _c.holder_id);
106
- const hasMergeBoundary = hasDiscount || Boolean(((_d = product.metadata) == null ? void 0 : _d._giftInfo) || product._giftInfo) || Boolean((_e = product.metadata) == null ? void 0 : _e._promotion) || isManualProductDiscountLine(product) || hasProductLineNote(product) || Number(((_f = product.product_sku) == null ? void 0 : _f.open_sold_weight) || 0) === 1 || ((_g = product.metadata) == null ? void 0 : _g.is_edit_for_runtime) === true || bookingId !== void 0 && bookingId !== null && bookingId !== 0 && bookingId !== "0" || bookingUid !== void 0 && bookingUid !== null && String(bookingUid) !== "" || holderId !== void 0 && holderId !== null && String(holderId) !== "" || orderDetailId !== void 0 && orderDetailId !== null && orderDetailId !== "";
149
+ const holderId = product.holder_id ?? product.metadata?.holder_id;
150
+
151
+ // 以下情况即使“看起来是同一个 SKU”也必须保持独立:
152
+ // - 仍有商品券/折扣:每条券行分别承担券归属和 savedAmount;
153
+ // - 赠品/促销:独立行承载策略来源,合并会破坏促销撤销和展示;
154
+ // - 手动改价/备注:用户显式表达了不同价格或不同制作要求;
155
+ // - 称重商品:每次称重的净重和金额属于独立交易事实;
156
+ // - 预约/holder/历史订单行:分别关联预约、持有人或后端 order_detail。
157
+ const hasMergeBoundary = hasDiscount || Boolean(product.metadata?._giftInfo || product._giftInfo) || Boolean(product.metadata?._promotion) || isManualProductDiscountLine(product) || hasProductLineNote(product) || Number(product.product_sku?.open_sold_weight || 0) === 1 || product.metadata?.is_edit_for_runtime === true || bookingId !== undefined && bookingId !== null && bookingId !== 0 && bookingId !== '0' || bookingUid !== undefined && bookingUid !== null && String(bookingUid) !== '' || holderId !== undefined && holderId !== null && String(holderId) !== '' || orderDetailId !== undefined && orderDetailId !== null && orderDetailId !== '';
107
158
  if (hasMergeBoundary) {
108
159
  consolidatedProducts.push(product);
109
160
  continue;
110
161
  }
111
162
  const productUid = getProductLineUid(product);
112
- const discountSplitOriginUid = productUid ? (_j = (_i = (_h = tempOrder._extend) == null ? void 0 : _h.productsByUid) == null ? void 0 : _i[productUid]) == null ? void 0 : _j[DISCOUNT_SPLIT_ORIGIN_UID_KEY] : void 0;
163
+ const discountSplitOriginUid = productUid ? tempOrder._extend?.productsByUid?.[productUid]?.[DISCOUNT_SPLIT_ORIGIN_UID_KEY] : undefined;
164
+
165
+ // 没有同源标记的两条可乐,可能是 onBeforeMergeProductToOrder 返回 false 后
166
+ // 由业务主动保留的独立行,也可能来自导入订单;不能仅凭 SKU 相同就擅自合并。
113
167
  if (!discountSplitOriginUid) {
114
168
  consolidatedProducts.push(product);
115
169
  continue;
116
170
  }
117
- const fingerprint = (0, import_utils.buildProductLineFingerprint)(
118
- getProductSkuOptions(product),
119
- productBundle
120
- );
171
+
172
+ // 同属一次券拆分仍不代表一定可以合并。
173
+ // 例如两行后来选择了不同 option、套餐子商品或自定义价格,需要继续保持独立。
174
+ const fingerprint = (0, _utils.buildProductLineFingerprint)(getProductSkuOptions(product), productBundle);
121
175
  const priceSignature = JSON.stringify({
122
- selling_price: String(product.selling_price ?? ""),
123
- original_price: String(product.original_price ?? ""),
124
- custom_price: String(product.custom_price ?? ""),
176
+ selling_price: String(product.selling_price ?? ''),
177
+ original_price: String(product.original_price ?? ''),
178
+ custom_price: String(product.custom_price ?? ''),
125
179
  is_charge_tax: Number(product.is_charge_tax ?? 0),
126
180
  gift_card: Number(product.gift_card ?? 0),
127
181
  bundle_edit: Number(product.bundle_edit ?? 0),
128
- price_schema_version: ((_k = product.metadata) == null ? void 0 : _k.price_schema_version) ?? "",
129
- source_product_price: String(((_l = product.metadata) == null ? void 0 : _l.source_product_price) ?? ""),
130
- main_product_selling_price: String(
131
- ((_m = product.metadata) == null ? void 0 : _m.main_product_selling_price) ?? ""
132
- ),
133
- main_product_original_price: String(
134
- ((_n = product.metadata) == null ? void 0 : _n.main_product_original_price) ?? ""
135
- ),
136
- bundle: productBundle.map((bundle) => ({
137
- bundle_id: (bundle == null ? void 0 : bundle.bundle_id) ?? (bundle == null ? void 0 : bundle.id) ?? "",
138
- product_id: (bundle == null ? void 0 : bundle.bundle_product_id) ?? (bundle == null ? void 0 : bundle._bundle_product_id) ?? (bundle == null ? void 0 : bundle.product_id) ?? "",
139
- product_variant_id: (bundle == null ? void 0 : bundle.bundle_variant_id) ?? (bundle == null ? void 0 : bundle.variant_id) ?? (bundle == null ? void 0 : bundle.product_variant_id) ?? 0,
140
- price: String((bundle == null ? void 0 : bundle.price) ?? ""),
141
- original_price: String((bundle == null ? void 0 : bundle.original_price) ?? ""),
142
- bundle_selling_price: String((bundle == null ? void 0 : bundle.bundle_selling_price) ?? "")
182
+ price_schema_version: product.metadata?.price_schema_version ?? '',
183
+ source_product_price: String(product.metadata?.source_product_price ?? ''),
184
+ main_product_selling_price: String(product.metadata?.main_product_selling_price ?? ''),
185
+ main_product_original_price: String(product.metadata?.main_product_original_price ?? ''),
186
+ bundle: productBundle.map(bundle => ({
187
+ bundle_id: bundle?.bundle_id ?? bundle?.id ?? '',
188
+ product_id: bundle?.bundle_product_id ?? bundle?._bundle_product_id ?? bundle?.product_id ?? '',
189
+ product_variant_id: bundle?.bundle_variant_id ?? bundle?.variant_id ?? bundle?.product_variant_id ?? 0,
190
+ price: String(bundle?.price ?? ''),
191
+ original_price: String(bundle?.original_price ?? ''),
192
+ bundle_selling_price: String(bundle?.bundle_selling_price ?? '')
143
193
  }))
144
194
  });
145
- const mergeKey = [
146
- discountSplitOriginUid,
147
- product.product_id,
148
- product.product_variant_id ?? 0,
149
- fingerprint,
150
- priceSignature
151
- ].join("#");
195
+ const mergeKey = [discountSplitOriginUid, product.product_id, product.product_variant_id ?? 0, fingerprint, priceSignature].join('#');
152
196
  const matchedIndex = productIndexByKey.get(mergeKey);
153
- if (matchedIndex === void 0) {
197
+
198
+ // 当前拆分来源 + 商品结构组合第一次出现时,保留该行作为回并目标。
199
+ // 后续相同行只累加数量,从而稳定保留首行 UID,避免 UI key 再次变化。
200
+ if (matchedIndex === undefined) {
154
201
  productIndexByKey.set(mergeKey, consolidatedProducts.length);
155
202
  consolidatedProducts.push(product);
156
203
  continue;
157
204
  }
158
205
  const matchedProduct = consolidatedProducts[matchedIndex];
159
- matchedProduct.num = (0, import_utils.getSafeProductNum)(
160
- Number(matchedProduct.num || 0) + Number(product.num || 0)
161
- );
206
+ matchedProduct.num = (0, _utils.getSafeProductNum)(Number(matchedProduct.num || 0) + Number(product.num || 0));
207
+ // 示例:目标行 ×2,依次吸收三条 ×1,最终得到 ×5。
208
+ // 被吸收行的 productsByUid runtime 暂不删除:异步 UI/日志可能仍持有旧 UID,
209
+ // 保留历史索引比立即清理更安全;当前购物车身份始终以 tempOrder.products 为准。
162
210
  }
163
211
  tempOrder.products = consolidatedProducts;
164
- }
165
- // Annotate the CommonJS export names for ESM import in node:
166
- 0 && (module.exports = {
167
- DISCOUNT_SPLIT_ORIGIN_UID_KEY,
168
- consolidateDiscountFreeProductLines,
169
- ensureUniqueProductLineUids
170
- });
212
+ }
@@ -1,113 +1,98 @@
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);
1
+ "use strict";
28
2
 
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
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
44
5
  });
45
- module.exports = __toCommonJS(manualProductDiscount_exports);
46
- var import_decimal = __toESM(require("decimal.js"));
6
+ exports.buildManualProductDiscountItem = buildManualProductDiscountItem;
7
+ exports.ensureManualProductDiscountList = ensureManualProductDiscountList;
8
+ exports.findManualProductDiscountItem = findManualProductDiscountItem;
9
+ exports.hasManualProductDiscountFlag = hasManualProductDiscountFlag;
10
+ exports.mergeManualProductDiscountIntoList = mergeManualProductDiscountIntoList;
11
+ exports.resolveManualDiscountMessage = resolveManualDiscountMessage;
12
+ exports.resolveManualDiscountOriginTotal = resolveManualDiscountOriginTotal;
13
+ exports.resolveManualDiscountReasonFromSources = resolveManualDiscountReasonFromSources;
14
+ exports.resolveSafeProductNum = resolveSafeProductNum;
15
+ exports.shouldBuildManualProductDiscount = shouldBuildManualProductDiscount;
16
+ exports.stripManualProductDiscountItems = stripManualProductDiscountItems;
17
+ exports.syncManualProductDiscountProductNum = syncManualProductDiscountProductNum;
18
+ var _decimal = _interopRequireDefault(require("decimal.js"));
19
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20
+ /** 解析商品行数量(checkout 协议 product_num 语义 = 当前行 num) */
47
21
  function resolveSafeProductNum(num) {
48
22
  const parsed = Number(num);
49
- if (!Number.isFinite(parsed) || parsed <= 0)
50
- return 1;
23
+ if (!Number.isFinite(parsed) || parsed <= 0) return 1;
51
24
  return Math.floor(parsed);
52
25
  }
26
+
27
+ /**
28
+ * 将 discount_list 中 type=product 项的 product_num 同步为当前商品数量。
29
+ *
30
+ * @example
31
+ * syncManualProductDiscountProductNum(line.discount_list, line.num);
32
+ */
53
33
  function syncManualProductDiscountProductNum(discountList, productNum) {
54
34
  const quantity = resolveSafeProductNum(productNum);
55
- return (discountList || []).map((item) => {
56
- if ((item == null ? void 0 : item.type) !== "product")
57
- return item;
35
+ return (discountList || []).map(item => {
36
+ if (item?.type !== 'product') return item;
58
37
  return {
59
38
  ...item,
60
39
  discount: {
61
- ...item.discount || {},
40
+ ...(item.discount || {}),
62
41
  product_num: quantity
63
42
  }
64
43
  };
65
44
  });
66
45
  }
46
+
47
+ /** 从多源解析改价前行总价(与 cacheItem._extend.origin_total 语义一致) */
67
48
  function resolveManualDiscountOriginTotal(sources) {
68
- const candidates = [
69
- sources.originTotal,
70
- sources.extendOriginTotal,
71
- sources.originExtendOriginTotal,
72
- sources.sourceExtendOriginTotal
73
- ];
49
+ const candidates = [sources.originTotal, sources.extendOriginTotal, sources.originExtendOriginTotal, sources.sourceExtendOriginTotal];
74
50
  for (const candidate of candidates) {
75
- if (candidate === void 0 || candidate === null || candidate === "")
76
- continue;
51
+ if (candidate === undefined || candidate === null || candidate === '') continue;
77
52
  const parsed = Number(candidate);
78
- if (Number.isFinite(parsed))
79
- return parsed;
53
+ if (Number.isFinite(parsed)) return parsed;
80
54
  }
81
55
  const unit = Number(sources.catalogUnitPrice);
82
56
  const quantity = sources.quantity ?? 1;
83
57
  if (Number.isFinite(unit) && unit > 0) {
84
- return new import_decimal.default(unit).mul(quantity).toNumber();
58
+ return new _decimal.default(unit).mul(quantity).toNumber();
85
59
  }
86
60
  return NaN;
87
61
  }
62
+
63
+ /** 从 payload / extend / origin 解析手动折扣原因 */
88
64
  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() !== "") {
65
+ for (const candidate of [sources.discountReason, sources.extendDiscountReason, sources.originExtendDiscountReason]) {
66
+ if (candidate != null && String(candidate).trim() !== '') {
95
67
  return String(candidate);
96
68
  }
97
69
  }
98
- return "";
70
+ return '';
99
71
  }
72
+
73
+ /** 是否带手动改价标记(price_override / is_manual_discount) */
100
74
  function hasManualProductDiscountFlag(metadata) {
101
- if (!metadata)
102
- return false;
75
+ if (!metadata) return false;
103
76
  const override = metadata.price_override;
104
- if (override !== void 0 && override !== null && override !== "") {
77
+ if (override !== undefined && override !== null && override !== '') {
105
78
  return true;
106
79
  }
107
80
  return metadata.is_manual_discount === 1 || metadata.is_manual_discount === true;
108
81
  }
82
+
83
+ /**
84
+ * normalize 兜底:手动改价但 discount_list 缺 type=product 时,按行级原价/折后价补写。
85
+ *
86
+ * @example
87
+ * ensureManualProductDiscountList({
88
+ * discountList: [],
89
+ * metadata: { price_override: '5', is_manual_discount: 1 },
90
+ * originalPrice: '11.00',
91
+ * sellingPrice: '5.00',
92
+ * quantity: 1,
93
+ * });
94
+ */
109
95
  function ensureManualProductDiscountList(params) {
110
- var _a, _b, _c, _d, _e, _f, _g, _h;
111
96
  const list = params.discountList || [];
112
97
  const quantity = resolveSafeProductNum(params.quantity);
113
98
  if (findManualProductDiscountItem(list)) {
@@ -128,79 +113,95 @@ function ensureManualProductDiscountList(params) {
128
113
  if (!Number.isFinite(originalNum) || !Number.isFinite(sellingNum) || originalNum === sellingNum) {
129
114
  return list;
130
115
  }
131
- const message = resolveManualDiscountMessage(
132
- list,
133
- resolveManualDiscountReasonFromSources({
134
- extendDiscountReason: (_b = (_a = metadata.origin) == null ? void 0 : _a._extend) == null ? void 0 : _b.discount_reason,
135
- originExtendDiscountReason: (_d = (_c = metadata.origin) == null ? void 0 : _c._extend) == null ? void 0 : _d.discount_reason
136
- })
137
- );
138
- return mergeManualProductDiscountIntoList(
139
- list,
140
- buildManualProductDiscountItem({
141
- originTotal: originalNum,
142
- sellingTotal: sellingNum,
143
- quantity,
144
- message,
145
- discountway: (_f = (_e = metadata.origin) == null ? void 0 : _e._extend) == null ? void 0 : _f.discountway,
146
- discount_per: (_h = (_g = metadata.origin) == null ? void 0 : _g._extend) == null ? void 0 : _h.discount_per
147
- })
148
- );
116
+ const message = resolveManualDiscountMessage(list, resolveManualDiscountReasonFromSources({
117
+ extendDiscountReason: metadata.origin?._extend?.discount_reason,
118
+ originExtendDiscountReason: metadata.origin?._extend?.discount_reason
119
+ }));
120
+ return mergeManualProductDiscountIntoList(list, buildManualProductDiscountItem({
121
+ originTotal: originalNum,
122
+ sellingTotal: sellingNum,
123
+ quantity,
124
+ message,
125
+ discountway: metadata.origin?._extend?.discountway,
126
+ discount_per: metadata.origin?._extend?.discount_per
127
+ }));
149
128
  }
129
+
130
+ /** 商品手动折扣 discount_list 项(checkout 协议,type = product) */
131
+
132
+ /**
133
+ * 从 discount_list 中取手动改价项(type = product)。
134
+ *
135
+ * @example
136
+ * const manual = findManualProductDiscountItem(product.discount_list);
137
+ * manual?.discount.message; // 折扣原因
138
+ */
150
139
  function findManualProductDiscountItem(discountList) {
151
- return (discountList || []).find((item) => (item == null ? void 0 : item.type) === "product");
140
+ return (discountList || []).find(item => item?.type === 'product');
152
141
  }
142
+
143
+ /**
144
+ * 解析折扣原因:优先 discount_list[type=product].discount.message。
145
+ *
146
+ * @example
147
+ * resolveManualDiscountMessage(line.discount_list, line.metadata?.legacy_reason);
148
+ */
153
149
  function resolveManualDiscountMessage(discountList, fallback) {
154
- var _a, _b;
155
- const message = (_b = (_a = findManualProductDiscountItem(discountList)) == null ? void 0 : _a.discount) == null ? void 0 : _b.message;
156
- if (message != null && String(message).trim() !== "") {
150
+ const message = findManualProductDiscountItem(discountList)?.discount?.message;
151
+ if (message != null && String(message).trim() !== '') {
157
152
  return String(message);
158
153
  }
159
- return fallback ?? "";
154
+ return fallback ?? '';
160
155
  }
156
+
157
+ /** 去掉 discount_list 中已有的手动改价项,避免重复叠加 */
161
158
  function stripManualProductDiscountItems(discountList) {
162
- return (discountList || []).filter((item) => (item == null ? void 0 : item.type) !== "product");
159
+ return (discountList || []).filter(item => item?.type !== 'product');
163
160
  }
161
+
162
+ /**
163
+ * 由改价前后行总价构建手动折扣项;amount = |originTotal - sellingTotal|(行级差额)。
164
+ *
165
+ * @example
166
+ * buildManualProductDiscountItem({
167
+ * originTotal: 11,
168
+ * sellingTotal: 4,
169
+ * quantity: 1,
170
+ * message: 'VIP',
171
+ * });
172
+ */
164
173
  function buildManualProductDiscountItem(params) {
165
- const origin = new import_decimal.default(Number(params.originTotal) || 0);
166
- const selling = new import_decimal.default(Number(params.sellingTotal) || 0);
174
+ const origin = new _decimal.default(Number(params.originTotal) || 0);
175
+ const selling = new _decimal.default(Number(params.sellingTotal) || 0);
167
176
  const diff = origin.minus(selling);
168
177
  const quantity = resolveSafeProductNum(params.quantity);
169
178
  return {
170
179
  amount: diff.toDecimalPlaces(2).toNumber(),
171
- type: "product",
180
+ type: 'product',
172
181
  discount: {
173
- message: params.message ?? "",
174
- discountway: params.discountway ?? "num",
182
+ message: params.message ?? '',
183
+ discountway: params.discountway ?? 'num',
175
184
  product_num: quantity,
176
- discount_per: params.discount_per ?? "",
177
- discount_type: diff.isNegative() ? "change_price" : "discount"
185
+ discount_per: params.discount_per ?? '',
186
+ discount_type: diff.isNegative() ? 'change_price' : 'discount'
178
187
  }
179
188
  };
180
189
  }
190
+
191
+ /**
192
+ * 将手动改价项合并进 discount_list(替换已有 type=product 项)。
193
+ *
194
+ * @example
195
+ * mergeManualProductDiscountIntoList(coupons, manualItem);
196
+ */
181
197
  function mergeManualProductDiscountIntoList(discountList, manualItem) {
182
198
  const base = stripManualProductDiscountItems(discountList);
183
- if (!manualItem)
184
- return base;
185
- if (manualItem.amount === 0 && !manualItem.discount.message)
186
- return base;
199
+ if (!manualItem) return base;
200
+ if (manualItem.amount === 0 && !manualItem.discount.message) return base;
187
201
  return [...base, manualItem];
188
202
  }
203
+
204
+ /** 是否应写入手动改价 discount_list 项 */
189
205
  function shouldBuildManualProductDiscount(params) {
190
206
  return Boolean(params.hasPriceOverride);
191
- }
192
- // Annotate the CommonJS export names for ESM import in node:
193
- 0 && (module.exports = {
194
- buildManualProductDiscountItem,
195
- ensureManualProductDiscountList,
196
- findManualProductDiscountItem,
197
- hasManualProductDiscountFlag,
198
- mergeManualProductDiscountIntoList,
199
- resolveManualDiscountMessage,
200
- resolveManualDiscountOriginTotal,
201
- resolveManualDiscountReasonFromSources,
202
- resolveSafeProductNum,
203
- shouldBuildManualProductDiscount,
204
- stripManualProductDiscountItems,
205
- syncManualProductDiscountProductNum
206
- });
207
+ }