@pisell/pisellos 2.3.73 → 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 (296) hide show
  1. package/dist/core/index.d.ts +7 -0
  2. package/dist/core/index.js +111 -71
  3. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  4. package/dist/model/strategy/adapter/walletPass/example.js +3 -26
  5. package/dist/model/strategy/strategy-example.js +5 -19
  6. package/dist/modules/Cart/index.js +0 -3
  7. package/dist/modules/Cart/utils/cartProduct.js +0 -1
  8. package/dist/modules/Date/index.js +1 -5
  9. package/dist/modules/Discount/index.js +2 -4
  10. package/dist/modules/OpenData/index.js +0 -2
  11. package/dist/modules/Order/index.d.ts +1 -1
  12. package/dist/modules/Order/index.js +36 -64
  13. package/dist/modules/Payment/index.js +97 -162
  14. package/dist/modules/Quotation/index.d.ts +6 -0
  15. package/dist/modules/Quotation/index.js +75 -19
  16. package/dist/modules/Rules/index.js +1 -4
  17. package/dist/modules/Schedule/index.js +0 -1
  18. package/dist/modules/Schedule/utils.js +0 -1
  19. package/dist/modules/Step/index.js +0 -1
  20. package/dist/plugins/request.d.ts +1 -0
  21. package/dist/plugins/request.js +1 -4
  22. package/dist/plugins/window.js +2 -6
  23. package/dist/server/index.d.ts +8 -2
  24. package/dist/server/index.js +303 -269
  25. package/dist/server/modules/floor-plan/index.d.ts +4 -0
  26. package/dist/server/modules/floor-plan/index.js +240 -98
  27. package/dist/server/modules/menu/index.js +75 -59
  28. package/dist/server/modules/order/index.d.ts +17 -7
  29. package/dist/server/modules/order/index.js +421 -211
  30. package/dist/server/modules/products/index.d.ts +8 -2
  31. package/dist/server/modules/products/index.js +191 -117
  32. package/dist/server/modules/quotation/index.js +29 -38
  33. package/dist/server/modules/resource/index.js +24 -17
  34. package/dist/server/modules/schedule/index.js +27 -35
  35. package/dist/server/utils/product.js +0 -1
  36. package/dist/solution/BaseSales/index.js +38 -41
  37. package/dist/solution/BookingByStep/index.d.ts +1 -1
  38. package/dist/solution/BookingByStep/index.js +7 -59
  39. package/dist/solution/BookingByStep/utils/capacity.js +1 -11
  40. package/dist/solution/BookingByStep/utils/resources.js +1 -3
  41. package/dist/solution/BookingByStep/utils/timeslots.js +2 -43
  42. package/dist/solution/BookingTicket/index.js +0 -2
  43. package/dist/solution/BookingTicket/utils/scan/cloudSearch.js +6 -7
  44. package/dist/solution/BookingTicket/utils/scan/handleScan.js +25 -31
  45. package/dist/solution/BookingTicket/utils/scan/index.js +6 -10
  46. package/dist/solution/BuyTickets/index.js +9 -12
  47. package/dist/solution/Checkout/index.js +177 -252
  48. package/dist/solution/Checkout/utils/index.js +4 -16
  49. package/dist/solution/RegisterAndLogin/index.js +30 -76
  50. package/dist/solution/ScanOrder/index.js +50 -60
  51. package/dist/solution/ShopDiscount/index.js +2 -7
  52. package/dist/solution/VenueBooking/index.js +45 -55
  53. package/dist/utils/task.js +15 -18
  54. package/dist/utils/watch.js +0 -1
  55. package/lib/apis/picoding.js +2 -0
  56. package/lib/core/index.d.ts +7 -0
  57. package/lib/core/index.js +149 -131
  58. package/lib/effects/index.js +46 -57
  59. package/lib/index.js +82 -49
  60. package/lib/model/index.js +14 -21
  61. package/lib/model/strategy/adapter/dataVariant/adapter.js +38 -50
  62. package/lib/model/strategy/adapter/dataVariant/evaluator.js +162 -236
  63. package/lib/model/strategy/adapter/dataVariant/examples.js +229 -237
  64. package/lib/model/strategy/adapter/dataVariant/index.js +39 -34
  65. package/lib/model/strategy/adapter/dataVariant/type.js +57 -28
  66. package/lib/model/strategy/adapter/index.js +100 -64
  67. package/lib/model/strategy/adapter/itemRule/adapter.js +156 -144
  68. package/lib/model/strategy/adapter/itemRule/evaluator.js +36 -48
  69. package/lib/model/strategy/adapter/itemRule/examples.js +295 -225
  70. package/lib/model/strategy/adapter/itemRule/index.js +83 -57
  71. package/lib/model/strategy/adapter/itemRule/type.js +97 -36
  72. package/lib/model/strategy/adapter/promotion/adapter.js +91 -69
  73. package/lib/model/strategy/adapter/promotion/evaluator.js +444 -310
  74. package/lib/model/strategy/adapter/promotion/examples.js +222 -234
  75. package/lib/model/strategy/adapter/promotion/index.js +1 -0
  76. package/lib/model/strategy/adapter/promotion/type.js +243 -36
  77. package/lib/model/strategy/adapter/type.js +4 -16
  78. package/lib/model/strategy/adapter/walletPass/evaluator.js +180 -150
  79. package/lib/model/strategy/adapter/walletPass/example.js +217 -190
  80. package/lib/model/strategy/adapter/walletPass/index.js +75 -51
  81. package/lib/model/strategy/adapter/walletPass/locales.js +36 -58
  82. package/lib/model/strategy/adapter/walletPass/type.js +4 -16
  83. package/lib/model/strategy/adapter/walletPass/utils.js +588 -378
  84. package/lib/model/strategy/engine.js +270 -168
  85. package/lib/model/strategy/index.js +49 -34
  86. package/lib/model/strategy/strategy-example.js +243 -239
  87. package/lib/model/strategy/type.js +100 -40
  88. package/lib/modules/Account/index.js +39 -53
  89. package/lib/modules/Account/types.js +20 -33
  90. package/lib/modules/AccountList/index.js +116 -154
  91. package/lib/modules/AccountList/types.js +30 -31
  92. package/lib/modules/AccountList/utils.js +18 -30
  93. package/lib/modules/BaseModule.js +23 -42
  94. package/lib/modules/BookingContext/index.js +158 -136
  95. package/lib/modules/BookingContext/types.js +46 -32
  96. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +138 -146
  97. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +78 -83
  98. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +170 -150
  99. package/lib/modules/BookingContext/utils/flexible.js +38 -55
  100. package/lib/modules/BookingContext/utils/formatResourceList.js +19 -34
  101. package/lib/modules/BookingContext/utils/index.js +124 -41
  102. package/lib/modules/BookingContext/utils/noResource.js +58 -70
  103. package/lib/modules/BookingContext/utils/orderLineDisplay.js +14 -41
  104. package/lib/modules/BookingContext/utils/productExtend.js +202 -155
  105. package/lib/modules/BookingContext/utils/resourceErrors.js +53 -53
  106. package/lib/modules/BookingContext/utils/resourceSelection.js +19 -41
  107. package/lib/modules/BookingContext/utils/resources.js +209 -167
  108. package/lib/modules/BookingContext/utils/serviceTimes.js +115 -116
  109. package/lib/modules/BookingContext/utils/timeSlices.js +76 -86
  110. package/lib/modules/Cart/index.js +170 -124
  111. package/lib/modules/Cart/types.js +46 -51
  112. package/lib/modules/Cart/utils/cartAccount.js +40 -39
  113. package/lib/modules/Cart/utils/cartDate.js +56 -61
  114. package/lib/modules/Cart/utils/cartDiscount.js +28 -33
  115. package/lib/modules/Cart/utils/cartNote.js +27 -32
  116. package/lib/modules/Cart/utils/cartProduct.js +321 -251
  117. package/lib/modules/Cart/utils/cartRelationForms.js +29 -35
  118. package/lib/modules/Cart/utils/cartResource.js +70 -78
  119. package/lib/modules/Cart/utils/changePrice.js +22 -50
  120. package/lib/modules/Cart/utils/index.js +106 -48
  121. package/lib/modules/Customer/constants.js +13 -34
  122. package/lib/modules/Customer/index.js +235 -172
  123. package/lib/modules/Customer/types.js +38 -35
  124. package/lib/modules/Date/index.js +116 -115
  125. package/lib/modules/Date/types.js +16 -28
  126. package/lib/modules/Date/utils.js +174 -123
  127. package/lib/modules/Discount/index.js +122 -127
  128. package/lib/modules/Discount/types.js +9 -31
  129. package/lib/modules/Guests/index.js +30 -56
  130. package/lib/modules/Guests/types.js +23 -33
  131. package/lib/modules/Holder/index.js +209 -189
  132. package/lib/modules/Holder/types.js +4 -16
  133. package/lib/modules/Holder/utils.js +20 -49
  134. package/lib/modules/OpenData/index.js +70 -76
  135. package/lib/modules/OpenData/types.js +4 -16
  136. package/lib/modules/OpenData/utils.js +44 -78
  137. package/lib/modules/Order/index.d.ts +1 -1
  138. package/lib/modules/Order/index.js +1713 -2118
  139. package/lib/modules/Order/payment-utils.js +77 -120
  140. package/lib/modules/Order/types.js +88 -35
  141. package/lib/modules/Order/utils/bundleDiscountHydration.js +41 -74
  142. package/lib/modules/Order/utils/discountProductLineIdentity.js +142 -100
  143. package/lib/modules/Order/utils/manualProductDiscount.js +124 -123
  144. package/lib/modules/Order/utils/orderCollectionIdentity.js +184 -244
  145. package/lib/modules/Order/utils.js +814 -647
  146. package/lib/modules/Payment/cash.js +20 -33
  147. package/lib/modules/Payment/cashRecommendationAlgorithm.js +145 -76
  148. package/lib/modules/Payment/eftpos.js +16 -30
  149. package/lib/modules/Payment/index.js +532 -399
  150. package/lib/modules/Payment/mx51.js +1 -0
  151. package/lib/modules/Payment/types.js +230 -108
  152. package/lib/modules/Payment/utils.js +52 -51
  153. package/lib/modules/Payment/walletpass.js +485 -660
  154. package/lib/modules/Product/index.js +51 -46
  155. package/lib/modules/Product/types.js +4 -16
  156. package/lib/modules/Product/utils.js +32 -33
  157. package/lib/modules/ProductList/index.js +113 -123
  158. package/lib/modules/ProductList/types.js +9 -31
  159. package/lib/modules/Quotation/index.d.ts +6 -0
  160. package/lib/modules/Quotation/index.js +110 -103
  161. package/lib/modules/Quotation/types.js +4 -16
  162. package/lib/modules/Resource/index.js +27 -59
  163. package/lib/modules/Resource/types.js +22 -32
  164. package/lib/modules/Resource/utils.js +30 -38
  165. package/lib/modules/ResourcePlanner/index.js +25 -23
  166. package/lib/modules/ResourcePlanner/localClock.js +54 -119
  167. package/lib/modules/ResourcePlanner/planner.js +589 -770
  168. package/lib/modules/ResourcePlanner/types.js +10 -29
  169. package/lib/modules/Rules/index.js +1218 -959
  170. package/lib/modules/Rules/types.js +17 -40
  171. package/lib/modules/SalesSummary/index.js +85 -90
  172. package/lib/modules/SalesSummary/types.js +4 -16
  173. package/lib/modules/SalesSummary/utils.js +355 -430
  174. package/lib/modules/ScanOrderLogger/index.js +59 -79
  175. package/lib/modules/ScanOrderLogger/providers/feishu.js +54 -78
  176. package/lib/modules/ScanOrderLogger/providers/grafana.js +13 -36
  177. package/lib/modules/ScanOrderLogger/types.js +4 -16
  178. package/lib/modules/Schedule/getDateIsInSchedule.js +334 -163
  179. package/lib/modules/Schedule/index.js +100 -114
  180. package/lib/modules/Schedule/type.js +4 -16
  181. package/lib/modules/Schedule/types.js +4 -16
  182. package/lib/modules/Schedule/utils.js +433 -291
  183. package/lib/modules/Step/index.js +40 -52
  184. package/lib/modules/Step/tyeps.js +4 -16
  185. package/lib/modules/Summary/index.js +66 -71
  186. package/lib/modules/Summary/types.js +4 -16
  187. package/lib/modules/Summary/utils.js +773 -418
  188. package/lib/modules/SurchargeList/index.js +46 -60
  189. package/lib/modules/SurchargeList/types.js +4 -16
  190. package/lib/modules/index.js +245 -63
  191. package/lib/plugins/app.js +4 -16
  192. package/lib/plugins/index.js +36 -25
  193. package/lib/plugins/request.d.ts +1 -0
  194. package/lib/plugins/request.js +137 -126
  195. package/lib/plugins/shopStore.js +4 -16
  196. package/lib/plugins/user.js +4 -16
  197. package/lib/plugins/window.js +171 -179
  198. package/lib/server/index.d.ts +8 -2
  199. package/lib/server/index.js +3083 -2663
  200. package/lib/server/modules/floor-plan/index.d.ts +4 -0
  201. package/lib/server/modules/floor-plan/index.js +159 -127
  202. package/lib/server/modules/floor-plan/types.js +15 -30
  203. package/lib/server/modules/index.js +106 -68
  204. package/lib/server/modules/menu/index.js +170 -124
  205. package/lib/server/modules/menu/types.js +18 -31
  206. package/lib/server/modules/order/index.d.ts +17 -7
  207. package/lib/server/modules/order/index.js +916 -977
  208. package/lib/server/modules/order/types.js +122 -33
  209. package/lib/server/modules/order/utils/filterBookings.js +219 -194
  210. package/lib/server/modules/order/utils/filterOrders.js +118 -92
  211. package/lib/server/modules/payment/index.js +59 -83
  212. package/lib/server/modules/payment/types.js +4 -16
  213. package/lib/server/modules/products/index.d.ts +8 -2
  214. package/lib/server/modules/products/index.js +656 -471
  215. package/lib/server/modules/products/types.js +44 -34
  216. package/lib/server/modules/quotation/index.js +137 -172
  217. package/lib/server/modules/quotation/types.js +21 -31
  218. package/lib/server/modules/resource/index.js +225 -186
  219. package/lib/server/modules/resource/types.js +42 -33
  220. package/lib/server/modules/schedule/index.js +135 -123
  221. package/lib/server/modules/schedule/types.js +14 -21
  222. package/lib/server/modules/schedule/utils.js +334 -163
  223. package/lib/server/types.js +4 -16
  224. package/lib/server/utils/index.js +25 -23
  225. package/lib/server/utils/product.js +196 -139
  226. package/lib/server/utils/schedule.js +34 -41
  227. package/lib/server/utils/small-ticket.js +479 -456
  228. package/lib/server/utils/time.js +40 -49
  229. package/lib/solution/BaseSales/index.js +1186 -1410
  230. package/lib/solution/BaseSales/types.js +42 -38
  231. package/lib/solution/BaseSales/utils/cartPromotion.js +642 -498
  232. package/lib/solution/BaseSales/utils/parseSalesResponse.js +85 -105
  233. package/lib/solution/BaseSales/utils/quotationPrice.js +56 -114
  234. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +108 -145
  235. package/lib/solution/BaseSales/utils.js +158 -143
  236. package/lib/solution/BookingByStep/index.d.ts +1 -1
  237. package/lib/solution/BookingByStep/index.js +1527 -1340
  238. package/lib/solution/BookingByStep/types.js +40 -99
  239. package/lib/solution/BookingByStep/utils/capacity.js +192 -160
  240. package/lib/solution/BookingByStep/utils/products.js +42 -52
  241. package/lib/solution/BookingByStep/utils/resources.js +527 -330
  242. package/lib/solution/BookingByStep/utils/stock.js +65 -44
  243. package/lib/solution/BookingByStep/utils/timeslots.js +129 -131
  244. package/lib/solution/BookingTicket/index.js +607 -522
  245. package/lib/solution/BookingTicket/types.js +99 -77
  246. package/lib/solution/BookingTicket/utils/addProductDecision.js +226 -189
  247. package/lib/solution/BookingTicket/utils/addTimeAvailability.js +58 -89
  248. package/lib/solution/BookingTicket/utils/bookingStatus.js +107 -78
  249. package/lib/solution/BookingTicket/utils/cartView.js +114 -99
  250. package/lib/solution/BookingTicket/utils/exampleData.js +185 -0
  251. package/lib/solution/BookingTicket/utils/orderCustomer.js +18 -41
  252. package/lib/solution/BookingTicket/utils/resolveBestAddTimePlan.js +219 -86
  253. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +168 -116
  254. package/lib/solution/BookingTicket/utils/scan/cloudSearch.js +79 -91
  255. package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.js +54 -41
  256. package/lib/solution/BookingTicket/utils/scan/handleScan.js +84 -81
  257. package/lib/solution/BookingTicket/utils/scan/index.js +98 -104
  258. package/lib/solution/BookingTicket/utils/scan/scanCache.js +90 -43
  259. package/lib/solution/BookingTicket/utils/scan/scanProductValues.js +52 -64
  260. package/lib/solution/BookingTicket/utils/sessionCatalogStale.js +56 -58
  261. package/lib/solution/BookingTicket/utils/weighingProductSku.js +34 -48
  262. package/lib/solution/BuyTickets/index.js +67 -70
  263. package/lib/solution/BuyTickets/types.js +22 -38
  264. package/lib/solution/Checkout/index.js +1451 -1158
  265. package/lib/solution/Checkout/types.js +91 -61
  266. package/lib/solution/Checkout/utils/index.js +228 -156
  267. package/lib/solution/PlaceOrder/index.js +55 -0
  268. package/lib/solution/RegisterAndLogin/config.js +493 -460
  269. package/lib/solution/RegisterAndLogin/index.js +633 -630
  270. package/lib/solution/RegisterAndLogin/types.js +189 -76
  271. package/lib/solution/RegisterAndLogin/utils.js +183 -125
  272. package/lib/solution/Sales/index.js +328 -324
  273. package/lib/solution/Sales/types.js +27 -33
  274. package/lib/solution/ScanOrder/index.js +832 -864
  275. package/lib/solution/ScanOrder/types.js +33 -34
  276. package/lib/solution/ScanOrder/utils.js +409 -374
  277. package/lib/solution/ShopDiscount/index.js +226 -232
  278. package/lib/solution/ShopDiscount/types.js +15 -37
  279. package/lib/solution/ShopDiscount/utils.js +300 -172
  280. package/lib/solution/UnifiedBookingSales/index.js +1035 -1201
  281. package/lib/solution/UnifiedBookingSales/remoteOccupancyCache.js +99 -159
  282. package/lib/solution/UnifiedBookingSales/types.js +10 -32
  283. package/lib/solution/VenueBooking/index.js +811 -879
  284. package/lib/solution/VenueBooking/types.js +19 -39
  285. package/lib/solution/VenueBooking/utils/dateSummary.js +27 -56
  286. package/lib/solution/VenueBooking/utils/resource.js +31 -54
  287. package/lib/solution/VenueBooking/utils/slotMerge.js +94 -107
  288. package/lib/solution/VenueBooking/utils/timeSlot.js +132 -132
  289. package/lib/solution/VenueBooking/utils.js +130 -67
  290. package/lib/solution/index.js +124 -41
  291. package/lib/store/createStore.js +32 -29
  292. package/lib/types/index.js +4 -16
  293. package/lib/utils/payment-number.js +26 -46
  294. package/lib/utils/task.js +36 -36
  295. package/lib/utils/watch.js +81 -47
  296. package/package.json +2 -1
