@pisell/pisellos 2.2.244 → 2.2.245

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 (317) hide show
  1. package/dist/model/strategy/adapter/promotion/evaluator.js +3 -2
  2. package/dist/model/strategy/adapter/promotion/index.js +0 -9
  3. package/dist/model/strategy/adapter/walletPass/utils.js +7 -4
  4. package/dist/modules/BookingContext/index.d.ts +48 -0
  5. package/dist/modules/BookingContext/index.js +566 -0
  6. package/dist/modules/BookingContext/types.d.ts +102 -0
  7. package/dist/modules/BookingContext/types.js +51 -0
  8. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.d.ts +16 -0
  9. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +284 -0
  10. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +8 -0
  11. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +145 -0
  12. package/dist/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +76 -0
  13. package/dist/modules/BookingContext/utils/cacheItemToBookingInput.js +218 -0
  14. package/dist/modules/BookingContext/utils/flexible.d.ts +28 -0
  15. package/dist/modules/BookingContext/utils/flexible.js +56 -0
  16. package/dist/modules/BookingContext/utils/formatResourceList.d.ts +8 -0
  17. package/dist/modules/BookingContext/utils/formatResourceList.js +38 -0
  18. package/dist/modules/BookingContext/utils/index.d.ts +11 -0
  19. package/dist/modules/BookingContext/utils/index.js +11 -0
  20. package/dist/modules/BookingContext/utils/noResource.d.ts +13 -0
  21. package/dist/modules/BookingContext/utils/noResource.js +77 -0
  22. package/dist/modules/BookingContext/utils/orderLineDisplay.d.ts +1 -0
  23. package/dist/modules/BookingContext/utils/orderLineDisplay.js +36 -0
  24. package/dist/modules/BookingContext/utils/productExtend.d.ts +72 -0
  25. package/dist/modules/BookingContext/utils/productExtend.js +339 -0
  26. package/dist/modules/BookingContext/utils/resourceErrors.d.ts +41 -0
  27. package/dist/modules/BookingContext/utils/resourceErrors.js +74 -0
  28. package/dist/modules/BookingContext/utils/resourceSelection.d.ts +7 -0
  29. package/dist/modules/BookingContext/utils/resourceSelection.js +24 -0
  30. package/dist/modules/BookingContext/utils/resources.d.ts +80 -0
  31. package/dist/modules/BookingContext/utils/resources.js +486 -0
  32. package/dist/modules/BookingContext/utils/serviceTimes.d.ts +55 -0
  33. package/dist/modules/BookingContext/utils/serviceTimes.js +151 -0
  34. package/dist/modules/BookingContext/utils/timeSlices.d.ts +42 -0
  35. package/dist/modules/BookingContext/utils/timeSlices.js +100 -0
  36. package/dist/modules/Cart/utils/cartProduct.js +24 -3
  37. package/dist/modules/Cart/utils/changePrice.js +11 -11
  38. package/dist/modules/Customer/index.d.ts +20 -0
  39. package/dist/modules/Customer/index.js +172 -83
  40. package/dist/modules/Customer/types.d.ts +2 -0
  41. package/dist/modules/Discount/index.d.ts +1 -1
  42. package/dist/modules/Discount/index.js +13 -6
  43. package/dist/modules/Discount/types.d.ts +1 -0
  44. package/dist/modules/OpenData/index.d.ts +8 -0
  45. package/dist/modules/OpenData/index.js +37 -17
  46. package/dist/modules/Order/index.d.ts +275 -19
  47. package/dist/modules/Order/index.js +3493 -809
  48. package/dist/modules/Order/types.d.ts +286 -31
  49. package/dist/modules/Order/types.js +38 -0
  50. package/dist/modules/Order/utils/manualProductDiscount.d.ts +106 -0
  51. package/dist/modules/Order/utils/manualProductDiscount.js +210 -0
  52. package/dist/modules/Order/utils.d.ts +147 -5
  53. package/dist/modules/Order/utils.js +750 -104
  54. package/dist/modules/Payment/index.d.ts +10 -13
  55. package/dist/modules/Payment/index.js +467 -837
  56. package/dist/modules/Payment/types.d.ts +2 -0
  57. package/dist/modules/Payment/utils.js +2 -1
  58. package/dist/modules/Payment/walletpass.js +41 -25
  59. package/dist/modules/ProductList/index.d.ts +16 -12
  60. package/dist/modules/ProductList/index.js +133 -59
  61. package/dist/modules/ProductList/types.d.ts +14 -0
  62. package/dist/modules/Quotation/index.d.ts +0 -1
  63. package/dist/modules/Quotation/index.js +25 -22
  64. package/dist/modules/Rules/index.d.ts +4 -0
  65. package/dist/modules/Rules/index.js +97 -70
  66. package/dist/modules/Rules/types.d.ts +1 -0
  67. package/dist/modules/SalesSummary/index.d.ts +8 -25
  68. package/dist/modules/SalesSummary/index.js +86 -35
  69. package/dist/modules/SalesSummary/types.d.ts +4 -1
  70. package/dist/modules/SalesSummary/utils.d.ts +2 -25
  71. package/dist/modules/SalesSummary/utils.js +794 -162
  72. package/dist/modules/Schedule/index.d.ts +7 -0
  73. package/dist/modules/Schedule/index.js +24 -2
  74. package/dist/modules/Summary/index.js +4 -3
  75. package/dist/modules/SurchargeList/index.d.ts +16 -0
  76. package/dist/modules/SurchargeList/index.js +162 -0
  77. package/dist/modules/SurchargeList/types.d.ts +11 -0
  78. package/dist/modules/SurchargeList/types.js +1 -0
  79. package/dist/modules/index.d.ts +2 -0
  80. package/dist/modules/index.js +3 -1
  81. package/dist/plugins/request.d.ts +1 -0
  82. package/dist/server/index.d.ts +204 -1
  83. package/dist/server/index.js +3654 -922
  84. package/dist/server/modules/index.d.ts +2 -0
  85. package/dist/server/modules/index.js +2 -0
  86. package/dist/server/modules/order/index.d.ts +120 -3
  87. package/dist/server/modules/order/index.js +1758 -448
  88. package/dist/server/modules/order/types.d.ts +32 -3
  89. package/dist/server/modules/order/types.js +8 -0
  90. package/dist/server/modules/order/utils/filterBookings.js +26 -3
  91. package/dist/server/modules/order/utils/filterOrders.js +23 -8
  92. package/dist/server/modules/payment/index.d.ts +28 -0
  93. package/dist/server/modules/payment/index.js +305 -0
  94. package/dist/server/modules/payment/types.d.ts +9 -0
  95. package/dist/server/modules/payment/types.js +1 -0
  96. package/dist/server/modules/products/index.d.ts +34 -7
  97. package/dist/server/modules/products/index.js +631 -317
  98. package/dist/server/modules/resource/index.d.ts +2 -0
  99. package/dist/server/modules/resource/index.js +29 -3
  100. package/dist/server/modules/schedule/index.d.ts +4 -4
  101. package/dist/server/modules/schedule/index.js +111 -88
  102. package/dist/server/test.json +713 -0
  103. package/dist/server/utils/small-ticket.d.ts +71 -0
  104. package/dist/server/utils/small-ticket.js +840 -0
  105. package/dist/solution/BaseSales/index.d.ts +133 -10
  106. package/dist/solution/BaseSales/index.js +1950 -447
  107. package/dist/solution/BaseSales/types.d.ts +82 -6
  108. package/dist/solution/BaseSales/types.js +5 -4
  109. package/dist/solution/BaseSales/utils/cartPromotion.d.ts +287 -0
  110. package/dist/solution/BaseSales/utils/cartPromotion.js +1438 -0
  111. package/dist/solution/BaseSales/utils/quotationPrice.d.ts +7 -0
  112. package/dist/solution/BaseSales/utils/quotationPrice.js +237 -0
  113. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
  114. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +105 -24
  115. package/dist/solution/BaseSales/utils.d.ts +1 -1
  116. package/dist/solution/BaseSales/utils.js +62 -21
  117. package/dist/solution/BookingByStep/index.d.ts +1 -1
  118. package/dist/solution/BookingTicket/index.d.ts +271 -11
  119. package/dist/solution/BookingTicket/index.js +1777 -242
  120. package/dist/solution/BookingTicket/types.d.ts +118 -1
  121. package/dist/solution/BookingTicket/types.js +41 -2
  122. package/dist/solution/BookingTicket/utils/addProductDecision.d.ts +117 -0
  123. package/dist/solution/BookingTicket/utils/addProductDecision.js +346 -0
  124. package/dist/solution/BookingTicket/utils/addTimeAvailability.d.ts +35 -0
  125. package/dist/solution/BookingTicket/utils/addTimeAvailability.js +95 -0
  126. package/dist/solution/BookingTicket/utils/bookingStatus.d.ts +40 -0
  127. package/dist/solution/BookingTicket/utils/bookingStatus.js +70 -0
  128. package/dist/solution/BookingTicket/utils/cartView.d.ts +9 -1
  129. package/dist/solution/BookingTicket/utils/cartView.js +94 -7
  130. package/dist/solution/BookingTicket/utils/exampleData.d.ts +123 -0
  131. package/dist/solution/BookingTicket/utils/exampleData.js +183 -0
  132. package/dist/solution/BookingTicket/utils/resolveBestAddTimePlan.d.ts +185 -0
  133. package/dist/solution/BookingTicket/utils/resolveBestAddTimePlan.js +438 -0
  134. package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +36 -0
  135. package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.js +400 -0
  136. package/dist/solution/BookingTicket/utils/scan/formatGlobalScan.d.ts +32 -0
  137. package/dist/solution/BookingTicket/utils/scan/formatGlobalScan.js +56 -0
  138. package/dist/solution/BookingTicket/utils/scan/index.d.ts +5 -0
  139. package/dist/solution/BookingTicket/utils/scan/index.js +20 -8
  140. package/dist/solution/BookingTicket/utils/scan/scanProductValues.d.ts +21 -0
  141. package/dist/solution/BookingTicket/utils/scan/scanProductValues.js +150 -0
  142. package/dist/solution/BookingTicket/utils/sessionCatalogStale.d.ts +23 -0
  143. package/dist/solution/BookingTicket/utils/sessionCatalogStale.js +78 -0
  144. package/dist/solution/Checkout/index.d.ts +1 -0
  145. package/dist/solution/Checkout/index.js +10 -9
  146. package/dist/solution/RegisterAndLogin/config.js +2 -10
  147. package/dist/solution/ScanOrder/index.d.ts +9 -3
  148. package/dist/solution/ScanOrder/index.js +241 -134
  149. package/dist/solution/ScanOrder/types.d.ts +9 -5
  150. package/dist/solution/ScanOrder/types.js +2 -3
  151. package/dist/solution/ScanOrder/utils.d.ts +1 -1
  152. package/dist/solution/ScanOrder/utils.js +84 -22
  153. package/dist/solution/VenueBooking/index.d.ts +5 -2
  154. package/dist/solution/VenueBooking/index.js +110 -59
  155. package/dist/solution/VenueBooking/sales-section-4-annotated.json +0 -2
  156. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +4 -0
  157. package/dist/solution/VenueBooking/utils/slotMerge.js +10 -0
  158. package/dist/types/index.d.ts +10 -0
  159. package/lib/model/strategy/adapter/promotion/evaluator.js +2 -1
  160. package/lib/model/strategy/adapter/promotion/index.js +49 -0
  161. package/lib/model/strategy/adapter/walletPass/utils.js +3 -2
  162. package/lib/modules/BookingContext/index.d.ts +48 -0
  163. package/lib/modules/BookingContext/index.js +368 -0
  164. package/lib/modules/BookingContext/types.d.ts +102 -0
  165. package/lib/modules/BookingContext/types.js +34 -0
  166. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.d.ts +16 -0
  167. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +276 -0
  168. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +8 -0
  169. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +151 -0
  170. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +76 -0
  171. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +201 -0
  172. package/lib/modules/BookingContext/utils/flexible.d.ts +28 -0
  173. package/lib/modules/BookingContext/utils/flexible.js +80 -0
  174. package/lib/modules/BookingContext/utils/formatResourceList.d.ts +8 -0
  175. package/lib/modules/BookingContext/utils/formatResourceList.js +50 -0
  176. package/lib/modules/BookingContext/utils/index.d.ts +11 -0
  177. package/lib/modules/BookingContext/utils/index.js +43 -0
  178. package/lib/modules/BookingContext/utils/noResource.d.ts +13 -0
  179. package/lib/modules/BookingContext/utils/noResource.js +90 -0
  180. package/lib/modules/BookingContext/utils/orderLineDisplay.d.ts +1 -0
  181. package/lib/modules/BookingContext/utils/orderLineDisplay.js +56 -0
  182. package/lib/modules/BookingContext/utils/productExtend.d.ts +72 -0
  183. package/lib/modules/BookingContext/utils/productExtend.js +283 -0
  184. package/lib/modules/BookingContext/utils/resourceErrors.d.ts +41 -0
  185. package/lib/modules/BookingContext/utils/resourceErrors.js +80 -0
  186. package/lib/modules/BookingContext/utils/resourceSelection.d.ts +7 -0
  187. package/lib/modules/BookingContext/utils/resourceSelection.js +46 -0
  188. package/lib/modules/BookingContext/utils/resources.d.ts +80 -0
  189. package/lib/modules/BookingContext/utils/resources.js +377 -0
  190. package/lib/modules/BookingContext/utils/serviceTimes.d.ts +55 -0
  191. package/lib/modules/BookingContext/utils/serviceTimes.js +162 -0
  192. package/lib/modules/BookingContext/utils/timeSlices.d.ts +42 -0
  193. package/lib/modules/BookingContext/utils/timeSlices.js +124 -0
  194. package/lib/modules/Cart/utils/cartProduct.js +20 -3
  195. package/lib/modules/Cart/utils/changePrice.js +12 -20
  196. package/lib/modules/Customer/index.d.ts +20 -0
  197. package/lib/modules/Customer/index.js +64 -11
  198. package/lib/modules/Customer/types.d.ts +2 -0
  199. package/lib/modules/Discount/index.d.ts +1 -1
  200. package/lib/modules/Discount/index.js +9 -1
  201. package/lib/modules/Discount/types.d.ts +1 -0
  202. package/lib/modules/OpenData/index.d.ts +8 -0
  203. package/lib/modules/OpenData/index.js +19 -5
  204. package/lib/modules/Order/index.d.ts +275 -19
  205. package/lib/modules/Order/index.js +2245 -336
  206. package/lib/modules/Order/types.d.ts +286 -31
  207. package/lib/modules/Order/types.js +1 -0
  208. package/lib/modules/Order/utils/manualProductDiscount.d.ts +106 -0
  209. package/lib/modules/Order/utils/manualProductDiscount.js +206 -0
  210. package/lib/modules/Order/utils.d.ts +147 -5
  211. package/lib/modules/Order/utils.js +615 -46
  212. package/lib/modules/Payment/index.d.ts +10 -13
  213. package/lib/modules/Payment/index.js +18 -150
  214. package/lib/modules/Payment/types.d.ts +2 -0
  215. package/lib/modules/Payment/utils.js +2 -1
  216. package/lib/modules/Payment/walletpass.js +16 -3
  217. package/lib/modules/ProductList/index.d.ts +16 -12
  218. package/lib/modules/ProductList/index.js +41 -4
  219. package/lib/modules/ProductList/types.d.ts +14 -0
  220. package/lib/modules/Quotation/index.d.ts +0 -1
  221. package/lib/modules/Quotation/index.js +19 -16
  222. package/lib/modules/Rules/index.d.ts +4 -0
  223. package/lib/modules/Rules/index.js +137 -120
  224. package/lib/modules/Rules/types.d.ts +1 -0
  225. package/lib/modules/SalesSummary/index.d.ts +8 -25
  226. package/lib/modules/SalesSummary/index.js +30 -4
  227. package/lib/modules/SalesSummary/types.d.ts +4 -1
  228. package/lib/modules/SalesSummary/utils.d.ts +2 -25
  229. package/lib/modules/SalesSummary/utils.js +645 -91
  230. package/lib/modules/Schedule/index.d.ts +7 -0
  231. package/lib/modules/Schedule/index.js +17 -1
  232. package/lib/modules/Summary/index.js +5 -4
  233. package/lib/modules/SurchargeList/index.d.ts +16 -0
  234. package/lib/modules/SurchargeList/index.js +89 -0
  235. package/lib/modules/SurchargeList/types.d.ts +11 -0
  236. package/lib/modules/SurchargeList/types.js +17 -0
  237. package/lib/modules/index.d.ts +2 -0
  238. package/lib/modules/index.js +5 -1
  239. package/lib/plugins/request.d.ts +1 -0
  240. package/lib/server/index.d.ts +204 -1
  241. package/lib/server/index.js +1891 -59
  242. package/lib/server/modules/index.d.ts +2 -0
  243. package/lib/server/modules/index.js +3 -0
  244. package/lib/server/modules/order/index.d.ts +120 -3
  245. package/lib/server/modules/order/index.js +883 -94
  246. package/lib/server/modules/order/types.d.ts +32 -3
  247. package/lib/server/modules/order/utils/filterBookings.js +24 -5
  248. package/lib/server/modules/order/utils/filterOrders.js +15 -6
  249. package/lib/server/modules/payment/index.d.ts +28 -0
  250. package/lib/server/modules/payment/index.js +192 -0
  251. package/lib/server/modules/payment/types.d.ts +9 -0
  252. package/lib/server/modules/payment/types.js +17 -0
  253. package/lib/server/modules/products/index.d.ts +34 -7
  254. package/lib/server/modules/products/index.js +189 -54
  255. package/lib/server/modules/resource/index.d.ts +2 -0
  256. package/lib/server/modules/resource/index.js +27 -3
  257. package/lib/server/modules/schedule/index.d.ts +4 -4
  258. package/lib/server/modules/schedule/index.js +47 -40
  259. package/lib/server/test.json +713 -0
  260. package/lib/server/utils/small-ticket.d.ts +71 -0
  261. package/lib/server/utils/small-ticket.js +800 -0
  262. package/lib/solution/BaseSales/index.d.ts +133 -10
  263. package/lib/solution/BaseSales/index.js +1111 -63
  264. package/lib/solution/BaseSales/types.d.ts +82 -6
  265. package/lib/solution/BaseSales/types.js +3 -1
  266. package/lib/solution/BaseSales/utils/cartPromotion.d.ts +287 -0
  267. package/lib/solution/BaseSales/utils/cartPromotion.js +992 -0
  268. package/lib/solution/BaseSales/utils/quotationPrice.d.ts +7 -0
  269. package/lib/solution/BaseSales/utils/quotationPrice.js +277 -0
  270. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
  271. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +106 -18
  272. package/lib/solution/BaseSales/utils.d.ts +1 -1
  273. package/lib/solution/BaseSales/utils.js +54 -10
  274. package/lib/solution/BookingByStep/index.d.ts +1 -1
  275. package/lib/solution/BookingTicket/index.d.ts +271 -11
  276. package/lib/solution/BookingTicket/index.js +922 -29
  277. package/lib/solution/BookingTicket/types.d.ts +118 -1
  278. package/lib/solution/BookingTicket/types.js +11 -0
  279. package/lib/solution/BookingTicket/utils/addProductDecision.d.ts +117 -0
  280. package/lib/solution/BookingTicket/utils/addProductDecision.js +318 -0
  281. package/lib/solution/BookingTicket/utils/addTimeAvailability.d.ts +35 -0
  282. package/lib/solution/BookingTicket/utils/addTimeAvailability.js +125 -0
  283. package/lib/solution/BookingTicket/utils/bookingStatus.d.ts +40 -0
  284. package/lib/solution/BookingTicket/utils/bookingStatus.js +44 -2
  285. package/lib/solution/BookingTicket/utils/cartView.d.ts +9 -1
  286. package/lib/solution/BookingTicket/utils/cartView.js +61 -6
  287. package/lib/solution/BookingTicket/utils/exampleData.d.ts +123 -0
  288. package/lib/solution/BookingTicket/utils/exampleData.js +0 -0
  289. package/lib/solution/BookingTicket/utils/resolveBestAddTimePlan.d.ts +185 -0
  290. package/lib/solution/BookingTicket/utils/resolveBestAddTimePlan.js +254 -0
  291. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +36 -0
  292. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +169 -0
  293. package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.d.ts +32 -0
  294. package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.js +51 -0
  295. package/lib/solution/BookingTicket/utils/scan/index.d.ts +5 -0
  296. package/lib/solution/BookingTicket/utils/scan/index.js +17 -3
  297. package/lib/solution/BookingTicket/utils/scan/scanProductValues.d.ts +21 -0
  298. package/lib/solution/BookingTicket/utils/scan/scanProductValues.js +127 -0
  299. package/lib/solution/BookingTicket/utils/sessionCatalogStale.d.ts +23 -0
  300. package/lib/solution/BookingTicket/utils/sessionCatalogStale.js +85 -0
  301. package/lib/solution/Checkout/index.d.ts +1 -0
  302. package/lib/solution/Checkout/index.js +1 -2
  303. package/lib/solution/RegisterAndLogin/config.js +2 -10
  304. package/lib/solution/ScanOrder/index.d.ts +9 -3
  305. package/lib/solution/ScanOrder/index.js +153 -70
  306. package/lib/solution/ScanOrder/types.d.ts +9 -5
  307. package/lib/solution/ScanOrder/utils.d.ts +1 -1
  308. package/lib/solution/ScanOrder/utils.js +83 -17
  309. package/lib/solution/VenueBooking/index.d.ts +5 -2
  310. package/lib/solution/VenueBooking/index.js +54 -17
  311. package/lib/solution/VenueBooking/sales-section-4-annotated.json +0 -2
  312. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +4 -0
  313. package/lib/solution/VenueBooking/utils/slotMerge.js +10 -0
  314. package/lib/types/index.d.ts +10 -0
  315. package/package.json +1 -1
  316. package/dist/solution/Checkout/appointmentDemo.json +0 -1
  317. package/lib/solution/Checkout/appointmentDemo.json +0 -1
@@ -37,37 +37,157 @@ var import_types = require("./types");
37
37
  var import_utils = require("./utils");
38
38
  var import_utils2 = require("../Product/utils");
39
39
  var import_dayjs = __toESM(require("dayjs"));
40
+ var import_cartPromotion = require("../../solution/BaseSales/utils/cartPromotion");
40
41
  var import_utils3 = require("../../solution/ScanOrder/utils");
42
+ var import_manualProductDiscount = require("./utils/manualProductDiscount");
41
43
  var import_Discount = require("../Discount");
42
44
  var import_Rules = require("../Rules");
43
45
  var import_types2 = require("../Rules/types");
44
46
  var import_decimal = __toESM(require("decimal.js"));
45
47
  var import_lodash_es = require("lodash-es");
