@pisell/pisellos 0.0.567 → 0.0.569

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 (557) hide show
  1. package/dist/core/index.js +6 -9
  2. package/dist/model/strategy/adapter/promotion/evaluator.js +3 -2
  3. package/dist/model/strategy/adapter/walletPass/evaluator.js +0 -2
  4. package/dist/model/strategy/adapter/walletPass/example.js +3 -26
  5. package/dist/model/strategy/adapter/walletPass/utils.js +7 -7
  6. package/dist/model/strategy/strategy-example.js +5 -19
  7. package/dist/modules/BaseModule.d.ts +2 -2
  8. package/dist/modules/BaseModule.js +4 -4
  9. package/dist/modules/BookingContext/index.d.ts +48 -0
  10. package/dist/modules/BookingContext/index.js +566 -0
  11. package/dist/modules/BookingContext/types.d.ts +102 -0
  12. package/dist/modules/BookingContext/types.js +51 -0
  13. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.d.ts +16 -0
  14. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +302 -0
  15. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +8 -0
  16. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +149 -0
  17. package/dist/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +76 -0
  18. package/dist/modules/BookingContext/utils/cacheItemToBookingInput.js +249 -0
  19. package/dist/modules/BookingContext/utils/flexible.d.ts +28 -0
  20. package/dist/modules/BookingContext/utils/flexible.js +56 -0
  21. package/dist/modules/BookingContext/utils/formatResourceList.d.ts +8 -0
  22. package/dist/modules/BookingContext/utils/formatResourceList.js +38 -0
  23. package/dist/modules/BookingContext/utils/index.d.ts +11 -0
  24. package/dist/modules/BookingContext/utils/index.js +11 -0
  25. package/dist/modules/BookingContext/utils/noResource.d.ts +13 -0
  26. package/dist/modules/BookingContext/utils/noResource.js +77 -0
  27. package/dist/modules/BookingContext/utils/orderLineDisplay.d.ts +1 -0
  28. package/dist/modules/BookingContext/utils/orderLineDisplay.js +36 -0
  29. package/dist/modules/BookingContext/utils/productExtend.d.ts +72 -0
  30. package/dist/modules/BookingContext/utils/productExtend.js +339 -0
  31. package/dist/modules/BookingContext/utils/resourceErrors.d.ts +41 -0
  32. package/dist/modules/BookingContext/utils/resourceErrors.js +74 -0
  33. package/dist/modules/BookingContext/utils/resourceSelection.d.ts +7 -0
  34. package/dist/modules/BookingContext/utils/resourceSelection.js +24 -0
  35. package/dist/modules/BookingContext/utils/resources.d.ts +80 -0
  36. package/dist/modules/BookingContext/utils/resources.js +486 -0
  37. package/dist/modules/BookingContext/utils/serviceTimes.d.ts +55 -0
  38. package/dist/modules/BookingContext/utils/serviceTimes.js +151 -0
  39. package/dist/modules/BookingContext/utils/timeSlices.d.ts +42 -0
  40. package/dist/modules/BookingContext/utils/timeSlices.js +100 -0
  41. package/dist/modules/Cart/index.js +0 -3
  42. package/dist/modules/Cart/utils/cartProduct.js +26 -6
  43. package/dist/modules/Cart/utils/changePrice.js +27 -20
  44. package/dist/modules/Customer/index.d.ts +20 -0
  45. package/dist/modules/Customer/index.js +172 -83
  46. package/dist/modules/Customer/types.d.ts +2 -0
  47. package/dist/modules/Date/index.js +1 -5
  48. package/dist/modules/Discount/index.d.ts +2 -1
  49. package/dist/modules/Discount/index.js +37 -12
  50. package/dist/modules/Discount/types.d.ts +1 -0
  51. package/dist/modules/OpenData/index.d.ts +8 -0
  52. package/dist/modules/OpenData/index.js +35 -17
  53. package/dist/modules/Order/index.d.ts +449 -24
  54. package/dist/modules/Order/index.js +5437 -608
  55. package/dist/modules/Order/types.d.ts +693 -88
  56. package/dist/modules/Order/types.js +68 -1
  57. package/dist/modules/Order/utils/bundleDiscountHydration.d.ts +5 -0
  58. package/dist/modules/Order/utils/bundleDiscountHydration.js +144 -0
  59. package/dist/modules/Order/utils/manualProductDiscount.d.ts +106 -0
  60. package/dist/modules/Order/utils/manualProductDiscount.js +210 -0
  61. package/dist/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
  62. package/dist/modules/Order/utils/orderCollectionIdentity.js +405 -0
  63. package/dist/modules/Order/utils.d.ts +167 -18
  64. package/dist/modules/Order/utils.js +960 -165
  65. package/dist/modules/Payment/index.d.ts +10 -9
  66. package/dist/modules/Payment/index.js +508 -874
  67. package/dist/modules/Payment/types.d.ts +40 -16
  68. package/dist/modules/Payment/utils.d.ts +1 -1
  69. package/dist/modules/Payment/utils.js +4 -3
  70. package/dist/modules/Payment/walletpass.js +48 -34
  71. package/dist/modules/Product/types.d.ts +29 -7
  72. package/dist/modules/ProductList/index.d.ts +17 -13
  73. package/dist/modules/ProductList/index.js +184 -74
  74. package/dist/modules/ProductList/types.d.ts +17 -0
  75. package/dist/modules/Quotation/index.d.ts +22 -2
  76. package/dist/modules/Quotation/index.js +108 -42
  77. package/dist/modules/Quotation/types.d.ts +19 -0
  78. package/dist/modules/ResourcePlanner/index.d.ts +24 -0
  79. package/dist/modules/ResourcePlanner/index.js +181 -0
  80. package/dist/modules/ResourcePlanner/planner.d.ts +14 -0
  81. package/dist/modules/ResourcePlanner/planner.js +1069 -0
  82. package/dist/modules/ResourcePlanner/types.d.ts +227 -0
  83. package/dist/modules/ResourcePlanner/types.js +1 -0
  84. package/dist/modules/Rules/index.d.ts +8 -10
  85. package/dist/modules/Rules/index.js +219 -114
  86. package/dist/modules/Rules/types.d.ts +14 -3
  87. package/dist/modules/SalesSummary/index.d.ts +23 -26
  88. package/dist/modules/SalesSummary/index.js +152 -46
  89. package/dist/modules/SalesSummary/types.d.ts +9 -1
  90. package/dist/modules/SalesSummary/utils.d.ts +3 -22
  91. package/dist/modules/SalesSummary/utils.js +803 -163
  92. package/dist/modules/Schedule/getDateIsInSchedule.js +14 -7
  93. package/dist/modules/Schedule/index.d.ts +18 -5
  94. package/dist/modules/Schedule/index.js +78 -24
  95. package/dist/modules/Schedule/types.d.ts +2 -0
  96. package/dist/modules/Schedule/utils.js +0 -1
  97. package/dist/modules/Step/index.js +0 -1
  98. package/dist/modules/Summary/index.js +4 -3
  99. package/dist/modules/SurchargeList/index.d.ts +18 -0
  100. package/dist/modules/SurchargeList/index.js +185 -0
  101. package/dist/modules/SurchargeList/types.d.ts +15 -0
  102. package/dist/modules/SurchargeList/types.js +1 -0
  103. package/dist/modules/index.d.ts +3 -0
  104. package/dist/modules/index.js +4 -1
  105. package/dist/plugins/app.d.ts +2 -0
  106. package/dist/plugins/request.d.ts +1 -0
  107. package/dist/plugins/request.js +1 -4
  108. package/dist/plugins/window.js +2 -6
  109. package/dist/server/index.d.ts +462 -8
  110. package/dist/server/index.js +6137 -714
  111. package/dist/server/modules/floor-plan/index.d.ts +39 -0
  112. package/dist/server/modules/floor-plan/index.js +595 -0
  113. package/dist/server/modules/floor-plan/types.d.ts +43 -0
  114. package/dist/server/modules/floor-plan/types.js +13 -0
  115. package/dist/server/modules/index.d.ts +7 -2
  116. package/dist/server/modules/index.js +6 -0
  117. package/dist/server/modules/menu/index.js +32 -41
  118. package/dist/server/modules/order/index.d.ts +207 -14
  119. package/dist/server/modules/order/index.js +2326 -379
  120. package/dist/server/modules/order/types.d.ts +76 -5
  121. package/dist/server/modules/order/types.js +14 -1
  122. package/dist/server/modules/order/utils/filterBookings.d.ts +7 -1
  123. package/dist/server/modules/order/utils/filterBookings.js +118 -11
  124. package/dist/server/modules/order/utils/filterOrders.js +242 -14
  125. package/dist/server/modules/payment/index.d.ts +28 -0
  126. package/dist/server/modules/payment/index.js +305 -0
  127. package/dist/server/modules/payment/types.d.ts +9 -0
  128. package/dist/server/modules/payment/types.js +1 -0
  129. package/dist/server/modules/products/index.d.ts +105 -14
  130. package/dist/server/modules/products/index.js +1397 -540
  131. package/dist/server/modules/products/types.d.ts +34 -1
  132. package/dist/server/modules/products/types.js +4 -0
  133. package/dist/server/modules/quotation/index.d.ts +39 -0
  134. package/dist/server/modules/quotation/index.js +289 -86
  135. package/dist/server/modules/resource/index.d.ts +2 -3
  136. package/dist/server/modules/resource/index.js +105 -84
  137. package/dist/server/modules/schedule/index.d.ts +6 -4
  138. package/dist/server/modules/schedule/index.js +137 -114
  139. package/dist/server/test.json +713 -0
  140. package/dist/server/types.d.ts +2 -0
  141. package/dist/server/utils/product.js +2 -3
  142. package/dist/server/utils/small-ticket.d.ts +71 -0
  143. package/dist/server/utils/small-ticket.js +963 -0
  144. package/dist/solution/BaseSales/index.d.ts +378 -0
  145. package/dist/solution/BaseSales/index.js +4006 -0
  146. package/dist/solution/BaseSales/types.d.ts +394 -0
  147. package/dist/solution/BaseSales/types.js +40 -0
  148. package/dist/solution/BaseSales/utils/cartPromotion.d.ts +287 -0
  149. package/dist/solution/BaseSales/utils/cartPromotion.js +1450 -0
  150. package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +144 -0
  151. package/dist/solution/BaseSales/utils/parseSalesResponse.js +157 -0
  152. package/dist/solution/BaseSales/utils/quotationPrice.d.ts +18 -0
  153. package/dist/solution/BaseSales/utils/quotationPrice.js +250 -0
  154. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +63 -0
  155. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +218 -0
  156. package/dist/solution/BaseSales/utils.d.ts +40 -0
  157. package/dist/solution/BaseSales/utils.js +263 -0
  158. package/dist/solution/BookingByStep/index.js +7 -59
  159. package/dist/solution/BookingByStep/utils/capacity.js +1 -11
  160. package/dist/solution/BookingByStep/utils/resources.js +1 -3
  161. package/dist/solution/BookingByStep/utils/timeslots.js +2 -43
  162. package/dist/solution/BookingTicket/index.d.ts +393 -24
  163. package/dist/solution/BookingTicket/index.js +2506 -445
  164. package/dist/solution/BookingTicket/types.d.ts +191 -6
  165. package/dist/solution/BookingTicket/types.js +83 -10
  166. package/dist/solution/BookingTicket/utils/addProductDecision.d.ts +117 -0
  167. package/dist/solution/BookingTicket/utils/addProductDecision.js +346 -0
  168. package/dist/solution/BookingTicket/utils/addTimeAvailability.d.ts +35 -0
  169. package/dist/solution/BookingTicket/utils/addTimeAvailability.js +95 -0
  170. package/dist/solution/BookingTicket/utils/bookingStatus.d.ts +77 -0
  171. package/dist/solution/BookingTicket/utils/bookingStatus.js +136 -0
  172. package/dist/solution/BookingTicket/utils/cartView.d.ts +29 -0
  173. package/dist/solution/BookingTicket/utils/cartView.js +209 -0
  174. package/dist/solution/BookingTicket/utils/exampleData.d.ts +123 -0
  175. package/dist/solution/BookingTicket/utils/exampleData.js +183 -0
  176. package/dist/solution/BookingTicket/utils/orderCustomer.d.ts +4 -0
  177. package/dist/solution/BookingTicket/utils/orderCustomer.js +31 -0
  178. package/dist/solution/BookingTicket/utils/resolveBestAddTimePlan.d.ts +185 -0
  179. package/dist/solution/BookingTicket/utils/resolveBestAddTimePlan.js +438 -0
  180. package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +36 -0
  181. package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.js +400 -0
  182. package/dist/solution/BookingTicket/utils/scan/cloudSearch.d.ts +4 -0
  183. package/dist/solution/BookingTicket/utils/scan/cloudSearch.js +41 -1
  184. package/dist/solution/BookingTicket/utils/scan/formatGlobalScan.d.ts +32 -0
  185. package/dist/solution/BookingTicket/utils/scan/formatGlobalScan.js +56 -0
  186. package/dist/solution/BookingTicket/utils/scan/handleScan.d.ts +3 -1
  187. package/dist/solution/BookingTicket/utils/scan/handleScan.js +36 -34
  188. package/dist/solution/BookingTicket/utils/scan/index.d.ts +5 -0
  189. package/dist/solution/BookingTicket/utils/scan/index.js +26 -18
  190. package/dist/solution/BookingTicket/utils/scan/scanProductValues.d.ts +21 -0
  191. package/dist/solution/BookingTicket/utils/scan/scanProductValues.js +150 -0
  192. package/dist/solution/BookingTicket/utils/sessionCatalogStale.d.ts +23 -0
  193. package/dist/solution/BookingTicket/utils/sessionCatalogStale.js +78 -0
  194. package/dist/solution/BuyTickets/index.js +9 -12
  195. package/dist/solution/Checkout/index.d.ts +1 -0
  196. package/dist/solution/Checkout/index.js +199 -277
  197. package/dist/solution/Checkout/utils/index.js +8 -20
  198. package/dist/solution/RegisterAndLogin/config.js +2 -10
  199. package/dist/solution/RegisterAndLogin/index.js +30 -76
  200. package/dist/solution/Sales/index.d.ts +50 -5
  201. package/dist/solution/Sales/index.js +484 -92
  202. package/dist/solution/Sales/types.d.ts +26 -2
  203. package/dist/solution/ScanOrder/index.d.ts +27 -21
  204. package/dist/solution/ScanOrder/index.js +509 -454
  205. package/dist/solution/ScanOrder/types.d.ts +33 -11
  206. package/dist/solution/ScanOrder/types.js +4 -5
  207. package/dist/solution/ScanOrder/utils.d.ts +4 -1
  208. package/dist/solution/ScanOrder/utils.js +109 -34
  209. package/dist/solution/ShopDiscount/index.js +6 -11
  210. package/dist/solution/UnifiedBookingSales/index.d.ts +183 -0
  211. package/dist/solution/UnifiedBookingSales/index.js +1871 -0
  212. package/dist/solution/UnifiedBookingSales/types.d.ts +143 -0
  213. package/dist/solution/UnifiedBookingSales/types.js +11 -0
  214. package/dist/solution/VenueBooking/index.d.ts +34 -20
  215. package/dist/solution/VenueBooking/index.js +630 -505
  216. package/dist/solution/VenueBooking/sales-section-4-annotated.json +0 -2
  217. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +6 -0
  218. package/dist/solution/VenueBooking/utils/slotMerge.js +9 -3
  219. package/dist/solution/index.d.ts +2 -0
  220. package/dist/solution/index.js +3 -1
  221. package/dist/types/index.d.ts +11 -1
  222. package/dist/utils/task.js +15 -18
  223. package/dist/utils/watch.js +0 -1
  224. package/lib/apis/picoding.js +2 -0
  225. package/lib/core/index.js +130 -131
  226. package/lib/effects/index.js +46 -57
  227. package/lib/index.js +92 -53
  228. package/lib/model/index.js +14 -21
  229. package/lib/model/strategy/adapter/dataVariant/adapter.js +38 -50
  230. package/lib/model/strategy/adapter/dataVariant/evaluator.js +162 -236
  231. package/lib/model/strategy/adapter/dataVariant/examples.js +229 -237
  232. package/lib/model/strategy/adapter/dataVariant/index.js +39 -34
  233. package/lib/model/strategy/adapter/dataVariant/type.js +57 -28
  234. package/lib/model/strategy/adapter/index.js +100 -64
  235. package/lib/model/strategy/adapter/itemRule/adapter.js +156 -144
  236. package/lib/model/strategy/adapter/itemRule/evaluator.js +36 -48
  237. package/lib/model/strategy/adapter/itemRule/examples.js +295 -225
  238. package/lib/model/strategy/adapter/itemRule/index.js +83 -57
  239. package/lib/model/strategy/adapter/itemRule/type.js +97 -36
  240. package/lib/model/strategy/adapter/promotion/adapter.js +84 -63
  241. package/lib/model/strategy/adapter/promotion/evaluator.js +383 -232
  242. package/lib/model/strategy/adapter/promotion/examples.js +139 -159
  243. package/lib/model/strategy/adapter/promotion/index.js +1 -49
  244. package/lib/model/strategy/adapter/promotion/type.js +199 -35
  245. package/lib/model/strategy/adapter/type.js +4 -16
  246. package/lib/model/strategy/adapter/walletPass/evaluator.js +180 -152
  247. package/lib/model/strategy/adapter/walletPass/example.js +217 -190
  248. package/lib/model/strategy/adapter/walletPass/index.js +75 -51
  249. package/lib/model/strategy/adapter/walletPass/locales.js +36 -58
  250. package/lib/model/strategy/adapter/walletPass/type.js +4 -16
  251. package/lib/model/strategy/adapter/walletPass/utils.js +654 -402
  252. package/lib/model/strategy/engine.js +270 -168
  253. package/lib/model/strategy/index.js +49 -34
  254. package/lib/model/strategy/strategy-example.js +243 -239
  255. package/lib/model/strategy/type.js +100 -40
  256. package/lib/modules/Account/index.js +39 -53
  257. package/lib/modules/Account/types.js +20 -33
  258. package/lib/modules/AccountList/index.js +116 -154
  259. package/lib/modules/AccountList/types.js +30 -31
  260. package/lib/modules/AccountList/utils.js +18 -30
  261. package/lib/modules/BaseModule.d.ts +2 -2
  262. package/lib/modules/BaseModule.js +26 -49
  263. package/lib/modules/BookingContext/index.d.ts +48 -0
  264. package/lib/modules/BookingContext/index.js +390 -0
  265. package/lib/modules/BookingContext/types.d.ts +102 -0
  266. package/lib/modules/BookingContext/types.js +48 -0
  267. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.d.ts +16 -0
  268. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +286 -0
  269. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +8 -0
  270. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +148 -0
  271. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +76 -0
  272. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +242 -0
  273. package/lib/modules/BookingContext/utils/flexible.d.ts +28 -0
  274. package/lib/modules/BookingContext/utils/flexible.js +63 -0
  275. package/lib/modules/BookingContext/utils/formatResourceList.d.ts +8 -0
  276. package/lib/modules/BookingContext/utils/formatResourceList.js +35 -0
  277. package/lib/modules/BookingContext/utils/index.d.ts +11 -0
  278. package/lib/modules/BookingContext/utils/index.js +126 -0
  279. package/lib/modules/BookingContext/utils/noResource.d.ts +13 -0
  280. package/lib/modules/BookingContext/utils/noResource.js +78 -0
  281. package/lib/modules/BookingContext/utils/orderLineDisplay.d.ts +1 -0
  282. package/lib/modules/BookingContext/utils/orderLineDisplay.js +29 -0
  283. package/lib/modules/BookingContext/utils/productExtend.d.ts +72 -0
  284. package/lib/modules/BookingContext/utils/productExtend.js +330 -0
  285. package/lib/modules/BookingContext/utils/resourceErrors.d.ts +41 -0
  286. package/lib/modules/BookingContext/utils/resourceErrors.js +80 -0
  287. package/lib/modules/BookingContext/utils/resourceSelection.d.ts +7 -0
  288. package/lib/modules/BookingContext/utils/resourceSelection.js +24 -0
  289. package/lib/modules/BookingContext/utils/resources.d.ts +80 -0
  290. package/lib/modules/BookingContext/utils/resources.js +419 -0
  291. package/lib/modules/BookingContext/utils/serviceTimes.d.ts +55 -0
  292. package/lib/modules/BookingContext/utils/serviceTimes.js +161 -0
  293. package/lib/modules/BookingContext/utils/timeSlices.d.ts +42 -0
  294. package/lib/modules/BookingContext/utils/timeSlices.js +114 -0
  295. package/lib/modules/Cart/index.js +170 -124
  296. package/lib/modules/Cart/types.js +46 -51
  297. package/lib/modules/Cart/utils/cartAccount.js +40 -39
  298. package/lib/modules/Cart/utils/cartDate.js +56 -61
  299. package/lib/modules/Cart/utils/cartDiscount.js +28 -33
  300. package/lib/modules/Cart/utils/cartNote.js +27 -32
  301. package/lib/modules/Cart/utils/cartProduct.js +331 -244
  302. package/lib/modules/Cart/utils/cartRelationForms.js +29 -35
  303. package/lib/modules/Cart/utils/cartResource.js +72 -78
  304. package/lib/modules/Cart/utils/changePrice.js +37 -67
  305. package/lib/modules/Cart/utils/index.js +106 -48
  306. package/lib/modules/Customer/constants.js +13 -34
  307. package/lib/modules/Customer/index.d.ts +20 -0
  308. package/lib/modules/Customer/index.js +270 -154
  309. package/lib/modules/Customer/types.d.ts +2 -0
  310. package/lib/modules/Customer/types.js +38 -35
  311. package/lib/modules/Date/index.js +116 -115
  312. package/lib/modules/Date/types.js +16 -28
  313. package/lib/modules/Date/utils.js +174 -123
  314. package/lib/modules/Discount/index.d.ts +2 -1
  315. package/lib/modules/Discount/index.js +133 -113
  316. package/lib/modules/Discount/types.d.ts +1 -0
  317. package/lib/modules/Discount/types.js +9 -31
  318. package/lib/modules/Guests/index.js +30 -56
  319. package/lib/modules/Guests/types.js +23 -33
  320. package/lib/modules/Holder/index.js +209 -189
  321. package/lib/modules/Holder/types.js +4 -16
  322. package/lib/modules/Holder/utils.js +20 -49
  323. package/lib/modules/OpenData/index.d.ts +8 -0
  324. package/lib/modules/OpenData/index.js +81 -74
  325. package/lib/modules/OpenData/types.js +4 -16
  326. package/lib/modules/OpenData/utils.js +44 -78
  327. package/lib/modules/Order/index.d.ts +449 -24
  328. package/lib/modules/Order/index.js +3834 -489
  329. package/lib/modules/Order/types.d.ts +693 -88
  330. package/lib/modules/Order/types.js +78 -33
  331. package/lib/modules/Order/utils/bundleDiscountHydration.d.ts +5 -0
  332. package/lib/modules/Order/utils/bundleDiscountHydration.js +106 -0
  333. package/lib/modules/Order/utils/manualProductDiscount.d.ts +106 -0
  334. package/lib/modules/Order/utils/manualProductDiscount.js +207 -0
  335. package/lib/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
  336. package/lib/modules/Order/utils/orderCollectionIdentity.js +353 -0
  337. package/lib/modules/Order/utils.d.ts +167 -18
  338. package/lib/modules/Order/utils.js +1247 -345
  339. package/lib/modules/Payment/cash.js +20 -33
  340. package/lib/modules/Payment/cashRecommendationAlgorithm.js +145 -76
  341. package/lib/modules/Payment/eftpos.js +16 -30
  342. package/lib/modules/Payment/index.d.ts +10 -9
  343. package/lib/modules/Payment/index.js +542 -502
  344. package/lib/modules/Payment/mx51.js +1 -0
  345. package/lib/modules/Payment/types.d.ts +40 -16
  346. package/lib/modules/Payment/types.js +216 -107
  347. package/lib/modules/Payment/utils.d.ts +1 -1
  348. package/lib/modules/Payment/utils.js +53 -49
  349. package/lib/modules/Payment/walletpass.js +231 -203
  350. package/lib/modules/Product/index.js +51 -46
  351. package/lib/modules/Product/types.d.ts +29 -7
  352. package/lib/modules/Product/types.js +4 -16
  353. package/lib/modules/Product/utils.js +32 -33
  354. package/lib/modules/ProductList/index.d.ts +17 -13
  355. package/lib/modules/ProductList/index.js +160 -118
  356. package/lib/modules/ProductList/types.d.ts +17 -0
  357. package/lib/modules/ProductList/types.js +9 -31
  358. package/lib/modules/Quotation/index.d.ts +22 -2
  359. package/lib/modules/Quotation/index.js +123 -89
  360. package/lib/modules/Quotation/types.d.ts +19 -0
  361. package/lib/modules/Quotation/types.js +4 -16
  362. package/lib/modules/Resource/index.js +27 -59
  363. package/lib/modules/Resource/types.js +22 -32
  364. package/lib/modules/Resource/utils.js +30 -38
  365. package/lib/modules/ResourcePlanner/index.d.ts +24 -0
  366. package/lib/modules/ResourcePlanner/index.js +147 -0
  367. package/lib/modules/ResourcePlanner/planner.d.ts +14 -0
  368. package/lib/modules/ResourcePlanner/planner.js +895 -0
  369. package/lib/modules/ResourcePlanner/types.d.ts +227 -0
  370. package/lib/modules/ResourcePlanner/types.js +5 -0
  371. package/lib/modules/Rules/index.d.ts +8 -10
  372. package/lib/modules/Rules/index.js +1286 -894
  373. package/lib/modules/Rules/types.d.ts +14 -3
  374. package/lib/modules/Rules/types.js +17 -40
  375. package/lib/modules/SalesSummary/index.d.ts +23 -26
  376. package/lib/modules/SalesSummary/index.js +130 -71
  377. package/lib/modules/SalesSummary/types.d.ts +9 -1
  378. package/lib/modules/SalesSummary/types.js +4 -16
  379. package/lib/modules/SalesSummary/utils.d.ts +3 -22
  380. package/lib/modules/SalesSummary/utils.js +738 -250
  381. package/lib/modules/ScanOrderLogger/index.js +59 -79
  382. package/lib/modules/ScanOrderLogger/providers/feishu.js +54 -78
  383. package/lib/modules/ScanOrderLogger/providers/grafana.js +13 -36
  384. package/lib/modules/ScanOrderLogger/types.js +4 -16
  385. package/lib/modules/Schedule/getDateIsInSchedule.js +345 -171
  386. package/lib/modules/Schedule/index.d.ts +18 -5
  387. package/lib/modules/Schedule/index.js +139 -114
  388. package/lib/modules/Schedule/type.js +4 -16
  389. package/lib/modules/Schedule/types.d.ts +2 -0
  390. package/lib/modules/Schedule/types.js +4 -16
  391. package/lib/modules/Schedule/utils.js +433 -291
  392. package/lib/modules/Step/index.js +40 -52
  393. package/lib/modules/Step/tyeps.js +4 -16
  394. package/lib/modules/Summary/index.js +66 -70
  395. package/lib/modules/Summary/types.js +4 -16
  396. package/lib/modules/Summary/utils.js +782 -429
  397. package/lib/modules/SurchargeList/index.d.ts +18 -0
  398. package/lib/modules/SurchargeList/index.js +95 -0
  399. package/lib/modules/SurchargeList/types.d.ts +15 -0
  400. package/lib/modules/SurchargeList/types.js +5 -0
  401. package/lib/modules/index.d.ts +3 -0
  402. package/lib/modules/index.js +245 -57
  403. package/lib/plugins/app.d.ts +2 -0
  404. package/lib/plugins/app.js +4 -16
  405. package/lib/plugins/index.js +36 -25
  406. package/lib/plugins/request.d.ts +1 -0
  407. package/lib/plugins/request.js +137 -126
  408. package/lib/plugins/shopStore.js +4 -16
  409. package/lib/plugins/user.js +4 -16
  410. package/lib/plugins/window.js +171 -179
  411. package/lib/server/index.d.ts +462 -8
  412. package/lib/server/index.js +4668 -713
  413. package/lib/server/modules/floor-plan/index.d.ts +39 -0
  414. package/lib/server/modules/floor-plan/index.js +306 -0
  415. package/lib/server/modules/floor-plan/types.d.ts +43 -0
  416. package/lib/server/modules/floor-plan/types.js +19 -0
  417. package/lib/server/modules/index.d.ts +7 -2
  418. package/lib/server/modules/index.js +106 -59
  419. package/lib/server/modules/menu/index.js +146 -122
  420. package/lib/server/modules/menu/types.js +18 -31
  421. package/lib/server/modules/order/index.d.ts +207 -14
  422. package/lib/server/modules/order/index.js +1463 -316
  423. package/lib/server/modules/order/types.d.ts +76 -5
  424. package/lib/server/modules/order/types.js +117 -32
  425. package/lib/server/modules/order/utils/filterBookings.d.ts +7 -1
  426. package/lib/server/modules/order/utils/filterBookings.js +288 -146
  427. package/lib/server/modules/order/utils/filterOrders.js +318 -64
  428. package/lib/server/modules/payment/index.d.ts +28 -0
  429. package/lib/server/modules/payment/index.js +168 -0
  430. package/lib/server/modules/payment/types.d.ts +9 -0
  431. package/lib/server/modules/payment/types.js +5 -0
  432. package/lib/server/modules/products/index.d.ts +105 -14
  433. package/lib/server/modules/products/index.js +969 -383
  434. package/lib/server/modules/products/types.d.ts +34 -1
  435. package/lib/server/modules/products/types.js +44 -34
  436. package/lib/server/modules/quotation/index.d.ts +39 -0
  437. package/lib/server/modules/quotation/index.js +220 -77
  438. package/lib/server/modules/quotation/types.js +21 -31
  439. package/lib/server/modules/resource/index.d.ts +2 -3
  440. package/lib/server/modules/resource/index.js +269 -214
  441. package/lib/server/modules/resource/types.js +42 -33
  442. package/lib/server/modules/schedule/index.d.ts +6 -4
  443. package/lib/server/modules/schedule/index.js +158 -132
  444. package/lib/server/modules/schedule/types.js +14 -21
  445. package/lib/server/modules/schedule/utils.js +334 -163
  446. package/lib/server/test.json +713 -0
  447. package/lib/server/types.d.ts +2 -0
  448. package/lib/server/types.js +4 -16
  449. package/lib/server/utils/index.js +25 -23
  450. package/lib/server/utils/product.js +197 -140
  451. package/lib/server/utils/schedule.js +34 -41
  452. package/lib/server/utils/small-ticket.d.ts +71 -0
  453. package/lib/server/utils/small-ticket.js +926 -0
  454. package/lib/server/utils/time.js +40 -49
  455. package/lib/solution/BaseSales/index.d.ts +378 -0
  456. package/lib/solution/BaseSales/index.js +2367 -0
  457. package/lib/solution/BaseSales/types.d.ts +394 -0
  458. package/lib/solution/BaseSales/types.js +47 -0
  459. package/lib/solution/BaseSales/utils/cartPromotion.d.ts +287 -0
  460. package/lib/solution/BaseSales/utils/cartPromotion.js +1155 -0
  461. package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +144 -0
  462. package/lib/solution/BaseSales/utils/parseSalesResponse.js +140 -0
  463. package/lib/solution/BaseSales/utils/quotationPrice.d.ts +18 -0
  464. package/lib/solution/BaseSales/utils/quotationPrice.js +231 -0
  465. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +63 -0
  466. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +215 -0
  467. package/lib/solution/BaseSales/utils.d.ts +40 -0
  468. package/lib/solution/BaseSales/utils.js +259 -0
  469. package/lib/solution/BookingByStep/index.js +1530 -1343
  470. package/lib/solution/BookingByStep/types.js +40 -99
  471. package/lib/solution/BookingByStep/utils/capacity.js +192 -160
  472. package/lib/solution/BookingByStep/utils/products.js +42 -52
  473. package/lib/solution/BookingByStep/utils/resources.js +527 -330
  474. package/lib/solution/BookingByStep/utils/stock.js +65 -44
  475. package/lib/solution/BookingByStep/utils/timeslots.js +129 -131
  476. package/lib/solution/BookingTicket/index.d.ts +393 -24
  477. package/lib/solution/BookingTicket/index.js +1459 -160
  478. package/lib/solution/BookingTicket/types.d.ts +191 -6
  479. package/lib/solution/BookingTicket/types.js +101 -66
  480. package/lib/solution/BookingTicket/utils/addProductDecision.d.ts +117 -0
  481. package/lib/solution/BookingTicket/utils/addProductDecision.js +353 -0
  482. package/lib/solution/BookingTicket/utils/addTimeAvailability.d.ts +35 -0
  483. package/lib/solution/BookingTicket/utils/addTimeAvailability.js +94 -0
  484. package/lib/solution/BookingTicket/utils/bookingStatus.d.ts +77 -0
  485. package/lib/solution/BookingTicket/utils/bookingStatus.js +136 -0
  486. package/lib/solution/BookingTicket/utils/cartView.d.ts +29 -0
  487. package/lib/solution/BookingTicket/utils/cartView.js +200 -0
  488. package/lib/solution/BookingTicket/utils/exampleData.d.ts +123 -0
  489. package/lib/solution/BookingTicket/utils/exampleData.js +185 -0
  490. package/lib/solution/BookingTicket/utils/orderCustomer.d.ts +4 -0
  491. package/lib/solution/BookingTicket/utils/orderCustomer.js +35 -0
  492. package/lib/solution/BookingTicket/utils/resolveBestAddTimePlan.d.ts +185 -0
  493. package/lib/solution/BookingTicket/utils/resolveBestAddTimePlan.js +387 -0
  494. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +36 -0
  495. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +220 -0
  496. package/lib/solution/BookingTicket/utils/scan/cloudSearch.d.ts +4 -0
  497. package/lib/solution/BookingTicket/utils/scan/cloudSearch.js +85 -80
  498. package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.d.ts +32 -0
  499. package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.js +64 -0
  500. package/lib/solution/BookingTicket/utils/scan/handleScan.d.ts +3 -1
  501. package/lib/solution/BookingTicket/utils/scan/handleScan.js +84 -80
  502. package/lib/solution/BookingTicket/utils/scan/index.d.ts +5 -0
  503. package/lib/solution/BookingTicket/utils/scan/index.js +103 -95
  504. package/lib/solution/BookingTicket/utils/scan/scanCache.js +90 -43
  505. package/lib/solution/BookingTicket/utils/scan/scanProductValues.d.ts +21 -0
  506. package/lib/solution/BookingTicket/utils/scan/scanProductValues.js +115 -0
  507. package/lib/solution/BookingTicket/utils/sessionCatalogStale.d.ts +23 -0
  508. package/lib/solution/BookingTicket/utils/sessionCatalogStale.js +83 -0
  509. package/lib/solution/BuyTickets/index.js +67 -70
  510. package/lib/solution/BuyTickets/types.js +22 -38
  511. package/lib/solution/Checkout/index.d.ts +1 -0
  512. package/lib/solution/Checkout/index.js +1461 -1169
  513. package/lib/solution/Checkout/types.js +91 -61
  514. package/lib/solution/Checkout/utils/index.js +228 -159
  515. package/lib/solution/PlaceOrder/index.js +55 -0
  516. package/lib/solution/RegisterAndLogin/config.js +495 -470
  517. package/lib/solution/RegisterAndLogin/index.js +633 -630
  518. package/lib/solution/RegisterAndLogin/types.js +189 -76
  519. package/lib/solution/RegisterAndLogin/utils.js +183 -125
  520. package/lib/solution/Sales/index.d.ts +50 -5
  521. package/lib/solution/Sales/index.js +495 -220
  522. package/lib/solution/Sales/types.d.ts +26 -2
  523. package/lib/solution/Sales/types.js +27 -33
  524. package/lib/solution/ScanOrder/index.d.ts +27 -21
  525. package/lib/solution/ScanOrder/index.js +908 -904
  526. package/lib/solution/ScanOrder/types.d.ts +33 -11
  527. package/lib/solution/ScanOrder/types.js +33 -34
  528. package/lib/solution/ScanOrder/utils.d.ts +4 -1
  529. package/lib/solution/ScanOrder/utils.js +457 -344
  530. package/lib/solution/ShopDiscount/index.js +230 -236
  531. package/lib/solution/ShopDiscount/types.js +15 -37
  532. package/lib/solution/ShopDiscount/utils.js +309 -172
  533. package/lib/solution/UnifiedBookingSales/index.d.ts +183 -0
  534. package/lib/solution/UnifiedBookingSales/index.js +1050 -0
  535. package/lib/solution/UnifiedBookingSales/types.d.ts +143 -0
  536. package/lib/solution/UnifiedBookingSales/types.js +14 -0
  537. package/lib/solution/VenueBooking/index.d.ts +34 -20
  538. package/lib/solution/VenueBooking/index.js +982 -950
  539. package/lib/solution/VenueBooking/sales-section-4-annotated.json +0 -2
  540. package/lib/solution/VenueBooking/types.js +20 -40
  541. package/lib/solution/VenueBooking/utils/dateSummary.js +22 -54
  542. package/lib/solution/VenueBooking/utils/resource.js +31 -54
  543. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +6 -0
  544. package/lib/solution/VenueBooking/utils/slotMerge.js +96 -108
  545. package/lib/solution/VenueBooking/utils/smartPricing.js +112 -100
  546. package/lib/solution/VenueBooking/utils/timeSlot.js +133 -132
  547. package/lib/solution/VenueBooking/utils.js +130 -67
  548. package/lib/solution/index.d.ts +2 -0
  549. package/lib/solution/index.js +124 -37
  550. package/lib/store/createStore.js +32 -29
  551. package/lib/types/index.d.ts +11 -1
  552. package/lib/types/index.js +4 -16
  553. package/lib/utils/task.js +36 -36
  554. package/lib/utils/watch.js +81 -47
  555. package/package.json +2 -1
  556. package/dist/solution/Checkout/appointmentDemo.json +0 -1
  557. package/lib/solution/Checkout/appointmentDemo.json +0 -1