@@ -1,125 +1,179 @@
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.ts
30
- var utils_exports = {};
31
- __export(utils_exports, {
32
- buildManualProductDiscountItem: () => import_manualProductDiscount.buildManualProductDiscountItem,
33
- buildSubmitPayload: () => buildSubmitPayload,
34
- calculateOrderProductsDeposit: () => calculateOrderProductsDeposit,
35
- clearTempOrderHolderAssignments: () => clearTempOrderHolderAssignments,
36
- composeLinePrice: () => composeLinePrice,
37
- createDefaultOrderRulesHooks: () => createDefaultOrderRulesHooks,
38
- createDefaultTempOrder: () => createDefaultTempOrder,
39
- createEmptySummary: () => import_utils3.createEmptySummary,
40
- createUuidV4: () => import_orderCollectionIdentity.createUuidV4,
41
- ensureCartItemOriginHolder: () => ensureCartItemOriginHolder,
42
- ensureManualProductDiscountList: () => import_manualProductDiscount.ensureManualProductDiscountList,
43
- ensureProductSku: () => ensureProductSku,
44
- findManualProductDiscountItem: () => import_manualProductDiscount.findManualProductDiscountItem,
45
- formatDateTime: () => formatDateTime,
46
- formatV1Product: () => formatV1Product,
47
- generateDuration: () => generateDuration,
48
- getAllDiscountList: () => getAllDiscountList,
49
- getBundleSellingMagnitude: () => getBundleSellingMagnitude,
50
- getBundleSignedUnit: () => getBundleSignedUnit,
51
- getOrderProductLineUid: () => getOrderProductLineUid,
52
- getProductSkuOptions: () => getProductSkuOptions,
53
- getRuntimeProductOrigin: () => getRuntimeProductOrigin,
54
- hasAssignedHolderId: () => hasAssignedHolderId,
55
- indexOrderProductsByUid: () => indexOrderProductsByUid,
56
- isEmptyOrderProductDisplayValue: () => isEmptyOrderProductDisplayValue,
57
- isHolderConfigRequired: () => isHolderConfigRequired,
58
- isMarkdownBundle: () => isMarkdownBundle,
59
- isTempOrder: () => isTempOrder,
60
- mapPaymentItemToOrderPayment: () => mapPaymentItemToOrderPayment,
61
- mapPaymentItemsToOrderPayments: () => mapPaymentItemsToOrderPayments,
62
- mergeManualProductDiscountIntoList: () => import_manualProductDiscount.mergeManualProductDiscountIntoList,
63
- mergeOrderProductDisplayFields: () => mergeOrderProductDisplayFields,
64
- mergeRelationForms: () => mergeRelationForms,
65
- normalizeBookingIsAll: () => normalizeBookingIsAll,
66
- normalizeBookingSubType: () => normalizeBookingSubType,
67
- normalizeOrderProductDiscountList: () => normalizeOrderProductDiscountList,
68
- normalizeProductSkuOptions: () => normalizeProductSkuOptions,
69
- normalizeSubmitBooking: () => normalizeSubmitBooking,
70
- normalizeSubmitCollectPaxValue: () => normalizeSubmitCollectPaxValue,
71
- productRequiresFormSubject: () => productRequiresFormSubject,
72
- resolveEffectivePerUnitDiscount: () => resolveEffectivePerUnitDiscount,
73
- resolveIsFormSubject: () => resolveIsFormSubject,
74
- resolveManualDiscountMessage: () => import_manualProductDiscount.resolveManualDiscountMessage,
75
- resolveManualDiscountOriginTotal: () => import_manualProductDiscount.resolveManualDiscountOriginTotal,
76
- resolveManualDiscountReasonFromSources: () => import_manualProductDiscount.resolveManualDiscountReasonFromSources,
77
- resolveManualOverrideLineOriginalPrice: () => resolveManualOverrideLineOriginalPrice,
78
- resolveRulesManualDiscountFlag: () => resolveRulesManualDiscountFlag,
79
- resolveSafeProductNum: () => import_manualProductDiscount.resolveSafeProductNum,
80
- resolveSubmitCollectPax: () => resolveSubmitCollectPax,
81
- shouldBuildManualProductDiscount: () => import_manualProductDiscount.shouldBuildManualProductDiscount,
82
- stripManualProductDiscountItems: () => import_manualProductDiscount.stripManualProductDiscountItems,
83
- sumOptionUnitPrice: () => sumOptionUnitPrice,
84
- syncManualProductDiscountProductNum: () => import_manualProductDiscount.syncManualProductDiscountProductNum
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "buildManualProductDiscountItem", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _manualProductDiscount.buildManualProductDiscountItem;
10
+ }
11
+ });
12
+ exports.buildSubmitPayload = buildSubmitPayload;
13
+ exports.calculateOrderProductsDeposit = calculateOrderProductsDeposit;
14
+ exports.clearTempOrderHolderAssignments = clearTempOrderHolderAssignments;
15
+ exports.composeLinePrice = composeLinePrice;
16
+ exports.createDefaultOrderRulesHooks = createDefaultOrderRulesHooks;
17
+ exports.createDefaultTempOrder = createDefaultTempOrder;
18
+ Object.defineProperty(exports, "createEmptySummary", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _utils2.createEmptySummary;
22
+ }
23
+ });
24
+ Object.defineProperty(exports, "createUuidV4", {
25
+ enumerable: true,
26
+ get: function () {
27
+ return _orderCollectionIdentity.createUuidV4;
28
+ }
29
+ });
30
+ exports.ensureCartItemOriginHolder = ensureCartItemOriginHolder;
31
+ Object.defineProperty(exports, "ensureManualProductDiscountList", {
32
+ enumerable: true,
33
+ get: function () {
34
+ return _manualProductDiscount.ensureManualProductDiscountList;
35
+ }
36
+ });
37
+ exports.ensureProductSku = ensureProductSku;
38
+ Object.defineProperty(exports, "findManualProductDiscountItem", {
39
+ enumerable: true,
40
+ get: function () {
41
+ return _manualProductDiscount.findManualProductDiscountItem;
42
+ }
43
+ });
44
+ exports.formatDateTime = formatDateTime;
45
+ exports.formatV1Product = formatV1Product;
46
+ exports.getAllDiscountList = exports.generateDuration = void 0;
47
+ exports.getBundleSellingMagnitude = getBundleSellingMagnitude;
48
+ exports.getBundleSignedUnit = getBundleSignedUnit;
49
+ exports.getOrderProductLineUid = getOrderProductLineUid;
50
+ exports.getProductSkuOptions = getProductSkuOptions;
51
+ exports.getRuntimeProductOrigin = getRuntimeProductOrigin;
52
+ exports.hasAssignedHolderId = hasAssignedHolderId;
53
+ exports.indexOrderProductsByUid = indexOrderProductsByUid;
54
+ exports.isEmptyOrderProductDisplayValue = isEmptyOrderProductDisplayValue;
55
+ exports.isHolderConfigRequired = isHolderConfigRequired;
56
+ exports.isMarkdownBundle = isMarkdownBundle;
57
+ exports.isTempOrder = isTempOrder;
58
+ exports.mapPaymentItemToOrderPayment = mapPaymentItemToOrderPayment;
59
+ exports.mapPaymentItemsToOrderPayments = mapPaymentItemsToOrderPayments;
60
+ Object.defineProperty(exports, "mergeManualProductDiscountIntoList", {
61
+ enumerable: true,
62
+ get: function () {
63
+ return _manualProductDiscount.mergeManualProductDiscountIntoList;
64
+ }
65
+ });
66
+ exports.mergeOrderProductDisplayFields = mergeOrderProductDisplayFields;
67
+ exports.mergeRelationForms = void 0;
68
+ exports.normalizeBookingIsAll = normalizeBookingIsAll;
69
+ exports.normalizeBookingSubType = normalizeBookingSubType;
70
+ exports.normalizeOrderProductDiscountList = normalizeOrderProductDiscountList;
71
+ exports.normalizeProductSkuOptions = normalizeProductSkuOptions;
72
+ exports.normalizeSubmitBooking = normalizeSubmitBooking;
73
+ exports.normalizeSubmitCollectPaxValue = normalizeSubmitCollectPaxValue;
74
+ exports.productRequiresFormSubject = productRequiresFormSubject;
75
+ exports.resolveEffectivePerUnitDiscount = resolveEffectivePerUnitDiscount;
76
+ exports.resolveIsFormSubject = resolveIsFormSubject;
77
+ Object.defineProperty(exports, "resolveManualDiscountMessage", {
78
+ enumerable: true,
79
+ get: function () {
80
+ return _manualProductDiscount.resolveManualDiscountMessage;
81
+ }
82
+ });
83
+ Object.defineProperty(exports, "resolveManualDiscountOriginTotal", {
84
+ enumerable: true,
85
+ get: function () {
86
+ return _manualProductDiscount.resolveManualDiscountOriginTotal;
87
+ }
88
+ });
89
+ Object.defineProperty(exports, "resolveManualDiscountReasonFromSources", {
90
+ enumerable: true,
91
+ get: function () {
92
+ return _manualProductDiscount.resolveManualDiscountReasonFromSources;
93
+ }
94
+ });
95
+ exports.resolveManualOverrideLineOriginalPrice = resolveManualOverrideLineOriginalPrice;
96
+ exports.resolveRulesManualDiscountFlag = resolveRulesManualDiscountFlag;
97
+ Object.defineProperty(exports, "resolveSafeProductNum", {
98
+ enumerable: true,
99
+ get: function () {
100
+ return _manualProductDiscount.resolveSafeProductNum;
101
+ }
102
+ });
103
+ exports.resolveSubmitCollectPax = resolveSubmitCollectPax;
104
+ Object.defineProperty(exports, "shouldBuildManualProductDiscount", {
105
+ enumerable: true,
106
+ get: function () {
107
+ return _manualProductDiscount.shouldBuildManualProductDiscount;
108
+ }
85
109
  });
86
- module.exports = __toCommonJS(utils_exports);
87
- var import_dayjs = __toESM(require("dayjs"));
88
- var import_decimal = __toESM(require("decimal.js"));
89
- var import_utils = require("../Holder/utils");
90
- var import_utils2 = require("../../solution/ScanOrder/utils");
91
- var import_orderCollectionIdentity = require("./utils/orderCollectionIdentity");
92
- var import_utils3 = require("../../solution/ScanOrder/utils");
93
- var import_manualProductDiscount = require("./utils/manualProductDiscount");
110
+ Object.defineProperty(exports, "stripManualProductDiscountItems", {
111
+ enumerable: true,
112
+ get: function () {
113
+ return _manualProductDiscount.stripManualProductDiscountItems;
114
+ }
115
+ });
116
+ exports.sumOptionUnitPrice = sumOptionUnitPrice;
117
+ Object.defineProperty(exports, "syncManualProductDiscountProductNum", {
118
+ enumerable: true,
119
+ get: function () {
120
+ return _manualProductDiscount.syncManualProductDiscountProductNum;
121
+ }
122
+ });
123
+ var _dayjs = _interopRequireDefault(require("dayjs"));
124
+ var _decimal = _interopRequireDefault(require("decimal.js"));
125
+ var _utils = require("../Holder/utils");
126
+ var _utils2 = require("../../solution/ScanOrder/utils");
127
+ var _orderCollectionIdentity = require("./utils/orderCollectionIdentity");
128
+ var _manualProductDiscount = require("./utils/manualProductDiscount");
129
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
130
+ /**
131
+ * 把"含 option 的主商品单价"与 bundle 合成"单行 composite 单价"。
132
+ *
133
+ * 新语义 v2 约定:
134
+ * - `mainPrice` 必须是**已经包含 option 的主商品单价**(即 `metadata.main_product_selling_price`
135
+ * 或 `metadata.main_product_original_price`),option 价格不由本函数叠加。
136
+ * - 套餐价:Σ((bundle.bundle_selling_price ?? bundle.price) × (bundle.num ?? bundle.quantity ?? 1))
137
+ * 当 `useOriginalBundle=true` 时,改用 `bundle.original_price ?? bundle.product_price ?? bundle.price`。
138
+ * - 返回值:保留 2 位小数的字符串,方便直接写回 `selling_price` / `original_price` 字段。
139
+ *
140
+ * 被 `normalizeOrderProduct`、Rules setProduct 钩子、各 Solution 的 setDiscountSelected 共用,
141
+ * 保证合成逻辑单点来源。
142
+ */
94
143
  function composeLinePrice(params) {
95
- const { mainPrice, bundle, useOriginalBundle } = params;
96
- let total = new import_decimal.default(Number(mainPrice) || 0);
144
+ const {
145
+ mainPrice,
146
+ bundle,
147
+ useOriginalBundle
148
+ } = params;
149
+ let total = new _decimal.default(Number(mainPrice) || 0);
97
150
  if (Array.isArray(bundle)) {
98
151
  for (const item of bundle) {
99
- const signedUnit = getBundleSignedUnit(item, { useOriginal: useOriginalBundle });
100
- const rawNum = (item == null ? void 0 : item.num) ?? (item == null ? void 0 : item.quantity) ?? 1;
101
- const num = new import_decimal.default(Number(rawNum) || 0);
152
+ // markdown(减价)按带符号净额取减;markup/原价维持相加。
153
+ const signedUnit = getBundleSignedUnit(item, {
154
+ useOriginal: useOriginalBundle
155
+ });
156
+ const rawNum = item?.num ?? item?.quantity ?? 1;
157
+ const num = new _decimal.default(Number(rawNum) || 0);
102
158
  total = total.plus(signedUnit.times(num));
103
159
  }
104
160
  }
105
161
  return total.toDecimalPlaces(2).toFixed(2);
106
162
  }