46
- var LOCAL_ORDER_STORE_NAME = "orders";
48
+ function normalizeDiscountListSignature(discountList) {
49
+ return (discountList || []).map((item) => ({
50
+ type: (item == null ? void 0 : item.type) ?? "",
51
+ discount_id: (item == null ? void 0 : item.discount_id) ?? null,
52
+ order_discount_id: (item == null ? void 0 : item.order_discount_id) ?? null,
53
+ amount: new import_decimal.default(Number(item == null ? void 0 : item.amount) || 0).toFixed(2)
54
+ }));
55
+ }
56
+ function isSameDiscountList(left, right) {
57
+ if (!Array.isArray(left) || !Array.isArray(right))
58
+ return false;
59
+ return JSON.stringify(normalizeDiscountListSignature(left)) === JSON.stringify(
60
+ normalizeDiscountListSignature(right)
61
+ );
62
+ }
63
+ function isManualProductDiscountProduct(product) {
64
+ var _a, _b;
65
+ return ((_a = product == null ? void 0 : product.metadata) == null ? void 0 : _a.is_manual_discount) === true || ((_b = product == null ? void 0 : product.metadata) == null ? void 0 : _b.is_manual_discount) === 1 || ((product == null ? void 0 : product.discount_list) || []).some((item) => (item == null ? void 0 : item.type) === "product");
66
+ }
47
67
  var OrderModule = class extends import_BaseModule.BaseModule {
48
68
  constructor(name, version) {
49
69
  super(name || "order", version);
50
70
  this.defaultName = "order";
51
71
  this.defaultVersion = "1.0.0";
72
+ // ─── 促销/赠品 ────────────────────────────────────
73
+ /** 评估器引用;由 SalesSdkProvider 注入,未注入时 applyPromotion 静默跳过 */
74
+ this.promotionEvaluator = null;
75
+ /** 赠品选择 resolver;由 SDK host bridge 注入 */
76
+ this.giftSelectResolver = null;
77
+ /** applyPromotion 递归保护 flag(写路径同步调 applyPromotion,禁止重入) */
78
+ this.isApplyingPromotion = false;
79
+ /** 最近一次 applyPromotion 的未满足促销提示 */
80
+ this.lastUnfulfilledPromotions = [];
81
+ /** 最近一次 applyPromotion 的赠品操作 diff(debug / SDK 读取使用) */
82
+ this.lastGiftActions = null;
83
+ /**
84
+ * 是否将 tempOrder 写入 IndexedDB 草稿(orders store)。
85
+ * BigSale 弹窗等短生命周期场景通过 setEnableTempOrderPersist(false) 关闭。
86
+ */
87
+ this.draftPersistEnabled = true;
88
+ }
89
+ collectHydratedEditDiscounts(products) {
90
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
91
+ const discountMap = /* @__PURE__ */ new Map();
92
+ for (const product of products || []) {
93
+ for (const item of (product == null ? void 0 : product.discount_list) || []) {
94
+ const type = (item == null ? void 0 : item.type) ?? (item == null ? void 0 : item.tag);
95
+ if (!type || type === "product")
96
+ continue;
97
+ const resourceId = ((_a = item == null ? void 0 : item.discount) == null ? void 0 : _a.resource_id) ?? (item == null ? void 0 : item.resource_id) ?? (item == null ? void 0 : item.discount_id) ?? (item == null ? void 0 : item.order_discount_id);
98
+ if (resourceId === void 0 || resourceId === null || resourceId === "")
99
+ continue;
100
+ const id = Number(resourceId);
101
+ const key = Number.isFinite(id) ? id : String(resourceId);
102
+ const title = ((_b = item == null ? void 0 : item.discount) == null ? void 0 : _b.title) ?? {};
103
+ const amount = Number((item == null ? void 0 : item.amount) || 0);
104
+ const detail = {
105
+ amount: String((item == null ? void 0 : item.amount) ?? "0"),
106
+ type,
107
+ resource_id: key,
108
+ title,
109
+ original_amount: String(((_c = item == null ? void 0 : item.discount) == null ? void 0 : _c.original_amount) ?? (item == null ? void 0 : item.amount) ?? "0"),
110
+ num: Number(((_d = item == null ? void 0 : item.metadata) == null ? void 0 : _d.num) ?? (product == null ? void 0 : product.num) ?? (product == null ? void 0 : product.product_quantity) ?? 1) || 1,
111
+ metadata: item == null ? void 0 : item.metadata,
112
+ discount: item == null ? void 0 : item.discount,
113
+ _num: Number(((_e = item == null ? void 0 : item.metadata) == null ? void 0 : _e.num) ?? (product == null ? void 0 : product.num) ?? (product == null ? void 0 : product.product_quantity) ?? 1) || 1
114
+ };
115
+ discountMap.set(key, {
116
+ id: key,
117
+ product_name: "",
118
+ encoded: "",
119
+ code: "",
120
+ tag: type,
121
+ product_id: ((_f = item == null ? void 0 : item.discount) == null ? void 0 : _f.discount_product_id) ?? (product == null ? void 0 : product.product_id) ?? 0,
122
+ relation_type: "",
123
+ par_value: String(((_g = item == null ? void 0 : item.discount) == null ? void 0 : _g.original_amount) ?? (item == null ? void 0 : item.amount) ?? "0"),
124
+ used_par_value: String((item == null ? void 0 : item.amount) ?? "0"),
125
+ limit_status: "enable",
126
+ limited_relation_product_data: {
127
+ id: 0,
128
+ type: "products",
129
+ product_ids: [product == null ? void 0 : product.product_id].filter((value) => value !== void 0 && value !== null),
130
+ product_collection_id: [],
131
+ filter: 0,
132
+ exclude_product_ids: []
133
+ },
134
+ balance: String((item == null ? void 0 : item.amount) ?? "0"),
135
+ format_title: title,
136
+ product: {
137
+ id: (product == null ? void 0 : product.product_id) ?? 0,
138
+ title: "",
139
+ is_charge_tax: (product == null ? void 0 : product.is_charge_tax) ?? 0,
140
+ base_price: String((product == null ? void 0 : product.original_price) ?? (product == null ? void 0 : product.selling_price) ?? "0")
141
+ },
142
+ type,
143
+ resource_id: key,
144
+ isEditMode: true,
145
+ isSelected: true,
146
+ isAvailable: true,
147
+ isUsed: true,
148
+ isDisabled: true,
149
+ amount,
150
+ discount: {
151
+ ...(item == null ? void 0 : item.discount) || {},
152
+ resource_id: key,
153
+ discount_product_id: ((_h = item == null ? void 0 : item.discount) == null ? void 0 : _h.discount_product_id) ?? (product == null ? void 0 : product.product_id) ?? 0,
154
+ discount_calculation_mode: ((_i = item == null ? void 0 : item.discount) == null ? void 0 : _i.discount_calculation_mode) ?? "item_level"
155
+ },
156
+ applicableProductDetails: [detail],
157
+ appliedProductDetails: [detail]
158
+ });
159
+ }
160
+ }
161
+ return Array.from(discountMap.values());
52
162
  }
53
163
  /**
54
164
  * Populate `savedAmount` on each discount based on product-level discount details.
55
165
  * Only selected discounts get a non-zero value.
56
166
  */
57
167
  static populateSavedAmounts(productList, discountList) {
58
- var _a, _b;
59
168
  const savedMap = /* @__PURE__ */ new Map();
169
+ const addDiscountAmount = (discount, quantity) => {
170
+ var _a, _b;
171
+ const discountKey = ((_a = discount.discount) == null ? void 0 : _a.resource_id) || discount.id;
172
+ if (discountKey == null)
173
+ return;
174
+ const qty = Number(quantity) || 1;
175
+ const amount = new import_decimal.default(discount.amount || 0).times(qty).plus(((_b = discount.metadata) == null ? void 0 : _b.product_discount_difference) || 0);
176
+ savedMap.set(
177
+ discountKey,
178
+ (savedMap.get(discountKey) || new import_decimal.default(0)).plus(amount)
179
+ );
180
+ };
60
181
  for (const product of productList) {
61
182
  const qty = product.num || 1;
62
183
  for (const pd of product.discount_list || []) {
63
- const discountKey = ((_a = pd.discount) == null ? void 0 : _a.resource_id) || pd.id;
64
- if (discountKey == null)
65
- continue;
66
- const amount = new import_decimal.default(pd.amount || 0).times(qty).plus(((_b = pd.metadata) == null ? void 0 : _b.product_discount_difference) || 0);
67
- savedMap.set(
68
- discountKey,
69
- (savedMap.get(discountKey) || new import_decimal.default(0)).plus(amount)
70
- );
184
+ addDiscountAmount(pd, qty);
185
+ }
186
+ for (const bundle of product.product_bundle || []) {
187
+ const bundleQty = new import_decimal.default(Number(qty) || 1).times(Number((bundle == null ? void 0 : bundle.num) ?? (bundle == null ? void 0 : bundle.quantity) ?? 1) || 1).toNumber();
188
+ for (const pd of (bundle == null ? void 0 : bundle.discount_list) || []) {
189
+ addDiscountAmount(pd, bundleQty);
190
+ }
71
191
  }
72
192
  }
73
193
  for (const d of discountList) {
@@ -75,6 +195,32 @@ var OrderModule = class extends import_BaseModule.BaseModule {
75
195
  d.savedAmount = d.isSelected && key != null && savedMap.has(key) ? savedMap.get(key).toNumber() : 0;
76
196
  }
77
197
  }
198
+ applyProductDiscountPrices(products) {
199
+ return (products || []).map((product) => {
200
+ var _a, _b;
201
+ if (isManualProductDiscountProduct(product))
202
+ return product;
203
+ const discountItems = Array.isArray(product.discount_list) ? product.discount_list : [];
204
+ const hasOnlyPersistedDiscountSnapshots = product.order_detail_id !== void 0 && product.order_detail_id !== null && discountItems.length > 0 && discountItems.every((discount) => (discount == null ? void 0 : discount.order_discount_id) !== void 0 && (discount == null ? void 0 : discount.order_discount_id) !== null);
205
+ if (hasOnlyPersistedDiscountSnapshots) {
206
+ return product;
207
+ }
208
+ const totalPerUnitDiscount = (0, import_utils.resolveEffectivePerUnitDiscount)(product);
209
+ const optionSum = (0, import_utils.sumOptionUnitPrice)((0, import_utils.getProductSkuOptions)(product));
210
+ const sourcePrice = ((_a = product.metadata) == null ? void 0 : _a.source_product_price) ?? (((_b = product.metadata) == null ? void 0 : _b.main_product_original_price) != null ? new import_decimal.default(Number(product.metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? "0");
211
+ const newSourceSellingPrice = new import_decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount).toDecimalPlaces(2).toString();
212
+ const newMainSellingPrice = new import_decimal.default(Number(newSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
213
+ if (product.metadata) {
214
+ product.metadata.main_product_selling_price = newMainSellingPrice;
215
+ product.metadata.price_schema_version = 2;
216
+ }
217
+ product.selling_price = (0, import_utils.composeLinePrice)({
218
+ mainPrice: newMainSellingPrice,
219
+ bundle: product.product_bundle
220
+ });
221
+ return product;
222
+ });
223
+ }
78
224
  async initialize(core, options) {
79
225
  var _a, _b, _c;
80
226
  this.core = core;
@@ -92,18 +238,54 @@ var OrderModule = class extends import_BaseModule.BaseModule {
92
238
  }
93
239
  const app = appPlugin.getApp();
94
240
  this.logger = app.logger;
95
- this.dbManager = app.sqlite;
96
241
  this.window = this.core.getPlugin("window");
97
242
  const otherParams = options.otherParams || {};
98
243
  this.cacheId = otherParams.cacheId;
99
244
  this.salesSummaryModuleName = otherParams.salesSummaryModuleName;
100
245
  this.rulesHooksOverride = (_a = otherParams.rules) == null ? void 0 : _a.hooks;
101
- this.orderHooks = options.hooks || ((_b = otherParams.order) == null ? void 0 : _b.hooks) || ((_c = otherParams.hooks) == null ? void 0 : _c.order);
246
+ this.moduleHooksOverride = options.hooks;
247
+ this.orderHooks = this.moduleHooksOverride || ((_b = otherParams.order) == null ? void 0 : _b.hooks) || ((_c = otherParams.hooks) == null ? void 0 : _c.order);
102
248
  this.otherParams = otherParams;
103
249
  this.registerDiscountModules(options);
104
- this.restoreTempOrderFromStorage();
105
250
  this.logInfo("OrderModule initialized successfully");
106
251
  }
252
+ async destroy() {
253
+ var _a, _b;
254
+ const childModules = [(_a = this.store) == null ? void 0 : _a.discount, (_b = this.store) == null ? void 0 : _b.rules];
255
+ for (const childModule of childModules) {
256
+ if (!childModule || typeof childModule.destroy !== "function")
257
+ continue;
258
+ try {
259
+ await childModule.destroy();
260
+ } catch (error) {
261
+ const errorMessage = error instanceof Error ? error.message : String(error);
262
+ this.logWarning("Destroy child module failed", {
263
+ module: childModule.name,
264
+ error: errorMessage
265
+ });
266
+ }
267
+ }
268
+ if (this.store) {
269
+ this.store.discount = null;
270
+ this.store.rules = null;
271
+ }
272
+ super.destroy();
273
+ }
274
+ /**
275
+ * 更新父级解决方案透传的运行态参数,并同步 Order 内部依赖的派生字段。
276
+ *
277
+ * @example
278
+ * orderModule.updateOtherParams({ cacheId: 'cache-2', channel: 'pos' });
279
+ */
280
+ updateOtherParams(params) {
281
+ var _a, _b, _c;
282
+ const otherParams = params || {};
283
+ this.cacheId = otherParams.cacheId;
284
+ this.salesSummaryModuleName = otherParams.salesSummaryModuleName;
285
+ this.rulesHooksOverride = (_a = otherParams.rules) == null ? void 0 : _a.hooks;
286
+ this.orderHooks = this.moduleHooksOverride || ((_b = otherParams.order) == null ? void 0 : _b.hooks) || ((_c = otherParams.hooks) == null ? void 0 : _c.order);
287
+ this.otherParams = otherParams;
288
+ }
107
289
  /**
108
290
  * 记录信息日志
109
291
  */
@@ -174,26 +356,57 @@ var OrderModule = class extends import_BaseModule.BaseModule {
174
356
  }
175
357
  // ─── Discount: 公共 API ───
176
358
  async loadDiscountConfig(params) {
177
- var _a, _b, _c, _d;
178
- const discountList = await ((_a = this.store.discount) == null ? void 0 : _a.loadPrepareConfig({
359
+ var _a, _b, _c, _d, _e, _f, _g;
360
+ const orderId = params.orderId || ((_a = this.store.tempOrder) == null ? void 0 : _a.order_id) || void 0;
361
+ const discountList = await ((_b = this.store.discount) == null ? void 0 : _b.loadPrepareConfig({
179
362
  customer_id: params.customerId,
180
- action: params.action || "create",
363
+ action: params.action || (orderId ? "edit" : "create"),
181
364
  with_good_pass: 1,
182
365
  with_discount_card: 1,
183
366
  with_wallet_pass_holder: 1,
184
- request_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
367
+ request_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
368
+ ...orderId ? { order_id: orderId } : {}
185
369
  }));
186
370
  if (discountList) {
187
- (_b = this.store.discount) == null ? void 0 : _b.setDiscountList(discountList);
371
+ const currentEditDiscounts = (((_c = this.store.discount) == null ? void 0 : _c.getDiscountList()) || []).filter((discount) => discount == null ? void 0 : discount.isEditMode);
372
+ const currentEditDiscountIds = new Set(
373
+ currentEditDiscounts.map((discount) => discount == null ? void 0 : discount.id)
374
+ );
375
+ const mergedDiscountList = [
376
+ ...currentEditDiscounts,
377
+ ...discountList.filter((discount) => !currentEditDiscountIds.has(discount == null ? void 0 : discount.id))
378
+ ];
379
+ await ((_d = this.store.discount) == null ? void 0 : _d.setOriginalDiscountList(mergedDiscountList));
380
+ await ((_e = this.store.discount) == null ? void 0 : _e.setDiscountList(mergedDiscountList));
188
381
  }
189
- if ((_d = (_c = this.store.tempOrder) == null ? void 0 : _c.products) == null ? void 0 : _d.length) {
382
+ if (params.apply !== false && ((_g = (_f = this.store.tempOrder) == null ? void 0 : _f.products) == null ? void 0 : _g.length)) {
190
383
  this.applyDiscount();
191
384
  }
385
+ return this.getDiscountList();
192
386
  }
193
387
  getDiscountList() {
194
388
  var _a;
195
389
  return ((_a = this.store.discount) == null ? void 0 : _a.getDiscountList()) || [];
196
390
  }
391
+ async ensureEditDiscountConfigForProductChange(tempOrder) {
392
+ var _a, _b, _c, _d, _e, _f;
393
+ const orderId = tempOrder.order_id;
394
+ const customerId = Number(
395
+ tempOrder.customer_id || ((_a = tempOrder.customer) == null ? void 0 : _a.id) || ((_c = (_b = tempOrder._extend) == null ? void 0 : _b.customerSnapshot) == null ? void 0 : _c.id) || ((_e = (_d = tempOrder._extend) == null ? void 0 : _d.customerSnapshot) == null ? void 0 : _e.customer_id) || 0
396
+ );
397
+ if (!orderId || !customerId || customerId === 1)
398
+ return;
399
+ const currentDiscountList = ((_f = this.store.discount) == null ? void 0 : _f.getDiscountList()) || [];
400
+ const hasRuntimeDiscounts = currentDiscountList.some((discount) => !(discount == null ? void 0 : discount.isEditMode));
401
+ if (hasRuntimeDiscounts)
402
+ return;
403
+ await this.loadDiscountConfig({
404
+ customerId,
405
+ action: "edit",
406
+ orderId: Number(orderId),
407
+ apply: false
408
+ });
409
+ }
197
410
  async scanCode(code, customerId) {
198
411
  var _a, _b, _c, _d, _e;
199
412
  const resultDiscountWithReason = await ((_a = this.store.discount) == null ? void 0 : _a.batchSearch(code, { customerId })) || { discountList: [], unavailableReasonKey: null };
@@ -204,6 +417,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
204
417
  type: "clientCalc",
205
418
  isAvailable: false,
206
419
  discountList: this.getDiscountList(),
420
+ scannedDiscountList: resultDiscountList,
207
421
  unavailableReason: import_types2.UnavailableReason.Unknown
208
422
  };
209
423
  }
@@ -212,6 +426,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
212
426
  type: "server",
213
427
  isAvailable: false,
214
428
  discountList: this.getDiscountList(),
429
+ scannedDiscountList: resultDiscountList,
215
430
  unavailableReasonKey
216
431
  };
217
432
  }
@@ -224,7 +439,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
224
439
  return {
225
440
  type: "clientCalc",
226
441
  isAvailable: true,
227
- discountList: this.getDiscountList()
442
+ discountList: this.getDiscountList(),
443
+ scannedDiscountList: resultDiscountList
228
444
  };
229
445
  }
230
446
  const tempOrder = this.store.tempOrder;
@@ -245,6 +461,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
245
461
  type: "clientCalc",
246
462
  isAvailable: isAvailable || false,
247
463
  discountList: newDiscountList || this.getDiscountList(),
464
+ scannedDiscountList: resultDiscountList,
248
465
  unavailableReason
249
466
  };
250
467
  }
@@ -253,6 +470,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
253
470
  const tempOrder = this.store.tempOrder;
254
471
  if (!tempOrder)
255
472
  return;
473
+ delete tempOrder.discount_list;
256
474
  const rulesModule = this.store.rules;
257
475
  if (!rulesModule)
258
476
  return;
@@ -266,7 +484,26 @@ var OrderModule = class extends import_BaseModule.BaseModule {
266
484
  orderTotalAmount: Number(((_d = this.store.summary) == null ? void 0 : _d.total_amount) || 0)
267
485
  });
268
486
  if (result == null ? void 0 : result.productList) {
269
- tempOrder.products = result.productList;
487
+ const previousProductsByUid = (0, import_utils.indexOrderProductsByUid)(tempOrder.products);
488
+ tempOrder.products = this.applyProductDiscountPrices(
489
+ (result.productList || []).map((product, index) => {
490
+ const uid = (0, import_utils.getOrderProductLineUid)(product);
491
+ const previous = (uid ? previousProductsByUid.get(uid) : void 0) ?? previousProductsByUid.get(`__index__:${index}`);
492
+ if (isManualProductDiscountProduct(previous)) {
493
+ return previous;
494
+ }
495
+ const mergedProduct = previous ? (0, import_utils.mergeOrderProductDisplayFields)(previous, product) : product;
496
+ return {
497
+ ...mergedProduct,
498
+ discount_list: (0, import_utils.normalizeOrderProductDiscountList)(
499
+ (0, import_manualProductDiscount.syncManualProductDiscountProductNum)(
500
+ mergedProduct.discount_list,
501
+ mergedProduct.num
502
+ )
503
+ )
504
+ };
505
+ })
506
+ );
270
507
  }
271
508
  if (result == null ? void 0 : result.discountList) {
272
509
  OrderModule.populateSavedAmounts(
@@ -274,80 +511,201 @@ var OrderModule = class extends import_BaseModule.BaseModule {
274
511
  result.discountList
275
512
  );
276
513
  (_e = this.store.discount) == null ? void 0 : _e.setDiscountList(result.discountList);
277
- tempOrder.discount_list = result.discountList.filter(
278
- (d) => d.isSelected
279
- );
280
514
  }
281
515
  }
282
- // ─── TempOrder: 初始化入口 ───
283
- initTempOrder(params) {
284
- if (params.cacheId !== void 0)
285
- this.cacheId = params.cacheId;
286
- if (params.salesSummaryModuleName !== void 0)
287
- this.salesSummaryModuleName = params.salesSummaryModuleName;
288
- this.restoreTempOrderFromStorage();
516
+ // ─── 促销/赠品 ──────────────────────────────────────
517
+ /**
518
+ * 注入促销评估器。
519
+ *
520
+ * @example
521
+ * order.setPromotionEvaluator(appHelper.utils.promotionEvaluator);
522
+ */
523
+ setPromotionEvaluator(evaluator) {
524
+ this.promotionEvaluator = evaluator || null;
289
525
  }
290
- // ─── TempOrder: localStorage 持久化 ───
291
- getTempOrderStorageKey() {
292
- if (!this.cacheId)
293
- return null;
294
- return `scanOrder:tempOrder:${this.cacheId}`;
526
+ /**
527
+ * 注入赠品选择 resolver。OS 需要补赠品时会 await 调用 resolver;缺省时跳过新增并 console.warn。
528
+ *
529
+ * @example
530
+ * order.setGiftSelectResolver(async (ctx) => {
531
+ * // SDK 内部决定弹窗 or 自动选第一项,返回完整 OrderProduct[]
532
+ * return giftSelectBridge.request(ctx);
533
+ * });
534
+ */
535
+ setGiftSelectResolver(resolver) {
536
+ this.giftSelectResolver = resolver || null;
295
537
  }
296
- restoreTempOrderFromStorage() {
297
- var _a, _b;
298
- const key = this.getTempOrderStorageKey();
299
- if (!key)
538
+ /**
539
+ * 为商品目录追加促销标签,供上层 Sales 门面复用。
540
+ *
541
+ * @example
542
+ * const products = order.appendPromotionTags(catalogProducts);
543
+ */
544
+ appendPromotionTags(products) {
545
+ return (0, import_cartPromotion.appendPromotionTags)(products, this.promotionEvaluator);
546
+ }
547
+ /**
548
+ * 应用购物车促销:计算 → 差异化赠品 → 写回 tempOrder.products → emit onPromotionApplied。
549
+ *
550
+ * 调用时机:写路径(add/update/remove/clear/setCustomer)末尾自动触发;外部一般无需手动调。
551
+ *
552
+ * 关键约束:
553
+ * - 不调用任何公开 CRUD API(如 removeProductFromOrder),全部内部 mutate tempOrder.products,避免事件风暴;
554
+ * - 用 `isApplyingPromotion` 防递归;
555
+ * - 多选项赠品依赖 giftSelectResolver,未注入则跳过且 console.warn;
556
+ * - 不主动调用 applyDiscount / recalculateSummary,调用方负责跟进。
557
+ */
558
+ async applyPromotion() {
559
+ var _a;
560
+ if (this.isApplyingPromotion) {
300
561
  return;
301
- if (!this.window)
562
+ }
563
+ if (!this.promotionEvaluator) {
302
564
  return;
303
- const cachedData = this.window.localStorage.getItem(key);
304
- if (!cachedData)
565
+ }
566
+ const tempOrder = this.store.tempOrder;
567
+ if (!tempOrder) {
305
568
  return;
569
+ }
570
+ this.isApplyingPromotion = true;
306
571
  try {
307
- const parsedData = JSON.parse(cachedData);
308
- if (!(0, import_utils.isTempOrder)(parsedData)) {
309
- this.window.localStorage.removeItem(key);
310
- return;
572
+ const result = (0, import_cartPromotion.processCartPromotion)(
573
+ tempOrder.products,
574
+ this.promotionEvaluator
575
+ );
576
+ if (result.giftActions.toRemove.length > 0) {
577
+ const removeSet = new Set(result.giftActions.toRemove.map(String));
578
+ result.products = result.products.filter((p) => {
579
+ const uid = (0, import_cartPromotion.getOrderProductUid)(p);
580
+ return uid ? !removeSet.has(String(uid)) : true;
581
+ });
311
582
  }
312
- if (Array.isArray(parsedData.products)) {
313
- for (let i = 0; i < parsedData.products.length; i++) {
314
- const p = parsedData.products[i];
315
- if (!p || typeof p !== "object")
316
- continue;
317
- if (!Array.isArray(p.product_option_item)) {
318
- p.product_option_item = [];
319
- }
320
- if (!Array.isArray(p.product_bundle)) {
321
- p.product_bundle = [];
583
+ for (const reduce of result.giftActions.toReduce) {
584
+ for (const item of reduce.items) {
585
+ const product = result.products.find(
586
+ (p) => (0, import_cartPromotion.getOrderProductUid)(p) === item.uid
587
+ );
588
+ if (product) {
589
+ product.num = item.newQuantity;
322
590
  }
323
- const row = p;
324
- parsedData.products[i] = (0, import_utils3.normalizeOrderProduct)(row);
325
591
  }
326
592
  }
327
- const parsedRecord = parsedData;
328
- this.store.summary = parsedRecord.summary || (0, import_utils.createEmptySummary)();
329
- delete parsedData.summary;
330
- if (parsedRecord.lastOrderInfo) {
331
- this.store.lastOrderInfo = parsedRecord.lastOrderInfo;
332
- delete parsedData.lastOrderInfo;
333
- }
334
- if (!parsedData._extend || typeof parsedData._extend !== "object") {
335
- parsedData._extend = { productsByUid: {} };
336
- } else if (!parsedData._extend.productsByUid) {
337
- parsedData._extend.productsByUid = {};
593
+ if (result.giftActions.toAdd.length > 0) {
594
+ if (!this.giftSelectResolver) {
595
+ if (result.giftActions.toAdd.some((g) => g.giftOptions.length > 1)) {
596
+ console.warn(
597
+ "[OrderModule] giftSelectResolver not set, skip applying gifts",
598
+ result.giftActions.toAdd
599
+ );
600
+ } else {
601
+ console.warn(
602
+ "[OrderModule] giftSelectResolver not set, skip applying single-option gifts",
603
+ result.giftActions.toAdd
604
+ );
605
+ }
606
+ } else {
607
+ for (const addAction of result.giftActions.toAdd) {
608
+ if (addAction.giftOptions.length === 1) {
609
+ const sameStrategy = result.products.find(
610
+ (p) => {
611
+ var _a2, _b;
612
+ return ((_b = (_a2 = p.metadata) == null ? void 0 : _a2._giftInfo) == null ? void 0 : _b.strategyId) === addAction.strategyId;
613
+ }
614
+ );
615
+ if (sameStrategy && !sameStrategy.booking_uid && !((_a = sameStrategy.metadata) == null ? void 0 : _a.booking_uid)) {
616
+ sameStrategy.num = (Number(sameStrategy.num) || 0) + (addAction.giftCount || 1);
617
+ continue;
618
+ }
619
+ }
620
+ try {
621
+ const giftResult = await this.giftSelectResolver({
622
+ strategyId: addAction.strategyId,
623
+ strategyName: addAction.strategyName,
624
+ giftCount: addAction.giftCount,
625
+ giftOptions: addAction.giftOptions,
626
+ sourceProductIds: addAction.sourceProductIds
627
+ });
628
+ const giftProducts = Array.isArray(giftResult) ? giftResult : giftResult == null ? void 0 : giftResult.products;
629
+ const giftBookings = Array.isArray(giftResult) ? [] : (giftResult == null ? void 0 : giftResult.bookings) || [];
630
+ if (Array.isArray(giftProducts) && giftProducts.length > 0) {
631
+ for (const [index, gp] of giftProducts.entries()) {
632
+ if (!gp)
633
+ continue;
634
+ const booking = giftBookings[index];
635
+ if (booking) {
636
+ const linked = this.createLinkedProductAndBooking({
637
+ product: gp,
638
+ booking
639
+ });
640
+ result.products.push(linked.product);
641
+ tempOrder.bookings = [...tempOrder.bookings || [], linked.booking];
642
+ continue;
643
+ }
644
+ result.products.push(gp);
645
+ }
646
+ }
647
+ } catch (error) {
648
+ console.warn(
649
+ "[OrderModule] giftSelectResolver rejected, skip add gift",
650
+ addAction.strategyId,
651
+ error
652
+ );
653
+ }
654
+ }
655
+ }
338
656
  }
339
- this.store.tempOrder = parsedData;
340
- } catch {
341
- (_b = (_a = this.window) == null ? void 0 : _a.localStorage) == null ? void 0 : _b.removeItem(key);
657
+ tempOrder.products = result.products;
658
+ this.lastUnfulfilledPromotions = result.unfulfilledPromotions;
659
+ this.lastGiftActions = result.giftActions;
660
+ const payload = {
661
+ unfulfilledPromotions: result.unfulfilledPromotions,
662
+ giftActions: result.giftActions,
663
+ gifts: result.gifts.map((g) => ({
664
+ strategyId: g.strategyId,
665
+ strategyName: g.strategyName,
666
+ giftCount: g.giftCount,
667
+ giftOptions: g.giftOptions
668
+ })),
669
+ products: tempOrder.products
670
+ };
671
+ this.effectsEmit("onPromotionApplied", payload);
672
+ } catch (error) {
673
+ console.error("[OrderModule] applyPromotion failed", error);
674
+ } finally {
675
+ this.isApplyingPromotion = false;
342
676
  }
343
677
  }
678
+ /** 最近一次 applyPromotion 输出的未满足促销列表 */
679
+ getUnfulfilledPromotions() {
680
+ return this.lastUnfulfilledPromotions;
681
+ }
682
+ /** 最近一次 applyPromotion 输出的赠品操作 diff */
683
+ getLastGiftActions() {
684
+ return this.lastGiftActions;
685
+ }
686
+ // ─── TempOrder: 初始化入口 ───
687
+ initTempOrder(params) {
688
+ if (params.cacheId !== void 0)
689
+ this.cacheId = params.cacheId;
690
+ if (params.salesSummaryModuleName !== void 0)
691
+ this.salesSummaryModuleName = params.salesSummaryModuleName;
692
+ }
693
+ /**
694
+ * 控制 IndexedDB 草稿(saveDraft)是否写入。
695
+ * localStorage 版 tempOrder 持久化已废弃,此方法仅影响 saveDraft。
696
+ *
697
+ * @example
698
+ * order.setEnableTempOrderPersist(false); // BigSale 弹窗:跳过 ~1s 的 dbUpdate
699
+ */
700
+ setEnableTempOrderPersist(enabled) {
701
+ this.draftPersistEnabled = enabled;
702
+ }
703
+ /** 是否允许 saveDraft 写入 IndexedDB 草稿。 */
704
+ isTempOrderPersistEnabled() {
705
+ return this.draftPersistEnabled;
706
+ }
707
+ /** @deprecated OrderModule 不再负责 tempOrder localStorage 持久化;草稿保存请使用 IndexedDB saveDraft。 */
344
708
  persistTempOrder() {
345
- const key = this.getTempOrderStorageKey();
346
- if (!key || !this.store.tempOrder)
347
- return;
348
- if (!this.window)
349
- return;
350
- this.window.localStorage.setItem(key, JSON.stringify(this.store.tempOrder));
351
709
  }
352
710
  // ─── TempOrder: 创建 & 获取 ───
353
711
  createDefaultTempOrderInstance() {
@@ -391,107 +749,18 @@ var OrderModule = class extends import_BaseModule.BaseModule {
391
749
  }
392
750
  return tempOrder.request_unique_idempotency_token;
393
751
  }
394
- hasLocalDatabase() {
395
- return !!this.dbManager;
396
- }
397
- buildLocalOrderRecord(tempOrder) {
398
- const externalSaleNumber = this.ensureExternalSaleNumber(tempOrder);
399
- return {
400
- ...tempOrder,
401
- id: tempOrder.order_id ?? externalSaleNumber,
402
- external_sale_number: externalSaleNumber,
403
- summary: this.store.summary || (0, import_utils.createEmptySummary)(),
404
- lastOrderInfo: this.store.lastOrderInfo
405
- };
406
- }
407
- async getLocalOrderByOrderId(orderId) {
408
- var _a, _b, _c, _d;
409
- if (!this.dbManager || orderId === void 0 || orderId === null)
410
- return null;
411
- try {
412
- const direct = await ((_b = (_a = this.dbManager).get) == null ? void 0 : _b.call(
413
- _a,
414
- LOCAL_ORDER_STORE_NAME,
415
- orderId
416
- ));
417
- if (direct)
418
- return direct;
419
- const orders = await ((_d = (_c = this.dbManager).getAll) == null ? void 0 : _d.call(_c, LOCAL_ORDER_STORE_NAME));
420
- return (orders || []).find(
421
- (order) => String(order == null ? void 0 : order.order_id) === String(orderId)
422
- ) || null;
423
- } catch (error) {
424
- this.logWarning("getLocalOrderByOrderId failed", {
425
- orderId,
426
- error: error instanceof Error ? error.message : String(error)
427
- });
428
- return null;
429
- }
430
- }
431
- async getLocalOrderByOrderNumber(orderNumber) {
432
- var _a, _b, _c, _d;
433
- if (!this.dbManager || !orderNumber)
434
- return null;
435
- try {
436
- const direct = await ((_b = (_a = this.dbManager).get) == null ? void 0 : _b.call(
437
- _a,
438
- LOCAL_ORDER_STORE_NAME,
439
- orderNumber
440
- ));
441
- if (direct)
442
- return direct;
443
- const orders = await ((_d = (_c = this.dbManager).getAll) == null ? void 0 : _d.call(_c, LOCAL_ORDER_STORE_NAME));
444
- return (orders || []).find(
445
- (order) => String(order == null ? void 0 : order.order_number) === String(orderNumber)
446
- ) || null;
447
- } catch (error) {
448
- this.logWarning("getLocalOrderByOrderNumber failed", {
449
- orderNumber,
450
- error: error instanceof Error ? error.message : String(error)
451
- });
452
- return null;
453
- }
454
- }
455
- async getLocalOrderByExternalSaleNumber(externalSaleNumber) {
456
- var _a, _b, _c, _d;
457
- if (!this.dbManager || !externalSaleNumber)
458
- return null;
459
- try {
460
- const direct = await ((_b = (_a = this.dbManager).get) == null ? void 0 : _b.call(
461
- _a,
462
- LOCAL_ORDER_STORE_NAME,
463
- externalSaleNumber
464
- ));
465
- if (direct)
466
- return direct;
467
- const orders = await ((_d = (_c = this.dbManager).getAll) == null ? void 0 : _d.call(_c, LOCAL_ORDER_STORE_NAME));
468
- return (orders || []).find(
469
- (order) => String(order == null ? void 0 : order.external_sale_number) === String(externalSaleNumber)
470
- ) || null;
471
- } catch (error) {
472
- this.logWarning("getLocalOrderByExternalSaleNumber failed", {
473
- externalSaleNumber,
474
- error: error instanceof Error ? error.message : String(error)
475
- });
476
- return null;
477
- }
752
+ buildPaymentSyncIdempotencyToken(tempOrder, payments) {
753
+ const baseToken = this.ensureRequestUniqueIdempotencyToken(tempOrder);
754
+ const paidPaymentsCount = (payments || []).filter((payment) => {
755
+ return String((payment == null ? void 0 : payment.status) || "").toLowerCase() === "paid";
756
+ }).length;
757
+ const paidCount = paidPaymentsCount > 0 ? paidPaymentsCount : payments.length;
758
+ return `${baseToken}_payment_${paidCount}`;
478
759
  }
479
760
  async saveDraft() {
480
- var _a, _b;
481
- if (!this.dbManager)
482
- return;
483
- const tempOrder = this.ensureTempOrder();
484
- const record = this.buildLocalOrderRecord(tempOrder);
485
- try {
486
- await ((_b = (_a = this.dbManager).update) == null ? void 0 : _b.call(_a, LOCAL_ORDER_STORE_NAME, record));
487
- } catch (error) {
488
- this.logWarning("saveDraft failed", {
489
- externalSaleNumber: tempOrder.external_sale_number,
490
- orderNumber: tempOrder.order_number,
491
- orderId: tempOrder.order_id,
492
- error: error instanceof Error ? error.message : String(error)
493
- });
494
- }
761
+ }
762
+ saveDraftInBackground() {
763
+ void this.saveDraft();
495
764
  }
496
765
  async hydrateTempOrderFromLocalRecord(record) {
497
766
  return this.hydrateTempOrderFromRecord(record);
@@ -500,15 +769,208 @@ var OrderModule = class extends import_BaseModule.BaseModule {
500
769
  var _a, _b;
501
770
  return ((_a = result == null ? void 0 : result.data) == null ? void 0 : _a.order_id) ?? (result == null ? void 0 : result.order_id) ?? ((_b = result == null ? void 0 : result.data) == null ? void 0 : _b.id) ?? (result == null ? void 0 : result.id) ?? null;
502
771
  }
772
+ calculatePaymentEffectiveAmount(payment) {
773
+ const amount = new import_decimal.default(payment.amount || 0).minus(new import_decimal.default(payment.service_fee || 0));
774
+ const rounding = new import_decimal.default(payment.rounding_amount || 0);
775
+ return amount.minus(rounding);
776
+ }
503
777
  calculatePaymentTotal(payments) {
504
778
  return (0, import_utils.mapPaymentItemsToOrderPayments)(payments, {
505
779
  includeVoided: false
506
780
  }).reduce((sum, payment) => {
507
- const amount = new import_decimal.default(payment.amount || 0);
508
- const rounding = new import_decimal.default(payment.rounding_amount || 0);
509
- return sum.plus(amount.minus(rounding));
781
+ return sum.plus(this.calculatePaymentEffectiveAmount(payment));
782
+ }, new import_decimal.default(0));
783
+ }
784
+ getDepositAmount(tempOrder, summary) {
785
+ return new import_decimal.default(summary.deposit_amount || tempOrder.deposit_amount || "0.00");
786
+ }
787
+ normalizeDepositAmount(amount) {
788
+ return import_decimal.default.max(new import_decimal.default(Number(amount) || 0), 0).toDecimalPlaces(2).toFixed(2);
789
+ }
790
+ applyDepositAmountToSummary(tempOrder, summary, amount) {
791
+ const depositAmount = this.normalizeDepositAmount(amount);
792
+ const hasDepositAmount = new import_decimal.default(depositAmount).gt(0);
793
+ const existedDeposit = summary.deposit && typeof summary.deposit === "object" ? summary.deposit : void 0;
794
+ const nextSummary = {
795
+ ...summary,
796
+ deposit_amount: depositAmount,
797
+ deposit: hasDepositAmount ? {
798
+ ...existedDeposit || {},
799
+ total: depositAmount,
800
+ deposit_policy_ids: (existedDeposit == null ? void 0 : existedDeposit.deposit_policy_ids) || [],
801
+ hasDeposit: true
802
+ } : void 0
803
+ };
804
+ tempOrder.deposit_amount = depositAmount;
805
+ tempOrder.is_deposit = hasDepositAmount ? 1 : 0;
806
+ return nextSummary;
807
+ }
808
+ isDepositOrder(tempOrder, depositAmount) {
809
+ return tempOrder.is_deposit === 1 || depositAmount.gt(0);
810
+ }
811
+ getOrderExpectedAmount(summary) {
812
+ return new import_decimal.default(summary.expect_amount || summary.total_amount || 0);
813
+ }
814
+ isDepositCovered(params) {
815
+ const depositAmount = this.getDepositAmount(params.tempOrder, params.summary);
816
+ if (!this.isDepositOrder(params.tempOrder, depositAmount))
817
+ return false;
818
+ if (depositAmount.lte(0))
819
+ return false;
820
+ return params.paidAmount.gte(depositAmount);
821
+ }
822
+ calculateDepositPaidAmount(payments) {
823
+ return (payments || []).reduce((sum, payment) => {
824
+ const paymentRecord = payment;
825
+ if ((paymentRecord == null ? void 0 : paymentRecord.status) !== "paid")
826
+ return sum;
827
+ const isDepositPayment = paymentRecord.type === "deposit" || paymentRecord.order_payment_type === "deposit";
828
+ if (!isDepositPayment)
829
+ return sum;
830
+ if (paymentRecord.origin_amount !== void 0 && paymentRecord.origin_amount !== null && paymentRecord.origin_amount !== "") {
831
+ return sum.plus(this.calculatePaymentGapAmount(paymentRecord));
832
+ }
833
+ const rounding = new import_decimal.default(paymentRecord.rounding_amount || 0);
834
+ return sum.plus(new import_decimal.default(paymentRecord.amount || 0).minus(rounding));
510
835
  }, new import_decimal.default(0));
511
836
  }
837
+ resolveNextOrderPaymentType(tempOrder) {
838
+ const depositAmount = new import_decimal.default(tempOrder.deposit_amount || "0.00");
839
+ if (!this.isDepositOrder(tempOrder, depositAmount))
840
+ return "normal";
841
+ if (depositAmount.lte(0))
842
+ return "normal";
843
+ const depositPaidAmount = this.calculateDepositPaidAmount(tempOrder.payments || []);
844
+ return depositPaidAmount.lt(depositAmount) ? "deposit" : "normal";
845
+ }
846
+ normalizePaymentSource(payment, options) {
847
+ const paymentRecord = payment;
848
+ const metadata = paymentRecord.metadata && typeof paymentRecord.metadata === "object" ? { ...paymentRecord.metadata } : {};
849
+ if (!metadata.unique_payment_number) {
850
+ metadata.unique_payment_number = (0, import_utils.createUuidV4)();
851
+ }
852
+ const normalized = {
853
+ ...paymentRecord,
854
+ metadata,
855
+ origin_amount: paymentRecord.origin_amount ?? paymentRecord.amount ?? "0.00"
856
+ };
857
+ if (paymentRecord.status !== void 0) {
858
+ normalized.status = paymentRecord.status;
859
+ } else if ((options == null ? void 0 : options.defaultPaid) !== false) {
860
+ normalized.status = "paid";
861
+ }
862
+ return normalized;
863
+ }
864
+ updateTempOrderPaymentStatus(tempOrder, options) {
865
+ const summary = (options == null ? void 0 : options.summary) || this.store.summary || (0, import_utils.createEmptySummary)();
866
+ const paymentTotal = this.calculatePaymentTotal(tempOrder.payments || []);
867
+ const refundAmount = this.getSummaryRefundAmount(summary);
868
+ const netPaymentTotal = import_decimal.default.max(paymentTotal.minus(refundAmount), 0);
869
+ const targetAmount = this.calculatePaymentTargetAmount(
870
+ tempOrder,
871
+ summary,
872
+ netPaymentTotal
873
+ );
874
+ if (this.shouldKeepPaymentStatusAfterAmountRecalc(tempOrder.payment_status, {
875
+ netPaymentTotal,
876
+ paymentTotal,
877
+ refundAmount,
878
+ targetAmount,
879
+ previousSummary: options == null ? void 0 : options.previousSummary,
880
+ tempOrder
881
+ })) {
882
+ return;
883
+ }
884
+ if (targetAmount.lte(0)) {
885
+ tempOrder.payment_status = "paid";
886
+ return;
887
+ }
888
+ if (netPaymentTotal.lte(0)) {
889
+ tempOrder.payment_status = "payment_processing";
890
+ return;
891
+ }
892
+ tempOrder.payment_status = netPaymentTotal.gte(targetAmount) ? "paid" : "partially_paid";
893
+ }
894
+ shouldKeepPaymentStatusAfterAmountRecalc(paymentStatus, params) {
895
+ const normalizedStatus = String(paymentStatus || "").trim().toLowerCase();
896
+ if (normalizedStatus !== "refunded" && normalizedStatus !== "partially_refunded") {
897
+ return false;
898
+ }
899
+ if (params.refundAmount.lte(0))
900
+ return false;
901
+ if (params.previousSummary) {
902
+ const previousTargetAmount = this.calculatePaymentTargetAmount(
903
+ params.tempOrder,
904
+ params.previousSummary,
905
+ params.netPaymentTotal
906
+ );
907
+ if (!previousTargetAmount.eq(params.targetAmount))
908
+ return false;
909
+ }
910
+ if (normalizedStatus === "refunded") {
911
+ return params.refundAmount.gte(params.paymentTotal);
912
+ }
913
+ return params.netPaymentTotal.gte(params.targetAmount);
914
+ }
915
+ resolveWalletPassUseValue(payment, amount) {
916
+ const usageUnit = payment.wallet_pass_usage_unit && typeof payment.wallet_pass_usage_unit === "object" ? payment.wallet_pass_usage_unit : null;
917
+ if (!usageUnit)
918
+ return payment.wallet_pass_use_value;
919
+ const price = new import_decimal.default(usageUnit.price || 0);
920
+ const points = new import_decimal.default(usageUnit.points || 0);
921
+ if (price.lte(0) || points.lte(0))
922
+ return payment.wallet_pass_use_value;
923
+ return amount.div(price).times(points).toDecimalPlaces(2).toFixed(2);
924
+ }
925
+ adjustVoucherFundRecord(params) {
926
+ var _a;
927
+ const fundRecord = params.voucher.fund_record && typeof params.voucher.fund_record === "object" && !Array.isArray(params.voucher.fund_record) ? { ...params.voucher.fund_record } : null;
928
+ if (!fundRecord || fundRecord.using_before_value === void 0 || fundRecord.using_before_value === null) {
929
+ return fundRecord || void 0;
930
+ }
931
+ const code = String(params.voucher.code || "").toUpperCase();
932
+ const isPointCard = code === "POINTCARD" || String(((_a = params.voucher.fund_record) == null ? void 0 : _a.tag) || "").toLowerCase() === "point_card";
933
+ const usingValue = isPointCard ? new import_decimal.default(params.walletPassUseValue || 0) : params.amount;
934
+ fundRecord.using_after_value = new import_decimal.default(fundRecord.using_before_value || 0).minus(usingValue).toDecimalPlaces(2).toFixed(2);
935
+ return fundRecord;
936
+ }
937
+ capVoucherPaymentsByRemainingAmount(params) {
938
+ const targetAmount = this.getPaymentTargetAmount();
939
+ const nonVoucherTotal = this.calculatePaymentTotal(params.nonVoucherPayments);
940
+ if (targetAmount.lte(0))
941
+ return [];
942
+ let remainingAmount = import_decimal.default.max(
943
+ targetAmount.minus(nonVoucherTotal),
944
+ 0
945
+ );
946
+ const cappedVouchers = [];
947
+ for (const voucher of params.vouchers) {
948
+ if (remainingAmount.lte(0))
949
+ break;
950
+ const voucherAmount = import_decimal.default.max(new import_decimal.default(voucher.amount || 0), 0);
951
+ if (voucherAmount.lte(0))
952
+ continue;
953
+ const cappedAmount = import_decimal.default.min(voucherAmount, remainingAmount);
954
+ const amountText = cappedAmount.toDecimalPlaces(2).toFixed(2);
955
+ const walletPassUseValue = this.resolveWalletPassUseValue(
956
+ voucher,
957
+ cappedAmount
958
+ );
959
+ cappedVouchers.push({
960
+ ...voucher,
961
+ amount: amountText,
962
+ origin_amount: amountText,
963
+ wallet_pass_use_value: walletPassUseValue,
964
+ fund_record: this.adjustVoucherFundRecord({
965
+ voucher,
966
+ amount: cappedAmount,
967
+ walletPassUseValue
968
+ })
969
+ });
970
+ remainingAmount = remainingAmount.minus(cappedAmount);
971
+ }
972
+ return cappedVouchers;
973
+ }
512
974
  calculatePaidPaymentSummary(payments) {
513
975
  return (payments || []).reduce(
514
976
  (summary, payment) => {
@@ -518,13 +980,17 @@ var OrderModule = class extends import_BaseModule.BaseModule {
518
980
  return {
519
981
  customerPaidAmount: summary.customerPaidAmount.plus(paymentRecord.amount || 0),
520
982
  orderPaidAmount: summary.orderPaidAmount.plus(paymentRecord.origin_amount || 0),
521
- payServiceChargeAmount: summary.payServiceChargeAmount.plus(this.calculatePaymentServiceFee(paymentRecord))
983
+ gapPaidAmount: summary.gapPaidAmount.plus(this.calculatePaymentGapAmount(paymentRecord)),
984
+ payServiceChargeAmount: summary.payServiceChargeAmount.plus(this.calculatePaymentServiceFee(paymentRecord)),
985
+ roundingAmount: summary.roundingAmount.plus(this.calculatePaymentRoundingAmount(paymentRecord))
522
986
  };
523
987
  },
524
988
  {
525
989
  customerPaidAmount: new import_decimal.default(0),
526
990
  orderPaidAmount: new import_decimal.default(0),
527
- payServiceChargeAmount: new import_decimal.default(0)
991
+ gapPaidAmount: new import_decimal.default(0),
992
+ payServiceChargeAmount: new import_decimal.default(0),
993
+ roundingAmount: new import_decimal.default(0)
528
994
  }
529
995
  );
530
996
  }
@@ -537,15 +1003,363 @@ var OrderModule = class extends import_BaseModule.BaseModule {
537
1003
  const fixedAmount = new import_decimal.default(serviceCharge.amount || 0);
538
1004
  return new import_decimal.default(payment.amount || 0).times(percentage).plus(fixedAmount);
539
1005
  }
1006
+ calculatePaymentGapAmount(payment) {
1007
+ if (payment.origin_amount === void 0 || payment.origin_amount === null || payment.origin_amount === "") {
1008
+ return new import_decimal.default(0);
1009
+ }
1010
+ const rounding = new import_decimal.default(payment.rounding_amount || 0);
1011
+ return new import_decimal.default(payment.origin_amount || 0).minus(rounding);
1012
+ }
1013
+ calculatePaymentRoundingAmount(payment) {
1014
+ if (payment.rounding_amount === void 0 || payment.rounding_amount === null || payment.rounding_amount === "") {
1015
+ return new import_decimal.default(0);
1016
+ }
1017
+ return new import_decimal.default(payment.rounding_amount || 0);
1018
+ }
1019
+ formatSummaryMetadataMoney(value) {
1020
+ if (value === void 0 || value === null || value === "")
1021
+ return void 0;
1022
+ if (value instanceof import_decimal.default)
1023
+ return value.toFixed(2);
1024
+ return new import_decimal.default(String(value || 0)).toFixed(2);
1025
+ }
1026
+ syncSummaryProductMetadata(products) {
1027
+ const moneyKeys = [
1028
+ "main_product_attached_bundle_surcharge_fee",
1029
+ "main_product_attached_bundle_tax_fee",
1030
+ "surcharge_rounding_remainder",
1031
+ "tax_fee_rounding_remainder"
1032
+ ];
1033
+ const metadataMoneyKeys = [
1034
+ "main_product_attached_bundle_selling_price",
1035
+ "main_product_attached_bundle_payment_price"
1036
+ ];
1037
+ for (const product of products || []) {
1038
+ const productRecord = product;
1039
+ const metadata = productRecord.metadata && typeof productRecord.metadata === "object" ? { ...productRecord.metadata } : {};
1040
+ let hasMetadataPatch = false;
1041
+ for (const key of moneyKeys) {
1042
+ const value = this.formatSummaryMetadataMoney(productRecord[key]);
1043
+ if (value === void 0)
1044
+ continue;
1045
+ metadata[key] = value;
1046
+ hasMetadataPatch = true;
1047
+ }
1048
+ for (const key of metadataMoneyKeys) {
1049
+ const value = this.formatSummaryMetadataMoney(metadata[key]);
1050
+ if (value === void 0)
1051
+ continue;
1052
+ metadata[key] = value;
1053
+ hasMetadataPatch = true;
1054
+ }
1055
+ if (metadata.average_discount_amount_rate !== void 0) {
1056
+ hasMetadataPatch = true;
1057
+ }
1058
+ if (Array.isArray(productRecord.relation_surcharge_ids)) {
1059
+ metadata.relation_surcharge_ids = productRecord.relation_surcharge_ids;
1060
+ hasMetadataPatch = true;
1061
+ }
1062
+ const productPaymentPrice = this.formatSummaryMetadataMoney(
1063
+ productRecord.payment_price
1064
+ );
1065
+ if (productPaymentPrice !== void 0) {
1066
+ productRecord.payment_price = productPaymentPrice;
1067
+ }
1068
+ if (hasMetadataPatch)
1069
+ productRecord.metadata = metadata;
1070
+ if (!Array.isArray(productRecord.product_bundle))
1071
+ continue;
1072
+ for (const bundle of productRecord.product_bundle) {
1073
+ const bundleRecord = bundle;
1074
+ const bundleMetadata = bundleRecord.metadata && typeof bundleRecord.metadata === "object" ? { ...bundleRecord.metadata } : {};
1075
+ let hasBundleMetadataPatch = false;
1076
+ const bundleSurchargeFee = this.formatSummaryMetadataMoney(
1077
+ bundleRecord.surcharge_fee
1078
+ );
1079
+ if (bundleSurchargeFee !== void 0) {
1080
+ bundleMetadata.surcharge_fee = bundleSurchargeFee;
1081
+ hasBundleMetadataPatch = true;
1082
+ }
1083
+ const bundlePaymentPrice = this.formatSummaryMetadataMoney(
1084
+ bundleRecord.bundle_payment_price
1085
+ );
1086
+ if (bundlePaymentPrice !== void 0) {
1087
+ bundleRecord.bundle_payment_price = bundlePaymentPrice;
1088
+ }
1089
+ if (Array.isArray(bundleRecord.relation_surcharge_ids)) {
1090
+ bundleMetadata.relation_surcharge_ids = bundleRecord.relation_surcharge_ids;
1091
+ hasBundleMetadataPatch = true;
1092
+ }
1093
+ if (hasBundleMetadataPatch)
1094
+ bundleRecord.metadata = bundleMetadata;
1095
+ }
1096
+ }
1097
+ }
1098
+ calculateSummaryAmountGap(params) {
1099
+ const { tempOrder, summary, orderPaidAmount } = params;
1100
+ const refundAmount = this.getSummaryRefundAmount(summary);
1101
+ const netOrderPaidAmount = import_decimal.default.max(orderPaidAmount.minus(refundAmount), 0);
1102
+ const targetAmount = this.calculatePaymentTargetAmount(
1103
+ tempOrder,
1104
+ summary,
1105
+ netOrderPaidAmount
1106
+ );
1107
+ return targetAmount.minus(netOrderPaidAmount).toFixed(2);
1108
+ }
1109
+ getSummaryRefundAmount(summary) {
1110
+ return import_decimal.default.max(new import_decimal.default((summary == null ? void 0 : summary.total_refund_amount) || 0), 0);
1111
+ }
1112
+ calculatePaymentTargetAmount(tempOrder, summary, paidAmount = new import_decimal.default(0)) {
1113
+ const depositAmount = this.getDepositAmount(tempOrder, summary);
1114
+ if (!this.isDepositOrder(tempOrder, depositAmount)) {
1115
+ return this.getOrderExpectedAmount(summary);
1116
+ }
1117
+ if (this.isDepositCovered({ tempOrder, summary, paidAmount })) {
1118
+ return this.getOrderExpectedAmount(summary);
1119
+ }
1120
+ return depositAmount;
1121
+ }
1122
+ normalizeFingerprintMoney(value) {
1123
+ if (value === void 0 || value === null || value === "")
1124
+ return "";
1125
+ try {
1126
+ const parsed = new import_decimal.default(String(value || 0));
1127
+ return parsed.toFixed(4);
1128
+ } catch {
1129
+ return String(value);
1130
+ }
1131
+ }
1132
+ normalizeFingerprintValue(value) {
1133
+ if (Array.isArray(value)) {
1134
+ return value.map((item) => this.normalizeFingerprintValue(item));
1135
+ }
1136
+ if (!value || typeof value !== "object")
1137
+ return value ?? "";
1138
+ return Object.keys(value).sort().reduce((result, key) => {
1139
+ result[key] = this.normalizeFingerprintValue(value[key]);
1140
+ return result;
1141
+ }, {});
1142
+ }
1143
+ buildProductFingerprintItem(product) {
1144
+ const sku = (product == null ? void 0 : product.product_sku) || {};
1145
+ const metadata = (product == null ? void 0 : product.metadata) || {};
1146
+ const discountTypes = ((product == null ? void 0 : product.discount_list) || []).map((discount) => (discount == null ? void 0 : discount.type) ?? (discount == null ? void 0 : discount.tag));
1147
+ const extensionType = (product == null ? void 0 : product.extension_type) || (discountTypes.includes("good_pass") ? "good_pass" : "normal");
1148
+ return {
1149
+ product_id: (product == null ? void 0 : product.product_id) ?? null,
1150
+ product_variant_id: (product == null ? void 0 : product.product_variant_id) ?? null,
1151
+ extension_type: extensionType,
1152
+ num: (0, import_utils3.getSafeProductNum)((product == null ? void 0 : product.num) ?? (product == null ? void 0 : product.product_quantity)),
1153
+ selling_price: this.normalizeFingerprintMoney(product == null ? void 0 : product.selling_price),
1154
+ original_price: this.normalizeFingerprintMoney(product == null ? void 0 : product.original_price),
1155
+ payment_price: this.normalizeFingerprintMoney((product == null ? void 0 : product.payment_price) ?? (product == null ? void 0 : product.selling_price)),
1156
+ metadata: {
1157
+ source_product_price: this.normalizeFingerprintMoney(metadata.source_product_price),
1158
+ main_product_selling_price: this.normalizeFingerprintMoney(metadata.main_product_selling_price),
1159
+ main_product_original_price: this.normalizeFingerprintMoney(metadata.main_product_original_price),
1160
+ product_discount_difference: this.normalizeFingerprintMoney(metadata.product_discount_difference)
1161
+ },
1162
+ product_sku: this.normalizeFingerprintValue({
1163
+ code: sku.code ?? "",
1164
+ barcode: sku.barcode ?? "",
1165
+ variant_id: sku.variant_id ?? (product == null ? void 0 : product.product_variant_id) ?? 0,
1166
+ variant: sku.variant || [],
1167
+ option: (0, import_utils.getProductSkuOptions)(product || {}).map((option) => ({
1168
+ id: (option == null ? void 0 : option.id) ?? (option == null ? void 0 : option.option_group_item_id) ?? null,
1169
+ option_group_id: (option == null ? void 0 : option.option_group_id) ?? null,
1170
+ option_group_item_id: (option == null ? void 0 : option.option_group_item_id) ?? (option == null ? void 0 : option.id) ?? null,
1171
+ num: Number((option == null ? void 0 : option.num) ?? 1) || 1,
1172
+ add_price: this.normalizeFingerprintMoney((option == null ? void 0 : option.add_price) ?? (option == null ? void 0 : option.price))
1173
+ }))
1174
+ }),
1175
+ product_bundle: this.normalizeFingerprintValue(((product == null ? void 0 : product.product_bundle) || []).map((bundle) => ({
1176
+ bundle_product_id: (bundle == null ? void 0 : bundle.bundle_product_id) ?? (bundle == null ? void 0 : bundle._bundle_product_id) ?? (bundle == null ? void 0 : bundle.product_id) ?? null,
1177
+ bundle_variant_id: (bundle == null ? void 0 : bundle.bundle_variant_id) ?? (bundle == null ? void 0 : bundle.product_variant_id) ?? 0,
1178
+ num: (0, import_utils3.getSafeProductNum)((bundle == null ? void 0 : bundle.num) ?? (bundle == null ? void 0 : bundle.quantity)),
1179
+ price: this.normalizeFingerprintMoney(bundle == null ? void 0 : bundle.price),
1180
+ bundle_selling_price: this.normalizeFingerprintMoney(bundle == null ? void 0 : bundle.bundle_selling_price),
1181
+ price_type: (bundle == null ? void 0 : bundle.price_type) ?? "",
1182
+ price_type_ext: (bundle == null ? void 0 : bundle.price_type_ext) ?? ""
1183
+ }))),
1184
+ discount_list: this.normalizeFingerprintValue(((product == null ? void 0 : product.discount_list) || []).map((discount) => {
1185
+ var _a;
1186
+ return {
1187
+ type: (discount == null ? void 0 : discount.type) ?? (discount == null ? void 0 : discount.tag) ?? "",
1188
+ discount_id: (discount == null ? void 0 : discount.discount_id) ?? (discount == null ? void 0 : discount.order_discount_id) ?? ((_a = discount == null ? void 0 : discount.discount) == null ? void 0 : _a.resource_id) ?? null,
1189
+ amount: this.normalizeFingerprintMoney(discount == null ? void 0 : discount.amount)
1190
+ };
1191
+ }))
1192
+ };
1193
+ }
1194
+ buildOrderProductsFingerprint(products) {
1195
+ const items = (products || []).map((product) => this.buildProductFingerprintItem(product));
1196
+ items.sort((left, right) => JSON.stringify(left).localeCompare(JSON.stringify(right)));
1197
+ return JSON.stringify(items);
1198
+ }
1199
+ buildProductStructuralFingerprintItem(product) {
1200
+ const sku = (product == null ? void 0 : product.product_sku) || {};
1201
+ const metadata = (product == null ? void 0 : product.metadata) || {};
1202
+ const discountTypes = ((product == null ? void 0 : product.discount_list) || []).map((discount) => (discount == null ? void 0 : discount.type) ?? (discount == null ? void 0 : discount.tag));
1203
+ const extensionType = (product == null ? void 0 : product.extension_type) || (discountTypes.includes("good_pass") ? "good_pass" : "normal");
1204
+ return {
1205
+ product_id: (product == null ? void 0 : product.product_id) ?? null,
1206
+ product_variant_id: (product == null ? void 0 : product.product_variant_id) ?? null,
1207
+ extension_type: extensionType,
1208
+ num: (0, import_utils3.getSafeProductNum)((product == null ? void 0 : product.num) ?? (product == null ? void 0 : product.product_quantity)),
1209
+ metadata: {
1210
+ unique_identification_number: metadata.unique_identification_number ?? (product == null ? void 0 : product.unique_identification_number) ?? "",
1211
+ price_override: metadata.price_override ?? "",
1212
+ is_manual_discount: metadata.is_manual_discount ?? "",
1213
+ product_discount_reason: metadata.product_discount_reason ?? ""
1214
+ },
1215
+ product_sku: this.normalizeFingerprintValue({
1216
+ code: sku.code ?? "",
1217
+ barcode: sku.barcode ?? "",
1218
+ variant_id: sku.variant_id ?? (product == null ? void 0 : product.product_variant_id) ?? 0,
1219
+ variant: sku.variant || [],
1220
+ option: (0, import_utils.getProductSkuOptions)(product || {}).map((option) => ({
1221
+ id: (option == null ? void 0 : option.id) ?? (option == null ? void 0 : option.option_group_item_id) ?? null,
1222
+ option_group_id: (option == null ? void 0 : option.option_group_id) ?? null,
1223
+ option_group_item_id: (option == null ? void 0 : option.option_group_item_id) ?? (option == null ? void 0 : option.id) ?? null,
1224
+ num: Number((option == null ? void 0 : option.num) ?? 1) || 1,
1225
+ add_price: this.normalizeFingerprintMoney((option == null ? void 0 : option.add_price) ?? (option == null ? void 0 : option.price))
1226
+ }))
1227
+ }),
1228
+ product_bundle: this.normalizeFingerprintValue(((product == null ? void 0 : product.product_bundle) || []).map((bundle) => ({
1229
+ bundle_id: (bundle == null ? void 0 : bundle.bundle_id) ?? (bundle == null ? void 0 : bundle.id) ?? null,
1230
+ bundle_group_id: (bundle == null ? void 0 : bundle.bundle_group_id) ?? (bundle == null ? void 0 : bundle.group_id) ?? null,
1231
+ bundle_product_id: (bundle == null ? void 0 : bundle.bundle_product_id) ?? (bundle == null ? void 0 : bundle._bundle_product_id) ?? (bundle == null ? void 0 : bundle.product_id) ?? null,
1232
+ bundle_variant_id: (bundle == null ? void 0 : bundle.bundle_variant_id) ?? (bundle == null ? void 0 : bundle.product_variant_id) ?? 0,
1233
+ num: (0, import_utils3.getSafeProductNum)((bundle == null ? void 0 : bundle.num) ?? (bundle == null ? void 0 : bundle.quantity)),
1234
+ price_type: (bundle == null ? void 0 : bundle.price_type) ?? "",
1235
+ price_type_ext: (bundle == null ? void 0 : bundle.price_type_ext) ?? "",
1236
+ option: this.normalizeFingerprintValue(((bundle == null ? void 0 : bundle.option) || []).map((option) => ({
1237
+ id: (option == null ? void 0 : option.id) ?? (option == null ? void 0 : option.option_group_item_id) ?? null,
1238
+ option_group_id: (option == null ? void 0 : option.option_group_id) ?? null,
1239
+ option_group_item_id: (option == null ? void 0 : option.option_group_item_id) ?? (option == null ? void 0 : option.id) ?? null,
1240
+ num: Number((option == null ? void 0 : option.num) ?? 1) || 1,
1241
+ add_price: this.normalizeFingerprintMoney((option == null ? void 0 : option.add_price) ?? (option == null ? void 0 : option.price))
1242
+ })))
1243
+ }))),
1244
+ discount_list: this.normalizeFingerprintValue(((product == null ? void 0 : product.discount_list) || []).map((discount) => {
1245
+ var _a;
1246
+ return {
1247
+ type: (discount == null ? void 0 : discount.type) ?? (discount == null ? void 0 : discount.tag) ?? "",
1248
+ discount_id: (discount == null ? void 0 : discount.discount_id) ?? (discount == null ? void 0 : discount.order_discount_id) ?? ((_a = discount == null ? void 0 : discount.discount) == null ? void 0 : _a.resource_id) ?? null,
1249
+ amount: this.normalizeFingerprintMoney(discount == null ? void 0 : discount.amount)
1250
+ };
1251
+ }))
1252
+ };
1253
+ }
1254
+ buildOrderProductsStructuralFingerprint(products) {
1255
+ const items = (products || []).map((product) => this.buildProductStructuralFingerprintItem(product));
1256
+ items.sort((left, right) => JSON.stringify(left).localeCompare(JSON.stringify(right)));
1257
+ return JSON.stringify(items);
1258
+ }
1259
+ getOriginalSalesSnapshot(tempOrder) {
1260
+ var _a;
1261
+ const snapshot = (_a = tempOrder._extend) == null ? void 0 : _a.originalSalesSnapshot;
1262
+ if (!snapshot || typeof snapshot !== "object")
1263
+ return null;
1264
+ if (typeof snapshot.productFingerprint !== "string")
1265
+ return null;
1266
+ return snapshot;
1267
+ }
1268
+ isSnapshotPayableAmountUnchanged(tempOrder, snapshot, snapshotSummary) {
1269
+ const currentPaidPaymentSummary = this.calculatePaidPaymentSummary(tempOrder.payments || []);
1270
+ const currentAmountGap = this.calculateSummaryAmountGap({
1271
+ tempOrder,
1272
+ summary: snapshotSummary,
1273
+ orderPaidAmount: currentPaidPaymentSummary.gapPaidAmount
1274
+ });
1275
+ const snapshotPaidPaymentSummary = this.calculatePaidPaymentSummary(
1276
+ Array.isArray(snapshot.payments) ? snapshot.payments : []
1277
+ );
1278
+ const snapshotAmountGap = this.calculateSummaryAmountGap({
1279
+ tempOrder,
1280
+ summary: snapshotSummary,
1281
+ orderPaidAmount: snapshotPaidPaymentSummary.gapPaidAmount
1282
+ });
1283
+ return currentAmountGap === snapshotAmountGap;
1284
+ }
1285
+ restoreOriginalSnapshotIfProductsUnchanged(tempOrder) {
1286
+ const snapshot = this.getOriginalSalesSnapshot(tempOrder);
1287
+ if (!snapshot)
1288
+ return null;
1289
+ const currentFingerprint = this.buildOrderProductsFingerprint(tempOrder.products);
1290
+ if (currentFingerprint !== snapshot.productFingerprint) {
1291
+ const currentStructuralFingerprint = this.buildOrderProductsStructuralFingerprint(tempOrder.products);
1292
+ const snapshotStructuralFingerprint = this.buildOrderProductsStructuralFingerprint(
1293
+ Array.isArray(snapshot.products) ? snapshot.products : []
1294
+ );
1295
+ if (currentStructuralFingerprint !== snapshotStructuralFingerprint)
1296
+ return null;
1297
+ }
1298
+ const summary = {
1299
+ ...(0, import_utils.createEmptySummary)(),
1300
+ ...(0, import_lodash_es.cloneDeep)(snapshot.summary || {})
1301
+ };
1302
+ if (!this.isSnapshotPayableAmountUnchanged(tempOrder, snapshot, summary))
1303
+ return null;
1304
+ if (Array.isArray(snapshot.products)) {
1305
+ tempOrder.products = (0, import_lodash_es.cloneDeep)(snapshot.products);
1306
+ }
1307
+ if (Array.isArray(snapshot.surcharges)) {
1308
+ tempOrder.surcharges = (0, import_lodash_es.cloneDeep)(snapshot.surcharges);
1309
+ }
1310
+ tempOrder.surcharge_fee = summary.surcharge_fee || tempOrder.surcharge_fee;
1311
+ tempOrder.deposit_amount = summary.deposit_amount || "0.00";
1312
+ tempOrder.is_deposit = summary.deposit_amount !== "0.00" ? 1 : 0;
1313
+ this.store.summary = summary;
1314
+ return summary;
1315
+ }
1316
+ clearPersistedAmountFieldsForFullRecalc(products) {
1317
+ const moneyKeys = [
1318
+ "surcharge_fee",
1319
+ "main_product_attached_bundle_surcharge_fee",
1320
+ "surcharge_rounding_remainder",
1321
+ "main_product_attached_bundle_tax_fee",
1322
+ "tax_fee",
1323
+ "original_tax_fee",
1324
+ "tax_fee_rounding_remainder",
1325
+ "original_tax_fee_rounding_remainder"
1326
+ ];
1327
+ const metadataMoneyKeys = [
1328
+ "main_product_attached_bundle_surcharge_fee",
1329
+ "surcharge_rounding_remainder",
1330
+ "main_product_attached_bundle_tax_fee",
1331
+ "tax_fee_rounding_remainder"
1332
+ ];
1333
+ for (const product of products || []) {
1334
+ const record = product;
1335
+ for (const key of moneyKeys)
1336
+ delete record[key];
1337
+ if (record.metadata && typeof record.metadata === "object") {
1338
+ record.metadata = { ...record.metadata };
1339
+ for (const key of metadataMoneyKeys)
1340
+ delete record.metadata[key];
1341
+ }
1342
+ for (const bundle of record.product_bundle || []) {
1343
+ for (const key of moneyKeys)
1344
+ delete bundle[key];
1345
+ if (bundle.metadata && typeof bundle.metadata === "object") {
1346
+ bundle.metadata = { ...bundle.metadata };
1347
+ for (const key of metadataMoneyKeys)
1348
+ delete bundle.metadata[key];
1349
+ }
1350
+ }
1351
+ }
1352
+ }
540
1353
  getPaymentTargetAmount() {
541
1354
  const tempOrder = this.ensureTempOrder();
542
1355
  const summary = this.store.summary || (0, import_utils.createEmptySummary)();
543
- if (tempOrder.is_deposit === 1) {
544
- return new import_decimal.default(
545
- tempOrder.deposit_amount || summary.deposit_amount || 0
546
- );
547
- }
548
- return new import_decimal.default(summary.total_amount || summary.expect_amount || 0);
1356
+ const paidPaymentSummary = this.calculatePaidPaymentSummary(tempOrder.payments || []);
1357
+ const refundAmount = this.getSummaryRefundAmount(summary);
1358
+ const netPaidAmount = import_decimal.default.max(
1359
+ paidPaymentSummary.gapPaidAmount.minus(refundAmount),
1360
+ 0
1361
+ );
1362
+ return this.calculatePaymentTargetAmount(tempOrder, summary, netPaidAmount);
549
1363
  }
550
1364
  ensureTempOrder() {
551
1365
  if (this.store.tempOrder) {
@@ -559,17 +1373,43 @@ var OrderModule = class extends import_BaseModule.BaseModule {
559
1373
  return newOrder;
560
1374
  }
561
1375
  restoreOrder() {
1376
+ var _a, _b;
562
1377
  const freshTempOrder = this.createDefaultTempOrderInstance();
563
1378
  this.ensureExternalSaleNumber(freshTempOrder);
564
1379
  this.store.tempOrder = freshTempOrder;
565
1380
  this.store.summary = (0, import_utils.createEmptySummary)();
566
1381
  this.store.lastOrderInfo = void 0;
1382
+ this.store.syncState = void 0;
1383
+ void ((_a = this.store.discount) == null ? void 0 : _a.setOriginalDiscountList([]));
1384
+ void ((_b = this.store.discount) == null ? void 0 : _b.setDiscountList([]));
567
1385
  this.persistTempOrder();
568
1386
  return freshTempOrder;
569
1387
  }
570
1388
  getTempOrder() {
571
1389
  return this.store.tempOrder;
572
1390
  }
1391
+ async replaceTempOrder(tempOrder, options) {
1392
+ if (!(0, import_utils.isTempOrder)(tempOrder)) {
1393
+ throw new Error("无效的 tempOrder 数据");
1394
+ }
1395
+ const nextTempOrder = this.normalizeTempOrderForRuntime(
1396
+ (0, import_lodash_es.cloneDeep)(tempOrder),
1397
+ { ensureIdentity: false }
1398
+ );
1399
+ this.store.tempOrder = nextTempOrder;
1400
+ if ((options == null ? void 0 : options.recalculateSummary) !== false) {
1401
+ await this.recalculateSummary({ createIfMissing: false });
1402
+ } else {
1403
+ this.store.summary = (0, import_utils.createEmptySummary)();
1404
+ }
1405
+ if ((options == null ? void 0 : options.persist) !== false) {
1406
+ this.persistTempOrder();
1407
+ }
1408
+ if (options == null ? void 0 : options.saveDraft) {
1409
+ await this.saveDraft();
1410
+ }
1411
+ return nextTempOrder;
1412
+ }
573
1413
  getOrderIdentity() {
574
1414
  var _a;
575
1415
  const tempOrder = this.store.tempOrder;
@@ -605,9 +1445,12 @@ var OrderModule = class extends import_BaseModule.BaseModule {
605
1445
  return null;
606
1446
  const summary = this.store.summary || (0, import_utils.createEmptySummary)();
607
1447
  const depositAmount = tempOrder.deposit_amount || summary.deposit_amount || "0.00";
608
- const targetAmount = tempOrder.is_deposit === 1 ? new import_decimal.default(depositAmount || 0) : new import_decimal.default(summary.total_amount || summary.expect_amount || 0);
609
- const paymentTotal = this.calculatePaymentTotal(tempOrder.payments || []);
610
- const amountGap = import_decimal.default.max(0, targetAmount.minus(paymentTotal)).toFixed(2);
1448
+ const paidPaymentSummary = this.calculatePaidPaymentSummary(tempOrder.payments || []);
1449
+ const amountGap = this.calculateSummaryAmountGap({
1450
+ tempOrder,
1451
+ summary,
1452
+ orderPaidAmount: paidPaymentSummary.gapPaidAmount
1453
+ });
611
1454
  return {
612
1455
  isDeposit: tempOrder.is_deposit === 1 || depositAmount !== "0.00",
613
1456
  depositAmount,
@@ -650,7 +1493,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
650
1493
  this.ensureExternalSaleNumber(tempOrder);
651
1494
  await this.recalculateSummary({ createIfMissing: true });
652
1495
  this.persistTempOrder();
653
- await this.saveDraft();
1496
+ if (this.draftPersistEnabled) {
1497
+ await this.saveDraft();
1498
+ }
654
1499
  return tempOrder;
655
1500
  }
656
1501
  getOrderProducts() {
@@ -664,6 +1509,17 @@ var OrderModule = class extends import_BaseModule.BaseModule {
664
1509
  product.metadata = metadata;
665
1510
  return String(uid);
666
1511
  }
1512
+ sanitizeOrderProductForTempOrder(product) {
1513
+ if (product.metadata && typeof product.metadata === "object") {
1514
+ delete product.metadata.origin;
1515
+ }
1516
+ return product;
1517
+ }
1518
+ sanitizeTempOrderProducts(tempOrder) {
1519
+ tempOrder.products = (tempOrder.products || []).map(
1520
+ (product) => this.sanitizeOrderProductForTempOrder(product)
1521
+ );
1522
+ }
667
1523
  ensureExtend(tempOrder) {
668
1524
  if (!tempOrder._extend || typeof tempOrder._extend !== "object") {
669
1525
  tempOrder._extend = { productsByUid: {} };
@@ -697,6 +1553,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
697
1553
  );
698
1554
  productMetadata.unique_identification_number = productUid;
699
1555
  bookingMetadata.unique_identification_number = bookingUid;
1556
+ this.syncBookingMetadataHolder(params.booking, bookingMetadata);
700
1557
  return {
701
1558
  productUid,
702
1559
  bookingUid,
@@ -718,44 +1575,256 @@ var OrderModule = class extends import_BaseModule.BaseModule {
718
1575
  }
719
1576
  };
720
1577
  }
1578
+ /**
1579
+ * booking.holder 是提交真源;metadata.holder 作为详情/回显冗余字段同步保存。
1580
+ *
1581
+ * @example
1582
+ * this.syncBookingMetadataHolder(booking, metadata);
1583
+ */
1584
+ syncBookingMetadataHolder(booking, metadata) {
1585
+ if ((booking == null ? void 0 : booking.holder) !== void 0) {
1586
+ metadata.holder = booking.holder;
1587
+ }
1588
+ }
1589
+ /**
1590
+ * 从单条 booking 的 holder / metadata 中收集 holder form_record。
1591
+ *
1592
+ * @example
1593
+ * const ids = this.collectBookingHolderRecords(booking);
1594
+ */
1595
+ collectBookingHolderRecords(booking) {
1596
+ var _a;
1597
+ const holder = (booking == null ? void 0 : booking.holder) && typeof booking.holder === "object" ? booking.holder : null;
1598
+ const source = (holder == null ? void 0 : holder.form_record) ?? ((_a = booking == null ? void 0 : booking.metadata) == null ? void 0 : _a.holder_id);
1599
+ const records = Array.isArray(source) ? source : [source];
1600
+ return records.filter((record) => record !== void 0 && record !== null && record !== "");
1601
+ }
1602
+ /**
1603
+ * 按 form_record 顺序读取 booking holder 的主字段名称。
1604
+ *
1605
+ * @example
1606
+ * const names = this.collectBookingHolderNames(booking);
1607
+ */
1608
+ collectBookingHolderNames(booking) {
1609
+ const holder = (booking == null ? void 0 : booking.holder) && typeof booking.holder === "object" ? booking.holder : null;
1610
+ const rawName = holder == null ? void 0 : holder.name;
1611
+ if (Array.isArray(rawName)) {
1612
+ return rawName.map((name) => String(name || "").trim());
1613
+ }
1614
+ if (typeof rawName === "string") {
1615
+ return rawName.split(",").map((name) => name.trim());
1616
+ }
1617
+ return [];
1618
+ }
1619
+ /**
1620
+ * 按老 ticketBooking `formatHolder` 语义汇总订单顶层 holder。
1621
+ *
1622
+ * @example
1623
+ * const holder = this.buildTempOrderHolderFromBookings(tempOrder);
1624
+ */
1625
+ buildTempOrderHolderFromBookings(tempOrder) {
1626
+ var _a, _b;
1627
+ const holderRecords = [];
1628
+ const holderNames = [];
1629
+ let baseHolder = null;
1630
+ const seen = /* @__PURE__ */ new Set();
1631
+ for (const booking of tempOrder.bookings || []) {
1632
+ const holder = (booking == null ? void 0 : booking.holder) && typeof booking.holder === "object" ? booking.holder : null;
1633
+ if (!baseHolder && holder) {
1634
+ baseHolder = holder;
1635
+ }
1636
+ const records = this.collectBookingHolderRecords(booking);
1637
+ const names = this.collectBookingHolderNames(booking);
1638
+ for (const [index, record] of records.entries()) {
1639
+ const key = String(record);
1640
+ if (seen.has(key))
1641
+ continue;
1642
+ seen.add(key);
1643
+ holderRecords.push(record);
1644
+ if (names[index]) {
1645
+ holderNames.push(names[index]);
1646
+ }
1647
+ }
1648
+ }
1649
+ if (!holderRecords.length) {
1650
+ return null;
1651
+ }
1652
+ const nextHolder = {
1653
+ customer_id: (baseHolder == null ? void 0 : baseHolder.customer_id) ?? tempOrder.customer_id,
1654
+ form_id: (baseHolder == null ? void 0 : baseHolder.form_id) ?? ((_a = tempOrder.holder) == null ? void 0 : _a.form_id) ?? 0,
1655
+ form_record: holderRecords
1656
+ };
1657
+ if (holderNames.length) {
1658
+ nextHolder.name = holderNames.join(",");
1659
+ }
1660
+ if ((baseHolder == null ? void 0 : baseHolder.is_source_shop) || ((_b = this.otherParams) == null ? void 0 : _b.isFranchisee)) {
1661
+ nextHolder.is_source_shop = 1;
1662
+ }
1663
+ return nextHolder;
1664
+ }
1665
+ /**
1666
+ * 将 booking 级 holder 汇总到 tempOrder 顶层 holder。
1667
+ *
1668
+ * @example
1669
+ * this.syncTempOrderHolderFromBookings(tempOrder);
1670
+ */
1671
+ syncTempOrderHolderFromBookings(tempOrder) {
1672
+ const bookings = tempOrder.bookings || [];
1673
+ const hasHolderSource = bookings.some((booking) => {
1674
+ var _a;
1675
+ return (booking == null ? void 0 : booking.holder) !== void 0 || ((_a = booking == null ? void 0 : booking.metadata) == null ? void 0 : _a.holder_id) !== void 0;
1676
+ });
1677
+ const nextHolder = this.buildTempOrderHolderFromBookings(tempOrder);
1678
+ if (nextHolder || hasHolderSource || bookings.length === 0) {
1679
+ tempOrder.holder = nextHolder;
1680
+ }
1681
+ }
1682
+ getBookingUniqueIdentificationNumber(booking) {
1683
+ var _a;
1684
+ const uid = (_a = booking == null ? void 0 : booking.metadata) == null ? void 0 : _a.unique_identification_number;
1685
+ if (uid === void 0 || uid === null || uid === "")
1686
+ return null;
1687
+ return String(uid);
1688
+ }
1689
+ findBookingIndexByUniqueIdentificationNumber(tempOrder, uniqueIdentificationNumber) {
1690
+ return (tempOrder.bookings || []).findIndex((booking) => {
1691
+ return this.getBookingUniqueIdentificationNumber(booking) === uniqueIdentificationNumber;
1692
+ });
1693
+ }
1694
+ removeLinkedBookingsForProduct(tempOrder, product) {
1695
+ var _a, _b;
1696
+ const productUid = ((_a = product == null ? void 0 : product.metadata) == null ? void 0 : _a.unique_identification_number) || (product == null ? void 0 : product.unique_identification_number);
1697
+ const bookingUid = (product == null ? void 0 : product.booking_uid) || ((_b = product == null ? void 0 : product.metadata) == null ? void 0 : _b.booking_uid);
1698
+ if (!productUid && !bookingUid)
1699
+ return;
1700
+ tempOrder.bookings = (tempOrder.bookings || []).filter((booking) => {
1701
+ const currentBookingUid = this.getBookingUniqueIdentificationNumber(booking);
1702
+ if (bookingUid && currentBookingUid === String(bookingUid))
1703
+ return false;
1704
+ if (productUid && String((booking == null ? void 0 : booking.product_uid) || "") === String(productUid))
1705
+ return false;
1706
+ return true;
1707
+ });
1708
+ }
721
1709
  // ─── TempOrder: 金额汇总 ───
722
1710
  getSalesSummary() {
723
1711
  if (!this.salesSummaryModuleName)
724
1712
  return null;
725
1713
  return this.core.getModule(this.salesSummaryModuleName);
726
1714
  }
1715
+ applyOrderProductsDepositSummary(tempOrder, summary) {
1716
+ var _a;
1717
+ const depositSummary = (0, import_utils.calculateOrderProductsDeposit)(tempOrder.products || [], {
1718
+ productsByUid: (_a = tempOrder._extend) == null ? void 0 : _a.productsByUid
1719
+ });
1720
+ const nextSummary = {
1721
+ ...summary,
1722
+ deposit_amount: depositSummary.totalText,
1723
+ deposit: depositSummary.hasDeposit ? {
1724
+ total: depositSummary.totalText,
1725
+ deposit_policy_ids: depositSummary.deposit_policy_ids,
1726
+ deposit_policy_data: depositSummary.protocols,
1727
+ hasDeposit: true
1728
+ } : void 0
1729
+ };
1730
+ tempOrder.deposit_amount = depositSummary.totalText;
1731
+ tempOrder.is_deposit = depositSummary.hasDeposit ? 1 : 0;
1732
+ return nextSummary;
1733
+ }
727
1734
  async recalculateSummary(options) {
728
1735
  const tempOrder = (options == null ? void 0 : options.createIfMissing) ? this.ensureTempOrder() : this.store.tempOrder;
729
1736
  if (!tempOrder)
730
1737
  return null;
1738
+ this.sanitizeTempOrderProducts(tempOrder);
1739
+ const snapshotSummary = this.restoreOriginalSnapshotIfProductsUnchanged(tempOrder);
1740
+ if (snapshotSummary)
1741
+ return snapshotSummary;
1742
+ const shouldFullRecalculateFromSnapshot = Boolean(this.getOriginalSalesSnapshot(tempOrder));
1743
+ const summaryProducts = shouldFullRecalculateFromSnapshot ? (0, import_lodash_es.cloneDeep)(tempOrder.products || []) : tempOrder.products;
1744
+ if (shouldFullRecalculateFromSnapshot) {
1745
+ this.clearPersistedAmountFieldsForFullRecalc(summaryProducts || []);
1746
+ }
731
1747
  const salesSummary = this.getSalesSummary();
732
1748
  const existedSummary = this.store.summary || (0, import_utils.createEmptySummary)();
1749
+ const totalRefundAmount = existedSummary.total_refund_amount || "0.00";
733
1750
  const paidPaymentSummary = this.calculatePaidPaymentSummary(
734
1751
  tempOrder.payments || []
735
1752
  );
736
1753
  if (!salesSummary) {
737
- const emptySummary = {
1754
+ const emptyBaseSummary = {
738
1755
  ...(0, import_utils.createEmptySummary)(),
739
- total_refund_amount: existedSummary.total_refund_amount || "0.00",
1756
+ ...existedSummary,
1757
+ total_refund_amount: totalRefundAmount
1758
+ };
1759
+ const emptySummaryBase = {
1760
+ ...emptyBaseSummary,
740
1761
  customer_paid_amount: paidPaymentSummary.customerPaidAmount.toFixed(2),
741
1762
  order_paid_amount: paidPaymentSummary.orderPaidAmount.toFixed(2),
742
- pay_service_charge_amount: paidPaymentSummary.payServiceChargeAmount.toFixed(2)
1763
+ pay_service_charge_amount: paidPaymentSummary.payServiceChargeAmount.toFixed(2),
1764
+ rounding_amount: paidPaymentSummary.roundingAmount.toFixed(2)
1765
+ };
1766
+ const emptySummaryWithDeposit = this.applyOrderProductsDepositSummary(
1767
+ tempOrder,
1768
+ emptySummaryBase
1769
+ );
1770
+ const emptySummary = {
1771
+ ...emptySummaryWithDeposit,
1772
+ amount_gap: this.calculateSummaryAmountGap({
1773
+ tempOrder,
1774
+ summary: emptySummaryWithDeposit,
1775
+ orderPaidAmount: paidPaymentSummary.gapPaidAmount
1776
+ })
743
1777
  };
744
- this.store.summary = emptySummary;
745
1778
  tempOrder.surcharge_fee = emptySummary.surcharge_fee;
1779
+ this.store.summary = emptySummary;
1780
+ this.updateTempOrderPaymentStatus(tempOrder, {
1781
+ previousSummary: existedSummary,
1782
+ summary: emptySummary
1783
+ });
746
1784
  return this.store.summary;
747
1785
  }
748
1786
  const salesSummaryResult = await salesSummary.getSummary({
749
- products: tempOrder.products,
1787
+ products: summaryProducts,
750
1788
  isPriceIncludeTax: tempOrder.is_price_include_tax,
751
1789
  shopDiscount: tempOrder.shop_discount
752
1790
  });
753
- const summary = {
1791
+ if (shouldFullRecalculateFromSnapshot) {
1792
+ tempOrder.products = summaryProducts;
1793
+ }
1794
+ this.syncSummaryProductMetadata(tempOrder.products || []);
1795
+ const roundingAmount = paidPaymentSummary.roundingAmount;
1796
+ const payServiceChargeAmount = paidPaymentSummary.payServiceChargeAmount;
1797
+ const hasSalesSummaryAmount = salesSummaryResult.expect_amount !== void 0 || salesSummaryResult.total_amount !== void 0;
1798
+ const expectAmount = hasSalesSummaryAmount ? new import_decimal.default(salesSummaryResult.expect_amount ?? salesSummaryResult.total_amount ?? 0) : null;
1799
+ const amountPaymentPatch = hasSalesSummaryAmount || !roundingAmount.eq(0) || !payServiceChargeAmount.eq(0) ? {
1800
+ rounding_amount: roundingAmount.toFixed(2),
1801
+ ...expectAmount ? {
1802
+ total_amount: import_decimal.default.max(
1803
+ 0,
1804
+ expectAmount.plus(roundingAmount).plus(payServiceChargeAmount)
1805
+ ).toFixed(2)
1806
+ } : {}
1807
+ } : {};
1808
+ const normalizedExpectAmountPatch = expectAmount && salesSummaryResult.expect_amount === void 0 ? { expect_amount: expectAmount.toFixed(2) } : {};
1809
+ const summaryForGap = this.applyOrderProductsDepositSummary(tempOrder, {
754
1810
  ...salesSummaryResult,
755
- total_refund_amount: existedSummary.total_refund_amount || "0.00",
1811
+ total_refund_amount: totalRefundAmount,
1812
+ ...amountPaymentPatch,
1813
+ ...normalizedExpectAmountPatch
1814
+ });
1815
+ const summary = {
1816
+ ...summaryForGap,
1817
+ total_refund_amount: totalRefundAmount,
756
1818
  customer_paid_amount: paidPaymentSummary.customerPaidAmount.toFixed(2),
757
1819
  order_paid_amount: paidPaymentSummary.orderPaidAmount.toFixed(2),
758
- pay_service_charge_amount: paidPaymentSummary.payServiceChargeAmount.toFixed(2)
1820
+ ...amountPaymentPatch,
1821
+ ...normalizedExpectAmountPatch,
1822
+ amount_gap: this.calculateSummaryAmountGap({
1823
+ tempOrder,
1824
+ summary: summaryForGap,
1825
+ orderPaidAmount: paidPaymentSummary.gapPaidAmount
1826
+ }),
1827
+ pay_service_charge_amount: payServiceChargeAmount.toFixed(2)
759
1828
  };
760
1829
  this.store.summary = summary;
761
1830
  if (summary.is_price_include_tax !== void 0) {
@@ -766,8 +1835,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
766
1835
  }
767
1836
  tempOrder.surcharge_fee = summary.surcharge_fee;
768
1837
  tempOrder.surcharges = summary.surcharges || [];
769
- tempOrder.deposit_amount = summary.deposit_amount || "0.00";
770
- tempOrder.is_deposit = summary.deposit_amount !== "0.00" ? 1 : 0;
1838
+ this.updateTempOrderPaymentStatus(tempOrder, {
1839
+ previousSummary: existedSummary,
1840
+ summary
1841
+ });
771
1842
  return this.store.summary;
772
1843
  }
773
1844
  async getOrderSummary() {
@@ -777,13 +1848,22 @@ var OrderModule = class extends import_BaseModule.BaseModule {
777
1848
  this.persistTempOrder();
778
1849
  return summary;
779
1850
  }
780
- // ─── TempOrder: 备注 ───
781
- updateTempOrderNote(note) {
1851
+ updateTempOrderNote(note, sync = false) {
782
1852
  const tempOrder = this.ensureTempOrder();
783
1853
  tempOrder.note = String(note || "");
784
1854
  this.persistTempOrder();
1855
+ if (sync) {
1856
+ const orderId = tempOrder.order_id;
1857
+ if (!orderId)
1858
+ return tempOrder.note;
1859
+ return this.syncTempOrderNoteToRemote(orderId, tempOrder.note);
1860
+ }
785
1861
  return tempOrder.note;
786
1862
  }
1863
+ async syncTempOrderNoteToRemote(orderId, note) {
1864
+ await this.request.put(`/order/order/${orderId}/note`, { note });
1865
+ return note;
1866
+ }
787
1867
  getTempOrderNote() {
788
1868
  var _a;
789
1869
  return ((_a = this.store.tempOrder) == null ? void 0 : _a.note) || "";
@@ -795,6 +1875,35 @@ var OrderModule = class extends import_BaseModule.BaseModule {
795
1875
  this.persistTempOrder();
796
1876
  return tempOrder.shop_discount;
797
1877
  }
1878
+ updateTempOrderDepositAmount(amount) {
1879
+ const tempOrder = this.ensureTempOrder();
1880
+ const depositAmount = this.normalizeDepositAmount(amount);
1881
+ const previousSummary = this.store.summary || (0, import_utils.createEmptySummary)();
1882
+ const summaryWithDeposit = this.applyDepositAmountToSummary(
1883
+ tempOrder,
1884
+ {
1885
+ ...(0, import_utils.createEmptySummary)(),
1886
+ ...previousSummary
1887
+ },
1888
+ depositAmount
1889
+ );
1890
+ const paidPaymentSummary = this.calculatePaidPaymentSummary(tempOrder.payments || []);
1891
+ const summary = {
1892
+ ...summaryWithDeposit,
1893
+ amount_gap: this.calculateSummaryAmountGap({
1894
+ tempOrder,
1895
+ summary: summaryWithDeposit,
1896
+ orderPaidAmount: paidPaymentSummary.gapPaidAmount
1897
+ })
1898
+ };
1899
+ this.store.summary = summary;
1900
+ this.updateTempOrderPaymentStatus(tempOrder, {
1901
+ previousSummary,
1902
+ summary
1903
+ });
1904
+ this.persistTempOrder();
1905
+ return summary;
1906
+ }
798
1907
  updateTempOrderBuzzer(buzzer) {
799
1908
  const tempOrder = this.ensureTempOrder();
800
1909
  tempOrder.buzzer = String(buzzer || "");
@@ -807,14 +1916,77 @@ var OrderModule = class extends import_BaseModule.BaseModule {
807
1916
  this.persistTempOrder();
808
1917
  return tempOrder.contacts_info;
809
1918
  }
1919
+ buildTempOrderCustomer(params) {
1920
+ if (!params.customerId)
1921
+ return null;
1922
+ const source = params.source ? (0, import_lodash_es.cloneDeep)(params.source) : {};
1923
+ const name = source.name ?? source.display_name ?? source.customerName ?? source.customer_name ?? params.customerName;
1924
+ const customerName = source.customer_name ?? source.customerName ?? source.display_name ?? source.name ?? params.customerName;
1925
+ return {
1926
+ ...source,
1927
+ id: source.id ?? params.customerId,
1928
+ customer_id: source.customer_id ?? params.customerId,
1929
+ name: String(name || ""),
1930
+ customer_name: String(customerName || ""),
1931
+ country_calling_code: String(
1932
+ source.country_calling_code ?? source.countryCallingCode ?? params.countryCallingCode
1933
+ ),
1934
+ phone: String(source.phone ?? params.phone),
1935
+ email: String(source.email ?? params.email)
1936
+ };
1937
+ }
1938
+ isCustomerBoundDiscount(discount) {
1939
+ const type = (discount == null ? void 0 : discount.type) ?? (discount == null ? void 0 : discount.tag);
1940
+ return type === "good_pass" || type === "discount_card" || type === "product_discount_card";
1941
+ }
1942
+ clearCustomerBoundDiscounts(tempOrder) {
1943
+ var _a, _b, _c, _d;
1944
+ const filterDiscountList = (discountList) => {
1945
+ if (!Array.isArray(discountList))
1946
+ return [];
1947
+ return discountList.filter((discount) => !this.isCustomerBoundDiscount(discount));
1948
+ };
1949
+ tempOrder.products = (tempOrder.products || []).map((product) => {
1950
+ const nextProduct = {
1951
+ ...product,
1952
+ discount_list: filterDiscountList(product.discount_list)
1953
+ };
1954
+ if (Array.isArray(nextProduct.product_bundle)) {
1955
+ nextProduct.product_bundle = nextProduct.product_bundle.map((bundle) => ({
1956
+ ...bundle,
1957
+ discount_list: filterDiscountList(bundle.discount_list)
1958
+ }));
1959
+ }
1960
+ return nextProduct;
1961
+ });
1962
+ delete tempOrder.discount_list;
1963
+ const discountModule = this.store.discount;
1964
+ if (!discountModule)
1965
+ return;
1966
+ const currentDiscounts = ((_a = discountModule.getDiscountList) == null ? void 0 : _a.call(discountModule)) || [];
1967
+ const currentOriginalDiscounts = ((_b = discountModule.getOriginalDiscountList) == null ? void 0 : _b.call(discountModule)) || [];
1968
+ const nextDiscounts = currentDiscounts.filter((discount) => {
1969
+ if (discount == null ? void 0 : discount.isEditMode)
1970
+ return true;
1971
+ return !this.isCustomerBoundDiscount(discount);
1972
+ });
1973
+ const nextOriginalDiscounts = currentOriginalDiscounts.filter((discount) => {
1974
+ if (discount == null ? void 0 : discount.isEditMode)
1975
+ return true;
1976
+ return !this.isCustomerBoundDiscount(discount);
1977
+ });
1978
+ void ((_c = discountModule.setDiscountList) == null ? void 0 : _c.call(discountModule, nextDiscounts));
1979
+ void ((_d = discountModule.setOriginalDiscountList) == null ? void 0 : _d.call(discountModule, nextOriginalDiscounts));
1980
+ }
810
1981
  /**
811
1982
  * 更新当前 tempOrder 的客户协议字段。
812
1983
  *
813
- * PaymentModal 只需要修改订单里的客户字段;如果外部还有客户模块需要同步,
1984
+ * PaymentModal 只需要修改订单里的客户事实;如果外部还有客户模块需要同步,
814
1985
  * 应由调用方通过回调处理,不能把外部 UI 状态写进 tempOrder。
815
1986
  */
816
1987
  updateTempOrderCustomer(customer) {
817
1988
  const tempOrder = this.ensureTempOrder();
1989
+ const previousCustomerId = tempOrder.customer_id ?? null;
818
1990
  const customerId = customer.customer_id ?? customer.customerId ?? customer.id ?? null;
819
1991
  const customerName = customer.customer_name ?? customer.customerName ?? customer.display_name ?? customer.name ?? "";
820
1992
  tempOrder.customer_id = customerId === null || customerId === void 0 || customerId === "" ? null : Number(customerId);
@@ -824,6 +1996,15 @@ var OrderModule = class extends import_BaseModule.BaseModule {
824
1996
  );
825
1997
  tempOrder.phone = String(customer.phone || "");
826
1998
  tempOrder.email = String(customer.email || "");
1999
+ tempOrder.customer = this.buildTempOrderCustomer({
2000
+ source: customer,
2001
+ customerId: tempOrder.customer_id,
2002
+ customerName: tempOrder.customer_name,
2003
+ countryCallingCode: tempOrder.country_calling_code,
2004
+ phone: tempOrder.phone,
2005
+ email: tempOrder.email
2006
+ });
2007
+ const nextCustomerId = tempOrder.customer_id ?? null;
827
2008
  this.persistTempOrder();
828
2009
  return {
829
2010
  customerId: tempOrder.customer_id,
@@ -838,11 +2019,20 @@ var OrderModule = class extends import_BaseModule.BaseModule {
838
2019
  return;
839
2020
  }
840
2021
  const tempOrder = this.ensureTempOrder();
2022
+ const previousCustomerId = tempOrder.customer_id ?? null;
841
2023
  tempOrder.customer_id = patch.customer_id || patch.id || null;
842
2024
  tempOrder.customer_name = String(patch.customer_name || "");
843
2025
  tempOrder.country_calling_code = String(patch.country_calling_code || "");
844
2026
  tempOrder.phone = String(patch.phone || "");
845
2027
  tempOrder.email = String(patch.email || "");
2028
+ tempOrder.customer = this.buildTempOrderCustomer({
2029
+ source: snapshot || null,
2030
+ customerId: tempOrder.customer_id,
2031
+ customerName: tempOrder.customer_name,
2032
+ countryCallingCode: tempOrder.country_calling_code,
2033
+ phone: tempOrder.phone,
2034
+ email: tempOrder.email
2035
+ });
846
2036
  if (snapshot !== void 0) {
847
2037
  const extend = this.ensureExtend(tempOrder);
848
2038
  if (snapshot === null)
@@ -850,12 +2040,20 @@ var OrderModule = class extends import_BaseModule.BaseModule {
850
2040
  else
851
2041
  extend.customerSnapshot = (0, import_lodash_es.cloneDeep)(snapshot);
852
2042
  }
2043
+ const nextCustomerId = tempOrder.customer_id ?? null;
2044
+ if (String(previousCustomerId ?? "") !== String(nextCustomerId ?? "")) {
2045
+ (0, import_utils.clearTempOrderHolderAssignments)(tempOrder);
2046
+ this.clearCustomerBoundDiscounts(tempOrder);
2047
+ }
853
2048
  this.persistTempOrder();
854
- this.emitOrderCustomerChange();
2049
+ this.saveDraftInBackground();
2050
+ if (String(previousCustomerId ?? "") !== String(nextCustomerId ?? "")) {
2051
+ this.emitOrderCustomerChange();
2052
+ }
855
2053
  }
856
2054
  getOrderCustomer() {
857
2055
  const tempOrder = this.store.tempOrder;
858
- if (!tempOrder || tempOrder.customer_id === null || tempOrder.customer_id === void 0) {
2056
+ if (!tempOrder || !tempOrder.customer_id) {
859
2057
  return null;
860
2058
  }
861
2059
  return {
@@ -873,14 +2071,18 @@ var OrderModule = class extends import_BaseModule.BaseModule {
873
2071
  }
874
2072
  clearOrderCustomer() {
875
2073
  const tempOrder = this.ensureTempOrder();
2074
+ (0, import_utils.clearTempOrderHolderAssignments)(tempOrder);
876
2075
  tempOrder.customer_id = null;
877
2076
  tempOrder.customer_name = "";
878
2077
  tempOrder.country_calling_code = "";
879
2078
  tempOrder.phone = "";
880
2079
  tempOrder.email = "";
2080
+ tempOrder.customer = null;
881
2081
  if (tempOrder._extend)
882
2082
  delete tempOrder._extend.customerSnapshot;
2083
+ this.clearCustomerBoundDiscounts(tempOrder);
883
2084
  this.persistTempOrder();
2085
+ this.saveDraftInBackground();
884
2086
  this.core.effects.emit(import_types.OrderHooks.OnOrderCustomerChange, null);
885
2087
  }
886
2088
  emitOrderCustomerChange() {
@@ -920,10 +2122,28 @@ var OrderModule = class extends import_BaseModule.BaseModule {
920
2122
  }
921
2123
  /** 追加单个支付项,并立即持久化当前 tempOrder。 */
922
2124
  addOrderPayment(payment) {
2125
+ this.logInfo("addOrderPayment", {
2126
+ payment
2127
+ });
923
2128
  const tempOrder = this.ensureTempOrder();
924
- const mapped = (0, import_utils.mapPaymentItemsToOrderPayments)([payment]);
2129
+ const orderPaymentType = this.resolveNextOrderPaymentType(tempOrder);
2130
+ const mapped = (0, import_utils.mapPaymentItemsToOrderPayments)([
2131
+ this.normalizePaymentSource(
2132
+ {
2133
+ ...payment,
2134
+ type: orderPaymentType,
2135
+ order_payment_type: orderPaymentType
2136
+ },
2137
+ { defaultPaid: true }
2138
+ )
2139
+ ]);
925
2140
  tempOrder.payments = [...tempOrder.payments || [], ...mapped];
926
2141
  this.persistTempOrder();
2142
+ void this.recalculateSummary({ createIfMissing: true }).catch((error) => {
2143
+ this.logError("recalculate summary after addOrderPayment failed", {
2144
+ error: error instanceof Error ? error.message : String(error)
2145
+ });
2146
+ });
927
2147
  return tempOrder.payments;
928
2148
  }
929
2149
  /**
@@ -989,14 +2209,48 @@ var OrderModule = class extends import_BaseModule.BaseModule {
989
2209
  */
990
2210
  updateVoucherOrderPayments(payments) {
991
2211
  const tempOrder = this.ensureTempOrder();
992
- const mappedVouchers = (0, import_utils.mapPaymentItemsToOrderPayments)(payments).filter(
993
- (payment) => payment.voucher_id !== void 0 && Number(payment.voucher_id) !== 0
994
- );
2212
+ const isVoucherPayment = (payment) => {
2213
+ return payment.voucher_id !== void 0 && Number(payment.voucher_id) !== 0;
2214
+ };
2215
+ const hasSyncedOrderPayment = (payment) => {
2216
+ return payment.order_payment_id !== void 0 && payment.order_payment_id !== null;
2217
+ };
2218
+ const mappedVouchers = (0, import_utils.mapPaymentItemsToOrderPayments)(
2219
+ payments.map(
2220
+ (payment) => this.normalizePaymentSource(payment, { defaultPaid: true })
2221
+ )
2222
+ ).filter((payment) => {
2223
+ return isVoucherPayment(payment);
2224
+ });
995
2225
  const nonVoucherPayments = (tempOrder.payments || []).filter((payment) => {
996
- return payment.voucher_id === void 0 || Number(payment.voucher_id) === 0;
2226
+ return !isVoucherPayment(payment);
997
2227
  });
998
- tempOrder.payments = [...nonVoucherPayments, ...mappedVouchers];
2228
+ const syncedVoucherPayments = (tempOrder.payments || []).filter((payment) => {
2229
+ return isVoucherPayment(payment) && hasSyncedOrderPayment(payment);
2230
+ });
2231
+ const syncedVoucherPaymentIds = new Set(
2232
+ syncedVoucherPayments.map((payment) => String(payment.order_payment_id))
2233
+ );
2234
+ const replaceableVouchers = mappedVouchers.filter((payment) => {
2235
+ if (!hasSyncedOrderPayment(payment))
2236
+ return true;
2237
+ return !syncedVoucherPaymentIds.has(String(payment.order_payment_id));
2238
+ });
2239
+ const cappedVouchers = this.capVoucherPaymentsByRemainingAmount({
2240
+ vouchers: replaceableVouchers,
2241
+ nonVoucherPayments: [
2242
+ ...nonVoucherPayments,
2243
+ ...syncedVoucherPayments
2244
+ ]
2245
+ });
2246
+ tempOrder.payments = [...nonVoucherPayments, ...syncedVoucherPayments, ...cappedVouchers];
2247
+ this.updateTempOrderPaymentStatus(tempOrder);
999
2248
  this.persistTempOrder();
2249
+ void this.recalculateSummary({ createIfMissing: true }).catch((error) => {
2250
+ this.logError("recalculate summary after updateVoucherOrderPayments failed", {
2251
+ error: error instanceof Error ? error.message : String(error)
2252
+ });
2253
+ });
1000
2254
  return tempOrder.payments;
1001
2255
  }
1002
2256
  async shouldMergeProductToOrder(params) {
@@ -1015,37 +2269,98 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1015
2269
  }
1016
2270
  return true;
1017
2271
  }
2272
+ hasOrderProductLineNote(product) {
2273
+ return typeof (product == null ? void 0 : product.note) === "string" && product.note.trim().length > 0;
2274
+ }
2275
+ /**
2276
+ * 判断商品行是否显式绑定了 booking。
2277
+ *
2278
+ * @example
2279
+ * this.hasLinkedBookingUid({ metadata: { booking_uid: 'booking-1' } });
2280
+ */
2281
+ hasLinkedBookingUid(product) {
2282
+ var _a;
2283
+ const bookingUid = (product == null ? void 0 : product.booking_uid) ?? ((_a = product == null ? void 0 : product.metadata) == null ? void 0 : _a.booking_uid);
2284
+ return bookingUid !== void 0 && bookingUid !== null && String(bookingUid) !== "";
2285
+ }
1018
2286
  // ─── TempOrder: 商品 CRUD ───
1019
- async addProductToOrder(product, booking) {
1020
- var _a;
1021
- const tempOrder = this.ensureTempOrder();
2287
+ /**
2288
+ * 预约商品加车后的统一收尾:促销、折扣、summary 重算与持久化(批量拆行时只调用一次)。
2289
+ *
2290
+ * @example
2291
+ * await this.finalizeProductOrderMutation(tempOrder);
2292
+ */
2293
+ async finalizeProductOrderMutation(tempOrder, options) {
2294
+ this.syncTempOrderHolderFromBookings(tempOrder);
2295
+ if (!(options == null ? void 0 : options.skipEditDiscountConfigRefresh)) {
2296
+ await this.ensureEditDiscountConfigForProductChange(tempOrder);
2297
+ }
2298
+ if (!(options == null ? void 0 : options.skipDiscountRecalculation)) {
2299
+ await this.applyPromotion();
2300
+ }
2301
+ if (!(options == null ? void 0 : options.skipDiscountRecalculation)) {
2302
+ this.applyDiscount();
2303
+ }
2304
+ this.sanitizeTempOrderProducts(tempOrder);
2305
+ await this.recalculateSummary({ createIfMissing: true });
2306
+ this.persistTempOrder();
2307
+ }
2308
+ /**
2309
+ * 向 tempOrder 追加一条商品行(及可选 booking),不触发 summary 重算。
2310
+ * 带 booking 且 num>1 时由 `addProductToOrder` 拆成多次本方法调用(每次 num=1)。
2311
+ *
2312
+ * @example
2313
+ * await this.appendProductLineToTempOrder(tempOrder, { product_id: 1, num: 1 }, booking);
2314
+ */
2315
+ async appendProductLineToTempOrder(tempOrder, product, booking) {
2316
+ var _a, _b;
1022
2317
  const linked = booking ? this.createLinkedProductAndBooking({ product, booking }) : null;
1023
2318
  const productToAdd = (linked == null ? void 0 : linked.product) || product;
1024
2319
  const incomingFingerprint = (0, import_utils3.buildProductLineFingerprint)(
1025
- productToAdd.product_option_item,
2320
+ (0, import_utils.getProductSkuOptions)(productToAdd),
1026
2321
  productToAdd.product_bundle
1027
2322
  );
1028
- const normalizedIncoming = (0, import_utils3.normalizeOrderProduct)(productToAdd);
2323
+ const normalizedIncoming = (0, import_utils.mergeOrderProductDisplayFields)(
2324
+ productToAdd,
2325
+ (0, import_utils3.normalizeOrderProduct)(productToAdd)
2326
+ );
2327
+ const incomingBookingUid = productToAdd.booking_uid ?? ((_a = productToAdd.metadata) == null ? void 0 : _a.booking_uid);
2328
+ if (incomingBookingUid !== void 0 && incomingBookingUid !== null && String(incomingBookingUid) !== "") {
2329
+ normalizedIncoming.booking_uid = String(incomingBookingUid);
2330
+ normalizedIncoming.metadata = {
2331
+ ...normalizedIncoming.metadata || {},
2332
+ booking_uid: String(incomingBookingUid)
2333
+ };
2334
+ }
2335
+ normalizedIncoming.discount_list = (0, import_utils.normalizeOrderProductDiscountList)(
2336
+ normalizedIncoming.discount_list
2337
+ );
1029
2338
  const hasIncomingGoodPass = this.hasGoodPassDiscount(
1030
2339
  normalizedIncoming
1031
2340
  );
1032
- const shouldForceNewLine = !!booking;
2341
+ const hasIncomingProductNote = this.hasOrderProductLineNote(normalizedIncoming);
2342
+ const hasIncomingBookingUid = this.hasLinkedBookingUid(productToAdd) || this.hasLinkedBookingUid(normalizedIncoming);
2343
+ const shouldForceNewLine = !!booking || hasIncomingProductNote || hasIncomingBookingUid;
1033
2344
  const matchedIndex = hasIncomingGoodPass || shouldForceNewLine ? -1 : tempOrder.products.findIndex((item) => {
1034
2345
  if (this.hasGoodPassDiscount(item))
1035
2346
  return false;
2347
+ if (this.hasOrderProductLineNote(item))
2348
+ return false;
2349
+ if (item.order_detail_id !== void 0 && item.order_detail_id !== null)
2350
+ return false;
1036
2351
  if (item.product_id !== productToAdd.product_id)
1037
2352
  return false;
1038
2353
  if (item.product_variant_id !== productToAdd.product_variant_id)
1039
2354
  return false;
1040
2355
  const existedFingerprint2 = (0, import_utils3.buildProductLineFingerprint)(
1041
- item.product_option_item,
2356
+ (0, import_utils.getProductSkuOptions)(item),
1042
2357
  item.product_bundle
1043
2358
  );
1044
2359
  return existedFingerprint2 === incomingFingerprint;
1045
2360
  });
1046
2361
  const matchedProduct = matchedIndex === -1 ? null : tempOrder.products[matchedIndex];
1047
2362
  const existedFingerprint = matchedProduct ? (0, import_utils3.buildProductLineFingerprint)(
1048
- matchedProduct.product_option_item,
2363
+ (0, import_utils.getProductSkuOptions)(matchedProduct),
1049
2364
  matchedProduct.product_bundle
1050
2365
  ) : "";
1051
2366
  const shouldMerge = matchedProduct ? await this.shouldMergeProductToOrder({
@@ -1071,28 +2386,58 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1071
2386
  booking_uid: linked.bookingUid
1072
2387
  };
1073
2388
  }
1074
- tempOrder.products.push(normalizedIncoming);
2389
+ tempOrder.products = [...tempOrder.products, normalizedIncoming];
1075
2390
  } else {
1076
2391
  const targetProduct = matchedProduct;
1077
- const targetUid = (_a = targetProduct.metadata) == null ? void 0 : _a.unique_identification_number;
1078
- const normalizedProduct = (0, import_utils3.normalizeOrderProduct)({
1079
- ...productToAdd,
1080
- metadata: {
1081
- ...productToAdd.metadata || {},
1082
- unique_identification_number: targetUid
1083
- }
1084
- });
2392
+ const targetUid = (_b = targetProduct.metadata) == null ? void 0 : _b.unique_identification_number;
2393
+ const normalizedProduct = (0, import_utils.mergeOrderProductDisplayFields)(
2394
+ targetProduct,
2395
+ (0, import_utils3.normalizeOrderProduct)({
2396
+ ...productToAdd,
2397
+ metadata: {
2398
+ ...productToAdd.metadata || {},
2399
+ unique_identification_number: targetUid
2400
+ }
2401
+ })
2402
+ );
2403
+ normalizedProduct.discount_list = (0, import_utils.normalizeOrderProductDiscountList)(
2404
+ normalizedProduct.discount_list
2405
+ );
2406
+ const nextNum = (0, import_utils3.getSafeProductNum)(targetProduct.num + normalizedProduct.num);
2407
+ const targetIsManualProductDiscount = isManualProductDiscountProduct(targetProduct);
2408
+ const nextDiscountList = targetIsManualProductDiscount ? (0, import_utils.normalizeOrderProductDiscountList)(
2409
+ (0, import_manualProductDiscount.syncManualProductDiscountProductNum)(
2410
+ targetProduct.discount_list,
2411
+ nextNum
2412
+ )
2413
+ ) : normalizedProduct.discount_list;
1085
2414
  tempOrder.products[matchedIndex] = {
1086
2415
  ...targetProduct,
1087
2416
  ...normalizedProduct,
2417
+ discount_list: nextDiscountList,
1088
2418
  metadata: {
1089
2419
  ...targetProduct.metadata || {},
1090
2420
  ...normalizedProduct.metadata || {},
1091
2421
  unique_identification_number: targetUid
1092
2422
  },
2423
+ product_sku: {
2424
+ ...targetProduct.product_sku || { option: [] },
2425
+ ...normalizedProduct.product_sku || { option: [] },
2426
+ option: (0, import_utils.getProductSkuOptions)(normalizedProduct)
2427
+ },
2428
+ ...targetIsManualProductDiscount ? {
2429
+ selling_price: targetProduct.selling_price,
2430
+ original_price: targetProduct.original_price,
2431
+ payment_price: targetProduct.payment_price,
2432
+ metadata: {
2433
+ ...normalizedProduct.metadata || {},
2434
+ ...targetProduct.metadata || {},
2435
+ unique_identification_number: targetUid
2436
+ }
2437
+ } : {},
1093
2438
  note: targetProduct.note,
1094
2439
  order_detail_id: targetProduct.order_detail_id,
1095
- num: (0, import_utils3.getSafeProductNum)(targetProduct.num + normalizedProduct.num)
2440
+ num: nextNum
1096
2441
  };
1097
2442
  this.captureProductRuntime(
1098
2443
  tempOrder,
@@ -1104,9 +2449,79 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1104
2449
  if (linked) {
1105
2450
  tempOrder.bookings = [...tempOrder.bookings || [], linked.booking];
1106
2451
  }
1107
- this.applyDiscount();
1108
- await this.recalculateSummary({ createIfMissing: true });
1109
- this.persistTempOrder();
2452
+ }
2453
+ /**
2454
+ * 添加商品行。带 booking 时强制独立行;num>1 时拆成多条 num=1 的 product+booking(对齐 BookingByStep / ticketBooking addService)。
2455
+ *
2456
+ * @example
2457
+ * await order.addProductToOrder({ product_id: 1, num: 3 }, { start_time: '10:00' });
2458
+ * // → tempOrder.products 新增 3 行,每行 num=1,bookings 3 条
2459
+ */
2460
+ async addProductToOrder(product, booking) {
2461
+ const tempOrder = this.ensureTempOrder();
2462
+ if (booking) {
2463
+ const productRecord = product;
2464
+ const splitCount = (0, import_utils3.getSafeProductNum)(
2465
+ productRecord.num ?? productRecord.product_quantity ?? 1
2466
+ );
2467
+ if (splitCount > 1) {
2468
+ for (let i = 0; i < splitCount; i += 1) {
2469
+ const singleLine = (0, import_lodash_es.cloneDeep)(productRecord);
2470
+ singleLine.num = 1;
2471
+ delete singleLine.product_quantity;
2472
+ await this.appendProductLineToTempOrder(
2473
+ tempOrder,
2474
+ singleLine,
2475
+ (0, import_lodash_es.cloneDeep)(booking)
2476
+ );
2477
+ }
2478
+ await this.finalizeProductOrderMutation(tempOrder);
2479
+ return tempOrder.products;
2480
+ }
2481
+ }
2482
+ await this.appendProductLineToTempOrder(tempOrder, product, booking);
2483
+ await this.finalizeProductOrderMutation(tempOrder);
2484
+ return tempOrder.products;
2485
+ }
2486
+ /**
2487
+ * 批量添加商品行,所有行追加完成后只触发一次促销、折扣、summary 重算与持久化。
2488
+ *
2489
+ * @example
2490
+ * await order.addProductsToOrder([
2491
+ * { product: { product_id: 1, product_variant_id: 0, num: 1 } },
2492
+ * { product: { product_id: 2, product_variant_id: 0, num: 1 } },
2493
+ * ]);
2494
+ */
2495
+ async addProductsToOrder(items, options) {
2496
+ const tempOrder = this.ensureTempOrder();
2497
+ if (!Array.isArray(items) || items.length === 0)
2498
+ return tempOrder.products;
2499
+ for (const item of items || []) {
2500
+ const { product, booking } = item;
2501
+ if (!product)
2502
+ continue;
2503
+ if (booking) {
2504
+ const productRecord = product;
2505
+ const splitCount = (0, import_utils3.getSafeProductNum)(
2506
+ productRecord.num ?? productRecord.product_quantity ?? 1
2507
+ );
2508
+ if (splitCount > 1) {
2509
+ for (let i = 0; i < splitCount; i += 1) {
2510
+ const singleLine = (0, import_lodash_es.cloneDeep)(productRecord);
2511
+ singleLine.num = 1;
2512
+ delete singleLine.product_quantity;
2513
+ await this.appendProductLineToTempOrder(
2514
+ tempOrder,
2515
+ singleLine,
2516
+ (0, import_lodash_es.cloneDeep)(booking)
2517
+ );
2518
+ }
2519
+ continue;
2520
+ }
2521
+ }
2522
+ await this.appendProductLineToTempOrder(tempOrder, product, booking);
2523
+ }
2524
+ await this.finalizeProductOrderMutation(tempOrder, options);
1110
2525
  return tempOrder.products;
1111
2526
  }
1112
2527
  hasGoodPassDiscount(product) {
@@ -1127,15 +2542,55 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1127
2542
  (item) => (item == null ? void 0 : item.type) === "good_pass" || (item == null ? void 0 : item.tag) === "good_pass"
1128
2543
  );
1129
2544
  }
1130
- async updateProductInOrder(params) {
1131
- var _a, _b, _c, _d, _e;
2545
+ getBundleRuntimeIdentity(bundle) {
2546
+ if (!bundle || typeof bundle !== "object")
2547
+ return "";
2548
+ return [
2549
+ bundle.bundle_id ?? bundle.id ?? "",
2550
+ bundle.bundle_group_id ?? bundle.group_id ?? "",
2551
+ bundle.bundle_product_id ?? bundle._bundle_product_id ?? bundle.product_id ?? "",
2552
+ bundle.bundle_variant_id ?? bundle.product_variant_id ?? 0
2553
+ ].join("|");
2554
+ }
2555
+ preservePersistedBundlePriceFields(previousBundles, nextBundles) {
2556
+ if (!Array.isArray(nextBundles))
2557
+ return nextBundles;
2558
+ if (!Array.isArray(previousBundles) || previousBundles.length === 0)
2559
+ return nextBundles;
2560
+ const previousByIdentity = /* @__PURE__ */ new Map();
2561
+ previousBundles.forEach((bundle) => {
2562
+ const identity = this.getBundleRuntimeIdentity(bundle);
2563
+ if (identity)
2564
+ previousByIdentity.set(identity, bundle);
2565
+ });
2566
+ return nextBundles.map((bundle, index) => {
2567
+ if (!bundle || typeof bundle !== "object")
2568
+ return bundle;
2569
+ const previous = previousByIdentity.get(this.getBundleRuntimeIdentity(bundle)) || previousBundles[index];
2570
+ if (!previous || typeof previous !== "object")
2571
+ return bundle;
2572
+ return {
2573
+ ...bundle,
2574
+ price: previous.price,
2575
+ custom_price: previous.custom_price,
2576
+ bundle_payment_price: previous.bundle_payment_price,
2577
+ bundle_selling_price: previous.bundle_selling_price,
2578
+ original_price: previous.original_price,
2579
+ product_price: previous.product_price
2580
+ };
2581
+ });
2582
+ }
2583
+ async updateOrderProduct(params) {
2584
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
1132
2585
  const {
1133
2586
  product_id,
1134
2587
  product_variant_id,
1135
2588
  updates,
1136
2589
  unique_identification_number,
1137
- product_option_item,
1138
- product_bundle
2590
+ identity_key,
2591
+ product_sku,
2592
+ product_bundle,
2593
+ booking
1139
2594
  } = params;
1140
2595
  const tempOrder = this.ensureTempOrder();
1141
2596
  const identityLookup = {
@@ -1144,12 +2599,30 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1144
2599
  };
1145
2600
  if (unique_identification_number !== void 0) {
1146
2601
  identityLookup.unique_identification_number = unique_identification_number;
2602
+ if (identity_key === void 0) {
2603
+ identityLookup.identity_key = unique_identification_number;
2604
+ }
1147
2605
  }
1148
- if (product_option_item !== void 0)
1149
- identityLookup.product_option_item = product_option_item;
2606
+ if (identity_key !== void 0) {
2607
+ identityLookup.identity_key = identity_key;
2608
+ }
2609
+ if (product_sku !== void 0)
2610
+ identityLookup.product_sku = product_sku;
1150
2611
  if (product_bundle !== void 0)
1151
2612
  identityLookup.product_bundle = product_bundle;
1152
- const productIndex = (0, import_utils3.getProductIdentityIndex)(tempOrder.products, identityLookup);
2613
+ let productIndex = -1;
2614
+ if (unique_identification_number !== void 0) {
2615
+ const targetUid = String(unique_identification_number);
2616
+ productIndex = tempOrder.products.findIndex((item) => {
2617
+ var _a2;
2618
+ return String(
2619
+ ((_a2 = item.metadata) == null ? void 0 : _a2.unique_identification_number) || item.unique_identification_number || ""
2620
+ ) === targetUid;
2621
+ });
2622
+ }
2623
+ if (productIndex === -1) {
2624
+ productIndex = (0, import_utils3.getProductIdentityIndex)(tempOrder.products, identityLookup);
2625
+ }
1153
2626
  if (productIndex === -1) {
1154
2627
  throw new Error("[Order] 目标商品不存在,无法更新");
1155
2628
  }
@@ -1163,12 +2636,49 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1163
2636
  ...targetProduct.metadata || {},
1164
2637
  ...(updates == null ? void 0 : updates.metadata) || {},
1165
2638
  unique_identification_number: ((_a = targetProduct.metadata) == null ? void 0 : _a.unique_identification_number) || unique_identification_number
2639
+ },
2640
+ product_sku: {
2641
+ ...targetProduct.product_sku || { option: [] },
2642
+ ...(updates == null ? void 0 : updates.product_sku) && typeof updates.product_sku === "object" ? updates.product_sku : {},
2643
+ option: Array.isArray((_b = updates == null ? void 0 : updates.product_sku) == null ? void 0 : _b.option) ? updates.product_sku.option : (0, import_utils.getProductSkuOptions)(targetProduct)
1166
2644
  }
1167
2645
  };
1168
2646
  nextProduct.num = (0, import_utils3.getSafeProductNum)(nextProduct.num);
1169
2647
  const callerUpdatesTopPrice = Object.prototype.hasOwnProperty.call(updates || {}, "selling_price") || Object.prototype.hasOwnProperty.call(updates || {}, "original_price");
1170
- const callerUpdatesMainMeta = ((_b = updates == null ? void 0 : updates.metadata) == null ? void 0 : _b.main_product_selling_price) !== void 0 || ((_c = updates == null ? void 0 : updates.metadata) == null ? void 0 : _c.main_product_original_price) !== void 0 || ((_d = updates == null ? void 0 : updates.metadata) == null ? void 0 : _d.source_product_price) !== void 0;
1171
- if (callerUpdatesTopPrice && !callerUpdatesMainMeta) {
2648
+ const callerUpdatesMainMeta = ((_c = updates == null ? void 0 : updates.metadata) == null ? void 0 : _c.main_product_selling_price) !== void 0 || ((_d = updates == null ? void 0 : updates.metadata) == null ? void 0 : _d.main_product_original_price) !== void 0 || ((_e = updates == null ? void 0 : updates.metadata) == null ? void 0 : _e.source_product_price) !== void 0;
2649
+ const isPersistedOrderLine = targetProduct.order_detail_id !== void 0 && targetProduct.order_detail_id !== null;
2650
+ const callerChangesDiscountList = Array.isArray(updates == null ? void 0 : updates.discount_list) && updates.discount_list.length > 0 && !isSameDiscountList(updates.discount_list, targetProduct.discount_list);
2651
+ const callerUpdatesManualPrice = ((_f = updates == null ? void 0 : updates.metadata) == null ? void 0 : _f.price_override) !== void 0 || ((_g = updates == null ? void 0 : updates.metadata) == null ? void 0 : _g.is_manual_discount) !== void 0 || ((_h = updates == null ? void 0 : updates.metadata) == null ? void 0 : _h.product_discount_reason) !== void 0 || callerChangesDiscountList;
2652
+ const callerAllowsBookingReprice = (() => {
2653
+ if (params.allow_booking_reprice !== true || !booking || !callerUpdatesTopPrice || !callerUpdatesMainMeta) {
2654
+ return false;
2655
+ }
2656
+ const hasChangedPrice = (nextValue, currentValue) => {
2657
+ if (nextValue === void 0 || nextValue === null || nextValue === "") {
2658
+ return false;
2659
+ }
2660
+ return !new import_decimal.default(Number(nextValue) || 0).equals(
2661
+ new import_decimal.default(Number(currentValue) || 0)
2662
+ );
2663
+ };
2664
+ return hasChangedPrice(updates.selling_price, targetProduct.selling_price) || hasChangedPrice(updates.original_price, targetProduct.original_price);
2665
+ })();
2666
+ if (isPersistedOrderLine && !callerUpdatesManualPrice && !callerAllowsBookingReprice) {
2667
+ nextProduct.selling_price = targetProduct.selling_price;
2668
+ nextProduct.original_price = targetProduct.original_price;
2669
+ nextProduct.payment_price = targetProduct.payment_price;
2670
+ nextProduct.metadata = {
2671
+ ...nextProduct.metadata || {},
2672
+ source_product_price: (_i = targetProduct.metadata) == null ? void 0 : _i.source_product_price,
2673
+ main_product_selling_price: (_j = targetProduct.metadata) == null ? void 0 : _j.main_product_selling_price,
2674
+ main_product_original_price: (_k = targetProduct.metadata) == null ? void 0 : _k.main_product_original_price,
2675
+ price_schema_version: ((_l = targetProduct.metadata) == null ? void 0 : _l.price_schema_version) ?? 2
2676
+ };
2677
+ nextProduct.product_bundle = this.preservePersistedBundlePriceFields(
2678
+ targetProduct.product_bundle,
2679
+ nextProduct.product_bundle
2680
+ );
2681
+ } else if (callerUpdatesTopPrice && !callerUpdatesMainMeta) {
1172
2682
  const existedMeta = nextProduct.metadata || {};
1173
2683
  nextProduct.metadata = { ...existedMeta };
1174
2684
  delete nextProduct.metadata.source_product_price;
@@ -1176,39 +2686,280 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1176
2686
  delete nextProduct.metadata.main_product_original_price;
1177
2687
  delete nextProduct.metadata.price_schema_version;
1178
2688
  }
1179
- tempOrder.products[productIndex] = (0, import_utils3.normalizeOrderProduct)(nextProduct);
2689
+ let normalizedProduct = (0, import_utils.mergeOrderProductDisplayFields)(
2690
+ nextProduct,
2691
+ (0, import_utils3.normalizeOrderProduct)(nextProduct)
2692
+ );
2693
+ normalizedProduct.discount_list = (0, import_utils.normalizeOrderProductDiscountList)(
2694
+ normalizedProduct.discount_list
2695
+ );
2696
+ const preservedBookingUid = nextProduct.booking_uid || ((_m = nextProduct.metadata) == null ? void 0 : _m.booking_uid) || targetProduct.booking_uid || ((_n = targetProduct.metadata) == null ? void 0 : _n.booking_uid);
2697
+ if (!booking && preservedBookingUid) {
2698
+ normalizedProduct.booking_uid = preservedBookingUid;
2699
+ normalizedProduct.metadata = {
2700
+ ...normalizedProduct.metadata || {},
2701
+ booking_uid: preservedBookingUid
2702
+ };
2703
+ }
2704
+ if (booking) {
2705
+ const productUid = String(
2706
+ ((_o = normalizedProduct.metadata) == null ? void 0 : _o.unique_identification_number) || ((_p = targetProduct.metadata) == null ? void 0 : _p.unique_identification_number) || unique_identification_number || (0, import_utils.createUuidV4)()
2707
+ );
2708
+ normalizedProduct.metadata = {
2709
+ ...normalizedProduct.metadata || {},
2710
+ unique_identification_number: productUid
2711
+ };
2712
+ const linked = this.createLinkedProductAndBooking({
2713
+ product: {
2714
+ ...normalizedProduct,
2715
+ unique_identification_number: productUid
2716
+ },
2717
+ booking
2718
+ });
2719
+ this.removeLinkedBookingsForProduct(tempOrder, targetProduct);
2720
+ normalizedProduct = {
2721
+ ...normalizedProduct,
2722
+ booking_uid: linked.bookingUid,
2723
+ metadata: {
2724
+ ...normalizedProduct.metadata || {},
2725
+ booking_uid: linked.bookingUid,
2726
+ unique_identification_number: productUid
2727
+ }
2728
+ };
2729
+ tempOrder.bookings = [...tempOrder.bookings || [], linked.booking];
2730
+ }
2731
+ tempOrder.products[productIndex] = normalizedProduct;
2732
+ this.syncTempOrderHolderFromBookings(tempOrder);
1180
2733
  this.captureProductRuntime(
1181
2734
  tempOrder,
1182
2735
  updates,
1183
2736
  tempOrder.products[productIndex],
1184
- (_e = tempOrder.products[productIndex].metadata) == null ? void 0 : _e.unique_identification_number
2737
+ (_q = tempOrder.products[productIndex].metadata) == null ? void 0 : _q.unique_identification_number
1185
2738
  );
2739
+ await this.applyPromotion();
1186
2740
  this.applyDiscount();
2741
+ this.sanitizeTempOrderProducts(tempOrder);
1187
2742
  await this.recalculateSummary({ createIfMissing: true });
1188
2743
  this.persistTempOrder();
1189
2744
  return tempOrder.products;
1190
2745
  }
1191
- async removeProductFromOrder(identity) {
2746
+ async updateOrderProductQuantity(params) {
2747
+ var _a;
2748
+ const {
2749
+ product_id,
2750
+ product_variant_id,
2751
+ num,
2752
+ unique_identification_number,
2753
+ identity_key,
2754
+ product_sku,
2755
+ product_bundle
2756
+ } = params;
2757
+ const tempOrder = this.ensureTempOrder();
2758
+ const identityLookup = {
2759
+ product_id,
2760
+ product_variant_id
2761
+ };
2762
+ if (unique_identification_number !== void 0) {
2763
+ identityLookup.unique_identification_number = unique_identification_number;
2764
+ if (identity_key === void 0) {
2765
+ identityLookup.identity_key = unique_identification_number;
2766
+ }
2767
+ }
2768
+ if (identity_key !== void 0)
2769
+ identityLookup.identity_key = identity_key;
2770
+ if (product_sku !== void 0)
2771
+ identityLookup.product_sku = product_sku;
2772
+ if (product_bundle !== void 0)
2773
+ identityLookup.product_bundle = product_bundle;
2774
+ let productIndex = -1;
2775
+ if (unique_identification_number !== void 0) {
2776
+ const targetUid = String(unique_identification_number);
2777
+ productIndex = tempOrder.products.findIndex((item) => {
2778
+ var _a2;
2779
+ return String(
2780
+ ((_a2 = item.metadata) == null ? void 0 : _a2.unique_identification_number) || item.unique_identification_number || ""
2781
+ ) === targetUid;
2782
+ });
2783
+ }
2784
+ if (productIndex === -1) {
2785
+ productIndex = (0, import_utils3.getProductIdentityIndex)(tempOrder.products, identityLookup);
2786
+ }
2787
+ if (productIndex === -1) {
2788
+ throw new Error("[Order] 目标商品不存在,无法更新数量");
2789
+ }
2790
+ const targetProduct = tempOrder.products[productIndex];
2791
+ const normalizedProduct = (0, import_utils3.normalizeOrderProduct)({
2792
+ ...targetProduct,
2793
+ num: (0, import_utils3.getSafeProductNum)(num),
2794
+ metadata: {
2795
+ ...targetProduct.metadata || {},
2796
+ unique_identification_number: ((_a = targetProduct.metadata) == null ? void 0 : _a.unique_identification_number) || unique_identification_number
2797
+ }
2798
+ });
2799
+ normalizedProduct.discount_list = (0, import_utils.normalizeOrderProductDiscountList)(
2800
+ normalizedProduct.discount_list
2801
+ );
2802
+ tempOrder.products[productIndex] = normalizedProduct;
2803
+ await this.applyPromotion();
2804
+ this.applyDiscount();
2805
+ this.sanitizeTempOrderProducts(tempOrder);
2806
+ await this.recalculateSummary({ createIfMissing: true });
2807
+ this.persistTempOrder();
2808
+ return tempOrder.products;
2809
+ }
2810
+ updateOrderBooking(params) {
2811
+ const { unique_identification_number, updates } = params;
1192
2812
  const tempOrder = this.ensureTempOrder();
1193
- tempOrder.products = tempOrder.products.filter(
1194
- (item) => !(0, import_utils3.isIdentityMatch)(item, identity)
2813
+ const bookingUid = String(unique_identification_number || "");
2814
+ const bookingIndex = this.findBookingIndexByUniqueIdentificationNumber(
2815
+ tempOrder,
2816
+ bookingUid
1195
2817
  );
2818
+ if (!bookingUid || bookingIndex === -1) {
2819
+ throw new Error("[Order] 目标 booking 不存在,无法更新");
2820
+ }
2821
+ const targetBooking = tempOrder.bookings[bookingIndex] || {};
2822
+ const nextBooking = {
2823
+ ...targetBooking,
2824
+ ...updates,
2825
+ metadata: {
2826
+ ...targetBooking.metadata || {},
2827
+ ...updates.metadata || {},
2828
+ unique_identification_number: bookingUid
2829
+ }
2830
+ };
2831
+ this.syncBookingMetadataHolder(nextBooking, nextBooking.metadata);
2832
+ nextBooking.is_all = (0, import_utils.normalizeBookingIsAll)(nextBooking);
2833
+ nextBooking.sub_type = (0, import_utils.normalizeBookingSubType)(nextBooking);
2834
+ tempOrder.bookings[bookingIndex] = nextBooking;
2835
+ this.syncTempOrderHolderFromBookings(tempOrder);
2836
+ this.persistTempOrder();
2837
+ return tempOrder.bookings;
2838
+ }
2839
+ /**
2840
+ * 商品行写路径收尾:促销 → 折扣 → 清洗 → summary → 持久化。
2841
+ * 批量删除等多行变更场景只应调用一次,避免 N 次 applyPromotion。
2842
+ *
2843
+ * @example
2844
+ * await this.finalizeAfterProductsMutation(tempOrder);
2845
+ */
2846
+ async finalizeAfterProductsMutation(tempOrder) {
2847
+ this.syncTempOrderHolderFromBookings(tempOrder);
2848
+ await this.applyPromotion();
1196
2849
  this.applyDiscount();
2850
+ this.sanitizeTempOrderProducts(tempOrder);
1197
2851
  await this.recalculateSummary({ createIfMissing: true });
1198
2852
  this.persistTempOrder();
2853
+ }
2854
+ /**
2855
+ * 批量按 identity 删除购物车行,末尾仅一次促销重算。
2856
+ *
2857
+ * @example
2858
+ * await order.removeProductsFromOrder([identityA, identityB]);
2859
+ */
2860
+ async removeProductsFromOrder(identities) {
2861
+ const tempOrder = this.ensureTempOrder();
2862
+ if (!identities.length) {
2863
+ return tempOrder.products;
2864
+ }
2865
+ const removedProducts = [];
2866
+ tempOrder.products = tempOrder.products.filter((item) => {
2867
+ const shouldRemove = identities.some((identity) => (0, import_utils3.isIdentityMatch)(item, identity));
2868
+ if (shouldRemove)
2869
+ removedProducts.push(item);
2870
+ return !shouldRemove;
2871
+ });
2872
+ for (const product of removedProducts) {
2873
+ this.removeLinkedBookingsForProduct(tempOrder, product);
2874
+ }
2875
+ await this.finalizeAfterProductsMutation(tempOrder);
1199
2876
  return tempOrder.products;
1200
2877
  }
2878
+ async removeProductFromOrder(identity) {
2879
+ return this.removeProductsFromOrder([identity]);
2880
+ }
2881
+ /**
2882
+ * 仅清空购物车行(products / bookings),不重置整单。
2883
+ * 用于「仅清空商品」;客户、备注、支付等协议字段保持不变。
2884
+ */
2885
+ async clearOrderCartLines() {
2886
+ const tempOrder = this.ensureTempOrder();
2887
+ tempOrder.products = [];
2888
+ tempOrder.bookings = [];
2889
+ this.syncTempOrderHolderFromBookings(tempOrder);
2890
+ if (tempOrder._extend && typeof tempOrder._extend === "object") {
2891
+ tempOrder._extend = {
2892
+ ...tempOrder._extend,
2893
+ productsByUid: {}
2894
+ };
2895
+ }
2896
+ await this.applyPromotion();
2897
+ this.applyDiscount();
2898
+ this.sanitizeTempOrderProducts(tempOrder);
2899
+ await this.recalculateSummary({ createIfMissing: true });
2900
+ this.persistTempOrder();
2901
+ return tempOrder;
2902
+ }
1201
2903
  // ─── TempOrder: 提交 ───
2904
+ buildCurrentSubmitPayloadForLocalPrint(params) {
2905
+ var _a, _b, _c;
2906
+ const tempOrder = this.ensureTempOrder();
2907
+ this.persistTempOrder();
2908
+ const payload = (0, import_utils.buildSubmitPayload)({
2909
+ tempOrder,
2910
+ cacheId: (params == null ? void 0 : params.cacheId) ?? this.cacheId,
2911
+ platform: (params == null ? void 0 : params.platform) || ((_a = this.otherParams) == null ? void 0 : _a.platform),
2912
+ businessCode: (params == null ? void 0 : params.businessCode) ?? ((_b = this.otherParams) == null ? void 0 : _b.businessCode) ?? ((_c = this.otherParams) == null ? void 0 : _c.business_code),
2913
+ channel: params == null ? void 0 : params.channel,
2914
+ type: params == null ? void 0 : params.type,
2915
+ summary: this.store.summary || (0, import_utils.createEmptySummary)(),
2916
+ enhance: (nextPayload) => ({
2917
+ ...nextPayload,
2918
+ order_number: tempOrder.order_number ?? nextPayload.order_number ?? null,
2919
+ shop_order_number: tempOrder.shop_order_number ?? nextPayload.shop_order_number ?? null,
2920
+ shop_full_order_number: tempOrder.shop_full_order_number ?? nextPayload.shop_full_order_number ?? null,
2921
+ small_ticket_data_flag: 1
2922
+ })
2923
+ });
2924
+ payload.created_at = void 0;
2925
+ return payload;
2926
+ }
2927
+ async applyLocalPrintOrderNumbers(order) {
2928
+ const tempOrder = this.ensureTempOrder();
2929
+ if (!order || typeof order !== "object")
2930
+ return tempOrder;
2931
+ const shopOrderNumber = order.shop_order_number;
2932
+ const shopFullOrderNumber = order.shop_full_order_number;
2933
+ if (shopOrderNumber !== void 0 && shopOrderNumber !== null && shopOrderNumber !== "") {
2934
+ tempOrder.shop_order_number = String(shopOrderNumber);
2935
+ }
2936
+ if (shopFullOrderNumber !== void 0 && shopFullOrderNumber !== null && shopFullOrderNumber !== "") {
2937
+ tempOrder.shop_full_order_number = String(shopFullOrderNumber);
2938
+ }
2939
+ this.persistTempOrder();
2940
+ await this.saveDraft();
2941
+ return tempOrder;
2942
+ }
1202
2943
  /**
1203
2944
  * 提交当前 Sales tempOrder。
1204
2945
  *
1205
2946
  * smallTicketDataFlag 用于 B 端 checkout 小票数据返回。PaymentModal 在支付提交时
1206
- * 应传 1,确保 /order/sales/checkout 返回打印所需数据。
2947
+ * 应传 1,确保 /shop/order/sales/checkout 返回打印所需数据。
1207
2948
  */
1208
2949
  async submitTempOrder(params) {
1209
- var _a, _b, _c;
2950
+ return this.runSubmitTempOrder(params);
2951
+ }
2952
+ async submitTempOrderAsync(params) {
2953
+ return this.runSubmitTempOrder({
2954
+ ...params,
2955
+ syncMode: true
2956
+ });
2957
+ }
2958
+ async runSubmitTempOrder(params) {
2959
+ var _a, _b, _c, _d, _e;
1210
2960
  const tempOrder = this.ensureTempOrder();
1211
2961
  this.persistTempOrder();
2962
+ const latestSummary = await this.recalculateSummary({ createIfMissing: true }) || this.store.summary || (0, import_utils.createEmptySummary)();
1212
2963
  const effectiveCacheId = (params == null ? void 0 : params.cacheId) ?? this.cacheId;
1213
2964
  const hasPaymentOverride = (params == null ? void 0 : params.payments) !== void 0;
1214
2965
  const hasPaymentStatusOverride = (params == null ? void 0 : params.paymentStatus) !== void 0;
@@ -1224,26 +2975,37 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1224
2975
  ...hasPaymentStatusOverride ? { payment_status: params == null ? void 0 : params.paymentStatus } : {},
1225
2976
  ...hasSmallTicketDataFlagOverride ? { small_ticket_data_flag: params == null ? void 0 : params.smallTicketDataFlag } : {}
1226
2977
  };
1227
- return (params == null ? void 0 : params.enhancePayload) ? params.enhancePayload(nextPayload, ctx) : nextPayload;
2978
+ const enhancedPayload = (params == null ? void 0 : params.enhancePayload) ? params.enhancePayload(nextPayload, ctx) : nextPayload;
2979
+ return enhancedPayload;
1228
2980
  } : void 0;
1229
2981
  const payload = (0, import_utils.buildSubmitPayload)({
1230
2982
  tempOrder,
1231
2983
  cacheId: effectiveCacheId,
1232
2984
  platform: (params == null ? void 0 : params.platform) || ((_a = this.otherParams) == null ? void 0 : _a.platform),
1233
- businessCode: params == null ? void 0 : params.businessCode,
2985
+ businessCode: (params == null ? void 0 : params.businessCode) ?? ((_b = this.otherParams) == null ? void 0 : _b.businessCode) ?? ((_c = this.otherParams) == null ? void 0 : _c.business_code),
1234
2986
  channel: params == null ? void 0 : params.channel,
1235
2987
  type: params == null ? void 0 : params.type,
2988
+ summary: latestSummary,
2989
+ request_unique_idempotency_token: params == null ? void 0 : params.request_unique_idempotency_token,
1236
2990
  enhance: enhancePayload
1237
2991
  });
2992
+ if (params == null ? void 0 : params.syncMode) {
2993
+ payload.sync_mode = true;
2994
+ }
2995
+ if (!payload.created_at) {
2996
+ payload.created_at = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
2997
+ }
1238
2998
  await this.saveDraft();
1239
2999
  let result;
1240
3000
  try {
1241
3001
  this.logInfo("submitTempOrder calling sales checkout", {
1242
3002
  orderId: payload.order_id,
1243
3003
  externalSaleNumber: payload.external_sale_number,
3004
+ requestUniqueIdempotencyToken: payload.request_unique_idempotency_token,
1244
3005
  paymentStatus: payload.payment_status,
1245
- paymentsCount: ((_b = payload.payments) == null ? void 0 : _b.length) || 0,
1246
- smallTicketDataFlag: payload.small_ticket_data_flag
3006
+ paymentsCount: ((_d = payload.payments) == null ? void 0 : _d.length) || 0,
3007
+ smallTicketDataFlag: payload.small_ticket_data_flag,
3008
+ syncMode: payload.sync_mode
1247
3009
  });
1248
3010
  result = await this.submitSalesOrder({
1249
3011
  query: payload
@@ -1261,7 +3023,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1261
3023
  orderId: payload.order_id,
1262
3024
  externalSaleNumber: payload.external_sale_number,
1263
3025
  paymentStatus: payload.payment_status,
1264
- paymentsCount: ((_c = payload.payments) == null ? void 0 : _c.length) || 0
3026
+ paymentsCount: ((_e = payload.payments) == null ? void 0 : _e.length) || 0
1265
3027
  });
1266
3028
  throw error;
1267
3029
  }
@@ -1271,6 +3033,11 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1271
3033
  return result;
1272
3034
  }
1273
3035
  const submittedOrderId = this.extractOrderIdFromSubmitResult(result);
3036
+ this.logInfo("runSubmitTempOrder: 提交成功", {
3037
+ submittedOrderId,
3038
+ result,
3039
+ tempOrder
3040
+ });
1274
3041
  if (submittedOrderId !== null && submittedOrderId !== void 0) {
1275
3042
  tempOrder.order_id = submittedOrderId;
1276
3043
  const resultRecord = result;
@@ -1278,23 +3045,43 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1278
3045
  submittedOrderId,
1279
3046
  (resultRecord == null ? void 0 : resultRecord.data) || resultRecord || {}
1280
3047
  );
3048
+ } else if (this.isLocalPendingSubmitResult(result)) {
3049
+ this.store.syncState = "local";
3050
+ } else {
3051
+ this.store.syncState = "submitted";
1281
3052
  }
1282
3053
  return result;
1283
3054
  }
1284
3055
  async markLocalOrderSynced(orderId, remoteOrder) {
1285
3056
  const tempOrder = this.ensureTempOrder();
1286
3057
  tempOrder.order_id = orderId;
3058
+ this.applyRemoteOrderNumbersToTempOrder(tempOrder, remoteOrder);
1287
3059
  this.store.lastOrderInfo = remoteOrder;
1288
3060
  this.store.syncState = "submitted";
1289
3061
  this.persistTempOrder();
1290
3062
  await this.saveDraft();
1291
3063
  }
3064
+ applyRemoteOrderNumbersToTempOrder(tempOrder, remoteOrder) {
3065
+ const applyOrderNumber = (key) => {
3066
+ const value = remoteOrder == null ? void 0 : remoteOrder[key];
3067
+ if (value !== void 0 && value !== null && value !== "") {
3068
+ tempOrder[key] = String(value);
3069
+ }
3070
+ };
3071
+ applyOrderNumber("order_number");
3072
+ applyOrderNumber("shop_order_number");
3073
+ applyOrderNumber("shop_full_order_number");
3074
+ }
1292
3075
  isSubmitResponseRejected(response) {
1293
3076
  const isErrorCode = (response == null ? void 0 : response.code) !== void 0 && response.code !== 200 && response.code !== "200";
1294
3077
  const isErrorStatus = (response == null ? void 0 : response.status) === false || typeof (response == null ? void 0 : response.status) === "number" && response.status >= 400;
1295
3078
  const isErrorSuccess = (response == null ? void 0 : response.success) === false;
1296
3079
  return isErrorCode || isErrorStatus || isErrorSuccess;
1297
3080
  }
3081
+ isLocalPendingSubmitResult(response) {
3082
+ const data = (response == null ? void 0 : response.data) && typeof response.data === "object" ? response.data : response;
3083
+ return Number(data == null ? void 0 : data.need_sync) === 1;
3084
+ }
1298
3085
  isSubmitErrorResponse(response) {
1299
3086
  if (!response || typeof response !== "object")
1300
3087
  return false;
@@ -1322,26 +3109,51 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1322
3109
  }
1323
3110
  });
1324
3111
  }
3112
+ generateIdempotencyToken() {
3113
+ const tempOrder = this.ensureTempOrder();
3114
+ const token = this.buildPaymentSyncIdempotencyToken(
3115
+ tempOrder,
3116
+ tempOrder.payments
3117
+ );
3118
+ return `${token}_${Date.now()}`;
3119
+ }
1325
3120
  async syncPaymentsToOrder(params) {
1326
3121
  const tempOrder = this.ensureTempOrder();
1327
3122
  const mappedPayments = (0, import_utils.mapPaymentItemsToOrderPayments)(
1328
3123
  params.payments || []
1329
3124
  );
3125
+ const paymentTotal = this.calculatePaymentTotal(mappedPayments);
3126
+ const targetAmount = this.getPaymentTargetAmount();
3127
+ const isFullyPaid = targetAmount.lte(0) ? true : paymentTotal.gte(targetAmount);
3128
+ const paymentStatus = isFullyPaid ? params.paymentStatus || "paid" : "partially_paid";
1330
3129
  tempOrder.payments = mappedPayments;
1331
- if (params.paymentStatus)
1332
- tempOrder.payment_status = params.paymentStatus;
3130
+ tempOrder.payment_status = paymentStatus;
1333
3131
  this.persistTempOrder();
1334
3132
  await this.saveDraft();
1335
- const paymentTotal = this.calculatePaymentTotal(mappedPayments);
1336
- const targetAmount = this.getPaymentTargetAmount();
1337
- const isFullyPaid = targetAmount.lte(0) ? false : paymentTotal.gte(targetAmount);
1338
- if (!isFullyPaid || !params.submitWhenPaid) {
3133
+ if (!params.submitWhenPaid) {
1339
3134
  return { isFullyPaid };
1340
3135
  }
3136
+ if (this.store.syncState === "submitting") {
3137
+ return { isFullyPaid };
3138
+ }
3139
+ this.store.syncState = "submitting";
3140
+ const paymentSyncIdempotencyToken = this.buildPaymentSyncIdempotencyToken(
3141
+ tempOrder,
3142
+ mappedPayments
3143
+ );
1341
3144
  const submitResult = await this.submitTempOrder({
1342
3145
  payments: mappedPayments,
1343
- paymentStatus: params.paymentStatus || "paid",
1344
- smallTicketDataFlag: params.smallTicketDataFlag
3146
+ paymentStatus,
3147
+ smallTicketDataFlag: params.smallTicketDataFlag,
3148
+ businessCode: params.businessCode,
3149
+ channel: params.channel,
3150
+ enhancePayload: (payload) => {
3151
+ const nextPayload = {
3152
+ ...payload,
3153
+ request_unique_idempotency_token: paymentSyncIdempotencyToken
3154
+ };
3155
+ return nextPayload;
3156
+ }
1345
3157
  });
1346
3158
  return { isFullyPaid, submitResult };
1347
3159
  }
@@ -1477,7 +3289,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1477
3289
  * Checkout 专用:创建订单到后端
1478
3290
  *
1479
3291
  * 专门为 Checkout 模块设计的订单创建方法,
1480
- * 直接调用 /order/checkout 接口创建订单
3292
+ * 通过 OS Server 调用 checkout 接口创建订单
1481
3293
  * 接收已经处理好的订单数据,无需再处理购物车
1482
3294
  *
1483
3295
  * @param params Checkout 订单参数(已处理的订单数据)
@@ -1546,7 +3358,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1546
3358
  orderData.schedule_date = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
1547
3359
  }
1548
3360
  console.log("[Order] 调用后端接口创建订单:", {
1549
- url: "/order/checkout",
3361
+ url: "/shop/order/checkout",
1550
3362
  orderType: orderData.type,
1551
3363
  platform: orderData.platform,
1552
3364
  isDeposit: orderData.is_deposit,
@@ -1557,7 +3369,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1557
3369
  paymentsMethods: ((_m = orderData.payments) == null ? void 0 : _m.map((p) => p.code)) || []
1558
3370
  });
1559
3371
  this.logInfo("Calling backend checkout API", {
1560
- url: "/order/checkout",
3372
+ url: "/shop/order/checkout",
1561
3373
  orderType: orderData.type,
1562
3374
  platform: orderData.platform,
1563
3375
  isDeposit: orderData.is_deposit,
@@ -1579,7 +3391,11 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1579
3391
  hasOrderId: !!orderData.order_id,
1580
3392
  smallTicketDataFlag: orderData.small_ticket_data_flag
1581
3393
  });
1582
- const response = await this.request.post("/order/checkout", orderData);
3394
+ const response = await this.request.post("/order/checkout", orderData, {
3395
+ osServer: true,
3396
+ customToast: () => {
3397
+ }
3398
+ });
1583
3399
  this.logInfo("Order API called successfully", {
1584
3400
  response
1585
3401
  });
@@ -1599,7 +3415,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1599
3415
  async submitSalesOrder(params) {
1600
3416
  const { url, query } = params;
1601
3417
  const fetchUrl = url || "/order/sales/checkout";
1602
- return this.request.post(fetchUrl, query, { customToast: () => {
3418
+ return this.request.post(fetchUrl, query, { osServer: true, customToast: () => {
1603
3419
  } });
1604
3420
  }
1605
3421
  /**
@@ -1623,13 +3439,18 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1623
3439
  emails: params.emails
1624
3440
  });
1625
3441
  }
1626
- // TODO 获取详情的接口
1627
- async getOrderInfoByRemote(order_id) {
1628
- const res = await this.request.get(`/order/sales/${order_id}`, {
1629
- with: ["products", "bookings", "payments", "customer", "summary", "contacts_info"]
1630
- }, {
1631
- osServer: true
1632
- });
3442
+ async getSalesOrderByLookup(params) {
3443
+ const lookup = params.lookup === void 0 || params.lookup === null ? "" : String(params.lookup).trim();
3444
+ if (!lookup) {
3445
+ throw new Error("加载销售详情需要 lookup");
3446
+ }
3447
+ if (lookup.startsWith("LOCAL_")) {
3448
+ params.forceRemote = false;
3449
+ }
3450
+ const res = await this.request.get(`/order/sales/${encodeURIComponent(lookup)}`, {
3451
+ with: ["products", "bookings", "payments", "customer", "summary", "contacts_info"],
3452
+ ...params.forceRemote ? { forceRemote: true } : {}
3453
+ }, { osServer: true });
1633
3454
  if (res.code === 200) {
1634
3455
  this.store.lastOrderInfo = res.data;
1635
3456
  }
@@ -1642,58 +3463,64 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1642
3463
  * 例如数组字段、商品行唯一值、价格 metadata、summary 派生状态和 _extend。
1643
3464
  */
1644
3465
  async hydrateTempOrderFromRecord(record, options) {
3466
+ var _a, _b, _c;
1645
3467
  const raw = record && typeof record === "object" && record.data && record.order_id == null ? record.data : record || {};
1646
- const defaults = this.createDefaultTempOrderInstance();
1647
- const nextTempOrder = {
1648
- ...defaults
3468
+ const nextTempOrder = this.normalizeTempOrderForRuntime(raw);
3469
+ const rawSummary = raw.summary && typeof raw.summary === "object" ? raw.summary : {};
3470
+ const summarySurcharges = Array.isArray(rawSummary.surcharges) ? rawSummary.surcharges.map((s) => ({ ...s || {} })) : (0, import_lodash_es.cloneDeep)(nextTempOrder.surcharges || []);
3471
+ this.store.tempOrder = nextTempOrder;
3472
+ this.store.summary = {
3473
+ ...(0, import_utils.createEmptySummary)(),
3474
+ ...rawSummary,
3475
+ surcharges: summarySurcharges
1649
3476
  };
1650
- const TEMP_ORDER_KEYS = [
1651
- "order_id",
1652
- "external_sale_number",
1653
- "order_number",
1654
- "shop_order_number",
1655
- "shop_full_order_number",
1656
- "type",
1657
- "business_code",
1658
- "platform",
1659
- "sales_channel",
1660
- "order_sales_channel",
1661
- "vouchers",
1662
- "status",
1663
- "payment_status",
1664
- "shipping_status",
1665
- "customer_id",
1666
- "customer_name",
1667
- "country_calling_code",
1668
- "phone",
1669
- "email",
1670
- "customer",
1671
- "is_price_include_tax",
1672
- "tax_title",
1673
- "tax_country_code",
1674
- "currency_code",
1675
- "currency_symbol",
1676
- "currency_format",
1677
- "is_deposit",
1678
- "deposit_amount",
1679
- "shop_discount",
1680
- "surcharge_fee",
1681
- "note",
1682
- "buzzer",
1683
- "delivery_type",
1684
- "table_number",
1685
- "schedule_date",
1686
- "created_at",
1687
- "request_unique_idempotency_token"
1688
- ];
1689
- TEMP_ORDER_KEYS.forEach((key) => {
1690
- if (raw[key] !== void 0) {
1691
- nextTempOrder[key] = raw[key];
3477
+ nextTempOrder._extend = {
3478
+ ...nextTempOrder._extend || {},
3479
+ originalSalesSnapshot: {
3480
+ summary: (0, import_lodash_es.cloneDeep)(this.store.summary),
3481
+ products: (0, import_lodash_es.cloneDeep)(nextTempOrder.products || []),
3482
+ payments: (0, import_lodash_es.cloneDeep)(nextTempOrder.payments || []),
3483
+ surcharges: (0, import_lodash_es.cloneDeep)(nextTempOrder.surcharges || []),
3484
+ productFingerprint: this.buildOrderProductsFingerprint(nextTempOrder.products || [])
1692
3485
  }
1693
- });
3486
+ };
3487
+ this.store.lastOrderInfo = raw.lastOrderInfo || raw;
3488
+ const hydratedEditDiscounts = this.collectHydratedEditDiscounts(nextTempOrder.products);
3489
+ const currentDiscounts = typeof ((_a = this.store.discount) == null ? void 0 : _a.getDiscountList) === "function" ? this.store.discount.getDiscountList() || [] : [];
3490
+ const shouldSkipEmptyDiscountSync = hydratedEditDiscounts.length === 0 && currentDiscounts.length === 0;
3491
+ if (!shouldSkipEmptyDiscountSync) {
3492
+ await ((_b = this.store.discount) == null ? void 0 : _b.setOriginalDiscountList(hydratedEditDiscounts));
3493
+ await ((_c = this.store.discount) == null ? void 0 : _c.setDiscountList(hydratedEditDiscounts));
3494
+ }
3495
+ if (options == null ? void 0 : options.recalcOnHydrate) {
3496
+ await this.recalculateSummary({ createIfMissing: false });
3497
+ }
3498
+ this.persistTempOrder();
3499
+ return nextTempOrder;
3500
+ }
3501
+ normalizeTempOrderForRuntime(raw, options) {
3502
+ var _a, _b;
3503
+ const nextTempOrder = {
3504
+ ...this.createDefaultTempOrderInstance(),
3505
+ ...raw || {}
3506
+ };
3507
+ delete nextTempOrder.summary;
3508
+ delete nextTempOrder.lastOrderInfo;
3509
+ delete nextTempOrder.discount_list;
3510
+ delete nextTempOrder.shop_id;
3511
+ delete nextTempOrder.create_date;
3512
+ delete nextTempOrder.total_amount;
3513
+ delete nextTempOrder.expect_amount;
3514
+ delete nextTempOrder.paid_amount;
3515
+ delete nextTempOrder.shop_note;
3516
+ delete nextTempOrder.start_time;
3517
+ delete nextTempOrder.tax_fee;
3518
+ delete nextTempOrder.total_refund_amount;
3519
+ delete nextTempOrder.holder_id;
1694
3520
  nextTempOrder.metadata = raw.metadata && typeof raw.metadata === "object" ? { ...raw.metadata } : {};
1695
3521
  nextTempOrder.holder = raw.holder && typeof raw.holder === "object" ? { ...raw.holder } : null;
1696
- nextTempOrder.products = Array.isArray(raw.products) ? raw.products.map((p) => this.normalizeHydratedOrderProduct(p)) : [];
3522
+ const rawProducts = Array.isArray(raw.products) ? raw.products : [];
3523
+ nextTempOrder.products = rawProducts.length > 0 ? rawProducts.map((p) => this.normalizeHydratedOrderProduct(p)) : [];
1697
3524
  nextTempOrder.bookings = Array.isArray(raw.bookings) ? raw.bookings.map((b) => ({
1698
3525
  ...b || {},
1699
3526
  is_all: (0, import_utils.normalizeBookingIsAll)(b || {}),
@@ -1701,7 +3528,6 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1701
3528
  })) : [];
1702
3529
  nextTempOrder.payments = Array.isArray(raw.payments) ? raw.payments.map((p) => ({ ...p || {} })) : [];
1703
3530
  nextTempOrder.surcharges = Array.isArray(raw.surcharges) ? raw.surcharges.map((s) => ({ ...s || {} })) : [];
1704
- nextTempOrder.discount_list = Array.isArray(raw.discount_list) ? raw.discount_list.map((d) => ({ ...d || {} })) : [];
1705
3531
  nextTempOrder.relation_forms = Array.isArray(raw.relation_forms) ? raw.relation_forms.map((f) => ({ ...f || {} })) : [];
1706
3532
  nextTempOrder.contacts = Array.isArray(raw.contacts) ? raw.contacts.map((c) => ({ ...c || {} })) : [];
1707
3533
  nextTempOrder.contacts_info = raw.contacts_info && typeof raw.contacts_info === "object" && !Array.isArray(raw.contacts_info) ? { ...raw.contacts_info } : null;
@@ -1709,35 +3535,120 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1709
3535
  ...raw._extend,
1710
3536
  productsByUid: raw._extend.productsByUid || {}
1711
3537
  } : { productsByUid: {} };
1712
- this.ensureExternalSaleNumber(nextTempOrder);
1713
- this.store.tempOrder = nextTempOrder;
1714
- this.store.summary = raw.summary && typeof raw.summary === "object" ? { ...(0, import_utils.createEmptySummary)(), ...raw.summary } : (0, import_utils.createEmptySummary)();
1715
- this.store.lastOrderInfo = raw.lastOrderInfo || raw;
1716
- if (options == null ? void 0 : options.recalcOnHydrate) {
1717
- await this.recalculateSummary({ createIfMissing: false });
3538
+ const tempOrderExtend = nextTempOrder._extend;
3539
+ const productsByUid = tempOrderExtend.productsByUid || {};
3540
+ for (const [index, product] of nextTempOrder.products.entries()) {
3541
+ const uid = (_a = product.metadata) == null ? void 0 : _a.unique_identification_number;
3542
+ if (!uid)
3543
+ continue;
3544
+ const existed = productsByUid[uid] && typeof productsByUid[uid] === "object" ? productsByUid[uid] : {};
3545
+ const rawProduct = rawProducts[index] && typeof rawProducts[index] === "object" ? rawProducts[index] : product;
3546
+ const origin = existed.origin ?? rawProduct._origin ?? ((_b = rawProduct.metadata) == null ? void 0 : _b.origin) ?? rawProduct;
3547
+ const originSnapshot = (0, import_lodash_es.cloneDeep)(origin);
3548
+ const productOptionString = this.buildHydratedProductOptionString(rawProduct) || this.buildHydratedProductOptionString(product);
3549
+ if (productOptionString && originSnapshot && typeof originSnapshot === "object") {
3550
+ if (originSnapshot.product_option_string === void 0) {
3551
+ originSnapshot.product_option_string = productOptionString;
3552
+ }
3553
+ if (originSnapshot.product_options_stirng === void 0) {
3554
+ originSnapshot.product_options_stirng = productOptionString;
3555
+ }
3556
+ }
3557
+ productsByUid[uid] = {
3558
+ ...existed,
3559
+ origin: originSnapshot
3560
+ };
1718
3561
  }
1719
- this.persistTempOrder();
3562
+ tempOrderExtend.productsByUid = productsByUid;
3563
+ if ((options == null ? void 0 : options.ensureIdentity) !== false) {
3564
+ this.ensureExternalSaleNumber(nextTempOrder);
3565
+ }
3566
+ nextTempOrder.vouchers = raw.vouchers || [];
1720
3567
  return nextTempOrder;
1721
3568
  }
3569
+ pickHydratedDisplayText(value) {
3570
+ if (value === void 0 || value === null)
3571
+ return "";
3572
+ if (typeof value === "string")
3573
+ return value;
3574
+ if (typeof value !== "object")
3575
+ return String(value);
3576
+ return value.auto || value.original || value.en || value["zh-CN"] || value["zh-HK"] || "";
3577
+ }
3578
+ formatHydratedNamePair(group, item) {
3579
+ const groupText = this.pickHydratedDisplayText(group);
3580
+ const itemText = this.pickHydratedDisplayText(item);
3581
+ if (groupText && itemText)
3582
+ return `${groupText}:${itemText}`;
3583
+ return groupText || itemText;
3584
+ }
3585
+ buildHydratedProductOptionString(product) {
3586
+ const segments = [];
3587
+ const sku = (product == null ? void 0 : product.product_sku) || {};
3588
+ if (Array.isArray(sku.variant)) {
3589
+ for (const variant of sku.variant) {
3590
+ const segment = this.formatHydratedNamePair(variant == null ? void 0 : variant.group, variant == null ? void 0 : variant.item);
3591
+ if (segment)
3592
+ segments.push(segment);
3593
+ }
3594
+ }
3595
+ return segments.join(", ");
3596
+ }
3597
+ normalizeHydratedProductOptionItem(optionItem) {
3598
+ const rawNum = (optionItem == null ? void 0 : optionItem.num) ?? (optionItem == null ? void 0 : optionItem.quantity) ?? 1;
3599
+ const parsedNum = Number(rawNum);
3600
+ const rawPrice = (optionItem == null ? void 0 : optionItem.add_price) ?? (optionItem == null ? void 0 : optionItem.price) ?? 0;
3601
+ const parsedPrice = Number(rawPrice);
3602
+ const normalized = {
3603
+ ...optionItem,
3604
+ option_group_item_id: optionItem == null ? void 0 : optionItem.option_group_item_id,
3605
+ option_group_id: optionItem == null ? void 0 : optionItem.option_group_id,
3606
+ num: Number.isFinite(parsedNum) && parsedNum > 0 ? parsedNum : 1,
3607
+ add_price: Number.isFinite(parsedPrice) ? parsedPrice : 0
3608
+ };
3609
+ delete normalized.price;
3610
+ if ((optionItem == null ? void 0 : optionItem.name) !== void 0)
3611
+ normalized.name = optionItem.name;
3612
+ if ((optionItem == null ? void 0 : optionItem.group_name) !== void 0)
3613
+ normalized.group_name = optionItem.group_name;
3614
+ if ((optionItem == null ? void 0 : optionItem.id) !== void 0)
3615
+ normalized.id = optionItem.id;
3616
+ return normalized;
3617
+ }
1722
3618
  normalizeHydratedOrderProduct(product) {
1723
3619
  const row = { ...product || {} };
1724
3620
  if (row.num === void 0 && row.product_quantity !== void 0) {
1725
3621
  row.num = row.product_quantity;
1726
3622
  }
1727
- if (!Array.isArray(row.product_option_item))
1728
- row.product_option_item = [];
3623
+ const productSku = (0, import_utils.ensureProductSku)(row);
3624
+ row.product_sku = {
3625
+ ...productSku,
3626
+ option: (0, import_utils.normalizeProductSkuOptions)(
3627
+ productSku.option.map(
3628
+ (optionItem) => this.normalizeHydratedProductOptionItem(optionItem || {})
3629
+ )
3630
+ )
3631
+ };
3632
+ delete row[`product_${"option"}_item`];
1729
3633
  if (!Array.isArray(row.product_bundle))
1730
3634
  row.product_bundle = [];
1731
3635
  if (!row.metadata || typeof row.metadata !== "object")
1732
3636
  row.metadata = {};
3637
+ if (row.booking_uid && !row.metadata.booking_uid) {
3638
+ row.metadata.booking_uid = row.booking_uid;
3639
+ }
1733
3640
  const existingIdentity = row.metadata.unique_identification_number || row.unique_identification_number;
1734
3641
  if (!existingIdentity) {
1735
3642
  row.metadata.unique_identification_number = (0, import_utils.createUuidV4)();
1736
3643
  }
1737
3644
  const normalized = (0, import_utils3.normalizeOrderProduct)(row);
3645
+ normalized.discount_list = (0, import_utils.normalizeOrderProductDiscountList)(
3646
+ normalized.discount_list
3647
+ );
1738
3648
  const result = {
1739
3649
  ...row,
1740
3650
  ...normalized,
3651
+ product_sku: normalized.product_sku,
1741
3652
  metadata: {
1742
3653
  ...row.metadata,
1743
3654
  ...normalized.metadata
@@ -1745,7 +3656,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1745
3656
  };
1746
3657
  if (result.metadata)
1747
3658
  delete result.metadata.price_schema_version;
1748
- return result;
3659
+ return this.sanitizeOrderProductForTempOrder(result);
1749
3660
  }
1750
3661
  getLastOrderInfo() {
1751
3662
  var _a;
@@ -1754,8 +3665,6 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1754
3665
  async getOrderInfo(order_id) {
1755
3666
  const res = await this.request.get(`/order/sales/${order_id}`, {
1756
3667
  with: ["products", "bookings"]
1757
- }, {
1758
- osServer: true
1759
3668
  });
1760
3669
  return res;
1761
3670
  }