@@ -1,122 +1,128 @@
1
- var __create = Object.create;
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __export = (target, all) => {
8
- for (var name in all)
9
- __defProp(target, name, { get: all[name], enumerable: true });
10
- };
11
- var __copyProps = (to, from, except, desc) => {
12
- if (from && typeof from === "object" || typeof from === "function") {
13
- for (let key of __getOwnPropNames(from))
14
- if (!__hasOwnProp.call(to, key) && key !== except)
15
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
- }
17
- return to;
18
- };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
- // If the importer is in node compatibility mode or this is not an ESM
21
- // file that has been converted to a CommonJS file using a Babel-
22
- // compatible transform (i.e. "__esModule" has not been set), then set
23
- // "default" to the CommonJS "module.exports" for node compatibility.
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
27
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
-
29
- // src/model/strategy/adapter/promotion/evaluator.ts
30
- var evaluator_exports = {};
31
- __export(evaluator_exports, {
32
- PromotionEvaluator: () => PromotionEvaluator
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
33
5
  });
34
- module.exports = __toCommonJS(evaluator_exports);
35
- var import_decimal = __toESM(require("decimal.js"));
36
- var import_engine = require("../../engine");
37
- var import_adapter = require("./adapter");
38
- var import_type = require("./type");
39
- var defaultLocales = {
6
+ exports.PromotionEvaluator = void 0;
7
+ var _decimal = _interopRequireDefault(require("decimal.js"));
8
+ var _engine = require("../../engine");
9
+ var _adapter = require("./adapter");
10
+ var _type = require("./type");
11
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
+ // ============================================
13
+ // 类型定义
14
+ // ============================================
15
+
16
+ // ============================================
17
+ // 多语言定义
18
+ // ============================================
19
+
20
+ const defaultLocales = {
40
21
  en: {
41
- no_applicable_promotion: "No applicable promotion",
42
- promotion_not_in_time_range: "Promotion not in valid time range",
43
- product_not_in_promotion: "Product not in promotion scope"
22
+ no_applicable_promotion: 'No applicable promotion',
23
+ promotion_not_in_time_range: 'Promotion not in valid time range',
24
+ product_not_in_promotion: 'Product not in promotion scope'
44
25
  },
45
- "zh-CN": {
46
- no_applicable_promotion: "无适用的促销活动",
47
- promotion_not_in_time_range: "促销活动不在有效时间范围内",
48
- product_not_in_promotion: "商品不在促销范围内"
26
+ 'zh-CN': {
27
+ no_applicable_promotion: '无适用的促销活动',
28
+ promotion_not_in_time_range: '促销活动不在有效时间范围内',
29
+ product_not_in_promotion: '商品不在促销范围内'
49
30
  },
50
- "zh-HK": {
51
- no_applicable_promotion: "無適用的促銷活動",
52
- promotion_not_in_time_range: "促銷活動不在有效時間範圍內",
53
- product_not_in_promotion: "商品不在促銷範圍內"
31
+ 'zh-HK': {
32
+ no_applicable_promotion: '無適用的促銷活動',
33
+ promotion_not_in_time_range: '促銷活動不在有效時間範圍內',
34
+ product_not_in_promotion: '商品不在促銷範圍內'
54
35
  }
55
36
  };
56
- var PromotionEvaluator = class {
37
+
38
+ // ============================================
39
+ // PromotionEvaluator 实现
40
+ // ============================================
41
+
42
+ /**
43
+ * Promotion 评估器
44
+ *
45
+ * 用于评估商品适用的促销活动
46
+ * 封装了 StrategyEngine 和 PromotionAdapter 的调用逻辑
47
+ */
48
+ class PromotionEvaluator {
49
+ engine;
50
+ adapter;
51
+ strategyConfigs = [];
52
+ locale = 'en';
53
+ locales = defaultLocales;
57
54
  constructor() {
58
- this.strategyConfigs = [];
59
- this.locale = "en";
60
- this.locales = defaultLocales;
61
- this.engine = new import_engine.StrategyEngine({
55
+ this.engine = new _engine.StrategyEngine({
62
56
  debug: false,
63
57
  enableTrace: false
64
58
  });
65
- this.adapter = new import_adapter.PromotionAdapter();
59
+ this.adapter = new _adapter.PromotionAdapter();
66
60
  }
61
+
67
62
  // ============================================
68
63
  // 配置管理
69
64
  // ============================================
65
+
70
66
  /**
71
67
  * 设置策略配置列表
72
68
  */
73
69
  setStrategyConfigs(strategyConfigs) {
74
- const newStrategyConfigs = strategyConfigs.filter((item) => item.metadata.type === "promotion");
70
+ const newStrategyConfigs = strategyConfigs.filter(item => item.metadata.type === 'promotion');
75
71
  this.strategyConfigs = newStrategyConfigs;
76
72
  }
73
+
77
74
  /**
78
75
  * 获取策略配置列表
79
76
  */
80
77
  getStrategyConfigs() {
81
78
  return this.strategyConfigs;
82
79
  }
80
+
83
81
  /**
84
82
  * 添加策略配置
85
83
  */
86
84
  addStrategyConfig(strategyConfig) {
87
85
  this.strategyConfigs.push(strategyConfig);
88
86
  }
87
+
89
88
  /**
90
89
  * 设置语言
91
90
  */
92
91
  setLocale(locale) {
93
92
  this.locale = locale;
94
93
  }
94
+
95
95
  /**
96
96
  * 设置自定义多语言文案
97
97
  */
98
98
  setLocales(locales) {
99
- this.locales = { ...defaultLocales, ...locales };
99
+ this.locales = {
100
+ ...defaultLocales,
101
+ ...locales
102
+ };
100
103
  }
104
+
101
105
  /**
102
106
  * 获取多语言文案
103
107
  */
104
108
  getText(key) {
105
- var _a, _b;
106
- return ((_b = (_a = this.locales) == null ? void 0 : _a[this.locale]) == null ? void 0 : _b[key]) || key;
109
+ return this.locales?.[this.locale]?.[key] || key;
107
110
  }
111
+
108
112
  /**
109
113
  * 获取多语言名称
110
114
  */
111
115
  getLocalizedName(name) {
112
- if (typeof name === "string") {
116
+ if (typeof name === 'string') {
113
117
  return name;
114
118
  }
115
- return name[this.locale] || name["en"] || Object.values(name)[0] || "";
119
+ return name[this.locale] || name['en'] || Object.values(name)[0] || '';
116
120
  }
121
+
117
122
  // ============================================
118
123
  // 核心评估方法
119
124
  // ============================================
125
+
120
126
  /**
121
127
  * 评估商品列表
122
128
  *
@@ -127,19 +133,31 @@ var PromotionEvaluator = class {
127
133
  * @returns 每个商品的促销评估结果
128
134
  */
129
135
  evaluateProducts(input) {
130
- const { products, strategyConfigs, channel } = input;
136
+ const {
137
+ products,
138
+ strategyConfigs,
139
+ channel
140
+ } = input;
131
141
  const configs = strategyConfigs || this.strategyConfigs;
132
142
  const results = [];
133
143
  for (const product of products) {
134
144
  const applicablePromotions = [];
145
+
146
+ // 遍历所有策略,检查此商品是否适用
135
147
  for (const config of configs) {
148
+ // 1. 先用 getProductMatchInfo 检查商品是否在策略的适用范围内(包含 bundle 子商品检查)
136
149
  const matchInfo = this.getProductMatchInfo(product, config);
137
150
  if (!matchInfo.isMatch) {
151
+ // 商品不在策略适用范围内,跳过
138
152
  continue;
139
153
  }
154
+
155
+ // 2. 准备上下文(如果是 bundle 子商品匹配,需要用 bundle 子商品的 ID)
140
156
  let contextProduct = product;
141
- if (matchInfo.matchedBundleIndex !== void 0 && product.bundle) {
157
+ if (matchInfo.matchedBundleIndex !== undefined && product.bundle) {
142
158
  const bundleItem = product.bundle[matchInfo.matchedBundleIndex];
159
+ // 创建一个临时的"虚拟商品"用于策略引擎评估
160
+ // 这样策略引擎的 product_match 条件能正确通过
143
161
  contextProduct = {
144
162
  ...product,
145
163
  product_id: bundleItem._bundle_product_id,
@@ -151,6 +169,8 @@ var PromotionEvaluator = class {
151
169
  currentProduct: contextProduct,
152
170
  channel
153
171
  });
172
+
173
+ // 3. 评估策略(检查其他条件如时间范围等)
154
174
  const result = this.engine.evaluate(config, context);
155
175
  if (result.applicable && result.matchedActions.length > 0) {
156
176
  const action = result.matchedActions[0];
@@ -181,6 +201,7 @@ var PromotionEvaluator = class {
181
201
  }
182
202
  return results;
183
203
  }
204
+
184
205
  /**
185
206
  * 评估购物车
186
207
  *
@@ -191,29 +212,42 @@ var PromotionEvaluator = class {
191
212
  * @returns 购物车评估结果
192
213
  */
193
214
  evaluateCart(input) {
194
- const { products, strategyConfigs, channel } = input;
215
+ const {
216
+ products,
217
+ strategyConfigs,
218
+ channel
219
+ } = input;
195
220
  const configs = strategyConfigs || this.strategyConfigs;
221
+
222
+ // 1. 先获取每个商品的促销结果
196
223
  const productResults = this.evaluateProducts(input);
197
- const promotionMap = /* @__PURE__ */ new Map();
224
+
225
+ // 2. 收集所有适用的促销(去重)
226
+ const promotionMap = new Map();
198
227
  for (const productResult of productResults) {
199
228
  for (const promo of productResult.applicablePromotions) {
200
229
  const existing = promotionMap.get(promo.strategyId);
201
230
  const product = productResult.product;
231
+
232
+ // 计算促销数量:如果是 bundle 子商品匹配,数量 = 主商品数量 × 子商品数量
202
233
  let promoQuantity = product.quantity;
203
- if (promo.matchedBundleIndex !== void 0 && product.bundle) {
234
+ if (promo.matchedBundleIndex !== undefined && product.bundle) {
204
235
  const bundleItem = product.bundle[promo.matchedBundleIndex];
205
236
  promoQuantity = product.quantity * (bundleItem.quantity || 1);
206
237
  }
207
238
  if (existing) {
239
+ // 已存在,添加商品到列表
208
240
  existing.applicableProducts.push(product);
209
241
  existing.totalQuantity += promoQuantity;
210
242
  existing.totalAmount += product.price * product.quantity;
243
+ // 记录每个商品的 matchedBundleIndex
211
244
  if (!existing.productMatchedBundleIndexMap) {
212
- existing.productMatchedBundleIndexMap = /* @__PURE__ */ new Map();
245
+ existing.productMatchedBundleIndexMap = new Map();
213
246
  }
214
247
  existing.productMatchedBundleIndexMap.set(product.id, promo.matchedBundleIndex);
215
248
  } else {
216
- const productMatchedBundleIndexMap = /* @__PURE__ */ new Map();
249
+ // 新促销
250
+ const productMatchedBundleIndexMap = new Map();
217
251
  productMatchedBundleIndexMap.set(product.id, promo.matchedBundleIndex);
218
252
  promotionMap.set(promo.strategyId, {
219
253
  ...promo,
@@ -226,30 +260,28 @@ var PromotionEvaluator = class {
226
260
  }
227
261
  }
228
262
  const applicablePromotions = Array.from(promotionMap.values());
229
- const promotionGroups = applicablePromotions.map(
230
- (promo) => {
231
- var _a;
232
- return {
233
- strategyId: promo.strategyId,
234
- strategyName: promo.strategyName,
235
- strategyMetadata: (_a = promo.strategyConfig) == null ? void 0 : _a.metadata,
236
- strategyConfig: promo.strategyConfig,
237
- actionType: promo.actionType,
238
- actionDetail: promo.actionDetail,
239
- products: promo.applicableProducts,
240
- totalQuantity: promo.totalQuantity,
241
- totalAmount: promo.totalAmount,
242
- // 传递 productMatchedBundleIndexMap 到 group
243
- productMatchedBundleIndexMap: promo.productMatchedBundleIndexMap
244
- };
245
- }
246
- );
263
+
264
+ // 3. 按促销分组
265
+ const promotionGroups = applicablePromotions.map(promo => ({
266
+ strategyId: promo.strategyId,
267
+ strategyName: promo.strategyName,
268
+ strategyMetadata: promo.strategyConfig?.metadata,
269
+ strategyConfig: promo.strategyConfig,
270
+ actionType: promo.actionType,
271
+ actionDetail: promo.actionDetail,
272
+ products: promo.applicableProducts,
273
+ totalQuantity: promo.totalQuantity,
274
+ totalAmount: promo.totalAmount,
275
+ // 传递 productMatchedBundleIndexMap 到 group
276
+ productMatchedBundleIndexMap: promo.productMatchedBundleIndexMap
277
+ }));
247
278
  return {
248
279
  productResults,
249
280
  applicablePromotions,
250
281
  promotionGroups
251
282
  };
252
283
  }
284
+
253
285
  /**
254
286
  * 评估购物车并计算定价
255
287
  *
@@ -261,60 +293,70 @@ var PromotionEvaluator = class {
261
293
  * @returns 带定价的购物车评估结果
262
294
  */
263
295
  evaluateCartWithPricing(input) {
264
- const { products } = input;
296
+ const {
297
+ products
298
+ } = input;
299
+
300
+ // 1. 先调用 evaluateCart 获取分组结果
265
301
  const cartResult = this.evaluateCart(input);
266
- const sortedGroups = this.sortPromotionGroupsByPriority(
267
- cartResult.promotionGroups,
268
- cartResult.applicablePromotions
269
- );
270
- const processedQuantityMap = /* @__PURE__ */ new Map();
302
+
303
+ // 2. 按 action priority 排序促销组(从 strategyConfig 获取 priority)
304
+ const sortedGroups = this.sortPromotionGroupsByPriority(cartResult.promotionGroups, cartResult.applicablePromotions);
305
+
306
+ // 3. 追踪已处理的商品(避免重复处理)
307
+ // key: `${product_id}_${product_variant_id}`
308
+ const processedQuantityMap = new Map();
309
+
310
+ // 4. 处理每个促销组,收集结果
271
311
  const pricedProducts = [];
272
312
  const gifts = [];
273
- let totalOriginalAmount = new import_decimal.default(0);
274
- let totalFinalAmount = new import_decimal.default(0);
313
+ let totalOriginalAmount = new _decimal.default(0);
314
+ let totalFinalAmount = new _decimal.default(0);
275
315
  for (const group of sortedGroups) {
276
- const { actionType } = group;
277
- const matchedBundleIndexMap = group.productMatchedBundleIndexMap || /* @__PURE__ */ new Map();
278
- if (actionType === import_type.PROMOTION_ACTION_TYPES.X_ITEMS_FOR_Y_PRICE) {
279
- const result = this.processXItemsForYPrice(
280
- group,
281
- processedQuantityMap,
282
- matchedBundleIndexMap
283
- );
316
+ const {
317
+ actionType
318
+ } = group;
319
+
320
+ // 直接使用 evaluateCart 阶段计算好的 matchedBundleIndexMap
321
+ const matchedBundleIndexMap = group.productMatchedBundleIndexMap || new Map();
322
+ if (actionType === _type.PROMOTION_ACTION_TYPES.X_ITEMS_FOR_Y_PRICE) {
323
+ // X件Y元处理
324
+ const result = this.processXItemsForYPrice(group, processedQuantityMap, matchedBundleIndexMap);
284
325
  pricedProducts.push(...result.products);
285
326
  totalOriginalAmount = totalOriginalAmount.plus(result.originalAmount);
286
327
  totalFinalAmount = totalFinalAmount.plus(result.finalAmount);
287
- } else if (actionType === import_type.PROMOTION_ACTION_TYPES.BUY_X_GET_Y_FREE) {
288
- const result = this.processBuyXGetYFree(
289
- group,
290
- processedQuantityMap,
291
- matchedBundleIndexMap
292
- );
328
+ } else if (actionType === _type.PROMOTION_ACTION_TYPES.BUY_X_GET_Y_FREE) {
329
+ // 买X送Y处理
330
+ const result = this.processBuyXGetYFree(group, processedQuantityMap, matchedBundleIndexMap);
293
331
  pricedProducts.push(...result.products);
294
332
  totalOriginalAmount = totalOriginalAmount.plus(result.originalAmount);
295
333
  totalFinalAmount = totalFinalAmount.plus(result.finalAmount);
334
+
335
+ // 添加赠品信息
296
336
  if (result.giftInfo) {
297
337
  gifts.push(result.giftInfo);
298
338
  }
299
339
  }
300
340
  }
301
- const remainingProducts = this.getRemainingProducts(
302
- products,
303
- processedQuantityMap
304
- );
341
+
342
+ // 5. 处理未参与任何促销的商品
343
+ const remainingProducts = this.getRemainingProducts(products, processedQuantityMap);
305
344
  for (const product of remainingProducts) {
306
- const amount = new import_decimal.default(product.price).mul(product.quantity);
345
+ const amount = new _decimal.default(product.price).mul(product.quantity);
307
346
  totalOriginalAmount = totalOriginalAmount.plus(amount);
308
347
  totalFinalAmount = totalFinalAmount.plus(amount);
309
348
  }
310
349
  pricedProducts.push(...remainingProducts);
350
+
351
+ // 6. 计算总优惠金额
311
352
  const totalDiscount = totalOriginalAmount.minus(totalFinalAmount);
312
353
  return {
313
354
  products: pricedProducts,
314
355
  gifts,
315
- totalDiscount: import_decimal.default.max(0, totalDiscount).toNumber()
356
+ totalDiscount: _decimal.default.max(0, totalDiscount).toNumber()
316
357
  };
317
358
  }
359
+
318
360
  /**
319
361
  * 获取商品适用的促销列表
320
362
  *
@@ -325,13 +367,13 @@ var PromotionEvaluator = class {
325
367
  * @returns 适用的促销列表
326
368
  */
327
369
  getProductPromotions(product, strategyConfigs) {
328
- var _a;
329
370
  const results = this.evaluateProducts({
330
371
  products: [product],
331
372
  strategyConfigs
332
373
  });
333
- return ((_a = results[0]) == null ? void 0 : _a.applicablePromotions) || [];
374
+ return results[0]?.applicablePromotions || [];
334
375
  }
376
+
335
377
  /**
336
378
  * 获取商品的促销标签
337
379
  *
@@ -343,12 +385,13 @@ var PromotionEvaluator = class {
343
385
  */
344
386
  getProductPromotionTags(product, strategyConfigs) {
345
387
  const promotions = this.getProductPromotions(product, strategyConfigs);
346
- return promotions.filter((promo) => promo.display).map((promo) => ({
388
+ return promotions.filter(promo => promo.display).map(promo => ({
347
389
  text: this.getLocalizedName(promo.display.text),
348
390
  type: promo.display.type,
349
391
  strategyId: promo.strategyId
350
392
  }));
351
393
  }
394
+
352
395
  /**
353
396
  * 查找商品适用的策略配置
354
397
  *
@@ -358,10 +401,9 @@ var PromotionEvaluator = class {
358
401
  */
359
402
  findApplicableStrategies(product, strategyConfigs) {
360
403
  const configs = strategyConfigs || this.strategyConfigs;
361
- return configs.filter(
362
- (config) => this.isProductInStrategy(product, config)
363
- );
404
+ return configs.filter(config => this.isProductInStrategy(product, config));
364
405
  }
406
+
365
407
  /**
366
408
  * 批量获取商品列表的适用策略信息
367
409
  *
@@ -373,23 +415,30 @@ var PromotionEvaluator = class {
373
415
  * @returns 每个商品的适用策略完整数据
374
416
  */
375
417
  getProductsApplicableStrategies(input, matchVariant = true) {
376
- const { products, strategyConfigs, channel } = input;
418
+ const {
419
+ products,
420
+ strategyConfigs,
421
+ channel
422
+ } = input;
377
423
  const configs = strategyConfigs || this.strategyConfigs;
378
424
  const results = [];
379
425
  for (const product of products) {
380
426
  const applicableStrategies = [];
427
+
428
+ // 遍历所有策略,检查此商品是否适用
381
429
  for (const config of configs) {
382
430
  let contextProduct = product;
383
431
  if (!matchVariant) {
432
+ // 只匹配 product_id,忽略 product_variant_id
384
433
  const productMatchRule = this.findProductMatchRule(config);
385
434
  if (productMatchRule) {
386
435
  const configProducts = productMatchRule.value;
387
- const matchedConfig = configProducts.find(
388
- (item) => item.product_id === product.product_id
389
- );
436
+ const matchedConfig = configProducts.find(item => item.product_id === product.product_id);
390
437
  if (!matchedConfig) {
438
+ // product_id 不在策略适用范围内,跳过
391
439
  continue;
392
440
  }
441
+ // 用配置中的 variant_id 构造上下文,确保引擎 product_match 通过
393
442
  if (matchedConfig.product_variant_id !== 0 && matchedConfig.product_variant_id !== product.product_variant_id) {
394
443
  contextProduct = {
395
444
  ...product,
@@ -403,6 +452,8 @@ var PromotionEvaluator = class {
403
452
  currentProduct: contextProduct,
404
453
  channel
405
454
  });
455
+
456
+ // 评估策略
406
457
  const result = this.engine.evaluate(config, context);
407
458
  if (result.applicable && result.matchedActions.length > 0) {
408
459
  const action = result.matchedActions[0];
@@ -412,11 +463,11 @@ var PromotionEvaluator = class {
412
463
  channel
413
464
  });
414
465
  if (transformedResult.actionDetail) {
415
- const { requiredQuantity, eligibleProducts } = this.getPromotionRequirements(
416
- action.type,
417
- transformedResult.actionDetail,
418
- config
419
- );
466
+ // 计算所需数量和可参与商品列表
467
+ const {
468
+ requiredQuantity,
469
+ eligibleProducts
470
+ } = this.getPromotionRequirements(action.type, transformedResult.actionDetail, config);
420
471
  applicableStrategies.push({
421
472
  strategyId: config.metadata.id,
422
473
  strategyName: config.metadata.name,
@@ -439,6 +490,7 @@ var PromotionEvaluator = class {
439
490
  }
440
491
  return results;
441
492
  }
493
+
442
494
  /**
443
495
  * 获取促销所需数量和可参与商品列表
444
496
  *
@@ -449,41 +501,50 @@ var PromotionEvaluator = class {
449
501
  */
450
502
  getPromotionRequirements(actionType, actionDetail, config) {
451
503
  let requiredQuantity = 0;
452
- if (actionType === "BUY_X_GET_Y_FREE") {
504
+
505
+ // 根据促销类型获取所需数量
506
+ if (actionType === 'BUY_X_GET_Y_FREE') {
453
507
  const detail = actionDetail;
454
508
  requiredQuantity = detail.buyQuantity || 0;
455
- } else if (actionType === "X_ITEMS_FOR_Y_PRICE") {
509
+ } else if (actionType === 'X_ITEMS_FOR_Y_PRICE') {
456
510
  const detail = actionDetail;
457
511
  requiredQuantity = detail.x || 0;
458
512
  }
513
+
514
+ // 获取可参与商品列表
459
515
  const productMatchRule = this.findProductMatchRule(config);
460
- const eligibleProducts = (productMatchRule == null ? void 0 : productMatchRule.value) || [];
516
+ const eligibleProducts = productMatchRule?.value || [];
461
517
  return {
462
518
  requiredQuantity,
463
519
  eligibleProducts
464
520
  };
465
521
  }
522
+
466
523
  // ============================================
467
524
  // 私有辅助方法
468
525
  // ============================================
526
+
469
527
  /**
470
528
  * 按优先级排序促销组
471
529
  * 优先级从 strategyConfig.actions[0].priority 获取,数值越小优先级越高
472
530
  */
473
531
  sortPromotionGroupsByPriority(groups, promotions) {
474
- var _a, _b;
475
- const priorityMap = /* @__PURE__ */ new Map();
532
+ // 创建策略ID到优先级的映射
533
+ const priorityMap = new Map();
476
534
  for (const promo of promotions) {
477
- const actions = ((_a = promo.strategyConfig) == null ? void 0 : _a.actions) || [];
478
- const priority = ((_b = actions[0]) == null ? void 0 : _b.priority) ?? 999;
535
+ const actions = promo.strategyConfig?.actions || [];
536
+ const priority = actions[0]?.priority ?? 999;
479
537
  priorityMap.set(promo.strategyId, priority);
480
538
  }
539
+
540
+ // 按优先级排序(数值越小优先级越高)
481
541
  return [...groups].sort((a, b) => {
482
542
  const priorityA = priorityMap.get(a.strategyId) ?? 999;
483
543
  const priorityB = priorityMap.get(b.strategyId) ?? 999;
484
544
  return priorityA - priorityB;
485
545
  });
486
546
  }
547
+
487
548
  /**
488
549
  * 处理 X件Y元 促销
489
550
  *
@@ -495,19 +556,32 @@ var PromotionEvaluator = class {
495
556
  * 注意:每个商品按 id 独立处理,不会合并不同 id 的商品
496
557
  */
497
558
  processXItemsForYPrice(group, processedQuantityMap, matchedBundleIndexMap) {
498
- const { strategyId, strategyMetadata, actionDetail, products: groupProducts } = group;
559
+ const {
560
+ strategyId,
561
+ strategyMetadata,
562
+ actionDetail,
563
+ products: groupProducts
564
+ } = group;
499
565
  const detail = actionDetail;
500
- const { x, price: groupPrice, cumulative } = detail;
566
+ const {
567
+ x,
568
+ price: groupPrice,
569
+ cumulative
570
+ } = detail;
501
571
  const result = [];
502
- let originalAmount = new import_decimal.default(0);
503
- let finalAmount = new import_decimal.default(0);
572
+ let originalAmount = new _decimal.default(0);
573
+ let finalAmount = new _decimal.default(0);
574
+
575
+ // 1. 展开所有商品为单件列表(排除已处理的数量)
576
+ // 每个单件记录来自哪个原商品(通过 product.id)
504
577
  const unitProducts = [];
505
578
  for (const product of groupProducts) {
506
579
  const key = this.getProductKey(product);
507
580
  const processedQty = processedQuantityMap.get(key) || 0;
508
581
  const availableQty = product.quantity - processedQty;
509
- if (availableQty <= 0)
510
- continue;
582
+ if (availableQty <= 0) continue;
583
+
584
+ // 展开为单件,每个单件都记录来源商品
511
585
  for (let i = 0; i < availableQty; i++) {
512
586
  unitProducts.push({
513
587
  product,
@@ -518,46 +592,67 @@ var PromotionEvaluator = class {
518
592
  }
519
593
  }
520
594
  if (unitProducts.length === 0) {
521
- return { products: [], originalAmount: 0, finalAmount: 0 };
595
+ return {
596
+ products: [],
597
+ originalAmount: 0,
598
+ finalAmount: 0
599
+ };
522
600
  }
601
+
602
+ // 2. 排序:优先选择来源数量是 x 倍数的商品(可完整凑组不拆分),然后按价格从高到低
523
603
  unitProducts.sort((a, b) => {
604
+ // 优先级1:来源购物车项数量是 x 的倍数的排前面(这些商品可以完整凑组,避免拆分)
524
605
  const aIsMultiple = a.sourceAvailableQty > 0 && a.sourceAvailableQty % x === 0 ? 1 : 0;
525
606
  const bIsMultiple = b.sourceAvailableQty > 0 && b.sourceAvailableQty % x === 0 ? 1 : 0;
526
- if (aIsMultiple !== bIsMultiple)
527
- return bIsMultiple - aIsMultiple;
607
+ if (aIsMultiple !== bIsMultiple) return bIsMultiple - aIsMultiple;
608
+ // 优先级2:按价格从高到低(优先使用高价商品)
528
609
  return b.price - a.price;
529
610
  });
611
+
612
+ // 3. 计算可以凑成多少组(cumulative 缺省视为 true,与 adapter 一致)
530
613
  const totalUnits = unitProducts.length;
531
- const groupCount = cumulative ? Math.floor(totalUnits / x) : totalUnits >= x ? 1 : 0;
614
+ const isCumulative = cumulative !== false;
615
+ const groupCount = isCumulative ? Math.floor(totalUnits / x) : totalUnits >= x ? 1 : 0;
532
616
  const promotionUnits = groupCount * x;
617
+
618
+ // 4. 分离参与促销的和不参与的商品
533
619
  const inPromotionUnits = unitProducts.slice(0, promotionUnits);
534
620
  const notInPromotionUnits = unitProducts.slice(promotionUnits);
535
- const promotionQtyByProductId = /* @__PURE__ */ new Map();
621
+
622
+ // 5. 按原商品 id 统计参与促销和不参与的数量
623
+ const promotionQtyByProductId = new Map();
536
624
  for (const unit of inPromotionUnits) {
537
625
  const id = unit.productId;
538
626
  promotionQtyByProductId.set(id, (promotionQtyByProductId.get(id) || 0) + 1);
539
627
  }
540
- const remainingQtyByProductId = /* @__PURE__ */ new Map();
628
+ const remainingQtyByProductId = new Map();
541
629
  for (const unit of notInPromotionUnits) {
542
630
  const id = unit.productId;
543
631
  remainingQtyByProductId.set(id, (remainingQtyByProductId.get(id) || 0) + 1);
544
632
  }
545
- const allocatedPricesByProductId = /* @__PURE__ */ new Map();
633
+
634
+ // 6. 为每个参与促销的单件计算均摊价格
635
+ // 按组内原价比例均摊
636
+ // 记录每个原商品的均摊价格累加(用于后续聚合)
637
+ const allocatedPricesByProductId = new Map();
546
638
  for (let g = 0; g < groupCount; g++) {
547
639
  const startIdx = g * x;
548
640
  const endIdx = startIdx + x;
549
641
  const groupUnits = inPromotionUnits.slice(startIdx, endIdx);
550
- const groupOriginalTotal = groupUnits.reduce(
551
- (sum, u) => sum.plus(u.price),
552
- new import_decimal.default(0)
553
- );
554
- const groupPriceDecimal = new import_decimal.default(groupPrice);
555
- let allocatedSum = new import_decimal.default(0);
642
+
643
+ // 计算组内原价总和
644
+ const groupOriginalTotal = groupUnits.reduce((sum, u) => sum.plus(u.price), new _decimal.default(0));
645
+
646
+ // 按原价比例均摊
647
+ const groupPriceDecimal = new _decimal.default(groupPrice);
648
+ let allocatedSum = new _decimal.default(0);
556
649
  for (let i = 0; i < groupUnits.length; i++) {
557
650
  const unit = groupUnits[i];
558
651
  const isLastUnit = i === groupUnits.length - 1;
559
- const ratio = groupOriginalTotal.eq(0) ? new import_decimal.default(0) : new import_decimal.default(unit.price).div(groupOriginalTotal);
652
+ const ratio = groupOriginalTotal.eq(0) ? new _decimal.default(0) : new _decimal.default(unit.price).div(groupOriginalTotal);
560
653
  const allocatedDecimal = isLastUnit ? groupPriceDecimal.minus(allocatedSum) : groupPriceDecimal.mul(ratio);
654
+
655
+ // 记录这个单件的均摊价格
561
656
  const productId = unit.productId;
562
657
  const prices = allocatedPricesByProductId.get(productId) || [];
563
658
  prices.push(allocatedDecimal);
@@ -565,23 +660,25 @@ var PromotionEvaluator = class {
565
660
  allocatedSum = allocatedSum.plus(allocatedDecimal);
566
661
  }
567
662
  }
663
+
664
+ // 7. 为每个原商品生成结果
568
665
  for (const product of groupProducts) {
569
666
  const key = this.getProductKey(product);
570
667
  const processedQty = processedQuantityMap.get(key) || 0;
571
668
  const availableQty = product.quantity - processedQty;
572
- if (availableQty <= 0)
573
- continue;
669
+ if (availableQty <= 0) continue;
574
670
  const promoQty = promotionQtyByProductId.get(product.id) || 0;
575
671
  const remainingQty = remainingQtyByProductId.get(product.id) || 0;
576
672
  const allocatedPrices = allocatedPricesByProductId.get(product.id) || [];
577
- const matchedBundleIndex = matchedBundleIndexMap == null ? void 0 : matchedBundleIndexMap.get(product.id);
673
+
674
+ // 获取当前商品的 matchedBundleIndex
675
+ const matchedBundleIndex = matchedBundleIndexMap?.get(product.id);
578
676
  if (promoQty > 0 && remainingQty === 0) {
579
- const totalAllocated = allocatedPrices.reduce(
580
- (sum, p) => sum.plus(p),
581
- new import_decimal.default(0)
582
- );
583
- const productOriginalAmount = new import_decimal.default(product.price).mul(promoQty);
584
- const actualTotal = import_decimal.default.min(totalAllocated, productOriginalAmount);
677
+ // 全部参与促销:保留原 id,计算总 finalPrice
678
+ const totalAllocated = allocatedPrices.reduce((sum, p) => sum.plus(p), new _decimal.default(0));
679
+ // 取促销价和原价的最小值,避免促销反而加价
680
+ const productOriginalAmount = new _decimal.default(product.price).mul(promoQty);
681
+ const actualTotal = _decimal.default.min(totalAllocated, productOriginalAmount);
585
682
  const finalPricePerUnit = this.formatPrice(actualTotal.div(promoQty));
586
683
  result.push({
587
684
  ...product,
@@ -596,25 +693,26 @@ var PromotionEvaluator = class {
596
693
  originalAmount = originalAmount.plus(productOriginalAmount);
597
694
  finalAmount = finalAmount.plus(actualTotal);
598
695
  } else if (promoQty === 0 && remainingQty > 0) {
696
+ // 全部不参与促销:保留原 id,finalPrice = 原价
599
697
  result.push({
600
698
  ...product,
601
699
  quantity: remainingQty,
602
700
  finalPrice: this.formatPrice(product.price),
603
- strategyId: void 0,
604
- strategyMetadata: void 0,
701
+ strategyId: undefined,
702
+ strategyMetadata: undefined,
605
703
  inPromotion: false,
606
704
  isSplit: false
607
705
  });
608
- const amount = new import_decimal.default(product.price).mul(remainingQty);
706
+ const amount = new _decimal.default(product.price).mul(remainingQty);
609
707
  originalAmount = originalAmount.plus(amount);
610
708
  finalAmount = finalAmount.plus(amount);
611
709
  } else if (promoQty > 0 && remainingQty > 0) {
612
- const totalAllocated = allocatedPrices.reduce(
613
- (sum, p) => sum.plus(p),
614
- new import_decimal.default(0)
615
- );
616
- const promoOriginalAmount = new import_decimal.default(product.price).mul(promoQty);
617
- const actualTotal = import_decimal.default.min(totalAllocated, promoOriginalAmount);
710
+ // 部分参与促销,部分不参与:需要拆分
711
+ // 参与促销的部分:新 id
712
+ const totalAllocated = allocatedPrices.reduce((sum, p) => sum.plus(p), new _decimal.default(0));
713
+ // 取促销价和原价的最小值,避免促销反而加价
714
+ const promoOriginalAmount = new _decimal.default(product.price).mul(promoQty);
715
+ const actualTotal = _decimal.default.min(totalAllocated, promoOriginalAmount);
618
716
  const finalPricePerUnit = this.formatPrice(actualTotal.div(promoQty));
619
717
  result.push({
620
718
  ...product,
@@ -630,44 +728,50 @@ var PromotionEvaluator = class {
630
728
  });
631
729
  originalAmount = originalAmount.plus(promoOriginalAmount);
632
730
  finalAmount = finalAmount.plus(actualTotal);
731
+
732
+ // 不参与促销的部分:保留原 id
633
733
  result.push({
634
734
  ...product,
635
735
  quantity: remainingQty,
636
736
  finalPrice: this.formatPrice(product.price),
637
- strategyId: void 0,
638
- strategyMetadata: void 0,
737
+ strategyId: undefined,
738
+ strategyMetadata: undefined,
639
739
  inPromotion: false,
640
740
  isSplit: true
641
741
  });
642
- const remainingAmount = new import_decimal.default(product.price).mul(remainingQty);
742
+ const remainingAmount = new _decimal.default(product.price).mul(remainingQty);
643
743
  originalAmount = originalAmount.plus(remainingAmount);
644
744
  finalAmount = finalAmount.plus(remainingAmount);
645
745
  }
746
+
747
+ // 更新已处理数量
646
748
  processedQuantityMap.set(key, processedQty + availableQty);
647
749
  }
750
+
751
+ // 8. 尾差调整:确保促销商品的 finalPrice × quantity 之和精确等于 groupPrice × groupCount
648
752
  if (groupCount > 0) {
649
- const expectedPromoTotal = new import_decimal.default(groupPrice).mul(groupCount);
650
- const promoItems = result.filter((p) => p.inPromotion);
651
- let actualPromoTotal = new import_decimal.default(0);
753
+ const expectedPromoTotal = new _decimal.default(groupPrice).mul(groupCount);
754
+ const promoItems = result.filter(p => p.inPromotion);
755
+ let actualPromoTotal = new _decimal.default(0);
652
756
  for (const p of promoItems) {
653
- actualPromoTotal = actualPromoTotal.plus(
654
- new import_decimal.default(p.finalPrice).mul(p.quantity)
655
- );
757
+ actualPromoTotal = actualPromoTotal.plus(new _decimal.default(p.finalPrice).mul(p.quantity));
656
758
  }
657
759
  const roundingDiff = actualPromoTotal.minus(expectedPromoTotal);
658
760
  if (!roundingDiff.eq(0)) {
659
- const adjustTarget = promoItems.find((p) => p.quantity === 1);
761
+ // 优先找 quantity=1 的促销商品调整(差额直接加减到单价上)
762
+ const adjustTarget = promoItems.find(p => p.quantity === 1);
660
763
  if (adjustTarget) {
661
- adjustTarget.finalPrice = this.formatPrice(
662
- new import_decimal.default(adjustTarget.finalPrice).minus(roundingDiff)
663
- );
764
+ adjustTarget.finalPrice = this.formatPrice(new _decimal.default(adjustTarget.finalPrice).minus(roundingDiff));
664
765
  } else if (promoItems.length > 0) {
766
+ // 没有 quantity=1 的促销商品,从最后一个促销商品中拆出1件做尾差调整
665
767
  const lastPromo = promoItems[promoItems.length - 1];
666
- const adjustedUnitPrice = this.formatPrice(
667
- new import_decimal.default(lastPromo.finalPrice).minus(roundingDiff)
668
- );
768
+ const adjustedUnitPrice = this.formatPrice(new _decimal.default(lastPromo.finalPrice).minus(roundingDiff));
769
+
770
+ // 原商品减少1件
669
771
  lastPromo.quantity -= 1;
670
772
  lastPromo.isSplit = true;
773
+
774
+ // 拆出1件用调整后的价格
671
775
  result.push({
672
776
  ...lastPromo,
673
777
  id: this.generateRandomId(),
@@ -677,11 +781,11 @@ var PromotionEvaluator = class {
677
781
  isSplit: true
678
782
  });
679
783
  }
680
- finalAmount = new import_decimal.default(0);
784
+
785
+ // 重新计算 finalAmount
786
+ finalAmount = new _decimal.default(0);
681
787
  for (const p of result) {
682
- finalAmount = finalAmount.plus(
683
- new import_decimal.default(p.finalPrice).mul(p.quantity)
684
- );
788
+ finalAmount = finalAmount.plus(new _decimal.default(p.finalPrice).mul(p.quantity));
685
789
  }
686
790
  }
687
791
  }
@@ -691,6 +795,7 @@ var PromotionEvaluator = class {
691
795
  finalAmount: finalAmount.toNumber()
692
796
  };
693
797
  }
798
+
694
799
  /**
695
800
  * 处理 买X送Y 促销
696
801
  *
@@ -706,34 +811,56 @@ var PromotionEvaluator = class {
706
811
  products: groupProducts
707
812
  } = group;
708
813
  const detail = actionDetail;
709
- const { buyQuantity, freeQuantity, cumulative, giftProducts } = detail;
814
+ const {
815
+ buyQuantity,
816
+ freeQuantity,
817
+ cumulative,
818
+ giftProducts
819
+ } = detail;
710
820
  const result = [];
711
- let originalAmount = new import_decimal.default(0);
712
- let finalAmount = new import_decimal.default(0);
821
+ let originalAmount = new _decimal.default(0);
822
+ let finalAmount = new _decimal.default(0);
823
+
824
+ // 1. 先计算可用商品总数量(第一次遍历)
825
+ // 对于 bundle 子商品匹配,促销数量 = 主商品数量 × bundle子商品数量
713
826
  let totalPromoQty = 0;
714
- const productInfoMap = /* @__PURE__ */ new Map();
827
+ const productInfoMap = new Map();
715
828
  for (const product of groupProducts) {
716
829
  const key = this.getProductKey(product);
717
830
  const processedQty = processedQuantityMap.get(key) || 0;
718
831
  const availableQty = product.quantity - processedQty;
719
- if (availableQty <= 0)
720
- continue;
721
- const matchedBundleIndex = matchedBundleIndexMap == null ? void 0 : matchedBundleIndexMap.get(product.id);
832
+ if (availableQty <= 0) continue;
833
+
834
+ // 获取 matchedBundleIndex
835
+ const matchedBundleIndex = matchedBundleIndexMap?.get(product.id);
836
+
837
+ // 计算用于促销的数量
722
838
  let promoQty = availableQty;
723
- if (matchedBundleIndex !== void 0 && product.bundle) {
839
+ if (matchedBundleIndex !== undefined && product.bundle) {
724
840
  const bundleItem = product.bundle[matchedBundleIndex];
841
+ // 促销数量 = 主商品数量 × bundle子商品数量
725
842
  promoQty = availableQty * (bundleItem.quantity || 1);
726
843
  }
727
844
  totalPromoQty += promoQty;
728
- productInfoMap.set(key, { availableQty, promoQty, matchedBundleIndex });
845
+ productInfoMap.set(key, {
846
+ availableQty,
847
+ promoQty,
848
+ matchedBundleIndex
849
+ });
729
850
  }
851
+
852
+ // 2. 判断是否满足促销条件
730
853
  const isFulfilled = totalPromoQty >= buyQuantity;
854
+
855
+ // 3. 生成商品结果(第二次遍历)
731
856
  for (const product of groupProducts) {
732
857
  const key = this.getProductKey(product);
733
858
  const info = productInfoMap.get(key);
734
- if (!info || info.availableQty <= 0)
735
- continue;
859
+ if (!info || info.availableQty <= 0) continue;
736
860
  const processedQty = processedQuantityMap.get(key) || 0;
861
+
862
+ // 商品本身价格不变,只是触发赠品
863
+ // inPromotion 只有在满足条件时才为 true
737
864
  result.push({
738
865
  ...product,
739
866
  quantity: info.availableQty,
@@ -745,15 +872,21 @@ var PromotionEvaluator = class {
745
872
  isSplit: info.availableQty < product.quantity,
746
873
  matchedBundleIndex: info.matchedBundleIndex
747
874
  });
748
- const amount = new import_decimal.default(product.price).mul(info.availableQty);
875
+ const amount = new _decimal.default(product.price).mul(info.availableQty);
749
876
  originalAmount = originalAmount.plus(amount);
750
877
  finalAmount = finalAmount.plus(amount);
878
+
879
+ // 更新已处理数量(使用主商品数量)
751
880
  processedQuantityMap.set(key, processedQty + info.availableQty);
752
881
  }
882
+
883
+ // 4. 计算赠品数量(使用促销数量)
753
884
  let giftCount = 0;
754
885
  if (isFulfilled) {
755
886
  giftCount = cumulative ? Math.floor(totalPromoQty / buyQuantity) * freeQuantity : freeQuantity;
756
887
  }
888
+
889
+ // 5. 构建赠品信息
757
890
  const giftInfo = giftCount > 0 ? {
758
891
  strategyId,
759
892
  strategyName,
@@ -767,6 +900,7 @@ var PromotionEvaluator = class {
767
900
  giftInfo
768
901
  };
769
902
  }
903
+
770
904
  /**
771
905
  * 获取未参与任何促销的商品
772
906
  */
@@ -781,7 +915,7 @@ var PromotionEvaluator = class {
781
915
  ...product,
782
916
  quantity: remainingQty,
783
917
  finalPrice: this.formatPrice(product.price),
784
- strategyId: void 0,
918
+ strategyId: undefined,
785
919
  inPromotion: false,
786
920
  isSplit: remainingQty < product.quantity
787
921
  });
@@ -789,12 +923,14 @@ var PromotionEvaluator = class {
789
923
  }
790
924
  return result;
791
925
  }
926
+
792
927
  /**
793
928
  * 价格统一保留两位小数
794
929
  */
795
930
  formatPrice(value) {
796
- return new import_decimal.default(value).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber();
931
+ return new _decimal.default(value).toDecimalPlaces(2, _decimal.default.ROUND_HALF_UP).toNumber();
797
932
  }
933
+
798
934
  /**
799
935
  * 获取商品唯一标识 key
800
936
  * 使用商品的 id 作为唯一标识,不同 id 的商品不会被合并
@@ -802,92 +938,107 @@ var PromotionEvaluator = class {
802
938
  getProductKey(product) {
803
939
  return String(product.id);
804
940
  }
941
+
805
942
  /**
806
943
  * 生成随机ID
807
944
  */
808
945
  generateRandomId() {
809
- return Math.floor(Math.random() * 1e9) + Date.now();
946
+ return Math.floor(Math.random() * 1000000000) + Date.now();
810
947
  }
948
+
811
949
  /**
812
950
  * 商品匹配结果信息
813
951
  */
814
952
  getProductMatchInfo(product, config) {
815
953
  const productMatchRule = this.findProductMatchRule(config);
816
954
  if (!productMatchRule) {
817
- return { isMatch: true };
955
+ // 没有商品范围条件,默认适用所有商品(匹配主商品)
956
+ return {
957
+ isMatch: true
958
+ };
818
959
  }
819
960
  const configProducts = productMatchRule.value;
961
+
962
+ // 1. 先检查主商品是否匹配
820
963
  if (this.isProductIdMatch(product.product_id, product.product_variant_id, configProducts)) {
821
- return { isMatch: true };
964
+ return {
965
+ isMatch: true
966
+ };
822
967
  }
968
+
969
+ // 2. 主商品不匹配,检查 bundle 子商品
823
970
  if (product.bundle && product.bundle.length > 0) {
824
971
  for (let i = 0; i < product.bundle.length; i++) {
825
972
  const bundleItem = product.bundle[i];
826
- if (this.isProductIdMatch(
827
- bundleItem._bundle_product_id,
828
- bundleItem.product_variant_id,
829
- configProducts
830
- )) {
831
- return { isMatch: true, matchedBundleIndex: i };
973
+ if (this.isProductIdMatch(bundleItem._bundle_product_id, bundleItem.product_variant_id, configProducts)) {
974
+ return {
975
+ isMatch: true,
976
+ matchedBundleIndex: i
977
+ };
832
978
  }
833
979
  }
834
980
  }
835
- return { isMatch: false };
981
+ return {
982
+ isMatch: false
983
+ };
836
984
  }
985
+
837
986
  /**
838
987
  * 检查商品是否在策略的适用范围内
839
988
  */
840
989
  isProductInStrategy(product, config) {
841
990
  return this.getProductMatchInfo(product, config).isMatch;
842
991
  }
992
+
843
993
  /**
844
994
  * 查找商品匹配规则
845
995
  */
846
996
  findProductMatchRule(config) {
847
- var _a;
848
- if (!((_a = config == null ? void 0 : config.conditions) == null ? void 0 : _a.rules)) {
997
+ if (!config?.conditions?.rules) {
849
998
  return null;
850
999
  }
851
- return config.conditions.rules.find(
852
- (rule) => rule.field === "productIdAndVariantId" && (rule.operator === "product_match" || rule.operator === "object_in")
853
- );
1000
+ return config.conditions.rules.find(rule => rule.field === 'productIdAndVariantId' && (rule.operator === 'product_match' || rule.operator === 'object_in'));
854
1001
  }
1002
+
855
1003
  /**
856
1004
  * 检查商品ID是否匹配配置列表
857
1005
  */
858
1006
  isProductIdMatch(productId, productVariantId, configProducts) {
859
- return configProducts.some((config) => {
1007
+ return configProducts.some(config => {
1008
+ // 首先检查 product_id
860
1009
  if (config.product_id !== productId) {
861
1010
  return false;
862
1011
  }
1012
+
1013
+ // 如果配置的 product_variant_id = 0,只需要 product_id 匹配
863
1014
  if (config.product_variant_id === 0) {
864
1015
  return true;
865
1016
  }
1017
+
1018
+ // 否则需要 product_variant_id 精确匹配
866
1019
  return config.product_variant_id === productVariantId;
867
1020
  });
868
1021
  }
1022
+
869
1023
  /**
870
1024
  * 检查商品是否匹配配置(兼容旧方法)
871
1025
  */
872
1026
  isProductMatch(product, configProducts) {
873
1027
  return this.isProductIdMatch(product.product_id, product.product_variant_id, configProducts);
874
1028
  }
1029
+
875
1030
  /**
876
1031
  * 获取展示配置
877
1032
  */
878
1033
  getDisplayConfig(config) {
879
- var _a;
880
1034
  const custom = config.metadata.custom;
881
- if ((_a = custom == null ? void 0 : custom.display) == null ? void 0 : _a.product_card) {
1035
+ if (custom?.display?.product_card) {
882
1036
  return {
883
1037
  text: custom.display.product_card.text,
884
1038
  type: custom.display.product_card.type
885
1039
  };
886
1040
  }
887
- return void 0;
1041
+ return undefined;
888
1042
  }
889
- };
890
- // Annotate the CommonJS export names for ESM import in node:
891
- 0 && (module.exports = {
892
- PromotionEvaluator
893
- });
1043
+ }
1044
+ exports.PromotionEvaluator = PromotionEvaluator;