@pisell/pisellos 0.0.569 → 0.10.2

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