107
163
  function normalizeProductSkuOptions(options) {
108
- if (!Array.isArray(options))
109
- return [];
110
- return options.map((option) => {
164
+ if (!Array.isArray(options)) return [];
165
+ return options.map(option => {
111
166
  const normalized = {
112
- ...option && typeof option === "object" ? option : {}
167
+ ...(option && typeof option === 'object' ? option : {})
113
168
  };
114
169
  const addPrice = normalized.add_price ?? normalized.price;
115
- if (addPrice !== void 0)
116
- normalized.add_price = addPrice;
170
+ if (addPrice !== undefined) normalized.add_price = addPrice;
117
171
  delete normalized.price;
118
172
  return normalized;
119
173
  });
120
174
  }
121
175
  function ensureProductSku(product) {
122
- const rawSku = (product == null ? void 0 : product.product_sku) && typeof product.product_sku === "object" ? product.product_sku : {};
176
+ const rawSku = product?.product_sku && typeof product.product_sku === 'object' ? product.product_sku : {};
123
177
  return {
124
178
  ...rawSku,
125
179
  option: normalizeProductSkuOptions(rawSku.option)
@@ -128,21 +182,25 @@ function ensureProductSku(product) {
128
182
  function getProductSkuOptions(product) {
129
183
  return ensureProductSku(product).option;
130
184
  }
185
+
186
+ /**
187
+ * 计算 option 单价合计:Σ(option.add_price × option.num)。
188
+ * 兼容入参仍带旧 `price` 的调用方,但运行时归一化后只维护 `add_price`。
189
+ * 在新语义 v2 下,main_product_original_price = source_product_price + 本函数结果。
190
+ */
131
191
  function sumOptionUnitPrice(options) {
132
- let total = new import_decimal.default(0);
133
- if (!Array.isArray(options))
134
- return total;
192
+ let total = new _decimal.default(0);
193
+ if (!Array.isArray(options)) return total;
135
194
  for (const opt of options) {
136
- const price = new import_decimal.default(Number((opt == null ? void 0 : opt.add_price) ?? (opt == null ? void 0 : opt.price)) || 0);
137
- const num = new import_decimal.default(Number(opt == null ? void 0 : opt.num) || 0);
195
+ const price = new _decimal.default(Number(opt?.add_price ?? opt?.price) || 0);
196
+ const num = new _decimal.default(Number(opt?.num) || 0);
138
197
  total = total.plus(price.times(num));
139
198
  }
140
199
  return total;
141
200
  }
142
201
  function getSafeOrderProductNum(num) {
143
202
  const parsedNum = Number(num ?? 1);
144
- if (!Number.isFinite(parsedNum) || parsedNum < 1)
145
- return 1;
203
+ if (!Number.isFinite(parsedNum) || parsedNum < 1) return 1;
146
204
  return Math.floor(parsedNum);
147
205
  }
148
206
  function getOrderProductDepositUnitTotal(product) {
@@ -150,48 +208,57 @@ function getOrderProductDepositUnitTotal(product) {
150
208
  const paymentPrice = metadata.main_product_attached_bundle_payment_price;
151
209
  const mainSellingPrice = metadata.main_product_selling_price;
152
210
  const fallbackPrice = product.selling_price;
153
- return new import_decimal.default(Number(paymentPrice ?? mainSellingPrice ?? fallbackPrice) || 0);
211
+ return new _decimal.default(Number(paymentPrice ?? mainSellingPrice ?? fallbackPrice) || 0);
154
212
  }
155
213
  function normalizeDepositProtocols(protocols) {
156
- if (!Array.isArray(protocols))
157
- return [];
214
+ if (!Array.isArray(protocols)) return [];
158
215
  return protocols.reduce((result, protocol) => {
159
- const id = Number(protocol == null ? void 0 : protocol.id);
160
- if (!Number.isFinite(id))
161
- return result;
216
+ const id = Number(protocol?.id);
217
+ if (!Number.isFinite(id)) return result;
162
218
  result.push({
163
219
  id: Math.floor(id),
164
- title: String((protocol == null ? void 0 : protocol.title) || "")
220
+ title: String(protocol?.title || '')
165
221
  });
166
222
  return result;
167
223
  }, []);
168
224
  }
169
225
  function getDepositPolicyIds(depositData) {
170
- const ids = [
171
- ...Array.isArray(depositData == null ? void 0 : depositData.self_deposit_policy_ids) ? depositData.self_deposit_policy_ids : [],
172
- ...Array.isArray(depositData == null ? void 0 : depositData.deposit_policy_ids) ? depositData.deposit_policy_ids : []
173
- ];
226
+ const ids = [...(Array.isArray(depositData?.self_deposit_policy_ids) ? depositData.self_deposit_policy_ids : []), ...(Array.isArray(depositData?.deposit_policy_ids) ? depositData.deposit_policy_ids : [])];
174
227
  return ids.reduce((result, id) => {
175
228
  const normalizedId = Number(id);
176
- if (!Number.isFinite(normalizedId))
177
- return result;
229
+ if (!Number.isFinite(normalizedId)) return result;
178
230
  result.push(Math.floor(normalizedId));
179
231
  return result;
180
232
  }, []);
181
233
  }
182
234
  function handleOrderProductDeposit(params) {
183
- const { depositData, total, num } = params;
184
- if (!depositData)
185
- return { result: false, depositTotal: new import_decimal.default(0) };
186
- const { deposit_fixed, deposit_percentage } = depositData;
187
- if (typeof deposit_fixed !== "string" || typeof deposit_percentage !== "string") {
188
- return { result: false, depositTotal: new import_decimal.default(0) };
235
+ const {
236
+ depositData,
237
+ total,
238
+ num
239
+ } = params;
240
+ if (!depositData) return {
241
+ result: false,
242
+ depositTotal: new _decimal.default(0)
243
+ };
244
+ const {
245
+ deposit_fixed,
246
+ deposit_percentage
247
+ } = depositData;
248
+ if (typeof deposit_fixed !== 'string' || typeof deposit_percentage !== 'string') {
249
+ return {
250
+ result: false,
251
+ depositTotal: new _decimal.default(0)
252
+ };
189
253
  }
190
- const depositFixed = new import_decimal.default(deposit_fixed || 0);
191
- const depositPercent = new import_decimal.default(deposit_percentage || 0);
192
- const productTotalPrice = new import_decimal.default(total || 0);
254
+ const depositFixed = new _decimal.default(deposit_fixed || 0);
255
+ const depositPercent = new _decimal.default(deposit_percentage || 0);
256
+ const productTotalPrice = new _decimal.default(total || 0);
193
257
  const deposit = depositFixed.plus(depositPercent.times(productTotalPrice));
194
- return { depositTotal: deposit.times(num), result: true };
258
+ return {
259
+ depositTotal: deposit.times(num),
260
+ result: true
261
+ };
195
262
  }
196
263
  function resolveOrderProductDepositSource(product, runtimeOrigin) {
197
264
  const record = product;
@@ -208,15 +275,14 @@ function resolveOrderProductDepositSource(product, runtimeOrigin) {
208
275
  function getOrderProductDeposit(product, runtimeOrigin) {
209
276
  const depositProduct = resolveOrderProductDepositSource(product, runtimeOrigin);
210
277
  const depositData = depositProduct.custom_deposit_data;
211
- if ((depositData == null ? void 0 : depositData.has_deposit) != 1)
212
- return null;
278
+ if (depositData?.has_deposit != 1) return null;
213
279
  const num = getSafeOrderProductNum(product.num);
214
280
  const total = getOrderProductDepositUnitTotal(product).times(num);
215
281
  const allProtocols = normalizeDepositProtocols(depositData.deposit_policy_data);
216
282
  const protocolIds = [];
217
- let depositTotal = new import_decimal.default(0);
283
+ let depositTotal = new _decimal.default(0);
218
284
  let hasDeposit = false;
219
- if (typeof depositData.deposit_fixed === "string" && typeof depositData.deposit_percentage === "string") {
285
+ if (typeof depositData.deposit_fixed === 'string' && typeof depositData.deposit_percentage === 'string') {
220
286
  const result = handleOrderProductDeposit({
221
287
  depositData,
222
288
  total,
@@ -232,10 +298,8 @@ function getOrderProductDeposit(product, runtimeOrigin) {
232
298
  } else {
233
299
  const productVariantId = depositProduct.product_variant_id ?? product.product_variant_id;
234
300
  if (productVariantId) {
235
- const variantProduct = (depositProduct.variant || []).find(
236
- (item) => (item == null ? void 0 : item.id) === productVariantId
237
- );
238
- const variantDepositData = variantProduct == null ? void 0 : variantProduct.custom_deposit_data;
301
+ const variantProduct = (depositProduct.variant || []).find(item => item?.id === productVariantId);
302
+ const variantDepositData = variantProduct?.custom_deposit_data;
239
303
  const result = handleOrderProductDeposit({
240
304
  depositData: variantDepositData,
241
305
  total,
@@ -244,221 +308,285 @@ function getOrderProductDeposit(product, runtimeOrigin) {
244
308
  if (result.result) {
245
309
  depositTotal = result.depositTotal;
246
310
  protocolIds.push(...getDepositPolicyIds({
247
- self_deposit_policy_ids: variantDepositData == null ? void 0 : variantDepositData.self_deposit_policy_ids
311
+ self_deposit_policy_ids: variantDepositData?.self_deposit_policy_ids
248
312
  }));
249
313
  hasDeposit = true;
250
314
  }
251
315
  }
252
316
  if (Array.isArray(product.product_bundle) && product.product_bundle.length) {
253
317
  depositTotal = product.product_bundle.reduce((accumulator, bundleProduct) => {
254
- const bundleDepositData = bundleProduct == null ? void 0 : bundleProduct.custom_deposit_data;
318
+ const bundleDepositData = bundleProduct?.custom_deposit_data;
255
319
  const result = handleOrderProductDeposit({
256
320
  depositData: bundleDepositData,
257
- total: bundleProduct == null ? void 0 : bundleProduct.price,
258
- num: getSafeOrderProductNum((bundleProduct == null ? void 0 : bundleProduct.num) || 1)
321
+ total: bundleProduct?.price,
322
+ num: getSafeOrderProductNum(bundleProduct?.num || 1)
259
323
  });
260
- if (!result.result)
261
- return accumulator;
324
+ if (!result.result) return accumulator;
262
325
  protocolIds.push(...getDepositPolicyIds({
263
- self_deposit_policy_ids: bundleDepositData == null ? void 0 : bundleDepositData.self_deposit_policy_ids
326
+ self_deposit_policy_ids: bundleDepositData?.self_deposit_policy_ids
264
327
  }));
265
328
  hasDeposit = true;
266
329
  return accumulator.plus(result.depositTotal);
267
- }, new import_decimal.default(0));
330
+ }, new _decimal.default(0));
268
331
  }
269
332
  }
270
- if (!hasDeposit)
271
- return null;
333
+ if (!hasDeposit) return null;
272
334
  const protocolIdSet = new Set(protocolIds);
273
- const protocols = allProtocols.filter((protocol) => protocolIdSet.has(protocol.id));
335
+ const protocols = allProtocols.filter(protocol => protocolIdSet.has(protocol.id));
274
336
  return {
275
337
  total: depositTotal.toNumber(),
276
338
  protocols
277
339
  };
278
340
  }
341
+
342
+ /**
343
+ * 仅基于 tempOrder.products 重算整单定金。
344
+ *
345
+ * 商品折扣在进入定金计算前已体现在商品行价格字段中,
346
+ * 因此这里只按商品定金规则汇总,不再扣减 discount_list;tempOrder.bookings 不参与这里的计算。
347
+ */
279
348
  function calculateOrderProductsDeposit(products = [], options) {
280
- var _a, _b, _c;
281
- const protocolMap = /* @__PURE__ */ new Map();
282
- let total = new import_decimal.default(0);
349
+ const protocolMap = new Map();
350
+ let total = new _decimal.default(0);
283
351
  let hasDeposit = false;
284
352
  for (const product of products || []) {
285
- const productUid = (_a = product.metadata) == null ? void 0 : _a.unique_identification_number;
286
- const runtimeOrigin = productUid ? (_c = (_b = options == null ? void 0 : options.productsByUid) == null ? void 0 : _b[productUid]) == null ? void 0 : _c.origin : void 0;
353
+ const productUid = product.metadata?.unique_identification_number;
354
+ const runtimeOrigin = productUid ? options?.productsByUid?.[productUid]?.origin : undefined;
287
355
  const deposit = getOrderProductDeposit(product, runtimeOrigin);
288
356
  product.deposit = deposit;
289
- if (!(deposit == null ? void 0 : deposit.total) || Number(deposit.total) <= 0)
290
- continue;
357
+ if (!deposit?.total || Number(deposit.total) <= 0) continue;
291
358
  total = total.plus(deposit.total);
292
359
  for (const protocol of deposit.protocols || []) {
293
- if (!protocolMap.has(protocol.id))
294
- protocolMap.set(protocol.id, protocol);
360
+ if (!protocolMap.has(protocol.id)) protocolMap.set(protocol.id, protocol);
295
361
  }
296
362
  hasDeposit = true;
297
363
  }
298
- const roundedTotal = total.toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP);
364
+ const roundedTotal = total.toDecimalPlaces(2, _decimal.default.ROUND_HALF_UP);
299
365
  const protocols = [...protocolMap.values()];
300
366
  return {
301
367
  total: roundedTotal.toNumber(),
302
368
  totalText: roundedTotal.toFixed(2),
303
369
  protocols,
304
- deposit_policy_ids: protocols.map((protocol) => protocol.id),
370
+ deposit_policy_ids: protocols.map(protocol => protocol.id),
305
371
  hasDeposit
306
372
  };
307
373
  }
374
+
375
+ /**
376
+ * 判定套餐子商品是否为 markdown(减价)类型。
377
+ * 与后端口径一致:price_type='markdown' 且 price_type_ext 非 'product_price'(原价子商品)。
378
+ */
308
379
  function isMarkdownBundle(bundle) {
309
- if (!bundle || typeof bundle !== "object")
310
- return false;
380
+ if (!bundle || typeof bundle !== 'object') return false;
311
381
  const ext = bundle.price_type_ext ?? bundle.custom_price_type_ext;
312
382
  const type = bundle.price_type ?? bundle.custom_price_type;
313
- return type === "markdown" && ext !== "product_price";
383
+ return type === 'markdown' && ext !== 'product_price';
314
384
  }
385
+
386
+ /**
387
+ * 套餐子商品对「行价」的带符号单位贡献(与后端 markdown 口径对齐)。
388
+ *
389
+ * - markdown(减价):净额 = |catalog 毛价| − Σ(option.add_price×num),**取负**(行内减)。
390
+ * catalog 毛价优先 `price`/`custom_price`(避免读已落净额的 `bundle_selling_price` 造成 option 二次扣减);
391
+ * 仅当毛价缺失(历史/hydrate 仅剩净额)时退回 `bundle_selling_price`,且此时不再扣 option。
392
+ * - markup(加价)/原价子商品:维持 `+(bundle_selling_price ?? price)`,行为不变。
393
+ */
315
394
  function getBundleSignedUnit(bundle, options) {
316
- if (!bundle || typeof bundle !== "object")
317
- return new import_decimal.default(0);
318
- const useOriginal = (options == null ? void 0 : options.useOriginal) ?? false;
395
+ if (!bundle || typeof bundle !== 'object') return new _decimal.default(0);
396
+ const useOriginal = options?.useOriginal ?? false;
319
397
  if (isMarkdownBundle(bundle)) {
320
398
  const catalog = useOriginal ? bundle.original_price ?? bundle.product_price ?? bundle.custom_price ?? bundle.base_price ?? bundle.price : bundle.custom_price ?? bundle.product_price ?? bundle.original_price ?? bundle.base_price ?? bundle.price;
321
- if (catalog !== void 0 && catalog !== null && catalog !== "") {
322
- const raw = new import_decimal.default(Number(catalog) || 0);
323
- if (raw.lt(0))
324
- return raw;
399
+ if (catalog !== undefined && catalog !== null && catalog !== '') {
400
+ const raw = new _decimal.default(Number(catalog) || 0);
401
+ // 负值表示价格已是「带符号净额」(如 cart/changePrice 产出的 -3.7),直接取用不再扣 option,
402
+ // 避免与下游 option 二次扣减;正值为毛价(H5 路径,如 5),净额 = price − Σoptions 后取负。
403
+ if (raw.lt(0)) return raw;
325
404
  return raw.minus(sumOptionUnitPrice(bundle.option)).negated();
326
405
  }
327
- return new import_decimal.default(Number(bundle.bundle_selling_price) || 0).abs().negated();
406
+ // 仅剩净额(无毛价)兜底:直接取负,不再扣 option
407
+ return new _decimal.default(Number(bundle.bundle_selling_price) || 0).abs().negated();
328
408
  }
329
409
  const rawPrice = useOriginal ? bundle.original_price ?? bundle.product_price ?? bundle.price : bundle.bundle_selling_price ?? bundle.price;
330
- return new import_decimal.default(Number(rawPrice) || 0);
410
+ return new _decimal.default(Number(rawPrice) || 0);
331
411
  }
412
+
413
+ /**
414
+ * 套餐子商品 `bundle_selling_price` 的存储净额(正值幅度)。
415
+ * markdown 取净额绝对值(3.70);markup/原价维持原值。
416
+ */
332
417
  function getBundleSellingMagnitude(bundle) {
333
418
  return getBundleSignedUnit(bundle).abs();
334
419
  }
420
+
421
+ /**
422
+ * OrderModule 默认 Rules 钩子工厂。
423
+ *
424
+ * 价格语义约定(订单域,v2 composite 口径):
425
+ * - `selling_price`:券后 **行 composite 单价**
426
+ * = `metadata.main_product_selling_price` + Σ(bundle_selling_price × num)。
427
+ * - `original_price`:券前 **行 composite 单价**
428
+ * = `metadata.main_product_original_price` + Σ(bundle 原价 × num)。
429
+ * - `metadata.source_product_price`:主商品/variant 基础价(已应用报价单),不含 option、
430
+ * 不含折扣。**权威源**。
431
+ * - `metadata.main_product_original_price` = source + Σ(option.price × option.num)(含 option、不含折扣)。
432
+ * - `metadata.main_product_selling_price` = main_original − 主商品券 per-unit amount(含 option、含折扣)。
433
+ * - `payment_price`:出站 payload 中为行 composite 已减整单折扣均摊价(无折扣时与 `selling_price` 同义)。
434
+ *
435
+ * Rules 钩子契约(hook_adapt 方案,Rules 内部保持不变):
436
+ * - `getProduct.price` / `getProduct.original_price` 回传 **source-level 主价**
437
+ * (`metadata.source_product_price`)。Rules 内部 `getProductTotalPrice` /
438
+ * `getProductOriginTotalPrice` 会自行叠加 option + bundle,喂 source 可避免 option 双加。
439
+ * - `getProduct.total` = `selling_price × num`(行 composite × num),与 Rules 内部产出的
440
+ * total(source + option + bundle)对齐。
441
+ * - `setProduct` 反向流程:把 Rules 返回的 source-level `main_product_selling_price` / `price`
442
+ * 加回 Σoptions,重新合成含 option 的 main_product_* 并派生 composite。
443
+ * 优先级:
444
+ * 1. `values.main_product_selling_price`(券应用分支,per-unit 券后 source-level 主价)
445
+ * 2. `values.price`(还原分支 `restoredPrice`、good_pass 归零)
446
+ * 3. `values.total / num`(仅当 Rules 只给出总价时的兜底)
447
+ *
448
+ * 导出为纯函数方便单测直接驱动钩子,不依赖 OrderModule 实例。
449
+ */
450
+
451
+ /** Rules calcDiscount 用手动价标记;undefined 表示交给 Rules 用 total/origin_total 推断 */
335
452
  function resolveRulesManualDiscountFlag(metadata) {
336
- if (!metadata)
337
- return void 0;
453
+ if (!metadata) return undefined;
338
454
  if (metadata.is_manual_discount === true || metadata.is_manual_discount === 1) {
339
455
  return true;
340
456
  }
341
457
  const priceOverride = metadata.price_override;
342
- if (priceOverride !== void 0 && priceOverride !== null && priceOverride !== "") {
458
+ if (priceOverride !== undefined && priceOverride !== null && priceOverride !== '') {
343
459
  return true;
344
460
  }
345
- return void 0;
461
+ return undefined;
346
462
  }
347
463
  function normalizeOrderProductDiscountAmount(amount) {
348
- if (amount === void 0 || amount === null)
349
- return void 0;
464
+ if (amount === undefined || amount === null) return undefined;
350
465
  return String(amount);
351
466
  }
467
+
468
+ /**
469
+ * 商品行折扣只保留后端 OrderProductDiscountItem 协议字段。
470
+ * Rules/券计算过程中的 `_num`、`config` 等运行态字段不应进入 tempOrder 或提交 payload。
471
+ */
352
472
  function normalizeOrderProductDiscountList(discountList) {
353
- if (!Array.isArray(discountList))
354
- return [];
355
- return discountList.filter((item) => !!item && typeof item === "object").map((item) => {
473
+ if (!Array.isArray(discountList)) return [];
474
+ return discountList.filter(item => !!item && typeof item === 'object').map(item => {
356
475
  const normalized = {
357
476
  discount_id: Number.isFinite(Number(item.discount_id)) ? Number(item.discount_id) : 0
358
477
  };
359
478
  if (item.order_discount_id === null) {
360
479
  normalized.order_discount_id = null;
361
- } else if (item.order_discount_id !== void 0) {
480
+ } else if (item.order_discount_id !== undefined) {
362
481
  const orderDiscountId = Number(item.order_discount_id);
363
482
  if (Number.isFinite(orderDiscountId)) {
364
483
  normalized.order_discount_id = orderDiscountId;
365
484
  }
366
485
  }
367
- if (item.type !== void 0)
368
- normalized.type = item.type;
486
+ if (item.type !== undefined) normalized.type = item.type;
369
487
  const amount = normalizeOrderProductDiscountAmount(item.amount);
370
- if (amount !== void 0)
371
- normalized.amount = amount;
372
- if (item.discount && typeof item.discount === "object") {
373
- normalized.discount = { ...item.discount };
488
+ if (amount !== undefined) normalized.amount = amount;
489
+ if (item.discount && typeof item.discount === 'object') {
490
+ normalized.discount = {
491
+ ...item.discount
492
+ };
374
493
  }
375
494
  if (item.metadata === null) {
376
495
  normalized.metadata = null;
377
- } else if (item.metadata && typeof item.metadata === "object") {
378
- normalized.metadata = { ...item.metadata };
496
+ } else if (item.metadata && typeof item.metadata === 'object') {
497
+ normalized.metadata = {
498
+ ...item.metadata
499
+ };
379
500
  }
380
501
  return normalized;
381
502
  });
382
503
  }
383
504
  function resolveSubmitBundleMapId(bundle) {
384
- var _a;
385
- const metadataMapId = (_a = bundle.metadata) == null ? void 0 : _a.custom_product_bundle_map_id;
386
- if (metadataMapId !== void 0 && metadataMapId !== null && metadataMapId !== "") {
505
+ const metadataMapId = bundle.metadata?.custom_product_bundle_map_id;
506
+ if (metadataMapId !== undefined && metadataMapId !== null && metadataMapId !== '') {
387
507
  return metadataMapId;
388
508
  }
389
- if (bundle._id !== void 0 && bundle._id !== null && bundle._id !== "") {
509
+ if (bundle._id !== undefined && bundle._id !== null && bundle._id !== '') {
390
510
  return bundle._id;
391
511
  }
392
- return void 0;
512
+ return undefined;
393
513
  }
394
514
  function collectSubmitProductDiscountList(product) {
395
- const submitDiscountList = Array.isArray(product == null ? void 0 : product.discount_list) ? [...product.discount_list] : [];
396
- for (const bundle of (product == null ? void 0 : product.product_bundle) || []) {
397
- if (!bundle || typeof bundle !== "object")
398
- continue;
515
+ const submitDiscountList = Array.isArray(product?.discount_list) ? [...product.discount_list] : [];
516
+ for (const bundle of product?.product_bundle || []) {
517
+ if (!bundle || typeof bundle !== 'object') continue;
399
518
  const bundleMapId = resolveSubmitBundleMapId(bundle);
400
519
  const bundleDiscountList = Array.isArray(bundle.discount_list) ? bundle.discount_list : [];
401
520
  for (const discount of bundleDiscountList) {
402
- if (!discount || typeof discount !== "object")
403
- continue;
404
- const discountMetadata = discount.metadata && typeof discount.metadata === "object" ? discount.metadata : {};
405
- const discountMapId = discountMetadata.custom_product_bundle_map_id !== void 0 && discountMetadata.custom_product_bundle_map_id !== null && discountMetadata.custom_product_bundle_map_id !== "" ? discountMetadata.custom_product_bundle_map_id : bundleMapId;
521
+ if (!discount || typeof discount !== 'object') continue;
522
+ const discountMetadata = discount.metadata && typeof discount.metadata === 'object' ? discount.metadata : {};
523
+ const discountMapId = discountMetadata.custom_product_bundle_map_id !== undefined && discountMetadata.custom_product_bundle_map_id !== null && discountMetadata.custom_product_bundle_map_id !== '' ? discountMetadata.custom_product_bundle_map_id : bundleMapId;
406
524
  submitDiscountList.push({
407
525
  ...discount,
408
- ...discountMapId !== void 0 ? {
526
+ ...(discountMapId !== undefined ? {
409
527
  metadata: {
410
528
  ...discountMetadata,
411
529
  custom_product_bundle_map_id: discountMapId
412
530
  }
413
- } : {}
531
+ } : {})
414
532
  });
415
533
  }
416
534
  }
417
535
  return normalizeOrderProductDiscountList(submitDiscountList);
418
536
  }
537
+
538
+ /**
539
+ * 手动改价(price_override)时行级 original_price(composite 单价):
540
+ * 购物车划线价应对齐 metadata.origin._extend.origin_total(改价前单价 composite,如 40),
541
+ * 而非 bundle 子项 catalog 原价合成的 composedOriginalPrice(如 30)。
542
+ *
543
+ * origin_total 与 SkuDetailModal / cacheItem._extend 一致,为单价语义,不再除以 num。
544
+ */
419
545
  function resolveManualOverrideLineOriginalPrice(params, fallbackCompositeOriginal) {
420
- var _a, _b;
421
546
  const metadata = params.metadata || {};
422
547
  const priceOverride = metadata.price_override;
423
- if (priceOverride === void 0 || priceOverride === null || priceOverride === "") {
548
+ if (priceOverride === undefined || priceOverride === null || priceOverride === '') {
424
549
  return fallbackCompositeOriginal;
425
550
  }
426
- const refTotal = (_b = (_a = metadata.origin) == null ? void 0 : _a._extend) == null ? void 0 : _b.origin_total;
427
- if (refTotal !== void 0 && refTotal !== null && refTotal !== "") {
551
+ const refTotal = metadata.origin?._extend?.origin_total;
552
+ if (refTotal !== undefined && refTotal !== null && refTotal !== '') {
428
553
  const parsed = Number(refTotal);
429
554
  if (Number.isFinite(parsed)) {
430
- return new import_decimal.default(parsed).toDecimalPlaces(2).toFixed(2);
555
+ return new _decimal.default(parsed).toDecimalPlaces(2).toFixed(2);
431
556
  }
432
557
  }
433
558
  const lineOriginal = params.lineOriginalPrice;
434
- if (lineOriginal !== void 0 && lineOriginal !== null && lineOriginal !== "") {
559
+ if (lineOriginal !== undefined && lineOriginal !== null && lineOriginal !== '') {
435
560
  const parsedLine = Number(lineOriginal);
436
561
  const parsedFallback = Number(fallbackCompositeOriginal);
437
562
  if (Number.isFinite(parsedLine) && Number.isFinite(parsedFallback) && parsedLine > parsedFallback) {
438
- return new import_decimal.default(parsedLine).toDecimalPlaces(2).toFixed(2);
563
+ return new _decimal.default(parsedLine).toDecimalPlaces(2).toFixed(2);
439
564
  }
440
565
  }
441
566
  return fallbackCompositeOriginal;
442
567
  }
568
+
569
+ /**
570
+ * 计算商品行「每单位有效折扣」:discount_list 合计 + 被 Rules 剥离但仍 inPromotion 的差额。
571
+ *
572
+ * Rules.calcDiscount 会把 type=promotion 从 discount_list 去掉,但 metadata._promotion 仍保留;
573
+ * applyProductDiscountPrices 必须回读 _promotion,否则抬价/降价都会在第二步被 source 原价覆盖。
574
+ *
575
+ * @example
576
+ * resolveEffectivePerUnitDiscount({ metadata: { _promotion: { inPromotion: true, originalPrice: 1, finalPrice: 5 } }, discount_list: [] });
577
+ * // => -4
578
+ */
443
579
  function resolveEffectivePerUnitDiscount(product) {
444
- const discountList = Array.isArray(product == null ? void 0 : product.discount_list) ? product.discount_list : [];
445
- const fromList = discountList.reduce(
446
- (sum, discount) => sum + Number((discount == null ? void 0 : discount.amount) || 0),
447
- 0
448
- );
449
- const hasPromoDiscountItem = discountList.some(
450
- (item) => {
451
- var _a, _b;
452
- return (item == null ? void 0 : item.type) === "promotion" || (item == null ? void 0 : item.type) === "product" && ((_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a.source) === "promotion" && ((_b = item == null ? void 0 : item.metadata) == null ? void 0 : _b.actionType) === "ITEM_REWARD";
453
- }
454
- );
455
- if (hasPromoDiscountItem)
456
- return fromList;
457
- const metadata = (product == null ? void 0 : product.metadata) || {};
580
+ const discountList = Array.isArray(product?.discount_list) ? product.discount_list : [];
581
+ const fromList = discountList.reduce((sum, discount) => sum + Number(discount?.amount || 0), 0);
582
+ const hasPromoDiscountItem = discountList.some(item => item?.type === 'promotion' || item?.type === 'product' && item?.metadata?.source === 'promotion' && item?.metadata?.actionType === 'ITEM_REWARD');
583
+ if (hasPromoDiscountItem) return fromList;
584
+ const metadata = product?.metadata || {};
458
585
  const promo = metadata._promotion;
459
- if ((promo == null ? void 0 : promo.inPromotion) !== true)
460
- return fromList;
586
+ if (promo?.inPromotion !== true) return fromList;
461
587
  const optionSum = sumOptionUnitPrice(getProductSkuOptions(product)).toNumber();
588
+
589
+ // applyPromotion 写价后、Rules 剥离 promotion discount 的兜底
462
590
  if (!discountList.length && metadata.source_product_price != null && metadata.main_product_selling_price != null) {
463
591
  const source = Number(metadata.source_product_price);
464
592
  const selling = Number(metadata.main_product_selling_price) - optionSum;
@@ -468,77 +596,70 @@ function resolveEffectivePerUnitDiscount(product) {
468
596
  }
469
597
  const originalPrice = Number(promo.originalPrice);
470
598
  const finalPrice = Number(promo.finalPrice);
471
- if (!Number.isFinite(originalPrice) || !Number.isFinite(finalPrice))
472
- return fromList;
599
+ if (!Number.isFinite(originalPrice) || !Number.isFinite(finalPrice)) return fromList;
473
600
  return fromList + (originalPrice - finalPrice);
474
601
  }
475
602
  function createDefaultOrderRulesHooks() {
476
603
  const toUnitPriceString = (totalLike, num) => {
477
604
  const effectiveNum = Number(num) > 0 ? Number(num) : 1;
478
- return new import_decimal.default(Number(totalLike) || 0).dividedBy(effectiveNum).toDecimalPlaces(2).toString();
605
+ return new _decimal.default(Number(totalLike) || 0).dividedBy(effectiveNum).toDecimalPlaces(2).toString();
479
606
  };
480
- const getBundleIdentity = (bundle) => {
481
- return [
482
- bundle.bundle_id ?? bundle.id ?? "",
483
- bundle.bundle_product_id ?? bundle._bundle_product_id ?? bundle.product_id ?? "",
484
- bundle.bundle_variant_id ?? bundle.variant_id ?? bundle.product_variant_id ?? 0,
485
- bundle.bundle_group_id ?? bundle.group_id ?? ""
486
- ].join("|");
607
+ const getBundleIdentity = bundle => {
608
+ return [bundle.bundle_id ?? bundle.id ?? '', bundle.bundle_product_id ?? bundle._bundle_product_id ?? bundle.product_id ?? '', bundle.bundle_variant_id ?? bundle.variant_id ?? bundle.product_variant_id ?? 0, bundle.bundle_group_id ?? bundle.group_id ?? ''].join('|');
487
609
  };
488
610
  const mergeRulesBundlePrices = (currentBundle, rulesBundle) => {
489
- if (!Array.isArray(rulesBundle))
490
- return rulesBundle;
491
- const currentByIdentity = /* @__PURE__ */ new Map();
492
- (currentBundle || []).forEach((bundle) => {
493
- if (!bundle || typeof bundle !== "object")
494
- return;
611
+ if (!Array.isArray(rulesBundle)) return rulesBundle;
612
+ const currentByIdentity = new Map();
613
+ (currentBundle || []).forEach(bundle => {
614
+ if (!bundle || typeof bundle !== 'object') return;
495
615
  currentByIdentity.set(getBundleIdentity(bundle), bundle);
496
616
  });
497
- return rulesBundle.map((bundle) => {
498
- if (!bundle || typeof bundle !== "object")
499
- return bundle;
617
+ return rulesBundle.map(bundle => {
618
+ if (!bundle || typeof bundle !== 'object') return bundle;
500
619
  const current = currentByIdentity.get(getBundleIdentity(bundle));
501
- if (!current)
502
- return bundle;
620
+ if (!current) return bundle;
503
621
  const bundleWithDisplayFields = {
504
622
  ...bundle,
505
- ...isEmptyOrderProductDisplayValue(bundle.cover) && !isEmptyOrderProductDisplayValue(current.cover) ? { cover: current.cover } : {}
623
+ ...(isEmptyOrderProductDisplayValue(bundle.cover) && !isEmptyOrderProductDisplayValue(current.cover) ? {
624
+ cover: current.cover
625
+ } : {})
506
626
  };
507
- const isProductPriceBundle = (bundle.price_type_ext ?? current.price_type_ext) === "product_price";
508
- if (!isProductPriceBundle)
509
- return bundleWithDisplayFields;
627
+ const isProductPriceBundle = (bundle.price_type_ext ?? current.price_type_ext) === 'product_price';
628
+ if (!isProductPriceBundle) return bundleWithDisplayFields;
510
629
  const sourcePrice = current.price ?? current.custom_price ?? current.original_price ?? current.bundle_selling_price;
511
630
  const originalPrice = current.original_price ?? current.product_price ?? current.price ?? current.custom_price ?? sourcePrice;
512
631
  return {
513
632
  ...bundleWithDisplayFields,
514
- ...sourcePrice !== void 0 ? { price: sourcePrice } : {},
515
- ...originalPrice !== void 0 ? { original_price: originalPrice } : {},
516
- ...current.original_total !== void 0 ? { original_total: current.original_total } : {}
633
+ ...(sourcePrice !== undefined ? {
634
+ price: sourcePrice
635
+ } : {}),
636
+ ...(originalPrice !== undefined ? {
637
+ original_price: originalPrice
638
+ } : {}),
639
+ ...(current.original_total !== undefined ? {
640
+ original_total: current.original_total
641
+ } : {})
517
642
  };
518
643
  });
519
644
  };
520
645
  return {
521
- getProduct: (product) => {
522
- var _a, _b, _c, _d, _e, _f;
646
+ getProduct: product => {
647
+ // source_product_price 是权威源;兜底链:source mainSelling options(反推)→ 行 selling_price
523
648
  const metadataAny = product.metadata || {};
524
649
  const optionSum = sumOptionUnitPrice(getProductSkuOptions(product));
525
650
  let sourcePrice;
526
- if (metadataAny.source_product_price !== void 0) {
651
+ if (metadataAny.source_product_price !== undefined) {
527
652
  sourcePrice = String(metadataAny.source_product_price);
528
- } else if (metadataAny.main_product_selling_price !== void 0) {
529
- sourcePrice = new import_decimal.default(
530
- Number(metadataAny.main_product_selling_price) || 0
531
- ).minus(optionSum).toDecimalPlaces(2).toString();
653
+ } else if (metadataAny.main_product_selling_price !== undefined) {
654
+ sourcePrice = new _decimal.default(Number(metadataAny.main_product_selling_price) || 0).minus(optionSum).toDecimalPlaces(2).toString();
532
655
  } else {
533
656
  sourcePrice = String(product.selling_price ?? 0);
534
657
  }
535
658
  let sourceOriginalPrice;
536
- if (metadataAny.source_product_price !== void 0) {
659
+ if (metadataAny.source_product_price !== undefined) {
537
660
  sourceOriginalPrice = String(metadataAny.source_product_price);
538
- } else if (metadataAny.main_product_original_price !== void 0) {
539
- sourceOriginalPrice = new import_decimal.default(
540
- Number(metadataAny.main_product_original_price) || 0
541
- ).minus(optionSum).toDecimalPlaces(2).toString();
661
+ } else if (metadataAny.main_product_original_price !== undefined) {
662
+ sourceOriginalPrice = new _decimal.default(Number(metadataAny.main_product_original_price) || 0).minus(optionSum).toDecimalPlaces(2).toString();
542
663
  } else {
543
664
  sourceOriginalPrice = sourcePrice;
544
665
  }
@@ -548,46 +669,50 @@ function createDefaultOrderRulesHooks() {
548
669
  // 否则同 SKU 不同小料会在 calcDiscount 重组时互相覆盖。
549
670
  // 不透明 identity 契约下,normalizeOrderProduct / hydrate 已保证唯一值存在;
550
671
  // 留 fingerprint 分支仅作 Rules 单测里直接传裸 product 时的兜底。
551
- _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_utils2.buildProductLineFingerprint)(
552
- getProductSkuOptions(product),
553
- product.product_bundle
554
- )}`,
672
+ _id: product.metadata?.unique_identification_number ? `${product.product_id}_${product.product_variant_id}_${product.metadata.unique_identification_number}` : `${product.product_id}_${product.product_variant_id}_${(0, _utils2.buildProductLineFingerprint)(getProductSkuOptions(product), product.product_bundle)}`,
555
673
  // Rules 内部 getProductTotalPrice / getProductOriginTotalPrice 会各自再叠加 bundle + option,
556
674
  // 所以这里必须喂 source-level(不含 option、不含 bundle、不含折扣)单价,避免双加 option。
557
675
  price: sourcePrice,
558
676
  // total / origin_total 使用 composite × num,跟 Rules 内部产出的 total 对齐(含 option + bundle)。
559
- total: new import_decimal.default(product.selling_price || 0).times(product.num || 1).toNumber(),
560
- origin_total: new import_decimal.default(
561
- product.original_price || product.selling_price || 0
562
- ).times(product.num || 1).toNumber(),
677
+ total: new _decimal.default(product.selling_price || 0).times(product.num || 1).toNumber(),
678
+ origin_total: new _decimal.default(product.original_price || product.selling_price || 0).times(product.num || 1).toNumber(),
563
679
  original_price: sourceOriginalPrice,
564
680
  quantity: product.num || 1,
565
681
  num: product.num || 1,
566
682
  discount_list: product.discount_list || [],
567
683
  bundle: product.product_bundle || [],
568
- booking_id: ((_b = product.metadata) == null ? void 0 : _b.booking_id) || null,
684
+ booking_id: product.metadata?.booking_id || null,
569
685
  isClient: false,
570
686
  // 勿写死 false:否则 Rules 不会走 total≠origin_total 的手动价推断,
571
687
  // 无券时会把 bundle 价还原成 original_price(手动改价套餐会从 20 回到 30)。
572
688
  isManualDiscount: resolveRulesManualDiscountFlag(metadataAny),
573
- holder_id: (_c = product.metadata) == null ? void 0 : _c.holder_id,
574
- startDate: ((_d = product.metadata) == null ? void 0 : _d.start_date) || ((_e = product.metadata) == null ? void 0 : _e.startDate),
575
- 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,
576
- inPromotion: ((_f = metadataAny._promotion) == null ? void 0 : _f.inPromotion) === true,
689
+ holder_id: product.metadata?.holder_id,
690
+ startDate: product.metadata?.start_date || product.metadata?.startDate,
691
+ main_product_selling_price: metadataAny.main_product_selling_price !== undefined ? new _decimal.default(Number(metadataAny.main_product_selling_price) || 0).minus(optionSum).toDecimalPlaces(2).toString() : undefined,
692
+ inPromotion: metadataAny._promotion?.inPromotion === true,
577
693
  _promotion: metadataAny._promotion
578
694
  };
579
695
  },
580
696
  setProduct: (product, values) => {
581
697
  const nextNum = Number(values.quantity ?? product.num ?? 1) || 1;
582
698
  const metadataAny = product.metadata || {};
583
- const existedSource = metadataAny.source_product_price ?? product.selling_price ?? "0";
699
+ const existedSource = metadataAny.source_product_price ?? product.selling_price ?? '0';
584
700
  const nextOptions = getProductSkuOptions(product);
585
701
  const optionSum = sumOptionUnitPrice(nextOptions);
586
- const nextSourceSellingPrice = values.main_product_selling_price !== void 0 ? String(values.main_product_selling_price) : values.price !== void 0 ? String(values.price) : values.total !== void 0 ? toUnitPriceString(values.total, nextNum) : String(existedSource);
587
- const nextSourceOriginalPrice = values.original_price !== void 0 ? String(values.original_price) : String(existedSource);
588
- const nextMainSellingPrice = new import_decimal.default(Number(nextSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
589
- const nextMainOriginalPrice = new import_decimal.default(Number(nextSourceOriginalPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
590
- const nextBundle = values.bundle !== void 0 ? mergeRulesBundlePrices(product.product_bundle, values.bundle) : product.product_bundle;
702
+
703
+ // Rules 返回的 main_product_selling_price / price / total 均为 source-level。
704
+ // 优先级:main_product_selling_price(per-unit 券后 source)> price(还原/good_pass 分支)>
705
+ // total/num(仅当 Rules 只给 total 时的兜底)> 保留当前 source。
706
+ const nextSourceSellingPrice = values.main_product_selling_price !== undefined ? String(values.main_product_selling_price) : values.price !== undefined ? String(values.price) : values.total !== undefined ? toUnitPriceString(values.total, nextNum) : String(existedSource);
707
+
708
+ // 券前 source:values.original_price 是 source-level(Rules 层本就不含 option),
709
+ // 缺省时保留现有 source(券前 = 当前 source)。
710
+ const nextSourceOriginalPrice = values.original_price !== undefined ? String(values.original_price) : String(existedSource);
711
+
712
+ // 含 option 的 main_product_*
713
+ const nextMainSellingPrice = new _decimal.default(Number(nextSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
714
+ const nextMainOriginalPrice = new _decimal.default(Number(nextSourceOriginalPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
715
+ const nextBundle = values.bundle !== undefined ? mergeRulesBundlePrices(product.product_bundle, values.bundle) : product.product_bundle;
591
716
  const composedSellingPrice = composeLinePrice({
592
717
  mainPrice: nextMainSellingPrice,
593
718
  bundle: nextBundle
@@ -597,10 +722,11 @@ function createDefaultOrderRulesHooks() {
597
722
  bundle: nextBundle,
598
723
  useOriginalBundle: true
599
724
  });
600
- const finalOriginalPrice = resolveManualOverrideLineOriginalPrice(
601
- { num: nextNum, metadata: metadataAny, lineOriginalPrice: product.original_price },
602
- composedOriginalPrice
603
- );
725
+ const finalOriginalPrice = resolveManualOverrideLineOriginalPrice({
726
+ num: nextNum,
727
+ metadata: metadataAny,
728
+ lineOriginalPrice: product.original_price
729
+ }, composedOriginalPrice);
604
730
  return {
605
731
  ...product,
606
732
  selling_price: composedSellingPrice,
@@ -619,47 +745,73 @@ function createDefaultOrderRulesHooks() {
619
745
  }
620
746
  };
621
747
  }
622
- var generateDuration = (cartItem) => {
623
- const startDate = (0, import_dayjs.default)(`${cartItem.start_date} ${cartItem.start_time}`);
624
- const endDate = (0, import_dayjs.default)(`${cartItem.end_date} ${cartItem.end_time}`);
625
- const duration = endDate.diff(startDate, "minutes");
626
- return { duration, durationType: "minutes" };
748
+
749
+ /**
750
+ * 通过 session 类商品的开始时间结束时间生成商品的时长
751
+ * @param {CartItem} cartItem
752
+ * @return {*}
753
+ */
754
+ const generateDuration = cartItem => {
755
+ const startDate = (0, _dayjs.default)(`${cartItem.start_date} ${cartItem.start_time}`);
756
+ const endDate = (0, _dayjs.default)(`${cartItem.end_date} ${cartItem.end_time}`);
757
+ const duration = endDate.diff(startDate, 'minutes');
758
+ return {
759
+ duration,
760
+ durationType: 'minutes'
761
+ };
627
762
  };
628
- var mergeRelationForms = (relationForms) => {
629
- return Object.values(
630
- relationForms.reduce((acc, cur) => {
631
- const { form_id, form_record_ids } = cur;
632
- if (!acc[form_id]) {
633
- acc[form_id] = { form_id, form_record_ids: [] };
634
- }
635
- const ids = Array.isArray(form_record_ids) ? form_record_ids : [form_record_ids];
636
- const validIds = ids.filter((id) => id != null);
637
- acc[form_id].form_record_ids.push(...validIds);
638
- acc[form_id].form_record_ids = [...new Set(acc[form_id].form_record_ids)];
639
- return acc;
640
- }, {})
641
- ).filter((item) => item.form_record_ids.length > 0);
763
+
764
+ /**
765
+ * 合并关联表单
766
+ * @param relationForms 关联表单
767
+ * @returns 合并后的关联表单
768
+ */
769
+ exports.generateDuration = generateDuration;
770
+ const mergeRelationForms = relationForms => {
771
+ return Object.values(relationForms.reduce((acc, cur) => {
772
+ const {
773
+ form_id,
774
+ form_record_ids
775
+ } = cur;
776
+ // 如果 acc 中没有 form_id,则初始化一个空数组
777
+ if (!acc[form_id]) {
778
+ acc[form_id] = {
779
+ form_id,
780
+ form_record_ids: []
781
+ };
782
+ }
783
+
784
+ // 兼容 form_record_id 可能是数组或单个数字
785
+ const ids = Array.isArray(form_record_ids) ? form_record_ids : [form_record_ids];
786
+ // 过滤掉空值(null、undefined等)
787
+ const validIds = ids.filter(id => id != null);
788
+ acc[form_id].form_record_ids.push(...validIds);
789
+ // 去重
790
+ acc[form_id].form_record_ids = [...new Set(acc[form_id].form_record_ids)];
791
+ return acc;
792
+ }, {})).filter(item => item.form_record_ids.length > 0); // 过滤掉没有有效记录的表单
642
793
  };
794
+ exports.mergeRelationForms = mergeRelationForms;
643
795
  function getCustomerIdFromStorage(window) {
644
- var _a;
645
796
  try {
646
- const customer = JSON.parse(((_a = window == null ? void 0 : window.getLocalStorage) == null ? void 0 : _a.call(window, "customer")) || "{}");
647
- const customerId = Number(customer == null ? void 0 : customer.id);
648
- return Number.isFinite(customerId) && customerId > 0 ? customerId : void 0;
797
+ const customer = JSON.parse(window?.getLocalStorage?.('customer') || '{}');
798
+ const customerId = Number(customer?.id);
799
+ return Number.isFinite(customerId) && customerId > 0 ? customerId : undefined;
649
800
  } catch {
650
- return void 0;
801
+ return undefined;
651
802
  }
652
803
  }
804
+
805
+ /**
806
+ * 为购物车行补齐订单所需的 holder 信息(与 cartAccount 结构保持一致)
807
+ */
653
808
  function ensureCartItemOriginHolder(cartItem, window) {
654
- var _a;
655
- if ((_a = cartItem == null ? void 0 : cartItem._origin) == null ? void 0 : _a.holder) {
809
+ if (cartItem?._origin?.holder) {
656
810
  return;
657
811
  }
658
- const holderConfig = (0, import_utils.getProductHolderConfig)(
659
- (cartItem == null ? void 0 : cartItem._productInit) ?? (cartItem == null ? void 0 : cartItem._productOrigin)
660
- );
661
- const formRecordId = cartItem == null ? void 0 : cartItem.holder_id;
662
- if (!(holderConfig == null ? void 0 : holderConfig.resource_id) || formRecordId == null) {
812
+ const holderConfig = (0, _utils.getProductHolderConfig)(cartItem?._productInit ?? cartItem?._productOrigin);
813
+ const formRecordId = cartItem?.holder_id;
814
+ if (!holderConfig?.resource_id || formRecordId == null) {
663
815
  return;
664
816
  }
665
817
  cartItem._origin.holder = {
@@ -668,24 +820,25 @@ function ensureCartItemOriginHolder(cartItem, window) {
668
820
  form_record: [formRecordId]
669
821
  };
670
822
  }
671
- var getAllDiscountList = (cartItem) => {
672
- var _a, _b, _c, _d;
673
- let discountList = ((_b = (_a = cartItem == null ? void 0 : cartItem._origin) == null ? void 0 : _a.product) == null ? void 0 : _b.discount_list) || [];
674
- (((_d = (_c = cartItem == null ? void 0 : cartItem._origin) == null ? void 0 : _c.product) == null ? void 0 : _d.product_bundle) || []).forEach((item) => {
675
- discountList = [...discountList, ...(item == null ? void 0 : item.discount_list) || []];
676
- item.discount_list = void 0;
823
+ ;
824
+ const getAllDiscountList = cartItem => {
825
+ let discountList = cartItem?._origin?.product?.discount_list || [];
826
+ (cartItem?._origin?.product?.product_bundle || []).forEach(item => {
827
+ discountList = [...discountList, ...(item?.discount_list || [])];
828
+ item.discount_list = undefined;
677
829
  });
678
830
  return discountList;
679
831
  };
832
+
833
+ // ─── 以下为从 ScanOrder/utils.ts 迁入的 Order 专属工具函数 ───
834
+ exports.getAllDiscountList = getAllDiscountList;
680
835
  function isTempOrder(data) {
681
- if (!data || typeof data !== "object")
682
- return false;
683
- if (!Array.isArray(data.products))
684
- return false;
836
+ if (!data || typeof data !== 'object') return false;
837
+ if (!Array.isArray(data.products)) return false;
685
838
  return true;
686
839
  }
687
840
  function formatDateTime(date) {
688
- const pad = (value) => value.toString().padStart(2, "0");
841
+ const pad = value => value.toString().padStart(2, '0');
689
842
  const year = date.getFullYear();
690
843
  const month = pad(date.getMonth() + 1);
691
844
  const day = pad(date.getDate());
@@ -695,29 +848,26 @@ function formatDateTime(date) {
695
848
  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
696
849
  }
697
850
  function normalizeSubmitPlatform(platform) {
698
- const value = String(platform || "").trim();
699
- if (!value)
700
- return "H5";
851
+ const value = String(platform || '').trim();
852
+ if (!value) return 'H5';
701
853
  const lower = value.toLowerCase();
702
- if (lower === "pc")
703
- return "PC";
704
- if (lower === "h5")
705
- return "H5";
854
+ if (lower === 'pc') return 'PC';
855
+ if (lower === 'h5') return 'H5';
706
856
  return value;
707
857
  }
858
+
859
+ // 后端 checkout 协议字段 option_group_item_id;tempOrder 内部也保持同一字段名。
708
860
  function formatSubmitOptionItems(options) {
709
- if (!Array.isArray(options))
710
- return [];
711
- return options.map((d) => {
861
+ if (!Array.isArray(options)) return [];
862
+ return options.map(d => {
712
863
  const option = {
713
- ...d && typeof d === "object" ? d : {},
714
- num: d == null ? void 0 : d.num,
715
- option_group_item_id: d == null ? void 0 : d.option_group_item_id,
716
- option_group_id: d == null ? void 0 : d.option_group_id
864
+ ...(d && typeof d === 'object' ? d : {}),
865
+ num: d?.num,
866
+ option_group_item_id: d?.option_group_item_id,
867
+ option_group_id: d?.option_group_id
717
868
  };
718
- const addPrice = (d == null ? void 0 : d.add_price) ?? (d == null ? void 0 : d.price);
719
- if (addPrice !== void 0)
720
- option.add_price = String(addPrice);
869
+ const addPrice = d?.add_price ?? d?.price;
870
+ if (addPrice !== undefined) option.add_price = String(addPrice);
721
871
  delete option.price;
722
872
  return option;
723
873
  });
@@ -728,33 +878,31 @@ function toBundleNumber(value, fallback = 0) {
728
878
  }
729
879
  function toMoneyString(value) {
730
880
  const parsed = Number(value);
731
- if (Number.isFinite(parsed))
732
- return parsed.toFixed(2);
733
- if (value === null || value === void 0 || value === "")
734
- return "0.00";
881
+ if (Number.isFinite(parsed)) return parsed.toFixed(2);
882
+ if (value === null || value === undefined || value === '') return '0.00';
735
883
  return String(value);
736
884
  }
885
+
886
+ // 出站补齐:只输出后端 checkout 协议字段,运行时/详情展示字段不进入 bundle payload。
737
887
  function formatSubmitBundleItems(bundle) {
738
- if (!Array.isArray(bundle))
739
- return [];
740
- return bundle.map((b) => {
741
- const rawBundle = b && typeof b === "object" ? b : {};
742
- const existedMetadata = rawBundle.metadata && typeof rawBundle.metadata === "object" ? rawBundle.metadata : {};
888
+ if (!Array.isArray(bundle)) return [];
889
+ return bundle.map(b => {
890
+ const rawBundle = b && typeof b === 'object' ? b : {};
891
+ const existedMetadata = rawBundle.metadata && typeof rawBundle.metadata === 'object' ? rawBundle.metadata : {};
743
892
  const {
744
893
  custom_product_bundle_map_id: _customProductBundleMapId,
745
894
  ...submitMetadata
746
895
  } = existedMetadata;
896
+
897
+ // bundle_selling_price 出站存「正净额」:markdown 为 |price| − Σoptions(如 3.70),
898
+ // markup/原价维持原值;与后端口径一致(price 仍为毛价)。
747
899
  const sellingPrice = getBundleSellingMagnitude(rawBundle).toFixed(2);
748
- const paymentPrice = rawBundle.bundle_payment_price !== void 0 && rawBundle.bundle_payment_price !== null && rawBundle.bundle_payment_price !== "" ? toMoneyString(rawBundle.bundle_payment_price) : sellingPrice;
900
+ // payment 价由整单折扣均摊层产出;缺省(无折扣)时与 selling 净额同义。
901
+ const paymentPrice = rawBundle.bundle_payment_price !== undefined && rawBundle.bundle_payment_price !== null && rawBundle.bundle_payment_price !== '' ? toMoneyString(rawBundle.bundle_payment_price) : sellingPrice;
749
902
  const priceValue = rawBundle.price ?? rawBundle.custom_price ?? rawBundle.bundle_selling_price;
750
903
  const relationSurchargeIds = Array.isArray(rawBundle.relation_surcharge_ids) ? rawBundle.relation_surcharge_ids : Array.isArray(existedMetadata.relation_surcharge_ids) ? existedMetadata.relation_surcharge_ids : [];
751
- const surchargeFee = toMoneyString(
752
- rawBundle.surcharge_fee ?? existedMetadata.surcharge_fee
753
- );
754
- const productDiscountDifference = toBundleNumber(
755
- existedMetadata.product_discount_difference,
756
- 0
757
- );
904
+ const surchargeFee = toMoneyString(rawBundle.surcharge_fee ?? existedMetadata.surcharge_fee);
905
+ const productDiscountDifference = toBundleNumber(existedMetadata.product_discount_difference, 0);
758
906
  const num = toBundleNumber(rawBundle.num ?? rawBundle.quantity, 1);
759
907
  const bundleMapId = resolveSubmitBundleMapId(rawBundle);
760
908
  const hasSubmitBundleDiscounts = Array.isArray(rawBundle.discount_list) && rawBundle.discount_list.length > 0;
@@ -764,20 +912,22 @@ function formatSubmitBundleItems(bundle) {
764
912
  num,
765
913
  quantity: toBundleNumber(rawBundle.quantity ?? rawBundle.num, num),
766
914
  extension_id: rawBundle.extension_id ?? 0,
767
- extension_type: rawBundle.extension_type ?? "normal",
915
+ extension_type: rawBundle.extension_type ?? 'normal',
768
916
  price: priceValue,
769
- price_type: rawBundle.price_type ?? rawBundle.custom_price_type ?? "",
770
- price_type_ext: rawBundle.price_type_ext ?? rawBundle.custom_price_type_ext ?? "",
917
+ price_type: rawBundle.price_type ?? rawBundle.custom_price_type ?? '',
918
+ price_type_ext: rawBundle.price_type_ext ?? rawBundle.custom_price_type_ext ?? '',
771
919
  bundle_selling_price: sellingPrice,
772
920
  bundle_payment_price: paymentPrice,
773
921
  option: formatSubmitOptionItems(rawBundle.option),
774
- bundle_group_id: (rawBundle == null ? void 0 : rawBundle.bundle_group_id) ?? (rawBundle == null ? void 0 : rawBundle.group_id),
775
- bundle_id: (rawBundle == null ? void 0 : rawBundle.bundle_id) ?? (rawBundle == null ? void 0 : rawBundle.id),
776
- bundle_product_id: (rawBundle == null ? void 0 : rawBundle.bundle_product_id) ?? (rawBundle == null ? void 0 : rawBundle._bundle_product_id),
922
+ bundle_group_id: rawBundle?.bundle_group_id ?? rawBundle?.group_id,
923
+ bundle_id: rawBundle?.bundle_id ?? rawBundle?.id,
924
+ bundle_product_id: rawBundle?.bundle_product_id ?? rawBundle?._bundle_product_id,
777
925
  cover: rawBundle.cover,
778
926
  metadata: {
779
927
  ...submitMetadata,
780
- ...hasSubmitBundleDiscounts && bundleMapId !== void 0 ? { custom_product_bundle_map_id: bundleMapId } : {},
928
+ ...(hasSubmitBundleDiscounts && bundleMapId !== undefined ? {
929
+ custom_product_bundle_map_id: bundleMapId
930
+ } : {}),
781
931
  surcharge_fee: surchargeFee,
782
932
  relation_surcharge_ids: relationSurchargeIds,
783
933
  product_discount_difference: productDiscountDifference
@@ -785,9 +935,28 @@ function formatSubmitBundleItems(bundle) {
785
935
  };
786
936
  });
787
937
  }
938
+
939
+ /**
940
+ * 把 tempOrder product 打包成出站 submit payload。
941
+ *
942
+ * 价格字段语义(出站口径,v2 composite):
943
+ * - `selling_price`:**行 composite 券后单价**
944
+ * = `metadata.main_product_selling_price` + Σ(bundle_selling_price × num)。
945
+ * - `original_price`:**行 composite 券前单价**
946
+ * = `metadata.main_product_original_price` + Σ(bundle 原价 × num)。
947
+ * - `payment_price`:兼容后端的出站字段,行 composite 已减整单折扣均摊(无折扣时与 `selling_price` 同义)。
948
+ * - `metadata.source_product_price`:主商品/variant 基础价(不含 option、不含折扣),权威源。
949
+ * - `metadata.main_product_original_price`:含 option、不含折扣。
950
+ * - `metadata.main_product_selling_price`:含 option、含主商品折扣。
951
+ * - `metadata.price_schema_version`:schema 版本号(当前 = 2),用于跨端协商价格口径。
952
+ *
953
+ * 本函数不再改造价格字段形状,仅做字段/metadata 裁剪。
954
+ */
788
955
  function normalizeSubmitProduct(product) {
789
- var _a;
790
- const { unique_identification_number: _runtimeUid, ...submitProduct } = product;
956
+ const {
957
+ unique_identification_number: _runtimeUid,
958
+ ...submitProduct
959
+ } = product;
791
960
  const {
792
961
  num,
793
962
  surcharge_fee: _productSurchargeFee,
@@ -798,54 +967,45 @@ function normalizeSubmitProduct(product) {
798
967
  discount_per: _deprecatedDiscountPer,
799
968
  ...productRest
800
969
  } = submitProduct;
801
- delete productRest[`product_${"option"}_item`];
970
+ delete productRest[`product_${'option'}_item`];
802
971
  const rawMetadata = submitProduct.metadata || {};
803
972
  const bookingUid = rawMetadata.booking_uid;
973
+ // 兼容历史 BigSale 编辑链路:bundle_edit 曾被写入 metadata,
974
+ // 出站时需提升到商品顶层;套餐未编辑时也必须显式提交 0。
804
975
  const hasProductBundle = Array.isArray(submitProduct.product_bundle) && submitProduct.product_bundle.length > 0;
805
- const bundleEdit = submitProduct.bundle_edit ?? rawMetadata.bundle_edit ?? (hasProductBundle ? 0 : void 0);
976
+ const bundleEdit = submitProduct.bundle_edit ?? rawMetadata.bundle_edit ?? (hasProductBundle ? 0 : undefined);
806
977
  const cleanMetadata = {};
807
978
  if (rawMetadata.unique_identification_number) {
808
979
  cleanMetadata.unique_identification_number = rawMetadata.unique_identification_number;
809
980
  }
810
- const priceMetaKeys = [
811
- "main_product_original_price",
812
- "main_product_selling_price",
813
- "main_product_attached_bundle_selling_price",
814
- "main_product_attached_bundle_payment_price",
815
- "average_discount_amount_rate",
816
- "source_product_price",
817
- "main_product_attached_bundle_surcharge_fee",
818
- "main_product_attached_bundle_tax_fee",
819
- "surcharge_rounding_remainder",
820
- "tax_fee_rounding_remainder",
821
- "relation_surcharge_ids",
822
- "discountable_flag",
823
- "parent_unique_identification_number",
824
- "product_add_schedule_time"
825
- ];
981
+ const priceMetaKeys = ['main_product_original_price', 'main_product_selling_price', 'main_product_attached_bundle_selling_price', 'main_product_attached_bundle_payment_price', 'average_discount_amount_rate', 'source_product_price', 'main_product_attached_bundle_surcharge_fee', 'main_product_attached_bundle_tax_fee', 'surcharge_rounding_remainder', 'tax_fee_rounding_remainder', 'relation_surcharge_ids', 'discountable_flag', 'parent_unique_identification_number', 'product_add_schedule_time'];
826
982
  for (const key of priceMetaKeys) {
827
- if (rawMetadata[key] !== void 0) {
983
+ if (rawMetadata[key] !== undefined) {
828
984
  cleanMetadata[key] = rawMetadata[key];
829
985
  }
830
986
  }
831
- cleanMetadata.product_discount_difference = rawMetadata.product_discount_difference ?? "";
987
+ cleanMetadata.product_discount_difference = rawMetadata.product_discount_difference ?? '';
832
988
  if (rawMetadata.price_breakdown) {
833
989
  cleanMetadata.price_breakdown = rawMetadata.price_breakdown;
834
990
  }
835
- if (rawMetadata.is_rule !== void 0) {
991
+ if (rawMetadata.is_rule !== undefined) {
836
992
  cleanMetadata.is_rule = rawMetadata.is_rule;
837
993
  }
838
- if (rawMetadata.holder_config !== void 0) {
994
+ if (rawMetadata.holder_config !== undefined) {
839
995
  cleanMetadata.holder_config = rawMetadata.holder_config;
840
996
  }
841
997
  const productSku = {
842
- ...submitProduct.product_sku && typeof submitProduct.product_sku === "object" ? submitProduct.product_sku : {},
843
- option: formatSubmitOptionItems((_a = submitProduct.product_sku) == null ? void 0 : _a.option)
998
+ ...(submitProduct.product_sku && typeof submitProduct.product_sku === 'object' ? submitProduct.product_sku : {}),
999
+ option: formatSubmitOptionItems(submitProduct.product_sku?.option)
844
1000
  };
845
1001
  return {
846
1002
  ...productRest,
847
- ...bookingUid ? { booking_uid: bookingUid } : {},
848
- ...bundleEdit !== void 0 ? { bundle_edit: bundleEdit } : {},
1003
+ ...(bookingUid ? {
1004
+ booking_uid: bookingUid
1005
+ } : {}),
1006
+ ...(bundleEdit !== undefined ? {
1007
+ bundle_edit: bundleEdit
1008
+ } : {}),
849
1009
  product_quantity: toBundleNumber(num ?? submitProduct.product_quantity, 1),
850
1010
  product_sku: productSku,
851
1011
  discount_list: collectSubmitProductDiscountList(submitProduct),
@@ -856,90 +1016,98 @@ function normalizeSubmitProduct(product) {
856
1016
  payment_price: submitProduct.payment_price ?? submitProduct.selling_price
857
1017
  };
858
1018
  }
859
- var SUBMIT_BOOKING_METADATA_WHITELIST = [
860
- "unique_identification_number",
861
- "collect_pax",
862
- "capacity",
863
- "holder_id",
864
- "resource_select_type",
865
- "holder"
866
- ];
1019
+ const SUBMIT_BOOKING_METADATA_WHITELIST = ['unique_identification_number', 'collect_pax', 'capacity', 'holder_id', 'resource_select_type', 'holder'];
867
1020
  function normalizeBookingIsAll(booking) {
868
- return booking.is_all === true || booking.is_all === 1 || booking.is_all === "1" || booking.is_all === "true" ? 1 : 0;
1021
+ return booking.is_all === true || booking.is_all === 1 || booking.is_all === '1' || booking.is_all === 'true' ? 1 : 0;
869
1022
  }
870
1023
  function normalizeBookingSubType(booking) {
871
- if (normalizeBookingIsAll(booking) === 1)
872
- return "days";
873
- if (booking.sub_type !== void 0 && booking.sub_type !== null && booking.sub_type !== "") {
1024
+ if (normalizeBookingIsAll(booking) === 1) return 'days';
1025
+ if (booking.sub_type !== undefined && booking.sub_type !== null && booking.sub_type !== '') {
874
1026
  return String(booking.sub_type);
875
1027
  }
876
- return "minutes";
1028
+ return 'minutes';
877
1029
  }
878
1030
  function normalizeSubmitBooking(booking) {
879
1031
  const rawMetadata = booking.metadata || {};
880
1032
  const cleanMetadata = {};
881
1033
  for (const key of SUBMIT_BOOKING_METADATA_WHITELIST) {
882
- if (rawMetadata[key] !== void 0) {
1034
+ if (rawMetadata[key] !== undefined) {
883
1035
  cleanMetadata[key] = rawMetadata[key];
884
1036
  }
885
1037
  }
886
- if (cleanMetadata.holder_id === void 0)
887
- cleanMetadata.holder_id = null;
1038
+ if (cleanMetadata.holder_id === undefined) cleanMetadata.holder_id = null;
888
1039
  const bookingRecord = booking;
889
1040
  const startDate = bookingRecord.start_date;
890
- const shouldRestoreSelectDate = bookingRecord.select_date === void 0 || bookingRecord.select_date === null || bookingRecord.select_date === "";
891
- const selectDateFromStartDate = typeof startDate === "string" ? startDate.split(/\s+/)[0] : startDate;
1041
+ const shouldRestoreSelectDate = bookingRecord.select_date === undefined || bookingRecord.select_date === null || bookingRecord.select_date === '';
1042
+ const selectDateFromStartDate = typeof startDate === 'string' ? startDate.split(/\s+/)[0] : startDate;
892
1043
  return {
893
1044
  ...booking,
894
- ...shouldRestoreSelectDate && selectDateFromStartDate ? { select_date: selectDateFromStartDate } : {},
1045
+ ...(shouldRestoreSelectDate && selectDateFromStartDate ? {
1046
+ select_date: selectDateFromStartDate
1047
+ } : {}),
895
1048
  is_all: normalizeBookingIsAll(bookingRecord),
896
1049
  sub_type: normalizeBookingSubType(bookingRecord),
897
1050
  metadata: cleanMetadata
898
1051
  };
899
1052
  }
1053
+ const DEFAULT_TABLE_OCCUPANCY_DURATION = 20;
1054
+ function resolveTableOccupancyDuration(tempOrder) {
1055
+ const metadata = tempOrder.metadata || {};
1056
+ const candidates = [metadata.table_occupancy_duration, metadata.booking_duration, metadata.table_duration, metadata.duration, metadata.table_config?.occupancy_duration, metadata.tableConfig?.occupancy_duration, metadata.resource_config?.occupancy_duration, metadata.resourceConfig?.occupancy_duration];
1057
+ for (const value of candidates) {
1058
+ const duration = Number(value);
1059
+ if (Number.isFinite(duration) && duration > 0) {
1060
+ return Math.floor(duration);
1061
+ }
1062
+ }
1063
+ return DEFAULT_TABLE_OCCUPANCY_DURATION;
1064
+ }
1065
+
1066
+ /** 提交用人数:有限且为正则向下取整,否则为 1 */
900
1067
  function normalizeSubmitCollectPaxValue(value) {
901
1068
  const n = Number(value);
902
1069
  return Number.isFinite(n) && n > 0 ? Math.floor(n) : 1;
903
1070
  }
1071
+
1072
+ /** 从临时订单 metadata 解析合成 booking 的 collect_pax */
904
1073
  function resolveSubmitCollectPax(tempOrder) {
905
- var _a;
906
- return normalizeSubmitCollectPaxValue((_a = tempOrder.metadata) == null ? void 0 : _a.collect_pax);
1074
+ return normalizeSubmitCollectPaxValue(tempOrder.metadata?.collect_pax);
907
1075
  }
908
1076
  function createDefaultTempOrder(params) {
909
1077
  return {
910
1078
  order_id: null,
911
- external_sale_number: "",
1079
+ external_sale_number: '',
912
1080
  order_number: null,
913
1081
  shop_order_number: null,
914
1082
  shop_full_order_number: null,
915
- type: "",
916
- business_code: void 0,
917
- platform: "h5",
918
- sales_channel: "my_pisel",
919
- order_sales_channel: "online_store",
920
- status: "normal",
921
- payment_status: "payment_processing",
922
- shipping_status: "unfulfilled",
1083
+ type: '',
1084
+ business_code: undefined,
1085
+ platform: 'h5',
1086
+ sales_channel: 'my_pisel',
1087
+ order_sales_channel: 'online_store',
1088
+ status: 'normal',
1089
+ payment_status: 'payment_processing',
1090
+ shipping_status: 'unfulfilled',
923
1091
  customer_id: 0,
924
- customer_name: "",
925
- country_calling_code: "",
926
- phone: "",
927
- email: "",
1092
+ customer_name: '',
1093
+ country_calling_code: '',
1094
+ phone: '',
1095
+ email: '',
928
1096
  customer: null,
929
1097
  is_price_include_tax: 1,
930
- tax_title: "",
931
- tax_country_code: "",
932
- currency_code: "",
933
- currency_symbol: "",
934
- currency_format: "symbol_first",
1098
+ tax_title: '',
1099
+ tax_country_code: '',
1100
+ currency_code: '',
1101
+ currency_symbol: '',
1102
+ currency_format: 'symbol_first',
935
1103
  is_deposit: 0,
936
- deposit_amount: "0.00",
937
- shop_discount: "0.00",
938
- surcharge_fee: "0.00",
939
- note: "",
1104
+ deposit_amount: '0.00',
1105
+ shop_discount: '0.00',
1106
+ surcharge_fee: '0.00',
1107
+ note: '',
940
1108
  schedule_date: params.now,
941
- created_at: void 0,
942
- request_unique_idempotency_token: "",
1109
+ created_at: undefined,
1110
+ request_unique_idempotency_token: '',
943
1111
  vouchers: [],
944
1112
  products: [],
945
1113
  bookings: [],
@@ -956,11 +1124,10 @@ function createDefaultTempOrder(params) {
956
1124
  };
957
1125
  }
958
1126
  function buildSubmitPayload(params) {
959
- var _a;
960
1127
  const {
961
1128
  tempOrder,
962
1129
  cacheId,
963
- now = /* @__PURE__ */ new Date(),
1130
+ now = new Date(),
964
1131
  platform,
965
1132
  businessCode,
966
1133
  channel,
@@ -969,9 +1136,9 @@ function buildSubmitPayload(params) {
969
1136
  enhance
970
1137
  } = params;
971
1138
  const scheduleDate = tempOrder.schedule_date || tempOrder.created_at || formatDateTime(now);
972
- const bookingUuid = (0, import_orderCollectionIdentity.createUuidV4)();
1139
+ const bookingUuid = (0, _orderCollectionIdentity.createUuidV4)();
973
1140
  const {
974
- _extend,
1141
+ _extend: _extend,
975
1142
  relation_id: _relationId,
976
1143
  table_form_id: _tableFormId,
977
1144
  resource_id: _resourceId,
@@ -993,69 +1160,72 @@ function buildSubmitPayload(params) {
993
1160
  } = tempOrder;
994
1161
  let submitType = type ?? tempOrder.type;
995
1162
  if (!submitType) {
996
- if ((_a = tempOrder == null ? void 0 : tempOrder.bookings) == null ? void 0 : _a.length) {
997
- if (businessCode === "dine_in") {
998
- submitType = "table-order";
1163
+ // 如果外部没有传递 types,根据订单里当前是否有 bookings 来决定是 appointment_booking 还是 virtual
1164
+ if (tempOrder?.bookings?.length) {
1165
+ // 260807 如果 biz 是堂食,type 使用table-order
1166
+ if (businessCode === 'dine_in') {
1167
+ submitType = 'table-order';
999
1168
  } else {
1000
- submitType = "appointment_booking";
1169
+ submitType = 'appointment_booking';
1001
1170
  }
1002
1171
  } else {
1003
- submitType = "virtual";
1172
+ submitType = 'virtual';
1004
1173
  }
1005
1174
  }
1006
1175
  const payload = {
1007
1176
  ...tempOrderRest,
1008
1177
  customer_id: tempOrder.customer_id ?? 1,
1009
- customer_name: tempOrder.customer_name || "Walk-In",
1010
- country_calling_code: String(tempOrder.country_calling_code ?? ""),
1011
- phone: String(tempOrder.phone ?? ""),
1012
- email: String(tempOrder.email ?? ""),
1178
+ customer_name: tempOrder.customer_name || 'Walk-In',
1179
+ country_calling_code: String(tempOrder.country_calling_code ?? ''),
1180
+ phone: String(tempOrder.phone ?? ''),
1181
+ email: String(tempOrder.email ?? ''),
1013
1182
  order_number: tempOrder.order_number ?? null,
1014
1183
  shop_order_number: tempOrder.shop_order_number ?? null,
1015
1184
  shop_full_order_number: tempOrder.shop_full_order_number ?? null,
1016
1185
  platform: normalizeSubmitPlatform(platform),
1017
- request_unique_idempotency_token: (params == null ? void 0 : params.request_unique_idempotency_token) || tempOrder.request_unique_idempotency_token || `${tempOrder.external_sale_number}_${now.getTime()}`,
1186
+ request_unique_idempotency_token: params?.request_unique_idempotency_token || tempOrder.request_unique_idempotency_token || `${tempOrder.external_sale_number}_${now.getTime()}`,
1018
1187
  type: submitType,
1019
1188
  business_code: businessCode ?? tempOrder.business_code,
1020
- sales_channel: tempOrder.sales_channel || "my_pisel",
1021
- order_sales_channel: channel ?? tempOrder.order_sales_channel ?? "online_store",
1022
- status: tempOrder.status || "normal",
1023
- payment_status: tempOrder.payment_status || "payment_processing",
1189
+ sales_channel: tempOrder.sales_channel || 'my_pisel',
1190
+ order_sales_channel: channel ?? tempOrder.order_sales_channel ?? 'online_store',
1191
+ status: tempOrder.status || 'normal',
1192
+ payment_status: tempOrder.payment_status || 'payment_processing',
1024
1193
  // shipping_status: tempOrder.shipping_status || 'unfulfilled',
1025
1194
  is_price_include_tax: tempOrder.is_price_include_tax ?? 1,
1026
- currency_format: tempOrder.currency_format || "symbol_first",
1195
+ currency_format: tempOrder.currency_format || 'symbol_first',
1027
1196
  is_deposit: tempOrder.is_deposit ?? 0,
1028
- deposit_amount: tempOrder.deposit_amount || "0.00",
1029
- shop_discount: tempOrder.shop_discount || "0.00",
1030
- surcharge_fee: tempOrder.surcharge_fee || "0.00",
1031
- note: tempOrder.note || "",
1032
- delivery_type: tempOrder.delivery_type || "nil",
1197
+ deposit_amount: tempOrder.deposit_amount || '0.00',
1198
+ shop_discount: tempOrder.shop_discount || '0.00',
1199
+ surcharge_fee: tempOrder.surcharge_fee || '0.00',
1200
+ note: tempOrder.note || '',
1201
+ delivery_type: tempOrder.delivery_type || 'nil',
1033
1202
  schedule_date: scheduleDate,
1034
1203
  // created_at: tempOrder.created_at || formatDateTime(now), 和后端协定这个字段先不提交到接口
1035
- bookings: (tempOrder.bookings || []).filter(
1036
- (booking) => Number(booking.parent_id) !== 0
1037
- ).map((booking) => normalizeSubmitBooking(booking)),
1204
+ bookings: (tempOrder.bookings || []).filter(booking => Number(booking.parent_id) !== 0).map(booking => normalizeSubmitBooking(booking)),
1038
1205
  payments: tempOrder.payments || [],
1039
1206
  relation_forms: tempOrder.relation_forms || [],
1040
1207
  // contacts: tempOrder.contacts || [],
1041
1208
  contacts_info: tempOrder.contacts_info && !Array.isArray(tempOrder.contacts_info) ? tempOrder.contacts_info : null,
1042
1209
  // holder: tempOrder.holder || null,
1043
- summary: summary || tempOrder.summary || (0, import_utils2.createEmptySummary)(),
1210
+ summary: summary || tempOrder.summary || (0, _utils2.createEmptySummary)(),
1044
1211
  metadata: (() => {
1045
1212
  const {
1046
1213
  collect_pax: _collectPax,
1047
1214
  table_occupancy_duration: _tableOccupancyDuration,
1048
1215
  ...rest
1049
1216
  } = tempOrder.metadata || {};
1050
- return { ...rest };
1217
+ return {
1218
+ ...rest
1219
+ };
1051
1220
  })(),
1052
- products: (tempOrder.products || []).map(
1053
- (product) => normalizeSubmitProduct(product)
1054
- )
1221
+ products: (tempOrder.products || []).map(product => normalizeSubmitProduct(product))
1055
1222
  };
1056
- if (!enhance)
1057
- return payload;
1058
- const enhancedPayload = enhance(payload, { tempOrder, bookingUuid, now });
1223
+ if (!enhance) return payload;
1224
+ const enhancedPayload = enhance(payload, {
1225
+ tempOrder,
1226
+ bookingUuid,
1227
+ now
1228
+ });
1059
1229
  return {
1060
1230
  ...enhancedPayload,
1061
1231
  summary: enhancedPayload.summary ?? payload.summary
@@ -1064,198 +1234,244 @@ function buildSubmitPayload(params) {
1064
1234
  function mapPaymentItemToOrderPayment(paymentItem) {
1065
1235
  const item = paymentItem;
1066
1236
  const customPaymentId = item.custom_payment_id ?? item.id;
1067
- const metadata = item.metadata && typeof item.metadata === "object" ? { ...item.metadata } : {};
1237
+ const metadata = item.metadata && typeof item.metadata === 'object' ? {
1238
+ ...item.metadata
1239
+ } : {};
1068
1240
  const paymentNumber = item.payment_number;
1069
- const paymentMetadataKeys = [
1070
- "rounding_rule",
1071
- "shop_wallet_pass_id",
1072
- "actual_paid_amount",
1073
- "change_given_amount"
1074
- ];
1241
+ const paymentMetadataKeys = ['rounding_rule', 'shop_wallet_pass_id', 'actual_paid_amount', 'change_given_amount'];
1075
1242
  for (const key of paymentMetadataKeys) {
1076
- if (item[key] !== void 0 && metadata[key] === void 0) {
1243
+ if (item[key] !== undefined && metadata[key] === undefined) {
1077
1244
  metadata[key] = item[key];
1078
1245
  }
1079
1246
  }
1080
- const timestamp = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
1247
+ const timestamp = (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss');
1081
1248
  const paymentTime = item.payment_time ?? timestamp;
1082
1249
  const createdAt = item.created_at ?? timestamp;
1083
1250
  return {
1084
- ...item.order_payment_id !== void 0 ? { order_payment_id: item.order_payment_id } : {},
1085
- ...paymentNumber !== void 0 && paymentNumber !== null && paymentNumber !== "" ? { payment_number: String(paymentNumber) } : {},
1086
- amount: String(item.amount ?? "0.00"),
1087
- code: String(item.code || ""),
1251
+ ...(item.order_payment_id !== undefined ? {
1252
+ order_payment_id: item.order_payment_id
1253
+ } : {}),
1254
+ ...(paymentNumber !== undefined && paymentNumber !== null && paymentNumber !== '' ? {
1255
+ payment_number: String(paymentNumber)
1256
+ } : {}),
1257
+ amount: String(item.amount ?? '0.00'),
1258
+ code: String(item.code || ''),
1088
1259
  custom_payment_id: Number(customPaymentId ?? 0),
1089
- ...item.custom_payment_type !== void 0 ? { custom_payment_type: String(item.custom_payment_type) } : {},
1090
- name: String(item.name || ""),
1091
- type: String(item.type || ""),
1092
- ...item.voucher_id !== void 0 ? { voucher_id: item.voucher_id } : {},
1093
- ...item.origin_amount !== void 0 ? { origin_amount: String(item.origin_amount) } : {},
1094
- ...item.service_fee !== void 0 ? { service_fee: String(item.service_fee) } : {},
1095
- ...item.status !== void 0 ? { status: item.status } : {},
1260
+ ...(item.custom_payment_type !== undefined ? {
1261
+ custom_payment_type: String(item.custom_payment_type)
1262
+ } : {}),
1263
+ name: String(item.name || ''),
1264
+ type: String(item.type || ''),
1265
+ ...(item.voucher_id !== undefined ? {
1266
+ voucher_id: item.voucher_id
1267
+ } : {}),
1268
+ ...(item.origin_amount !== undefined ? {
1269
+ origin_amount: String(item.origin_amount)
1270
+ } : {}),
1271
+ ...(item.service_fee !== undefined ? {
1272
+ service_fee: String(item.service_fee)
1273
+ } : {}),
1274
+ ...(item.status !== undefined ? {
1275
+ status: item.status
1276
+ } : {}),
1096
1277
  payment_time: paymentTime,
1097
1278
  created_at: createdAt,
1098
- ...item.wallet_pass_usage_unit !== void 0 ? { wallet_pass_usage_unit: item.wallet_pass_usage_unit } : {},
1099
- ...item.wallet_pass_use_value !== void 0 ? { wallet_pass_use_value: item.wallet_pass_use_value } : {},
1100
- ...item.fund_record && typeof item.fund_record === "object" && !Array.isArray(item.fund_record) ? { fund_record: { ...item.fund_record } } : {},
1279
+ ...(item.wallet_pass_usage_unit !== undefined ? {
1280
+ wallet_pass_usage_unit: item.wallet_pass_usage_unit
1281
+ } : {}),
1282
+ ...(item.wallet_pass_use_value !== undefined ? {
1283
+ wallet_pass_use_value: item.wallet_pass_use_value
1284
+ } : {}),
1285
+ ...(item.fund_record && typeof item.fund_record === 'object' && !Array.isArray(item.fund_record) ? {
1286
+ fund_record: {
1287
+ ...item.fund_record
1288
+ }
1289
+ } : {}),
1101
1290
  metadata,
1102
- ...item.rounding_amount !== void 0 ? { rounding_amount: String(item.rounding_amount) } : {},
1103
- ...item.service_charge !== void 0 ? { service_charge: item.service_charge } : {},
1104
- ...item.order_payment_type !== void 0 ? { order_payment_type: item.order_payment_type } : {},
1105
- ...item.updated_at !== void 0 ? { updated_at: item.updated_at } : {}
1291
+ ...(item.rounding_amount !== undefined ? {
1292
+ rounding_amount: String(item.rounding_amount)
1293
+ } : {}),
1294
+ ...(item.service_charge !== undefined ? {
1295
+ service_charge: item.service_charge
1296
+ } : {}),
1297
+ ...(item.order_payment_type !== undefined ? {
1298
+ order_payment_type: item.order_payment_type
1299
+ } : {}),
1300
+ ...(item.updated_at !== undefined ? {
1301
+ updated_at: item.updated_at
1302
+ } : {})
1106
1303
  };
1107
1304
  }
1108
1305
  function mapPaymentItemsToOrderPayments(paymentItems, options = {}) {
1109
- if (!Array.isArray(paymentItems))
1110
- return [];
1111
- return paymentItems.filter((item) => options.includeVoided || item.status !== "voided").map((item) => mapPaymentItemToOrderPayment(item));
1306
+ if (!Array.isArray(paymentItems)) return [];
1307
+ return paymentItems.filter(item => options.includeVoided || item.status !== 'voided').map(item => mapPaymentItemToOrderPayment(item));
1112
1308
  }
1309
+
1310
+ /**
1311
+ * 历史 V1 加餐结构映射器。
1312
+ *
1313
+ * @deprecated 标准 Sales checkout 已统一提交结构。
1314
+ * 本函数仅保留以兼容历史接入方,未来会移除。新代码请勿再调用。
1315
+ */
1113
1316
  function formatV1Product(products) {
1114
- return products.map((product) => {
1115
- var _a;
1317
+ return products.map(product => {
1116
1318
  return {
1117
1319
  bundle: product.product_bundle,
1118
1320
  key: product.product_id,
1119
- option: ((_a = product.product_sku) == null ? void 0 : _a.option) || [],
1321
+ option: product.product_sku?.option || [],
1120
1322
  product_id: product.product_id,
1121
1323
  product_variant_id: product.product_variant_id,
1122
1324
  num: product.product_quantity,
1123
- note: String(product.note ?? ""),
1325
+ note: String(product.note ?? ''),
1124
1326
  rowKey: product.product_id,
1125
1327
  session: null,
1126
- unique: (0, import_orderCollectionIdentity.createUuidV4)()
1328
+ unique: (0, _orderCollectionIdentity.createUuidV4)()
1127
1329
  };
1128
1330
  });
1129
1331
  }
1332
+
1333
+ /**
1334
+ * 判断 holder_id 是否已分配(非空)。
1335
+ *
1336
+ * @example
1337
+ * hasAssignedHolderId(12); // true
1338
+ * hasAssignedHolderId([]); // false
1339
+ */
1130
1340
  function hasAssignedHolderId(value) {
1131
- if (value === void 0 || value === null || value === "")
1132
- return false;
1133
- if (Array.isArray(value))
1134
- return value.length > 0;
1341
+ if (value === undefined || value === null || value === '') return false;
1342
+ if (Array.isArray(value)) return value.length > 0;
1135
1343
  return true;
1136
1344
  }
1345
+
1346
+ /**
1347
+ * 清空 tempOrder 购物车行上的 holder 分配(products / bookings / runtime origin)。
1348
+ * 移除或更换下单客户时调用,与 booking 页换客户清 holder 行为对齐。
1349
+ *
1350
+ * @example
1351
+ * clearTempOrderHolderAssignments(tempOrder);
1352
+ */
1137
1353
  function clearTempOrderHolderAssignments(tempOrder) {
1138
- var _a;
1139
1354
  let changed = false;
1140
- const resetHolderField = (target, key = "holder_id") => {
1141
- if (!hasAssignedHolderId(target[key]))
1142
- return;
1355
+ const resetHolderField = (target, key = 'holder_id') => {
1356
+ if (!hasAssignedHolderId(target[key])) return;
1143
1357
  target[key] = null;
1144
1358
  changed = true;
1145
1359
  };
1146
1360
  for (const product of tempOrder.products || []) {
1147
- if (product.metadata && typeof product.metadata === "object") {
1361
+ if (product.metadata && typeof product.metadata === 'object') {
1148
1362
  resetHolderField(product.metadata);
1149
1363
  }
1150
1364
  }
1151
1365
  for (const booking of tempOrder.bookings || []) {
1152
1366
  const bookingRecord = booking;
1153
- if (booking.metadata && typeof booking.metadata === "object") {
1367
+ if (booking.metadata && typeof booking.metadata === 'object') {
1154
1368
  resetHolderField(booking.metadata);
1155
1369
  }
1156
- if (bookingRecord.holder !== void 0 && bookingRecord.holder !== null) {
1370
+ if (bookingRecord.holder !== undefined && bookingRecord.holder !== null) {
1157
1371
  delete bookingRecord.holder;
1158
1372
  changed = true;
1159
1373
  }
1160
1374
  }
1161
- const productsByUid = (_a = tempOrder._extend) == null ? void 0 : _a.productsByUid;
1162
- if (productsByUid && typeof productsByUid === "object") {
1375
+ const productsByUid = tempOrder._extend?.productsByUid;
1376
+ if (productsByUid && typeof productsByUid === 'object') {
1163
1377
  for (const entry of Object.values(productsByUid)) {
1164
- const origin = entry == null ? void 0 : entry.origin;
1165
- if (!origin || typeof origin !== "object")
1166
- continue;
1167
- if (origin.metadata && typeof origin.metadata === "object") {
1378
+ const origin = entry?.origin;
1379
+ if (!origin || typeof origin !== 'object') continue;
1380
+ if (origin.metadata && typeof origin.metadata === 'object') {
1168
1381
  resetHolderField(origin.metadata);
1169
1382
  }
1170
- if (origin._extend && typeof origin._extend === "object") {
1383
+ if (origin._extend && typeof origin._extend === 'object') {
1171
1384
  resetHolderField(origin._extend);
1172
1385
  }
1173
1386
  }
1174
1387
  }
1175
1388
  return changed;
1176
1389
  }
1390
+
1391
+ /**
1392
+ * 读取购物车行的 stable uid(优先 metadata.unique_identification_number)。
1393
+ *
1394
+ * @example
1395
+ * getOrderProductLineUid({ metadata: { unique_identification_number: 'line-1' } }); // 'line-1'
1396
+ */
1177
1397
  function getOrderProductLineUid(product) {
1178
- var _a;
1179
- if (!product || typeof product !== "object")
1180
- return null;
1181
- const uid = ((_a = product.metadata) == null ? void 0 : _a.unique_identification_number) ?? product.unique_identification_number;
1182
- if (uid === void 0 || uid === null || uid === "")
1183
- return null;
1398
+ if (!product || typeof product !== 'object') return null;
1399
+ const uid = product.metadata?.unique_identification_number ?? product.unique_identification_number;
1400
+ if (uid === undefined || uid === null || uid === '') return null;
1184
1401
  return String(uid);
1185
1402
  }
1186
1403
  function getRuntimeProductOrigin(tempOrder, product) {
1187
- var _a, _b, _c, _d, _e, _f;
1188
1404
  const uid = getOrderProductLineUid(product);
1189
- if (uid && ((_c = (_b = (_a = tempOrder == null ? void 0 : tempOrder._extend) == null ? void 0 : _a.productsByUid) == null ? void 0 : _b[uid]) == null ? void 0 : _c.origin)) {
1405
+ if (uid && tempOrder?._extend?.productsByUid?.[uid]?.origin) {
1190
1406
  return tempOrder._extend.productsByUid[uid].origin;
1191
1407
  }
1192
- const matchedProduct = ((tempOrder == null ? void 0 : tempOrder.products) || []).find((item) => item === product || getOrderProductLineUid(item) === uid || String((item == null ? void 0 : item.product_id) ?? (item == null ? void 0 : item.id) ?? "") === String((product == null ? void 0 : product.product_id) ?? (product == null ? void 0 : product.id) ?? ""));
1193
- const matchedUid = matchedProduct ? getOrderProductLineUid(matchedProduct) : "";
1194
- return matchedUid ? ((_f = (_e = (_d = tempOrder == null ? void 0 : tempOrder._extend) == null ? void 0 : _d.productsByUid) == null ? void 0 : _e[matchedUid]) == null ? void 0 : _f.origin) || null : null;
1408
+ const matchedProduct = (tempOrder?.products || []).find(item => item === product || getOrderProductLineUid(item) === uid || String(item?.product_id ?? item?.id ?? '') === String(product?.product_id ?? product?.id ?? ''));
1409
+ const matchedUid = matchedProduct ? getOrderProductLineUid(matchedProduct) : '';
1410
+ return matchedUid ? tempOrder?._extend?.productsByUid?.[matchedUid]?.origin || null : null;
1195
1411
  }
1196
1412
  function isHolderConfigRequired(holderConfig) {
1197
- if (!holderConfig || typeof holderConfig !== "object")
1198
- return false;
1199
- if (holderConfig.status === "disable")
1200
- return false;
1413
+ if (!holderConfig || typeof holderConfig !== 'object') return false;
1414
+ if (holderConfig.status === 'disable') return false;
1201
1415
  return Number(holderConfig.required) === 1;
1202
1416
  }
1203
1417
  function productRequiresFormSubject(tempOrder, product) {
1204
- var _a, _b;
1205
- const _orderProduct = (_a = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _a.find((item) => {
1418
+ const _orderProduct = tempOrder?.products?.find(item => {
1206
1419
  return item.metadata.unique_identification_number === product._id || item.product_id === product.id;
1207
1420
  });
1208
1421
  const runtimeOrigin = getRuntimeProductOrigin(tempOrder, product);
1209
- return isHolderConfigRequired((_b = _orderProduct == null ? void 0 : _orderProduct.metadata) == null ? void 0 : _b.holder_config) || isHolderConfigRequired(runtimeOrigin == null ? void 0 : runtimeOrigin.holder_config) || isHolderConfigRequired(product == null ? void 0 : product.holder_config);
1422
+ return isHolderConfigRequired(_orderProduct?.metadata?.holder_config) || isHolderConfigRequired(runtimeOrigin?.holder_config) || isHolderConfigRequired(product?.holder_config);
1210
1423
  }
1211
1424
  function resolveIsFormSubject(tempOrder, product) {
1212
- var _a;
1213
- if (((_a = tempOrder == null ? void 0 : tempOrder.holder) == null ? void 0 : _a.type) === "form")
1214
- return true;
1215
- if (product)
1216
- return productRequiresFormSubject(tempOrder, product);
1217
- return ((tempOrder == null ? void 0 : tempOrder.products) || []).some(
1218
- (item) => productRequiresFormSubject(tempOrder, item)
1219
- );
1425
+ // 旧版预约维度的 holder 类型仍然生效;新版则从当前商品 holder_config 判断。
1426
+ if (tempOrder?.holder?.type === 'form') return true;
1427
+ if (product) return productRequiresFormSubject(tempOrder, product);
1428
+ return (tempOrder?.products || []).some(item => productRequiresFormSubject(tempOrder, item));
1220
1429
  }
1430
+
1431
+ /**
1432
+ * 判断展示字段是否为空(含 i18n 对象全空)。
1433
+ *
1434
+ * @example
1435
+ * isEmptyOrderProductDisplayValue(''); // true
1436
+ * isEmptyOrderProductDisplayValue({ auto: '桌台费' }); // false
1437
+ */
1221
1438
  function isEmptyOrderProductDisplayValue(value) {
1222
- if (value === void 0 || value === null)
1223
- return true;
1224
- if (typeof value === "string")
1225
- return value.trim() === "";
1226
- if (typeof value === "object") {
1439
+ if (value === undefined || value === null) return true;
1440
+ if (typeof value === 'string') return value.trim() === '';
1441
+ if (typeof value === 'object') {
1227
1442
  const record = value;
1228
- return !Object.values(record).some(
1229
- (item) => typeof item === "string" && item.trim() !== ""
1230
- );
1443
+ return !Object.values(record).some(item => typeof item === 'string' && item.trim() !== '');
1231
1444
  }
1232
1445
  return false;
1233
1446
  }
1447
+
1448
+ /**
1449
+ * calcDiscount / applyDiscount 回写时 Rules 往往不带 product_title 等展示字段;
1450
+ * 用旧行补齐,避免编辑态 hydrate 后标题被冲掉。
1451
+ *
1452
+ * @example
1453
+ * mergeOrderProductDisplayFields(
1454
+ * { product_title: { auto: '桌台费' }, metadata: { unique_identification_number: 'u1' } },
1455
+ * { selling_price: '10.00', metadata: { unique_identification_number: 'u1' } },
1456
+ * );
1457
+ */
1234
1458
  function mergeOrderProductDisplayFields(previous, next) {
1235
- const merged = { ...next };
1236
- const displayFields = [
1237
- "product_title",
1238
- "product_name",
1239
- "product_cover",
1240
- "cover",
1241
- "product_cover",
1242
- "variant_title",
1243
- "product_sku",
1244
- "payment_price"
1245
- ];
1246
- displayFields.forEach((field) => {
1459
+ const merged = {
1460
+ ...next
1461
+ };
1462
+ const displayFields = ['product_title', 'product_name', 'product_cover', 'cover', 'product_cover', 'variant_title', 'product_sku', 'payment_price'];
1463
+ displayFields.forEach(field => {
1247
1464
  if (isEmptyOrderProductDisplayValue(merged[field]) && !isEmptyOrderProductDisplayValue(previous[field])) {
1248
1465
  merged[field] = previous[field];
1249
1466
  }
1250
1467
  });
1251
1468
  if (previous.metadata || next.metadata) {
1252
1469
  merged.metadata = {
1253
- ...previous.metadata || {},
1254
- ...next.metadata || {}
1470
+ ...(previous.metadata || {}),
1471
+ ...(next.metadata || {})
1255
1472
  };
1256
- ["product_title", "product_name"].forEach((field) => {
1257
- var _a;
1258
- if (isEmptyOrderProductDisplayValue(merged.metadata[field]) && !isEmptyOrderProductDisplayValue((_a = previous.metadata) == null ? void 0 : _a[field])) {
1473
+ ['product_title', 'product_name'].forEach(field => {
1474
+ if (isEmptyOrderProductDisplayValue(merged.metadata[field]) && !isEmptyOrderProductDisplayValue(previous.metadata?.[field])) {
1259
1475
  merged.metadata[field] = previous.metadata[field];
1260
1476
  }
1261
1477
  });
@@ -1265,8 +1481,15 @@ function mergeOrderProductDisplayFields(previous, next) {
1265
1481
  }
1266
1482
  return merged;
1267
1483
  }
1484
+
1485
+ /**
1486
+ * 按 uid 索引 tempOrder.products,供 applyDiscount 合并展示字段。
1487
+ *
1488
+ * @example
1489
+ * indexOrderProductsByUid([{ metadata: { unique_identification_number: 'u1' } }]);
1490
+ */
1268
1491
  function indexOrderProductsByUid(products) {
1269
- const map = /* @__PURE__ */ new Map();
1492
+ const map = new Map();
1270
1493
  (products || []).forEach((product, index) => {
1271
1494
  const uid = getOrderProductLineUid(product);
1272
1495
  if (uid) {
@@ -1276,60 +1499,4 @@ function indexOrderProductsByUid(products) {
1276
1499
  map.set(`__index__:${index}`, product);
1277
1500
  });
1278
1501
  return map;
1279
- }
1280
- // Annotate the CommonJS export names for ESM import in node:
1281
- 0 && (module.exports = {
1282
- buildManualProductDiscountItem,
1283
- buildSubmitPayload,
1284
- calculateOrderProductsDeposit,
1285
- clearTempOrderHolderAssignments,
1286
- composeLinePrice,
1287
- createDefaultOrderRulesHooks,
1288
- createDefaultTempOrder,
1289
- createEmptySummary,
1290
- createUuidV4,
1291
- ensureCartItemOriginHolder,
1292
- ensureManualProductDiscountList,
1293
- ensureProductSku,
1294
- findManualProductDiscountItem,
1295
- formatDateTime,
1296
- formatV1Product,
1297
- generateDuration,
1298
- getAllDiscountList,
1299
- getBundleSellingMagnitude,
1300
- getBundleSignedUnit,
1301
- getOrderProductLineUid,
1302
- getProductSkuOptions,
1303
- getRuntimeProductOrigin,
1304
- hasAssignedHolderId,
1305
- indexOrderProductsByUid,
1306
- isEmptyOrderProductDisplayValue,
1307
- isHolderConfigRequired,
1308
- isMarkdownBundle,
1309
- isTempOrder,
1310
- mapPaymentItemToOrderPayment,
1311
- mapPaymentItemsToOrderPayments,
1312
- mergeManualProductDiscountIntoList,
1313
- mergeOrderProductDisplayFields,
1314
- mergeRelationForms,
1315
- normalizeBookingIsAll,
1316
- normalizeBookingSubType,
1317
- normalizeOrderProductDiscountList,
1318
- normalizeProductSkuOptions,
1319
- normalizeSubmitBooking,
1320
- normalizeSubmitCollectPaxValue,
1321
- productRequiresFormSubject,
1322
- resolveEffectivePerUnitDiscount,
1323
- resolveIsFormSubject,
1324
- resolveManualDiscountMessage,
1325
- resolveManualDiscountOriginTotal,
1326
- resolveManualDiscountReasonFromSources,
1327
- resolveManualOverrideLineOriginalPrice,
1328
- resolveRulesManualDiscountFlag,
1329
- resolveSafeProductNum,
1330
- resolveSubmitCollectPax,
1331
- shouldBuildManualProductDiscount,
1332
- stripManualProductDiscountItems,
1333
- sumOptionUnitPrice,
1334
- syncManualProductDiscountProductNum
1335
- });
1502
+ }