@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,32 +1,58 @@
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/modules/Rules/index.ts
30
+ var Rules_exports = {};
31
+ __export(Rules_exports, {
32
+ RulesModule: () => RulesModule
5
33
  });
6
- exports.RulesModule = void 0;
7
- var _BaseModule = require("../BaseModule");
8
- var _types = require("./types");
9
- var _utils = require("../../solution/ShopDiscount/utils");
10
- var _utils2 = require("../Cart/utils");
11
- var _decimal = _interopRequireDefault(require("decimal.js"));
12
- var _lodashEs = require("lodash-es");
13
- var _dayjs = _interopRequireDefault(require("dayjs"));
14
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
- class RulesModule extends _BaseModule.BaseModule {
16
- defaultName = 'rules';
17
- defaultVersion = '1.0.0';
18
- store;
19
- window; // WindowPlugin 实例
20
- hooks;
34
+ module.exports = __toCommonJS(Rules_exports);
35
+ var import_BaseModule = require("../BaseModule");
36
+ var import_types = require("./types");
37
+ var import_utils = require("../../solution/ShopDiscount/utils");
38
+ var import_utils2 = require("../Cart/utils");
39
+ var import_decimal = __toESM(require("decimal.js"));
40
+ var import_lodash_es = require("lodash-es");
41
+ var import_dayjs = __toESM(require("dayjs"));
42
+ var import_utils3 = require("../../solution/ShopDiscount/utils");
43
+ var import_utils4 = require("../../solution/ShopDiscount/utils");
44
+ var RulesModule = class extends import_BaseModule.BaseModule {
21
45
  constructor(name, version) {
22
46
  super(name, version);
47
+ this.defaultName = "rules";
48
+ this.defaultVersion = "1.0.0";
23
49
  this.hooks = {};
24
50
  }
25
51
  async initialize(core, options) {
26
52
  this.core = core;
27
- this.hooks = options?.hooks;
28
- this.store = options?.store;
29
- this.window = core.getPlugin('window');
53
+ this.hooks = options == null ? void 0 : options.hooks;
54
+ this.store = options == null ? void 0 : options.store;
55
+ this.window = core.getPlugin("window");
30
56
  }
31
57
  async setRulesList(rulesList) {
32
58
  this.store.rulesList = rulesList;
@@ -36,25 +62,22 @@ class RulesModule extends _BaseModule.BaseModule {
36
62
  return this.store.rulesList;
37
63
  }
38
64
  getWalletPassEvaluator() {
39
- return this.window.getWalletPassEvaluator?.();
65
+ var _a, _b;
66
+ return (_b = (_a = this.window).getWalletPassEvaluator) == null ? void 0 : _b.call(_a);
40
67
  }
41
-
42
68
  // 商品不需要holder,则不需要判断,直接返回true,商品需要holder但是还没填写,那么暂时不使用带有holder的券,直到填写才去匹配
43
69
  checkHolderMatch(discount, product, holders) {
44
- // 非表单类型 holder 视为匹配
45
- if (discount.holder?.holder_type !== 'form') return true;
46
- // 主预约holder, 目前(20251124)默认只考虑单个holder的情况
47
- // 旧版 holders[0].form_record_id 新版 holders[0]
48
- const orderHolderId = Array.isArray(holders) && holders.length > 0 ? holders[0].form_record_id || holders[0] : undefined;
70
+ var _a;
71
+ if (((_a = discount.holder) == null ? void 0 : _a.holder_type) !== "form")
72
+ return true;
73
+ const orderHolderId = Array.isArray(holders) && holders.length > 0 ? holders[0].form_record_id || holders[0] : void 0;
49
74
  const productHolderId = Array.isArray(product.holder_id) ? product.holder_id[0] : product.holder_id;
50
- // 商品不需要选holder,则不对比holder,直接返回true,
51
- if (!product.isNeedHolder) return true;
52
- // 商品需要holder,但父预约及商品都无holder,返回false
53
- if (!orderHolderId && !productHolderId) return false;
54
- // 最终直接匹配 holder 是否相同
75
+ if (!product.isNeedHolder)
76
+ return true;
77
+ if (!orderHolderId && !productHolderId)
78
+ return false;
55
79
  return (productHolderId || orderHolderId) === discount.holder.holder_id;
56
80
  }
57
-
58
81
  // 判断discountList 是否可以对当前productList生效
59
82
  isDiscountListAvailable({
60
83
  oldDiscountList,
@@ -64,7 +87,6 @@ class RulesModule extends _BaseModule.BaseModule {
64
87
  holders,
65
88
  isFormSubject
66
89
  }) {
67
- // 首先检查是否有新的优惠券可应用
68
90
  if (!newDiscountList || newDiscountList.length === 0) {
69
91
  return {
70
92
  isAvailable: false,
@@ -72,58 +94,57 @@ class RulesModule extends _BaseModule.BaseModule {
72
94
  productList
73
95
  };
74
96
  }
75
-
76
- // 编辑商品已有商品券
77
- if (productList.every(item => {
97
+ if (productList.every((item) => {
98
+ var _a;
78
99
  const product = this.hooks.getProduct(item);
79
- return product.booking_id && (product.discount_list?.length || product.total == 0);
100
+ return product.booking_id && (((_a = product.discount_list) == null ? void 0 : _a.length) || product.total == 0);
80
101
  })) {
81
102
  return {
82
103
  isAvailable: false,
83
104
  discountList: oldDiscountList,
84
105
  productList,
85
- unavailableReason: _types.UnavailableReason.AlreadyUsed
106
+ unavailableReason: import_types.UnavailableReason.AlreadyUsed
86
107
  };
87
108
  }
88
-
89
- // 合并新旧折扣列表,并计算折扣结果,注意,如果旧折扣里有 isEditMode 为 true 的优惠券,则不合并
90
- // 保留之前扫码得到的商品券(isScan: true)
91
- const filteredOldDiscountList = oldDiscountList.filter(discount => !discount.isEditMode && (discount.tag !== 'good_pass' || discount.isScan));
92
- const mergedDiscountList = (0, _utils.uniqueById)([...filteredOldDiscountList, ...newDiscountList]);
93
- const result = this.calcDiscount({
94
- discountList: mergedDiscountList,
95
- productList: [...productList],
96
- orderTotalAmount,
97
- holders,
98
- isFormSubject
99
- }, {
100
- scan: true
101
- });
102
-
103
- // 检查是否有产品使用了新折扣
109
+ const filteredOldDiscountList = oldDiscountList.filter(
110
+ (discount) => !discount.isEditMode && (discount.tag !== "good_pass" || discount.isScan)
111
+ );
112
+ const mergedDiscountList = (0, import_utils.uniqueById)([
113
+ ...filteredOldDiscountList,
114
+ ...newDiscountList
115
+ ]);
116
+ const result = this.calcDiscount(
117
+ {
118
+ discountList: mergedDiscountList,
119
+ productList: [...productList],
120
+ orderTotalAmount,
121
+ holders,
122
+ isFormSubject
123
+ },
124
+ {
125
+ scan: true
126
+ }
127
+ );
104
128
  let hasApplicableDiscount = false;
105
- const newDiscountIds = newDiscountList.map(discount => discount.id);
106
-
107
- // 遍历处理后的产品列表,检查是否有产品使用了新折扣
108
- result.productList.forEach(product => {
109
- const {
110
- discount_list,
111
- bundle
112
- } = this.hooks.getProduct(product);
113
- const allDiscountList = [...(discount_list || [])];
114
- (bundle || []).forEach(item => {
115
- allDiscountList.push(...(item?.discount_list || []));
129
+ const newDiscountIds = newDiscountList.map((discount) => discount.id);
130
+ result.productList.forEach((product) => {
131
+ const { discount_list, bundle } = this.hooks.getProduct(product);
132
+ const allDiscountList = [...discount_list || []];
133
+ (bundle || []).forEach((item) => {
134
+ allDiscountList.push(...(item == null ? void 0 : item.discount_list) || []);
116
135
  });
117
136
  if (allDiscountList && allDiscountList.length > 0) {
118
- // 检查是否有使用新折扣的情况
119
- const usedNewDiscount = allDiscountList.some(discount => newDiscountIds.includes(discount?.discount?.resource_id));
137
+ const usedNewDiscount = allDiscountList.some(
138
+ (discount) => {
139
+ var _a;
140
+ return newDiscountIds.includes((_a = discount == null ? void 0 : discount.discount) == null ? void 0 : _a.resource_id);
141
+ }
142
+ );
120
143
  if (usedNewDiscount) {
121
144
  hasApplicableDiscount = true;
122
145
  }
123
146
  }
124
147
  });
125
-
126
- // 如果券不可用,判断不可用原因
127
148
  let unavailableReason;
128
149
  if (!hasApplicableDiscount) {
129
150
  unavailableReason = this.getUnavailableReason(newDiscountList, productList);
@@ -136,51 +157,47 @@ class RulesModule extends _BaseModule.BaseModule {
136
157
  };
137
158
  }
138
159
  filterDiscountListByType(discountList, type) {
139
- return (discountList || []).filter(item => item.type === type || item.tag === type);
160
+ return (discountList || []).filter((item) => item.type === type || item.tag === type);
140
161
  }
141
-
142
162
  /** 剔除指定 type/tag 的折扣项,保留手动改价(type=product) / 券等 */
143
163
  excludeDiscountListByType(discountList, type) {
144
- return (discountList || []).filter(item => item.type !== type && item.tag !== type);
164
+ return (discountList || []).filter((item) => item.type !== type && item.tag !== type);
145
165
  }
146
-
147
166
  /** 手动改价场景:去掉 promotion,保留 type=product 等行内折扣 */
148
167
  resolveDiscountListForManualOverride(discountList) {
149
- return this.excludeDiscountListByType(discountList, 'promotion');
168
+ return this.excludeDiscountListByType(discountList, "promotion");
150
169
  }
151
170
  // 获取券不可用的原因
152
171
  getUnavailableReason(discountList, productList) {
153
- // 检查时间限制
172
+ var _a;
154
173
  for (const discount of discountList) {
155
174
  for (const item of productList) {
156
175
  const product = this.hooks.getProduct(item);
157
- const bookingTime = (product?.startDate || (0, _dayjs.default)()).format('YYYY-MM-DD HH:mm:ss');
158
- const filteredList = (0, _utils.filterDiscountListByBookingTime)([discount], bookingTime);
176
+ const bookingTime = ((product == null ? void 0 : product.startDate) || (0, import_dayjs.default)()).format("YYYY-MM-DD HH:mm:ss");
177
+ const filteredList = (0, import_utils.filterDiscountListByBookingTime)([discount], bookingTime);
159
178
  if (filteredList.length === 0) {
160
- return _types.UnavailableReason.TimeLimit;
179
+ return import_types.UnavailableReason.TimeLimit;
161
180
  }
162
181
  }
163
182
  }
164
-
165
- // 检查商品适用性
166
183
  for (const discount of discountList) {
167
184
  const limitedData = discount.limited_relation_product_data;
168
185
  let hasApplicableProduct = false;
169
186
  for (const item of productList) {
170
187
  const product = this.hooks.getProduct(item);
171
- if (limitedData.type === 'product_all') {
188
+ if (limitedData.type === "product_all") {
172
189
  hasApplicableProduct = true;
173
190
  break;
174
- } else if (limitedData.product_ids?.includes(product.id)) {
191
+ } else if ((_a = limitedData.product_ids) == null ? void 0 : _a.includes(product.id)) {
175
192
  hasApplicableProduct = true;
176
193
  break;
177
194
  }
178
195
  }
179
196
  if (!hasApplicableProduct) {
180
- return _types.UnavailableReason.ProductNotApplicable;
197
+ return import_types.UnavailableReason.ProductNotApplicable;
181
198
  }
182
199
  }
183
- return _types.UnavailableReason.Unknown;
200
+ return import_types.UnavailableReason.Unknown;
184
201
  }
185
202
  calcDiscount({
186
203
  discountList,
@@ -189,84 +206,83 @@ class RulesModule extends _BaseModule.BaseModule {
189
206
  isFormSubject,
190
207
  orderTotalAmount
191
208
  }, options) {
192
- const resolveIsFormSubject = product => typeof isFormSubject === 'function' ? Boolean(isFormSubject(product)) : Boolean(isFormSubject);
193
-
194
- // 识别出来是不是在编辑的界面里又新增了商品
195
- // 这种情况下,如果有可用的优惠券,也会自动勾选上
196
- const isEditModeAddNewProduct = productList.find(n => n.booking_id) && productList.find(n => !n.booking_id);
197
- const reapplyBookingDiscountProductUids = new Set((options?.reapplyBookingDiscountProductUids || []).filter(uid => uid !== undefined && uid !== null && uid !== '').map(String));
198
- const getOriginProductUid = originProduct => {
199
- const uid = originProduct?.metadata?.unique_identification_number ?? originProduct?.unique_identification_number;
200
- if (uid === undefined || uid === null || uid === '') return undefined;
209
+ var _a;
210
+ const resolveIsFormSubject = (product) => typeof isFormSubject === "function" ? Boolean(isFormSubject(product)) : Boolean(isFormSubject);
211
+ const isEditModeAddNewProduct = productList.find((n) => n.booking_id) && productList.find((n) => !n.booking_id);
212
+ const reapplyBookingDiscountProductUids = new Set(
213
+ ((options == null ? void 0 : options.reapplyBookingDiscountProductUids) || []).filter((uid) => uid !== void 0 && uid !== null && uid !== "").map(String)
214
+ );
215
+ const getOriginProductUid = (originProduct) => {
216
+ var _a2;
217
+ const uid = ((_a2 = originProduct == null ? void 0 : originProduct.metadata) == null ? void 0 : _a2.unique_identification_number) ?? (originProduct == null ? void 0 : originProduct.unique_identification_number);
218
+ if (uid === void 0 || uid === null || uid === "")
219
+ return void 0;
201
220
  return String(uid);
202
221
  };
203
222
  const shouldReapplyBookingDiscount = (originProduct, selectedDiscount) => {
204
- if (!selectedDiscount) return false;
223
+ if (!selectedDiscount)
224
+ return false;
205
225
  const uid = getOriginProductUid(originProduct);
206
- if (!uid || !reapplyBookingDiscountProductUids.has(uid)) return false;
226
+ if (!uid || !reapplyBookingDiscountProductUids.has(uid))
227
+ return false;
207
228
  const discountType = selectedDiscount.tag || selectedDiscount.type;
208
- return selectedDiscount.isEditMode === true && selectedDiscount.isSelected === true && ['good_pass', 'discount_card', 'product_discount_card'].includes(discountType);
229
+ return selectedDiscount.isEditMode === true && selectedDiscount.isSelected === true && ["good_pass", "discount_card", "product_discount_card"].includes(discountType);
209
230
  };
210
231
  const resolveReapplyEditModeDiscountPercent = (originProduct, selectedDiscount) => {
211
- if (!shouldReapplyBookingDiscount(originProduct, selectedDiscount)) return undefined;
212
- const discountType = selectedDiscount?.tag || selectedDiscount?.type;
213
- if (discountType !== 'discount_card' && discountType !== 'product_discount_card') {
214
- return undefined;
232
+ var _a2;
233
+ if (!shouldReapplyBookingDiscount(originProduct, selectedDiscount))
234
+ return void 0;
235
+ const discountType = (selectedDiscount == null ? void 0 : selectedDiscount.tag) || (selectedDiscount == null ? void 0 : selectedDiscount.type);
236
+ if (discountType !== "discount_card" && discountType !== "product_discount_card") {
237
+ return void 0;
215
238
  }
216
- const percent = Number(selectedDiscount.discount?.percent);
217
- return Number.isFinite(percent) ? percent : undefined;
239
+ const percent = Number((_a2 = selectedDiscount.discount) == null ? void 0 : _a2.percent);
240
+ return Number.isFinite(percent) ? percent : void 0;
218
241
  };
219
242
  const editModeDiscount = [];
220
243
  const addModeDiscount = [];
221
- discountList.forEach(discount => {
244
+ discountList.forEach((discount) => {
222
245
  if (discount.isEditMode) {
223
246
  editModeDiscount.push(discount);
224
247
  } else {
225
248
  addModeDiscount.push(discount);
226
249
  }
227
250
  });
228
-
229
- // 🔥 检查 editModeDiscount 中是否有订单级别的折扣,如果有则禁用 addModeDiscount 中相同 product_id 的折扣卡
230
- const editModeOrderLevelProductIds = new Set();
231
- editModeDiscount.forEach(discount => {
232
- if (discount.discount?.discount_calculation_mode === 'order_level') {
233
- editModeOrderLevelProductIds.add(discount?.discount?.discount_product_id);
251
+ const editModeOrderLevelProductIds = /* @__PURE__ */ new Set();
252
+ editModeDiscount.forEach((discount) => {
253
+ var _a2, _b;
254
+ if (((_a2 = discount.discount) == null ? void 0 : _a2.discount_calculation_mode) === "order_level") {
255
+ editModeOrderLevelProductIds.add((_b = discount == null ? void 0 : discount.discount) == null ? void 0 : _b.discount_product_id);
234
256
  }
235
257
  });
236
-
237
- // 如果存在订单级别的编辑模式折扣,禁用 addModeDiscount 中相同 product_id 的折扣卡
238
258
  if (editModeOrderLevelProductIds.size > 0) {
239
- addModeDiscount.forEach(discount => {
259
+ addModeDiscount.forEach((discount) => {
240
260
  if (editModeOrderLevelProductIds.has(discount.product_id)) {
241
261
  discount.isDisabled = true;
242
262
  }
243
263
  });
244
264
  }
245
- const hasDiscountInput = editModeDiscount.length > 0 || addModeDiscount.length > 0 || Boolean(options?.discountId) || Boolean(options?.selectedList?.length) || Boolean(options?.scan);
265
+ const hasDiscountInput = editModeDiscount.length > 0 || addModeDiscount.length > 0 || Boolean(options == null ? void 0 : options.discountId) || Boolean((_a = options == null ? void 0 : options.selectedList) == null ? void 0 : _a.length) || Boolean(options == null ? void 0 : options.scan);
246
266
  if (!hasDiscountInput) {
247
267
  return {
248
268
  discountList,
249
269
  productList
250
270
  };
251
271
  }
252
- const canUseEditModeDiscountForReapply = discount => {
272
+ const canUseEditModeDiscountForReapply = (discount) => {
253
273
  const discountType = discount.tag || discount.type;
254
- return reapplyBookingDiscountProductUids.size > 0 && discount.isEditMode === true && discount.isSelected === true && ['good_pass', 'discount_card', 'product_discount_card'].includes(discountType);
274
+ return reapplyBookingDiscountProductUids.size > 0 && discount.isEditMode === true && discount.isSelected === true && ["good_pass", "discount_card", "product_discount_card"].includes(discountType);
255
275
  };
256
-
257
- // 过滤掉手动取消false的优惠券,但仅用于应用优惠逻辑。
258
- // Change time 重报价需要把已选编辑态折扣卡重新放入候选,再由目标 uid 限定作用范围。
259
- const filteredDiscountList = [...addModeDiscount.filter(discount => !discount.isManualSelect), ...editModeDiscount.filter(canUseEditModeDiscountForReapply)];
260
-
261
- // 🔥 扁平化商品列表:将 bundle 子商品展开为虚拟商品
262
- const flattenProductsWithBundle = productList => {
276
+ const filteredDiscountList = [
277
+ ...addModeDiscount.filter((discount) => !discount.isManualSelect),
278
+ ...editModeDiscount.filter(canUseEditModeDiscountForReapply)
279
+ ];
280
+ const flattenProductsWithBundle = (productList2) => {
263
281
  const flattened = [];
264
- productList.forEach(originProduct => {
282
+ productList2.forEach((originProduct) => {
265
283
  const product = this.hooks.getProduct(originProduct);
266
-
267
- // 1. 添加主商品
268
284
  flattened.push({
269
- type: 'main',
285
+ type: "main",
270
286
  originProduct,
271
287
  product,
272
288
  price: Number(product.price || 0),
@@ -277,12 +293,10 @@ class RulesModule extends _BaseModule.BaseModule {
277
293
  num: product.num,
278
294
  booking_id: product.booking_id
279
295
  });
280
-
281
- // 2. 展开 bundle 子商品
282
296
  if (product.bundle && Array.isArray(product.bundle) && product.bundle.length > 0) {
283
297
  product.bundle.forEach((bundleItem, bundleIndex) => {
284
298
  flattened.push({
285
- type: 'bundle',
299
+ type: "bundle",
286
300
  originProduct,
287
301
  parentProduct: product,
288
302
  bundleItem,
@@ -295,8 +309,8 @@ class RulesModule extends _BaseModule.BaseModule {
295
309
  parentId: product._id,
296
310
  num: bundleItem.num || 1,
297
311
  quantity: bundleItem.num || 1,
298
- total: new _decimal.default(bundleItem.price || 0).mul(bundleItem.num || 1).toNumber(),
299
- origin_total: new _decimal.default(bundleItem.price || 0).mul(bundleItem.num || 1).toNumber(),
312
+ total: new import_decimal.default(bundleItem.price || 0).mul(bundleItem.num || 1).toNumber(),
313
+ origin_total: new import_decimal.default(bundleItem.price || 0).mul(bundleItem.num || 1).toNumber(),
300
314
  original_price: bundleItem.original_price,
301
315
  // 继承主商品属性
302
316
  booking_id: bundleItem.booking_id,
@@ -307,157 +321,120 @@ class RulesModule extends _BaseModule.BaseModule {
307
321
  });
308
322
  return flattened;
309
323
  };
310
-
311
- // 优惠力度排序,传进来的数据里可能有商品券,也可能有优惠券
312
- // 新的优先级排序规则(从高到低):
313
- // 1. 带有Holder的商品券(metadata?.holder?.type === 'custom' && tag === 'good_pass')
314
- // 2. 带有Holder的商品级折扣卡(metadata?.holder?.type === 'custom' && tag === 'product_discount_card' && discount_calculation_mode !== 'order_level')
315
- // 3. 带有Holder的订单级折扣卡(metadata?.holder?.type === 'custom' && tag === 'product_discount_card' && discount_calculation_mode === 'order_level')
316
- // 4. Customer商品券(metadata?.holder?.type !== 'custom' && tag === 'good_pass')
317
- // 5. Customer商品级折扣卡(metadata?.holder?.type !== 'custom' && tag === 'product_discount_card' && discount_calculation_mode !== 'order_level')
318
- // 6. Customer订单级固定金额折扣(metadata?.holder?.type !== 'custom' && tag === 'product_discount_card' && discount_calculation_mode === 'order_level')
319
- // 同一优先级内部:固定金额优先于百分比,金额/折扣力度越大越优先,最后按过期时间排序
320
324
  const sortedDiscountList = [...filteredDiscountList].sort((a, b) => {
321
- // 辅助函数:判断是否是带有Holder的优惠券
322
- const isHolderDiscount = discount => discount.metadata?.holder?.type === 'custom';
323
-
324
- // 辅助函数:判断是否是商品券
325
- const isGoodPass = discount => discount.tag === 'good_pass';
326
-
327
- // 辅助函数:判断是否是订单级折扣卡
328
- const isOrderLevelDiscount = discount => discount.tag === 'product_discount_card' && discount.metadata?.discount_calculation_mode === 'order_level';
329
-
330
- // 辅助函数:判断是否是商品级折扣卡
331
- const isItemLevelDiscount = discount => discount.tag === 'product_discount_card' && discount.metadata?.discount_calculation_mode !== 'order_level';
332
-
333
- // 辅助函数:获取优先级(数字越小优先级越高)
334
- const getPriority = discount => {
325
+ const isHolderDiscount = (discount) => {
326
+ var _a2, _b;
327
+ return ((_b = (_a2 = discount.metadata) == null ? void 0 : _a2.holder) == null ? void 0 : _b.type) === "custom";
328
+ };
329
+ const isGoodPass = (discount) => discount.tag === "good_pass";
330
+ const isOrderLevelDiscount = (discount) => {
331
+ var _a2;
332
+ return discount.tag === "product_discount_card" && ((_a2 = discount.metadata) == null ? void 0 : _a2.discount_calculation_mode) === "order_level";
333
+ };
334
+ const isItemLevelDiscount = (discount) => {
335
+ var _a2;
336
+ return discount.tag === "product_discount_card" && ((_a2 = discount.metadata) == null ? void 0 : _a2.discount_calculation_mode) !== "order_level";
337
+ };
338
+ const getPriority = (discount) => {
335
339
  const isHolder = isHolderDiscount(discount);
336
340
  if (isHolder) {
337
- if (isGoodPass(discount)) return 1; // 带有Holder的商品券
338
- if (isItemLevelDiscount(discount)) return 2; // 带有Holder的商品级折扣卡
339
- if (isOrderLevelDiscount(discount)) return 3; // 带有Holder的订单级折扣卡
341
+ if (isGoodPass(discount))
342
+ return 1;
343
+ if (isItemLevelDiscount(discount))
344
+ return 2;
345
+ if (isOrderLevelDiscount(discount))
346
+ return 3;
340
347
  } else {
341
- if (isGoodPass(discount)) return 4; // Customer商品券
342
- if (isItemLevelDiscount(discount)) return 5; // Customer商品级折扣卡
343
- if (isOrderLevelDiscount(discount)) return 6; // Customer订单级固定金额折扣
348
+ if (isGoodPass(discount))
349
+ return 4;
350
+ if (isItemLevelDiscount(discount))
351
+ return 5;
352
+ if (isOrderLevelDiscount(discount))
353
+ return 6;
344
354
  }
345
- return 7; // 其他情况
355
+ return 7;
346
356
  };
347
-
348
- // 辅助函数:按过期时间比较
349
357
  function compareByExpireTime(itemA, itemB) {
350
358
  if (itemA.expire_time && itemB.expire_time) {
351
359
  const timeA = new Date(itemA.expire_time).getTime();
352
360
  const timeB = new Date(itemB.expire_time).getTime();
353
361
  return timeA - timeB;
354
362
  }
355
- // 有过期时间的优先级高于永久的
356
363
  return itemA.expire_time ? -1 : itemB.expire_time ? 1 : 0;
357
364
  }
358
-
359
- // 辅助函数:同类型折扣卡内部排序(固定金额优先于百分比,金额/折扣力度排序)
360
365
  function compareDiscountCardValue(itemA, itemB) {
361
- const typeA = itemA.metadata?.discount_card_type || 'percent';
362
- const typeB = itemB.metadata?.discount_card_type || 'percent';
363
-
364
- // 1. 固定金额优先于百分比
365
- if (typeA === 'fixed_amount' && typeB === 'percent') return -1;
366
- if (typeA === 'percent' && typeB === 'fixed_amount') return 1;
367
-
368
- // 2. 都是固定金额时,金额越大越优先
369
- if (typeA === 'fixed_amount' && typeB === 'fixed_amount') {
366
+ var _a2, _b;
367
+ const typeA = ((_a2 = itemA.metadata) == null ? void 0 : _a2.discount_card_type) || "percent";
368
+ const typeB = ((_b = itemB.metadata) == null ? void 0 : _b.discount_card_type) || "percent";
369
+ if (typeA === "fixed_amount" && typeB === "percent")
370
+ return -1;
371
+ if (typeA === "percent" && typeB === "fixed_amount")
372
+ return 1;
373
+ if (typeA === "fixed_amount" && typeB === "fixed_amount") {
370
374
  if (itemA.par_value !== itemB.par_value) {
371
- const valueA = new _decimal.default(itemA.par_value || 0);
372
- const valueB = new _decimal.default(itemB.par_value || 0);
373
- return valueB.minus(valueA).toNumber(); // 金额大的在前
375
+ const valueA = new import_decimal.default(itemA.par_value || 0);
376
+ const valueB = new import_decimal.default(itemB.par_value || 0);
377
+ return valueB.minus(valueA).toNumber();
374
378
  }
375
379
  }
376
-
377
- // 3. 都是百分比时,折扣越大越优先(par_value越大越优先)
378
- if (typeA === 'percent' && typeB === 'percent') {
380
+ if (typeA === "percent" && typeB === "percent") {
379
381
  if (itemA.par_value !== itemB.par_value) {
380
- const valueA = new _decimal.default(100).minus(itemA.par_value || 0);
381
- const valueB = new _decimal.default(100).minus(itemB.par_value || 0);
382
- return valueA.minus(valueB).toNumber(); // 折扣大的在前
382
+ const valueA = new import_decimal.default(100).minus(itemA.par_value || 0);
383
+ const valueB = new import_decimal.default(100).minus(itemB.par_value || 0);
384
+ return valueA.minus(valueB).toNumber();
383
385
  }
384
386
  }
385
387
  return 0;
386
388
  }
387
-
388
- // 1. 先按优先级排序
389
389
  const priorityA = getPriority(a);
390
390
  const priorityB = getPriority(b);
391
391
  if (priorityA !== priorityB) {
392
392
  return priorityA - priorityB;
393
393
  }
394
-
395
- // 2. 同一优先级内部排序
396
- // 如果是商品券(优先级1或4),按过期时间排序
397
394
  if (isGoodPass(a) && isGoodPass(b)) {
398
395
  return compareByExpireTime(a, b);
399
396
  }
400
-
401
- // 如果是折扣卡(优先级2、3、5、6),按折扣力度排序,然后按过期时间
402
- if (a.tag === 'product_discount_card' && b.tag === 'product_discount_card') {
397
+ if (a.tag === "product_discount_card" && b.tag === "product_discount_card") {
403
398
  const valueCompare = compareDiscountCardValue(a, b);
404
- if (valueCompare !== 0) return valueCompare;
399
+ if (valueCompare !== 0)
400
+ return valueCompare;
405
401
  return compareByExpireTime(a, b);
406
402
  }
407
-
408
- // 3. 其他情况按照过期时间排序
409
403
  return compareByExpireTime(a, b);
410
404
  });
411
-
412
- // const newProductList = [];
413
- //
414
- // productList.forEach(item => {
415
- // const product = this.hooks.getProduct(item);
416
- // if (product.quantity > 1) {
417
- // for (let i = 1; i < product.quantity; i++) {
418
- // newProductList.push(product)
419
- // }
420
- // } else {
421
- // newProductList.push(item)
422
- // }
423
- // })
424
-
425
- // 🔥 扁平化商品列表(包含主商品和bundle子商品)
426
405
  const flattenedList = flattenProductsWithBundle(productList);
427
-
428
- // 对扁平化后的列表按价格降序排序(用于应用优惠券时优先选择高价商品)
429
406
  const sortedFlattenedList = flattenedList.sort((a, b) => {
430
- // 子商品优先使用 original_price,主商品使用 price
431
- const priceA = new _decimal.default(a.type === 'bundle' ? a.original_price ?? a.price ?? '0' : a.price || '0');
432
- const priceB = new _decimal.default(b.type === 'bundle' ? b.original_price ?? b.price ?? '0' : b.price || '0');
407
+ var _a2, _b;
408
+ const priceA = new import_decimal.default(
409
+ a.type === "bundle" ? a.original_price ?? a.price ?? "0" : a.price || "0"
410
+ );
411
+ const priceB = new import_decimal.default(
412
+ b.type === "bundle" ? b.original_price ?? b.price ?? "0" : b.price || "0"
413
+ );
433
414
  if (priceA.equals(priceB)) {
434
- // 价格相同时,主商品优先
435
415
  if (a.type !== b.type) {
436
- return a.type === 'main' ? -1 : 1;
416
+ return a.type === "main" ? -1 : 1;
437
417
  }
438
- // 都是主商品时,按原有逻辑排序
439
- if (a.type === 'main' && b.type === 'main') {
418
+ if (a.type === "main" && b.type === "main") {
440
419
  if (a.product.quantity === b.product.quantity) {
441
- return (b.product.discount_list?.length || 0) - (a.product.discount_list?.length || 0);
420
+ return (((_a2 = b.product.discount_list) == null ? void 0 : _a2.length) || 0) - (((_b = a.product.discount_list) == null ? void 0 : _b.length) || 0);
442
421
  }
443
422
  return a.product.quantity - b.product.quantity;
444
423
  }
445
- // 都是bundle时,按数量排序
446
- if (a.type === 'bundle' && b.type === 'bundle') {
424
+ if (a.type === "bundle" && b.type === "bundle") {
447
425
  return (a.num || 1) - (b.num || 1);
448
426
  }
449
427
  }
450
428
  return priceB.minus(priceA).toNumber();
451
429
  });
452
-
453
- // 🔥 为每个折扣卡/商品券执行策略检查并附加config
454
430
  const evaluator = this.getWalletPassEvaluator();
455
431
  if (evaluator) {
456
- addModeDiscount.forEach(discount => {
432
+ addModeDiscount.forEach((discount) => {
433
+ var _a2, _b;
457
434
  const discountType = discount.tag || discount.type;
458
- // 只对 good_pass 和 discount_card 类型执行策略检查
459
- if (['good_pass', 'discount_card', 'product_discount_card'].includes(discountType)) {
460
- // 转换 discount 为 Voucher 格式
435
+ if (["good_pass", "discount_card", "product_discount_card"].includes(
436
+ discountType
437
+ )) {
461
438
  const voucher = {
462
439
  id: discount.id,
463
440
  amount: Number(discount.par_value || 0),
@@ -465,27 +442,24 @@ class RulesModule extends _BaseModule.BaseModule {
465
442
  type: discountType,
466
443
  product_id: discount.product_id,
467
444
  unified_available_status: 1,
468
- available_product_type: discount.limited_relation_product_data?.type,
469
- available_product_ids: discount.limited_relation_product_data?.product_ids
445
+ available_product_type: (_a2 = discount.limited_relation_product_data) == null ? void 0 : _a2.type,
446
+ available_product_ids: (_b = discount.limited_relation_product_data) == null ? void 0 : _b.product_ids
470
447
  };
471
-
472
- // 转换 sortedFlattenedList 为 Product 格式
473
- const productsForEvaluate = sortedFlattenedList.map(item => ({
474
- product_id: item.id,
475
- price: item.price || 0,
476
- quantity: item.quantity || item.num || 1,
477
- selling_price: item.price || 0,
478
- product_options: item.type === 'main' ? item.product?.options : undefined
479
- }));
480
-
481
- // 调用策略检查
448
+ const productsForEvaluate = sortedFlattenedList.map((item) => {
449
+ var _a3;
450
+ return {
451
+ product_id: item.id,
452
+ price: item.price || 0,
453
+ quantity: item.quantity || item.num || 1,
454
+ selling_price: item.price || 0,
455
+ product_options: item.type === "main" ? (_a3 = item.product) == null ? void 0 : _a3.options : void 0
456
+ };
457
+ });
482
458
  const result = evaluator.checkVoucherAvailability({
483
- orderTotalAmount: orderTotalAmount,
459
+ orderTotalAmount,
484
460
  products: productsForEvaluate,
485
461
  vouchers: [voucher]
486
462
  });
487
-
488
- // 将 config 附加到 discount 对象
489
463
  if (result.isAvailable) {
490
464
  discount.config = {
491
465
  ...result.config,
@@ -499,74 +473,21 @@ class RulesModule extends _BaseModule.BaseModule {
499
473
  }
500
474
  });
501
475
  }
502
- // 检查商品是否被排除(全品类)
503
- const isProductIncludedByLimitedData = (limitedData, productId) => {
504
- const excludedIds = limitedData?.exclude_product_ids || [];
505
- const isExcluded = limitedData?.filter === 1 && excludedIds.some(id => String(id) === String(productId));
506
- return !isExcluded;
507
- };
508
-
509
- /**
510
- // 对productList按价格降序排序(用于应用优惠券时优先选择高价商品) 价格相同时使用quantity 排序
511
- const sortedProductList = [...productList].sort((a, b) => {
512
- const aProduct = this.hooks.getProduct(a);
513
- const bProduct = this.hooks.getProduct(b);
514
- const priceA = new Decimal((aProduct.price as string) || '0');
515
- const priceB = new Decimal((bProduct.price as string) || '0');
516
- if (priceA.toNumber() === priceB.toNumber()) {
517
- if (aProduct.quantity === bProduct.quantity) {
518
- return bProduct.discount_list?.length - aProduct.discount_list?.length;
519
- }
520
- return aProduct.quantity - bProduct.quantity;
521
- }
522
- return priceB.toNumber() - priceA.toNumber();
523
- });
524
- */
525
-
526
- // 标记已使用的优惠券
527
- const usedDiscounts = new Map();
528
-
529
- // 🔥 统计每个 product_id(商品券商品id)已使用的数量,用于 maxUsagePerOrder 限制
530
- const usedProductIdCounts = new Map();
531
-
532
- // 🔥 统计每张折扣卡的 applicableProductLimit 已使用次数(跨商品全局计数)
533
- const usedDiscountCardLimitCounts = new Map();
534
-
535
- // 🔥 预先将 editModeDiscount 中的折扣卡计入 applicableProductLimit 已使用次数
536
- editModeDiscount.forEach(discount => {
537
- const discountType = discount.tag || discount.type;
538
- if (['discount_card', 'product_discount_card'].includes(discountType)) {
539
- const currentCount = usedDiscountCardLimitCounts.get(discount.id) || 0;
540
- usedDiscountCardLimitCounts.set(discount.id, currentCount + (discount.metadata?.num || 1));
541
- }
542
- });
543
-
544
- // 记录每个优惠券适用的商品ID
545
- const discountApplicability = new Map();
546
-
547
- // 记录每个优惠券适用的商品详细信息
548
- const discountApplicableProducts = new Map();
549
-
550
- // 初始化每个优惠券的适用性和可抵扣商品
551
- addModeDiscount.forEach(discount => {
476
+ const usedDiscounts = /* @__PURE__ */ new Map();
477
+ const usedProductIdCounts = /* @__PURE__ */ new Map();
478
+ const discountApplicability = /* @__PURE__ */ new Map();
479
+ const discountApplicableProducts = /* @__PURE__ */ new Map();
480
+ addModeDiscount.forEach((discount) => {
552
481
  discountApplicability.set(discount.id, []);
553
482
  discountApplicableProducts.set(discount.id, []);
554
483
  });
555
-
556
- // 预处理 order_level 固定金额折扣卡的分摊信息
557
- // Map<discountId, Map<productId, { discountAmount, difference }>>
558
- const orderLevelDiscountAllocations = new Map();
559
-
560
- // 第一步:收集所有被勾选的 order_level 折扣卡及其适用商品
561
- // Map<discountId, Set<flatItemId>> - 记录每个折扣卡适用的商品
562
- const orderLevelDiscountApplicableItems = new Map();
563
- // Map<flatItemId, Set<discountId>> - 记录每个商品可以被哪些折扣卡使用
564
- const itemApplicableDiscounts = new Map();
565
-
566
- // 辅助函数:检查商品是否对某个折扣卡可用
484
+ const orderLevelDiscountAllocations = /* @__PURE__ */ new Map();
485
+ const orderLevelDiscountApplicableItems = /* @__PURE__ */ new Map();
486
+ const itemApplicableDiscounts = /* @__PURE__ */ new Map();
567
487
  const checkItemApplicableForDiscount = (flatItem, discount) => {
488
+ var _a2, _b, _c, _d, _e, _f, _g, _h;
568
489
  let product;
569
- if (flatItem.type === 'main') {
490
+ if (flatItem.type === "main") {
570
491
  product = flatItem.product;
571
492
  } else {
572
493
  product = {
@@ -577,38 +498,27 @@ class RulesModule extends _BaseModule.BaseModule {
577
498
  num: flatItem.num,
578
499
  booking_id: flatItem.booking_id,
579
500
  discount_list: flatItem.discount_list || [],
580
- startDate: flatItem.parentProduct?.startDate
501
+ startDate: (_a2 = flatItem.parentProduct) == null ? void 0 : _a2.startDate
581
502
  };
582
503
  }
583
-
584
- // 编辑的商品使用了优惠券不可用
585
- const isAvailableProduct = flatItem.type === 'main' ? !(product?.booking_id && product?.discount_list?.length && product?.discount_list?.every(d => d.id && ['good_pass', 'discount_card', 'product_discount_card'].includes(d.tag || d.type))) : !(flatItem?.booking_id && !!flatItem?.bundleItem?.discount_list?.length && flatItem?.bundleItem?.discount_list?.every(d => d.id));
504
+ const isAvailableProduct = flatItem.type === "main" ? !((product == null ? void 0 : product.booking_id) && ((_b = product == null ? void 0 : product.discount_list) == null ? void 0 : _b.length) && ((_c = product == null ? void 0 : product.discount_list) == null ? void 0 : _c.every((d) => d.id && ["good_pass", "discount_card", "product_discount_card"].includes(d.tag || d.type)))) : !((flatItem == null ? void 0 : flatItem.booking_id) && !!((_e = (_d = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _d.discount_list) == null ? void 0 : _e.length) && ((_g = (_f = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _f.discount_list) == null ? void 0 : _g.every((d) => d.id)));
586
505
  if (!isAvailableProduct) {
587
506
  return false;
588
507
  }
589
-
590
- // vouchersApplicable 为 false 的商品不参与订单级别折扣均摊
591
- if ((0, _lodashEs.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
508
+ if ((0, import_lodash_es.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
592
509
  return false;
593
510
  }
594
-
595
- // 商品价格为0时不可用
596
511
  if (Number(product.price) <= 0 || !product.price) {
597
512
  return false;
598
513
  }
599
514
  const limitedData = discount.limited_relation_product_data;
600
-
601
- // 时间限制检查
602
- const timeLimit = !!(0, _utils.filterDiscountListByBookingTime)([discount], (product?.startDate || (0, _dayjs.default)()).format('YYYY-MM-DD HH:mm:ss')).length;
515
+ const timeLimit = !!(0, import_utils.filterDiscountListByBookingTime)([discount], ((product == null ? void 0 : product.startDate) || (0, import_dayjs.default)()).format("YYYY-MM-DD HH:mm:ss")).length;
603
516
  if (!timeLimit) {
604
517
  return false;
605
518
  }
606
-
607
- // 判断商品是否适用
608
519
  let isLimitedProduct = false;
609
- if (limitedData.type === 'product_all') {
610
- // 全品类,但需要检查是否被排除
611
- if (limitedData.filter === 1 && limitedData.exclude_product_ids?.includes(product.id)) {
520
+ if (limitedData.type === "product_all") {
521
+ if (limitedData.filter === 1 && ((_h = limitedData.exclude_product_ids) == null ? void 0 : _h.includes(product.id))) {
612
522
  isLimitedProduct = false;
613
523
  } else {
614
524
  isLimitedProduct = true;
@@ -616,51 +526,33 @@ class RulesModule extends _BaseModule.BaseModule {
616
526
  } else if (limitedData.product_ids && limitedData.product_ids.includes(product.id)) {
617
527
  isLimitedProduct = true;
618
528
  }
619
-
620
- // 套餐规则检查
621
529
  const isBundleAvailable = this.checkPackageSubItemUsageRules(discount, flatItem);
622
530
  return isLimitedProduct && isBundleAvailable;
623
531
  };
624
-
625
- // 收集所有被勾选的 order_level 折扣卡及其适用商品
626
- const selectedOrderLevelDiscounts = sortedDiscountList.filter(discount => {
627
- return (0, _utils.isOrderLevelFixedAmountDiscount)(discount) && discount.isSelected !== false;
532
+ const selectedOrderLevelDiscounts = sortedDiscountList.filter((discount) => {
533
+ return (0, import_utils3.isOrderLevelFixedAmountDiscount)(discount) && discount.isSelected !== false;
628
534
  });
629
-
630
- // 遍历所有被勾选的 order_level 折扣卡,建立双向映射
631
- selectedOrderLevelDiscounts.forEach(discount => {
632
- const applicableItemIds = new Set();
633
- sortedFlattenedList.forEach(flatItem => {
535
+ selectedOrderLevelDiscounts.forEach((discount) => {
536
+ const applicableItemIds = /* @__PURE__ */ new Set();
537
+ sortedFlattenedList.forEach((flatItem) => {
634
538
  if (checkItemApplicableForDiscount(flatItem, discount)) {
635
539
  applicableItemIds.add(flatItem._id);
636
-
637
- // 记录商品可以被哪些折扣卡使用
638
540
  if (!itemApplicableDiscounts.has(flatItem._id)) {
639
- itemApplicableDiscounts.set(flatItem._id, new Set());
541
+ itemApplicableDiscounts.set(flatItem._id, /* @__PURE__ */ new Set());
640
542
  }
641
543
  itemApplicableDiscounts.get(flatItem._id).add(discount.id);
642
544
  }
643
545
  });
644
546
  orderLevelDiscountApplicableItems.set(discount.id, applicableItemIds);
645
547
  });
646
-
647
- // 专属折扣卡定义:限定了特定商品(product_ids),而不是全品类(product_all)的折扣卡
648
- // 如果专属折扣卡被勾选,它适用的商品会被占用,其他折扣卡均摊时应排除这些商品
649
- // Map<flatItemId, discountId> - 记录被占用的商品及其对应的折扣卡
650
- const occupiedItems = new Map();
651
-
652
- // 按排序顺序遍历折扣卡,判断哪些是专属折扣卡
653
- selectedOrderLevelDiscounts.forEach(discount => {
548
+ const occupiedItems = /* @__PURE__ */ new Map();
549
+ selectedOrderLevelDiscounts.forEach((discount) => {
654
550
  const limitedData = discount.limited_relation_product_data;
655
-
656
- // 判断是否是专属折扣卡(只能用于特定商品,而不是全品类)
657
- const isExclusiveDiscount = limitedData.type !== 'product_all';
551
+ const isExclusiveDiscount = limitedData.type !== "product_all";
658
552
  if (isExclusiveDiscount) {
659
- // 专属折扣卡:它适用的所有商品都会被它占用
660
553
  const applicableItems = orderLevelDiscountApplicableItems.get(discount.id);
661
554
  if (applicableItems) {
662
- applicableItems.forEach(itemId => {
663
- // 如果商品还没被占用,则标记为被当前折扣卡占用
555
+ applicableItems.forEach((itemId) => {
664
556
  if (!occupiedItems.has(itemId)) {
665
557
  occupiedItems.set(itemId, discount.id);
666
558
  }
@@ -668,27 +560,22 @@ class RulesModule extends _BaseModule.BaseModule {
668
560
  }
669
561
  }
670
562
  });
671
-
672
- // 🔥 第三步:识别 order_level 折扣卡并预计算分摊(排除被其他专属折扣卡占用的商品)
673
- sortedDiscountList.forEach(discount => {
674
- if (!(0, _utils.isOrderLevelFixedAmountDiscount)(discount)) {
563
+ sortedDiscountList.forEach((discount) => {
564
+ if (!(0, import_utils3.isOrderLevelFixedAmountDiscount)(discount)) {
675
565
  return;
676
566
  }
677
-
678
- // 收集该折扣卡适用的商品(排除被其他专属折扣卡占用的商品)
679
567
  const applicableProducts = [];
680
- sortedFlattenedList.forEach(flatItem => {
681
- // 🔥 检查该商品是否被其他专属折扣卡占用
568
+ sortedFlattenedList.forEach((flatItem) => {
569
+ var _a2, _b, _c;
682
570
  const occupyingDiscountId = occupiedItems.get(flatItem._id);
683
- if (occupyingDiscountId !== undefined && occupyingDiscountId !== discount.id) {
684
- // 该商品被其他专属折扣卡占用,跳过
571
+ if (occupyingDiscountId !== void 0 && occupyingDiscountId !== discount.id) {
685
572
  return;
686
573
  }
687
574
  if (!checkItemApplicableForDiscount(flatItem, discount)) {
688
575
  return;
689
576
  }
690
577
  let product;
691
- if (flatItem.type === 'main') {
578
+ if (flatItem.type === "main") {
692
579
  product = flatItem.product;
693
580
  } else {
694
581
  product = {
@@ -699,53 +586,33 @@ class RulesModule extends _BaseModule.BaseModule {
699
586
  num: flatItem.num
700
587
  };
701
588
  }
702
-
703
- // 对于 bundle 子商品,quantity 需要乘以主商品的购买数量
704
- const quantity = flatItem.type === 'main' ? product.num || product.quantity || 1 : (product.num || product.quantity || 1) * (flatItem.parentProduct?.num || flatItem.parentProduct?.quantity || 1);
705
-
706
- // 对于主商品:使用 price
707
- // 对于子商品:优先使用 flatItem.original_price,否则使用 flatItem.price
708
- const originalAmount = flatItem.type === 'main' ? Number(product.price ?? 0) : Number(flatItem.original_price ?? flatItem.price ?? 0);
709
-
710
- // 传递 parentQuantity 用于差值处理时判断是否是真正的"数量为1"
589
+ const quantity = flatItem.type === "main" ? product.num || product.quantity || 1 : (product.num || product.quantity || 1) * (((_a2 = flatItem.parentProduct) == null ? void 0 : _a2.num) || ((_b = flatItem.parentProduct) == null ? void 0 : _b.quantity) || 1);
590
+ const originalAmount = flatItem.type === "main" ? Number(product.price ?? 0) : Number(flatItem.original_price ?? flatItem.price ?? 0);
711
591
  const productData = {
712
592
  productId: flatItem._id,
713
593
  amount: originalAmount,
714
- quantity: quantity
594
+ quantity
715
595
  };
716
-
717
- // 子商品需要传递主商品数量
718
- if (flatItem.type === 'bundle') {
719
- productData.parentQuantity = flatItem.parentProduct?.quantity || 1;
596
+ if (flatItem.type === "bundle") {
597
+ productData.parentQuantity = ((_c = flatItem.parentProduct) == null ? void 0 : _c.quantity) || 1;
720
598
  }
721
599
  applicableProducts.push(productData);
722
600
  });
723
-
724
- // 计算分摊
725
601
  if (applicableProducts.length > 0) {
726
- const allocation = (0, _utils.calculateOrderLevelDiscountAllocation)(discount, applicableProducts);
602
+ const allocation = (0, import_utils4.calculateOrderLevelDiscountAllocation)(discount, applicableProducts);
727
603
  orderLevelDiscountAllocations.set(discount.id, allocation);
728
604
  }
729
605
  });
730
-
731
- // 处理后的商品列表(按排序后的顺序处理,记录优惠信息)
732
- const processedProductsMap = new Map();
733
-
734
- // 记录已应用优惠券的商品信息
735
- const appliedDiscountProducts = new Map();
736
-
737
- // 首先遍历所有商品和所有优惠券,确定每个优惠券的适用范围,包括isSelected为false的优惠券
738
- // 🔥 使用扁平化后的列表,包含主商品和bundle子商品
739
- sortedFlattenedList.forEach(flatItem => {
740
- // 获取商品数据
606
+ const processedProductsMap = /* @__PURE__ */ new Map();
607
+ const appliedDiscountProducts = /* @__PURE__ */ new Map();
608
+ sortedFlattenedList.forEach((flatItem) => {
609
+ var _a2;
741
610
  let product, originProduct;
742
- if (flatItem.type === 'main') {
611
+ if (flatItem.type === "main") {
743
612
  product = flatItem.product;
744
613
  originProduct = flatItem.originProduct;
745
614
  } else {
746
- // bundle子商品:构造虚拟商品对象
747
615
  product = {
748
- startDate: flatItem?.parentProduct?.startDate,
749
616
  _id: flatItem._id,
750
617
  id: flatItem.id,
751
618
  price: flatItem.price,
@@ -754,49 +621,48 @@ class RulesModule extends _BaseModule.BaseModule {
754
621
  total: flatItem.total,
755
622
  origin_total: flatItem.origin_total,
756
623
  booking_id: flatItem.booking_id,
757
- discount_list: flatItem.discount_list || []
624
+ discount_list: flatItem.discount_list || [],
625
+ startDate: (_a2 = flatItem.parentProduct) == null ? void 0 : _a2.startDate
758
626
  };
759
627
  originProduct = flatItem.originProduct;
760
628
  }
761
- addModeDiscount.forEach(discount => {
762
- const limitedData = discount?.limited_relation_product_data;
763
- // 拿到discount配置的holder信息 product信息 product.holder 加在 isLimitedProduct
764
- const _tempVar = flatItem?.type === 'bundle' ? flatItem?.parentProduct : flatItem?.product;
765
- const isHolderMatch = this.checkHolderMatch(discount, {
766
- isNeedHolder: resolveIsFormSubject(_tempVar) && !_tempVar?.isNormalProduct,
767
- holder_id: _tempVar?.holder_id || product.holder_id
768
- }, holders);
629
+ addModeDiscount.forEach((discount) => {
630
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j;
631
+ const limitedData = discount == null ? void 0 : discount.limited_relation_product_data;
632
+ const _tempVar = (flatItem == null ? void 0 : flatItem.type) === "bundle" ? flatItem == null ? void 0 : flatItem.parentProduct : flatItem == null ? void 0 : flatItem.product;
633
+ const isHolderMatch = this.checkHolderMatch(
634
+ discount,
635
+ {
636
+ isNeedHolder: resolveIsFormSubject(_tempVar) && !(_tempVar == null ? void 0 : _tempVar.isNormalProduct),
637
+ holder_id: (_tempVar == null ? void 0 : _tempVar.holder_id) || product.holder_id
638
+ },
639
+ holders
640
+ );
769
641
  let timeLimit = true;
770
- timeLimit = !!(0, _utils.filterDiscountListByBookingTime)([discount], (product?.startDate || (0, _dayjs.default)()).format('YYYY-MM-DD HH:mm:ss')).length;
771
- // 是符合折扣的商品
772
- const isLimitedProduct = (limitedData.type === 'product_all' && limitedData.filter !== 1 || limitedData.type === 'product_all' && limitedData.filter === 1 && !limitedData.exclude_product_ids.includes(product.id) || limitedData.product_ids && limitedData.product_ids.includes(product.id)) && isHolderMatch;
773
-
774
- // 编辑的商品 使用了优惠券不可用
775
- const isAvailableProduct = flatItem.type === 'main' ? !(product?.booking_id && product?.discount_list?.length && product?.discount_list?.every(discount => discount.id && ['good_pass', 'discount_card', 'product_discount_card'].includes(discount.tag || discount.type))) : !(flatItem?.booking_id && !!flatItem?.bundleItem?.discount_list?.length && flatItem?.bundleItem?.discount_list?.every(discount => discount.id));
776
-
777
- // 套餐是否可用判断
642
+ timeLimit = !!(0, import_utils.filterDiscountListByBookingTime)([discount], ((product == null ? void 0 : product.startDate) || (0, import_dayjs.default)()).format("YYYY-MM-DD HH:mm:ss")).length;
643
+ const isLimitedProduct = (limitedData.type === "product_all" && limitedData.filter !== 1 || limitedData.type === "product_all" && limitedData.filter === 1 && !limitedData.exclude_product_ids.includes(product.id) || limitedData.product_ids && limitedData.product_ids.includes(product.id)) && isHolderMatch;
644
+ const isAvailableProduct = flatItem.type === "main" ? !((product == null ? void 0 : product.booking_id) && ((_a3 = product == null ? void 0 : product.discount_list) == null ? void 0 : _a3.length) && ((_b = product == null ? void 0 : product.discount_list) == null ? void 0 : _b.every(
645
+ (discount2) => discount2.id && [
646
+ "good_pass",
647
+ "discount_card",
648
+ "product_discount_card"
649
+ ].includes(discount2.tag || discount2.type)
650
+ ))) : !((flatItem == null ? void 0 : flatItem.booking_id) && !!((_d = (_c = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _c.discount_list) == null ? void 0 : _d.length) && ((_f = (_e = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _e.discount_list) == null ? void 0 : _f.every((discount2) => discount2.id)));
778
651
  const isBundleAvailable = this.checkPackageSubItemUsageRules(discount, flatItem);
779
-
780
- // 判断优惠券是否适用于该商品
781
- if (isAvailableProduct && isLimitedProduct && timeLimit && isBundleAvailable && discount.config?.isAvailable) {
782
- // 记录此优惠券适用的商品
783
- discountApplicability.get(discount.id)?.push(product.id);
784
-
785
- // 记录可抵扣的商品详情
652
+ if (isAvailableProduct && isLimitedProduct && timeLimit && isBundleAvailable && ((_g = discount.config) == null ? void 0 : _g.isAvailable)) {
653
+ (_h = discountApplicability.get(discount.id)) == null ? void 0 : _h.push(product.id);
786
654
  const applicableProducts = discountApplicableProducts.get(discount.id) || [];
787
655
  const discountType = discount.tag || discount.type;
788
- const isGoodPass = discountType === 'good_pass';
789
-
790
- // 使用数量
791
- const num = isGoodPass || flatItem?.type === 'main' ? 1 : product.num;
656
+ const isGoodPass = discountType === "good_pass";
657
+ const num = isGoodPass || (flatItem == null ? void 0 : flatItem.type) === "main" ? 1 : product.num;
792
658
  const productData = {
793
659
  amount: product.price * num,
794
660
  type: discountType,
795
661
  tag: discountType,
796
662
  discount: {
797
- discount_card_type: discount?.metadata?.discount_card_type,
663
+ discount_card_type: (_i = discount == null ? void 0 : discount.metadata) == null ? void 0 : _i.discount_card_type,
798
664
  fixed_amount: product.price,
799
- discount_calculation_mode: discount?.metadata?.discount_calculation_mode,
665
+ discount_calculation_mode: (_j = discount == null ? void 0 : discount.metadata) == null ? void 0 : _j.discount_calculation_mode,
800
666
  resource_id: discount.id,
801
667
  title: discount.format_title,
802
668
  original_amount: product.price || product.origin_total,
@@ -805,8 +671,8 @@ class RulesModule extends _BaseModule.BaseModule {
805
671
  discount_product_id: discount.product_id
806
672
  },
807
673
  metadata: {
808
- num: num,
809
- discount_rule_uncheck_flag: discount?.discount_rule_uncheck_flag
674
+ num,
675
+ discount_rule_uncheck_flag: discount == null ? void 0 : discount.discount_rule_uncheck_flag
810
676
  }
811
677
  };
812
678
  applicableProducts.push(productData);
@@ -814,145 +680,128 @@ class RulesModule extends _BaseModule.BaseModule {
814
680
  }
815
681
  });
816
682
  });
817
-
818
- // 🔥 用于存储扁平化商品处理结果的Map
819
- const processedFlatItemsMap = new Map();
820
-
821
- // 🔥 Option 折扣辅助函数
822
- const applyDiscountToOptions = (options, discount) => {
823
- if (!options?.length) return {
824
- discountedOptions: options,
825
- optionDiscountAmount: 0
826
- };
683
+ const processedFlatItemsMap = /* @__PURE__ */ new Map();
684
+ const applyDiscountToOptions = (options2, discount) => {
685
+ if (!(options2 == null ? void 0 : options2.length))
686
+ return { discountedOptions: options2, optionDiscountAmount: 0 };
827
687
  let optionDiscountAmount = 0;
828
- const discountedOptions = options.map(option => {
829
- // 折前单价:优先 price,缺失再 add_price;已写回折后价时用 _original_price(或旧字段 _original_add_price)
688
+ const discountedOptions = options2.map((option) => {
830
689
  const rawUnit = option._original_price ?? option._original_add_price ?? option.price ?? option.add_price;
831
690
  const baseUnitNum = Number(rawUnit ?? 0);
832
- if (baseUnitNum <= 0) return option;
833
- const discountedPrice = (0, _utils.getDiscountAmount)(discount, baseUnitNum, baseUnitNum);
691
+ if (baseUnitNum <= 0)
692
+ return option;
693
+ const discountedPrice = (0, import_utils.getDiscountAmount)(discount, baseUnitNum, baseUnitNum);
834
694
  const optQty = Number(option.num ?? option.quantity ?? 1);
835
- optionDiscountAmount = new _decimal.default(optionDiscountAmount).plus(new _decimal.default(baseUnitNum).minus(discountedPrice).mul(optQty)).toNumber();
836
- const {
837
- _original_add_price,
838
- ...rest
839
- } = option;
695
+ optionDiscountAmount = new import_decimal.default(optionDiscountAmount).plus(new import_decimal.default(baseUnitNum).minus(discountedPrice).mul(optQty)).toNumber();
696
+ const { _original_add_price, ...rest } = option;
840
697
  const tmpl = rest.price ?? rest.add_price;
841
- const nextPrice = typeof tmpl === 'string' ? String(discountedPrice) : discountedPrice;
698
+ const nextPrice = typeof tmpl === "string" ? String(discountedPrice) : discountedPrice;
842
699
  return {
843
700
  ...rest,
844
- _original_price: option._original_price ?? (_original_add_price !== undefined ? _original_add_price : rawUnit),
701
+ _original_price: option._original_price ?? (_original_add_price !== void 0 ? _original_add_price : rawUnit),
845
702
  price: nextPrice
846
703
  };
847
704
  });
848
- return {
849
- discountedOptions,
850
- optionDiscountAmount
851
- };
705
+ return { discountedOptions, optionDiscountAmount };
852
706
  };
853
- const restoreOptionPrices = options => {
854
- if (!options?.length) return options;
855
- return options.map(option => {
856
- const orig = option._original_price !== undefined ? option._original_price : option._original_add_price;
857
- if (orig !== undefined) {
858
- const {
859
- _original_price,
860
- _original_add_price,
861
- ...rest
862
- } = option;
863
- return {
864
- ...rest,
865
- price: orig
866
- };
707
+ const restoreOptionPrices = (options2) => {
708
+ if (!(options2 == null ? void 0 : options2.length))
709
+ return options2;
710
+ return options2.map((option) => {
711
+ const orig = option._original_price !== void 0 ? option._original_price : option._original_add_price;
712
+ if (orig !== void 0) {
713
+ const { _original_price, _original_add_price, ...rest } = option;
714
+ return { ...rest, price: orig };
867
715
  }
868
716
  return option;
869
717
  });
870
718
  };
871
- const getOptionTotal = options => {
872
- if (!options?.length) return 0;
873
- return options.reduce((sum, opt) => {
719
+ const getOptionTotal = (options2) => {
720
+ if (!(options2 == null ? void 0 : options2.length))
721
+ return 0;
722
+ return options2.reduce((sum, opt) => {
874
723
  const unit = Number(opt.price ?? opt.add_price ?? 0);
875
724
  const n = Number(opt.num ?? opt.quantity ?? 1);
876
- return new _decimal.default(sum).plus(new _decimal.default(unit).mul(n)).toNumber();
725
+ return new import_decimal.default(sum).plus(new import_decimal.default(unit).mul(n)).toNumber();
877
726
  }, 0);
878
727
  };
879
-
880
- // 然后再处理应用哪些优惠券,此时只考虑filteredDiscountList中的优惠券
881
- // 🔥 使用扁平化后的列表进行处理
882
728
  sortedFlattenedList.forEach((flatItem, index) => {
883
- // 获取商品数据
729
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I;
884
730
  let product, originProduct;
885
- if (flatItem.type === 'main') {
731
+ if (flatItem.type === "main") {
886
732
  product = flatItem.product;
887
733
  originProduct = flatItem.originProduct;
888
734
  } else {
889
- // bundle子商品
890
735
  product = {
891
- startDate: flatItem?.parentProduct?.startDate,
892
736
  _id: flatItem._id,
893
737
  id: flatItem.id,
894
738
  price: flatItem.price,
895
739
  quantity: flatItem.quantity,
896
740
  num: flatItem.num,
897
741
  total: flatItem.total,
898
- original_price: flatItem?.bundleItem?.original_price,
899
- origin_total: flatItem?.bundleItem?.original_price,
742
+ original_price: (_a2 = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _a2.original_price,
743
+ origin_total: (_b = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _b.original_price,
900
744
  booking_id: flatItem.booking_id,
901
- discount_list: flatItem?.bundleItem?.discount_list || []
745
+ discount_list: ((_c = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _c.discount_list) || [],
746
+ startDate: (_d = flatItem.parentProduct) == null ? void 0 : _d.startDate
902
747
  };
903
748
  originProduct = flatItem.originProduct;
904
749
  }
905
- const isPersistedProduct = product?.booking_id || originProduct?.order_detail_id || originProduct?.orderDetailId || originProduct?.booking_id;
906
- const hasExistingWalletDiscount = product.discount_list?.length && product?.discount_list?.every(discount => {
907
- const discountIdentity = discount.id ?? discount.discount?.resource_id;
750
+ const isPersistedProduct = (product == null ? void 0 : product.booking_id) || (originProduct == null ? void 0 : originProduct.order_detail_id) || (originProduct == null ? void 0 : originProduct.orderDetailId) || (originProduct == null ? void 0 : originProduct.booking_id);
751
+ const hasExistingWalletDiscount = ((_e = product.discount_list) == null ? void 0 : _e.length) && ((_f = product == null ? void 0 : product.discount_list) == null ? void 0 : _f.every((discount) => {
752
+ var _a3;
753
+ const discountIdentity = discount.id ?? ((_a3 = discount.discount) == null ? void 0 : _a3.resource_id);
908
754
  const discountType = discount.tag || discount.type;
909
- return Boolean(discountIdentity && ['good_pass', 'discount_card', 'product_discount_card'].includes(discountType));
910
- });
911
-
912
- // 已持久化且已有钱包券/折扣卡的商品行跳过,保留后端历史折扣结果。
755
+ return Boolean(
756
+ discountIdentity && ["good_pass", "discount_card", "product_discount_card"].includes(
757
+ discountType
758
+ )
759
+ );
760
+ }));
913
761
  if (isPersistedProduct && hasExistingWalletDiscount) {
914
- if (flatItem.type === 'main') {
762
+ if (flatItem.type === "main") {
915
763
  processedProductsMap.set(product._id, [originProduct]);
916
764
  } else {
917
- processedFlatItemsMap.set(flatItem._id, [{
918
- ...flatItem,
919
- processed: true
920
- }]);
765
+ processedFlatItemsMap.set(flatItem._id, [
766
+ {
767
+ ...flatItem,
768
+ processed: true
769
+ }
770
+ ]);
921
771
  }
922
772
  return;
923
773
  }
924
-
925
- // 找到适用于此商品的所有优惠券,仅考虑isSelected不为false的优惠券
926
- const applicableDiscounts = sortedDiscountList.filter(discount => {
927
- // 🔥 检查策略可用性(针对 good_pass 和折扣卡)
774
+ const applicableDiscounts = sortedDiscountList.filter((discount) => {
775
+ var _a3, _b2, _c2, _d2;
928
776
  const discountType = discount.tag || discount.type;
929
777
  const currentOriginUid = getOriginProductUid(originProduct);
930
778
  const isReapplyEditModeDiscountForProduct = discount.isEditMode && reapplyBookingDiscountProductUids.size > 0 && currentOriginUid && reapplyBookingDiscountProductUids.has(String(currentOriginUid)) && discount.isSelected === true;
931
779
  if (discount.isEditMode && reapplyBookingDiscountProductUids.size > 0) {
932
780
  const uid = currentOriginUid;
933
- if (!uid || !reapplyBookingDiscountProductUids.has(uid)) return false;
934
- if (!discount.isSelected) return false;
781
+ if (!uid || !reapplyBookingDiscountProductUids.has(uid))
782
+ return false;
783
+ if (!discount.isSelected)
784
+ return false;
935
785
  }
936
- if (['good_pass', 'discount_card', 'product_discount_card'].includes(discountType) && !isReapplyEditModeDiscountForProduct) {
937
- // 如果策略检查后没有config,说明不可用
938
- if (discount.config === undefined || !discount?.config?.isAvailable) {
786
+ if (["good_pass", "discount_card", "product_discount_card"].includes(
787
+ discountType
788
+ ) && !isReapplyEditModeDiscountForProduct) {
789
+ if (discount.config === void 0 || !((_a3 = discount == null ? void 0 : discount.config) == null ? void 0 : _a3.isAvailable)) {
939
790
  return false;
940
791
  }
941
792
  }
942
-
943
- // 如果商品价格为 0,其实不需要使用任何优惠券,直接 return true
944
- // 商品券时主商品价格为0不可用
945
- if ((Number(product.price) <= 0 || !product.price) && !product.discount_list?.length && (discount.tag || discount.type) === 'good_pass') return false;
946
-
947
- // 折扣卡商品价格为0时不可用
948
- if ((Number(product.price) <= 0 || !product.price) && !product.discount_list?.find(n => n.discount?.resource_id === discount.id) && (discount.tag || discount.type) !== 'good_pass') return false;
949
- // 如果优惠券已被使用,则跳过
793
+ if ((Number(product.price) <= 0 || !product.price) && !((_b2 = product.discount_list) == null ? void 0 : _b2.length) && (discount.tag || discount.type) === "good_pass")
794
+ return false;
795
+ if ((Number(product.price) <= 0 || !product.price) && !((_c2 = product.discount_list) == null ? void 0 : _c2.find((n) => {
796
+ var _a4;
797
+ return ((_a4 = n.discount) == null ? void 0 : _a4.resource_id) === discount.id;
798
+ })) && (discount.tag || discount.type) !== "good_pass")
799
+ return false;
950
800
  const targetUsedDiscounts = usedDiscounts.get(discount.id);
951
- if (targetUsedDiscounts && (discount.tag || discount.type) === 'good_pass') return false;
952
-
953
- // 🔥 检查 maxUsagePerOrder 限制:同一 product_id 的商品券使用数量不能超过配置值
954
- if ((discount.tag || discount.type) === 'good_pass') {
955
- const maxUsagePerOrder = discount.config?.maxUsagePerOrder;
801
+ if (targetUsedDiscounts && (discount.tag || discount.type) === "good_pass")
802
+ return false;
803
+ if ((discount.tag || discount.type) === "good_pass") {
804
+ const maxUsagePerOrder = (_d2 = discount.config) == null ? void 0 : _d2.maxUsagePerOrder;
956
805
  if (maxUsagePerOrder && maxUsagePerOrder > 0) {
957
806
  const currentUsedCount = usedProductIdCounts.get(discount.product_id) || 0;
958
807
  if (currentUsedCount >= maxUsagePerOrder) {
@@ -960,47 +809,32 @@ class RulesModule extends _BaseModule.BaseModule {
960
809
  }
961
810
  }
962
811
  }
963
-
964
- // 🔥 检查折扣卡的 applicableProductLimit 限制:折扣卡可使用的最大次数(跨商品全局)
965
- const discountTypeForLimit = discount.tag || discount.type;
966
- if (['discount_card', 'product_discount_card'].includes(discountTypeForLimit)) {
967
- const applicableProductLimitConfig = discount.config?.applicableProductLimit || 0;
968
- if (applicableProductLimitConfig > 0) {
969
- const currentUsedLimitCount = usedDiscountCardLimitCounts.get(discount.id) || 0;
970
- if (currentUsedLimitCount >= applicableProductLimitConfig) {
971
- return false;
972
- }
973
- }
974
- }
975
812
  const limitedData = discount.limited_relation_product_data;
976
-
977
- // 拿到discount配置的holder信息 product信息 product.holder 不可用return false
978
- const _tempVar = flatItem?.type === 'bundle' ? flatItem?.parentProduct : flatItem?.product;
979
- const isHolderMatch = this.checkHolderMatch(discount, {
980
- isNeedHolder: resolveIsFormSubject(_tempVar) && !_tempVar?.isNormalProduct,
981
- holder_id: _tempVar?.holder_id || product.holder_id
982
- }, holders);
983
- // 如果 holder 不匹配,则不适用
984
- if (!isHolderMatch) return false;
813
+ const _tempVar = (flatItem == null ? void 0 : flatItem.type) === "bundle" ? flatItem == null ? void 0 : flatItem.parentProduct : flatItem == null ? void 0 : flatItem.product;
814
+ const isHolderMatch = this.checkHolderMatch(
815
+ discount,
816
+ {
817
+ isNeedHolder: resolveIsFormSubject(_tempVar) && !(_tempVar == null ? void 0 : _tempVar.isNormalProduct),
818
+ holder_id: (_tempVar == null ? void 0 : _tempVar.holder_id) || product.holder_id
819
+ },
820
+ holders
821
+ );
822
+ if (!isHolderMatch)
823
+ return false;
985
824
  let timeLimit = true;
986
- timeLimit = !!(0, _utils.filterDiscountListByBookingTime)([discount], (product.startDate || (0, _dayjs.default)()).format('YYYY-MM-DD HH:mm:ss')).length;
825
+ timeLimit = !!(0, import_utils.filterDiscountListByBookingTime)([discount], (product.startDate || (0, import_dayjs.default)()).format("YYYY-MM-DD HH:mm:ss")).length;
987
826
  if (!timeLimit) {
988
827
  return false;
989
828
  }
990
-
991
- // 判断优惠券是否适用于该商品
992
- if (limitedData.type === 'product_all') {
993
- if (!isProductIncludedByLimitedData(limitedData, product.id)) {
829
+ if (limitedData.type === "product_all") {
830
+ if (limitedData.filter === 1 && limitedData.exclude_product_ids.includes(product.id)) {
994
831
  return false;
995
832
  }
996
-
997
- // 检查 package_sub_item_usage_rules
998
833
  if (!this.checkPackageSubItemUsageRules(discount, flatItem)) {
999
834
  return false;
1000
835
  }
1001
836
  return true;
1002
837
  } else if (limitedData.product_ids && limitedData.product_ids.includes(product.id)) {
1003
- // 检查 package_sub_item_usage_rules
1004
838
  if (!this.checkPackageSubItemUsageRules(discount, flatItem)) {
1005
839
  return false;
1006
840
  }
@@ -1008,109 +842,158 @@ class RulesModule extends _BaseModule.BaseModule {
1008
842
  }
1009
843
  return false;
1010
844
  });
1011
-
1012
- // 选择第一个适用的优惠券(已经按过期时间排序)
1013
- // 如果有 isScan 且 isSelected 的折扣卡,则优先选中,否则再选择第一个
1014
- // 用于处理:先手动扫描了一张折扣卡,扫描完以后带入客户信息,但是之前那张折扣卡不是最优惠的情况
1015
- const selectedDiscountCard = applicableDiscounts.find(n => n.isScan && n.isSelected && (n.tag || n.type) !== 'good_pass');
845
+ const selectedDiscountCard = applicableDiscounts.find(
846
+ (n) => n.isScan && n.isSelected && (n.tag || n.type) !== "good_pass"
847
+ );
1016
848
  const selectedDiscount = selectedDiscountCard || applicableDiscounts[0];
1017
-
1018
- // 如果是手动折扣,则不适用优惠券
1019
849
  let isManualDiscount = false;
1020
- if (flatItem.type === 'main') {
1021
- // 主商品:判断自身是否手动折扣
1022
- isManualDiscount = typeof product.isManualDiscount === 'boolean' ? product.isManualDiscount : product.discount_list?.some(item => item.type === 'product') || product.total != product.origin_total && (product.bundle || []).every(item => !(item.discount_list || [])?.length) && (!product.discount_list?.length || product?.discount_list?.every?.(item => item.type === 'product'));
850
+ if (flatItem.type === "main") {
851
+ isManualDiscount = typeof product.isManualDiscount === "boolean" ? product.isManualDiscount : ((_g = product.discount_list) == null ? void 0 : _g.some((item) => item.type === "product")) || product.total != product.origin_total && (product.bundle || []).every(
852
+ (item) => {
853
+ var _a3;
854
+ return !((_a3 = item.discount_list || []) == null ? void 0 : _a3.length);
855
+ }
856
+ ) && (!((_h = product.discount_list) == null ? void 0 : _h.length) || ((_j = (_i = product == null ? void 0 : product.discount_list) == null ? void 0 : _i.every) == null ? void 0 : _j.call(
857
+ _i,
858
+ (item) => item.type === "product"
859
+ )));
1023
860
  if (product.inPromotion) {
1024
861
  isManualDiscount = false;
1025
862
  }
1026
863
  } else {
1027
- // bundle子商品:判断父主商品是否手动折扣
1028
864
  const parentProduct = flatItem.parentProduct;
1029
865
  if (parentProduct) {
1030
- isManualDiscount = typeof parentProduct.isManualDiscount === 'boolean' ? parentProduct.isManualDiscount : parentProduct.discount_list?.some(item => item.type === 'product') || parentProduct.total != parentProduct.origin_total && (parentProduct.bundle || []).every(item => !(item.discount_list || [])?.length) && (!parentProduct.discount_list?.length || parentProduct?.discount_list?.every?.(item => item.type === 'product'));
866
+ isManualDiscount = typeof parentProduct.isManualDiscount === "boolean" ? parentProduct.isManualDiscount : ((_k = parentProduct.discount_list) == null ? void 0 : _k.some((item) => item.type === "product")) || parentProduct.total != parentProduct.origin_total && (parentProduct.bundle || []).every(
867
+ (item) => {
868
+ var _a3;
869
+ return !((_a3 = item.discount_list || []) == null ? void 0 : _a3.length);
870
+ }
871
+ ) && (!((_l = parentProduct.discount_list) == null ? void 0 : _l.length) || ((_n = (_m = parentProduct == null ? void 0 : parentProduct.discount_list) == null ? void 0 : _m.every) == null ? void 0 : _n.call(
872
+ _m,
873
+ (item) => item.type === "product"
874
+ )));
1031
875
  }
1032
876
  }
1033
-
1034
- // 勾选时覆盖手动折扣
1035
- if (options?.discountId) {
1036
- // 主商品:检查自己的 discount_list
1037
- if (flatItem.type === 'main' && product.discount_list?.some(item => item.discount?.resource_id === options.discountId)) {
877
+ if (options == null ? void 0 : options.discountId) {
878
+ if (flatItem.type === "main" && ((_o = product.discount_list) == null ? void 0 : _o.some(
879
+ (item) => {
880
+ var _a3;
881
+ return ((_a3 = item.discount) == null ? void 0 : _a3.resource_id) === options.discountId;
882
+ }
883
+ ))) {
1038
884
  isManualDiscount = false;
1039
885
  }
1040
- // bundle子商品:检查自己的 discount_list 或父主商品的 discount_list
1041
- if (flatItem.type === 'bundle') {
1042
- if (product.discount_list?.some(item => item.discount?.resource_id === options.discountId) || flatItem.parentProduct?.discount_list?.some(item => item.discount?.resource_id === options.discountId)) {
886
+ if (flatItem.type === "bundle") {
887
+ if (((_p = product.discount_list) == null ? void 0 : _p.some(
888
+ (item) => {
889
+ var _a3;
890
+ return ((_a3 = item.discount) == null ? void 0 : _a3.resource_id) === options.discountId;
891
+ }
892
+ )) || ((_r = (_q = flatItem.parentProduct) == null ? void 0 : _q.discount_list) == null ? void 0 : _r.some(
893
+ (item) => {
894
+ var _a3;
895
+ return ((_a3 = item.discount) == null ? void 0 : _a3.resource_id) === options.discountId;
896
+ }
897
+ ))) {
1043
898
  isManualDiscount = false;
1044
899
  }
1045
900
  }
1046
901
  }
1047
- if (options?.selectedList) {
1048
- // 主商品:检查自己的 discount_list
1049
- if (flatItem.type === 'main' && product.discount_list?.some(item => options?.selectedList?.some(n => n.discountId === item.discount?.resource_id))) {
902
+ if (options == null ? void 0 : options.selectedList) {
903
+ if (flatItem.type === "main" && ((_s = product.discount_list) == null ? void 0 : _s.some(
904
+ (item) => {
905
+ var _a3;
906
+ return (_a3 = options == null ? void 0 : options.selectedList) == null ? void 0 : _a3.some(
907
+ (n) => {
908
+ var _a4;
909
+ return n.discountId === ((_a4 = item.discount) == null ? void 0 : _a4.resource_id);
910
+ }
911
+ );
912
+ }
913
+ ))) {
1050
914
  isManualDiscount = false;
1051
915
  }
1052
- // bundle子商品:检查自己的 discount_list 或父主商品的 discount_list
1053
- if (flatItem.type === 'bundle') {
1054
- if (product.discount_list?.some(item => options?.selectedList?.some(n => n.discountId === item.discount?.resource_id)) || flatItem.parentProduct?.discount_list?.some(item => options?.selectedList?.some(n => n.discountId === item.discount?.resource_id))) {
916
+ if (flatItem.type === "bundle") {
917
+ if (((_t = product.discount_list) == null ? void 0 : _t.some(
918
+ (item) => {
919
+ var _a3;
920
+ return (_a3 = options == null ? void 0 : options.selectedList) == null ? void 0 : _a3.some(
921
+ (n) => {
922
+ var _a4;
923
+ return n.discountId === ((_a4 = item.discount) == null ? void 0 : _a4.resource_id);
924
+ }
925
+ );
926
+ }
927
+ )) || ((_v = (_u = flatItem.parentProduct) == null ? void 0 : _u.discount_list) == null ? void 0 : _v.some(
928
+ (item) => {
929
+ var _a3;
930
+ return (_a3 = options == null ? void 0 : options.selectedList) == null ? void 0 : _a3.some(
931
+ (n) => {
932
+ var _a4;
933
+ return n.discountId === ((_a4 = item.discount) == null ? void 0 : _a4.resource_id);
934
+ }
935
+ );
936
+ }
937
+ ))) {
1055
938
  isManualDiscount = false;
1056
939
  }
1057
940
  }
1058
941
  }
1059
-
1060
- // 如果没有适用的优惠券,或者手动折扣,则不适用优惠券
1061
- if (applicableDiscounts.length === 0 || isManualDiscount || (0, _lodashEs.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
1062
- if (flatItem.type === 'main') {
1063
- // 主商品:保持原有逻辑,还原 option 价格
942
+ if (applicableDiscounts.length === 0 || isManualDiscount || (0, import_lodash_es.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
943
+ if (flatItem.type === "main") {
1064
944
  const restoredOptions = restoreOptionPrices(product.options);
1065
945
  if (product.isClient) {
1066
- processedProductsMap.set(product._id, [this.hooks.setProduct(originProduct, {
1067
- ...(isManualDiscount ? {} : {
1068
- origin_total: (0, _utils2.getProductOriginTotalPrice)({
1069
- product: {
1070
- original_price: product.original_price
1071
- },
1072
- bundle: product.bundle,
1073
- options: restoredOptions
1074
- }),
1075
- variant: originProduct._productInit.variant,
1076
- original_price: originProduct._productInit.original_price,
1077
- total: (0, _utils2.getProductTotalPrice)({
1078
- product: {
1079
- price: product.price
1080
- },
1081
- bundle: product.bundle,
946
+ processedProductsMap.set(product._id, [
947
+ this.hooks.setProduct(originProduct, {
948
+ ...isManualDiscount ? {} : {
949
+ origin_total: (0, import_utils2.getProductOriginTotalPrice)({
950
+ product: {
951
+ original_price: product.original_price
952
+ },
953
+ bundle: product.bundle,
954
+ options: restoredOptions
955
+ }),
956
+ variant: originProduct._productInit.variant,
957
+ original_price: originProduct._productInit.original_price,
958
+ total: (0, import_utils2.getProductTotalPrice)({
959
+ product: {
960
+ price: product.price
961
+ },
962
+ bundle: product.bundle,
963
+ options: restoredOptions
964
+ }),
965
+ price: product.price,
1082
966
  options: restoredOptions
1083
- }),
1084
- price: product.price,
1085
- options: restoredOptions
1086
- }),
1087
- discount_list: isManualDiscount ? this.resolveDiscountListForManualOverride(product.discount_list) : this.filterDiscountListByType(product.discount_list, 'promotion')
1088
- })]);
967
+ },
968
+ discount_list: isManualDiscount ? this.resolveDiscountListForManualOverride(product.discount_list) : this.filterDiscountListByType(product.discount_list, "promotion")
969
+ })
970
+ ]);
1089
971
  } else {
1090
- let total = product.inPromotion ? product?._promotion?.finalPrice ?? product.origin_total ?? product.total : product.origin_total ?? product.total;
1091
- let main_product_selling_price = product.price ?? product.main_product_selling_price;
1092
- if ((product.discount_list || []).some(item => item.type === 'promotion') || (0, _lodashEs.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
972
+ let total = product.inPromotion ? ((_w = product == null ? void 0 : product._promotion) == null ? void 0 : _w.finalPrice) ?? product.origin_total ?? product.total : product.origin_total ?? product.total;
973
+ let main_product_selling_price = product.price;
974
+ if ((product.discount_list || []).some((item) => item.type === "promotion") || (0, import_lodash_es.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
1093
975
  total = product.total ?? product.origin_total;
1094
976
  main_product_selling_price = product.main_product_selling_price ?? main_product_selling_price;
1095
977
  }
1096
- processedProductsMap.set(product._id, [this.hooks.setProduct(originProduct, {
1097
- ...(isManualDiscount ? {
1098
- price: product.price
1099
- } : {
1100
- _id: product._id.split('___')[0] + '___' + index,
1101
- total,
1102
- price: product.price,
1103
- main_product_selling_price,
1104
- options: restoredOptions
1105
- }),
1106
- discount_list: isManualDiscount ? this.resolveDiscountListForManualOverride(product.discount_list) : this.filterDiscountListByType(product.discount_list, 'promotion')
1107
- })]);
978
+ processedProductsMap.set(product._id, [
979
+ this.hooks.setProduct(originProduct, {
980
+ ...isManualDiscount ? {
981
+ price: product.price
982
+ } : {
983
+ _id: product._id.split("___")[0] + "___" + index,
984
+ total,
985
+ price: product.price,
986
+ main_product_selling_price,
987
+ options: restoredOptions
988
+ },
989
+ discount_list: isManualDiscount ? this.resolveDiscountListForManualOverride(product.discount_list) : this.filterDiscountListByType(product.discount_list, "promotion")
990
+ })
991
+ ]);
1108
992
  }
1109
993
  } else {
1110
- // bundle子商品:保存到扁平化Map
1111
994
  processedFlatItemsMap.set(flatItem._id, [{
1112
995
  ...flatItem,
1113
- discount_list: isManualDiscount ? this.resolveDiscountListForManualOverride(flatItem.bundleItem?.discount_list || []) : this.filterDiscountListByType(flatItem.bundleItem?.discount_list || [], 'promotion'),
996
+ discount_list: isManualDiscount ? this.resolveDiscountListForManualOverride(((_x = flatItem.bundleItem) == null ? void 0 : _x.discount_list) || []) : this.filterDiscountListByType(((_y = flatItem.bundleItem) == null ? void 0 : _y.discount_list) || [], "promotion"),
1114
997
  price: isManualDiscount ? flatItem.bundleItem.price : flatItem.bundleItem.original_price,
1115
998
  processed: true
1116
999
  }]);
@@ -1118,98 +1001,57 @@ class RulesModule extends _BaseModule.BaseModule {
1118
1001
  return;
1119
1002
  }
1120
1003
  const shouldReapplyBookingDiscountForProduct = shouldReapplyBookingDiscount(originProduct, selectedDiscount);
1121
- if (applicableDiscounts.length && product.booking_id && typeof selectedDiscount.isManualSelect === 'undefined' && !options?.scan && !isEditModeAddNewProduct && !shouldReapplyBookingDiscountForProduct) {
1004
+ if (applicableDiscounts.length && product.booking_id && typeof selectedDiscount.isManualSelect === "undefined" && !(options == null ? void 0 : options.scan) && !isEditModeAddNewProduct && !shouldReapplyBookingDiscountForProduct) {
1122
1005
  return;
1123
1006
  }
1124
-
1125
- // 是否需要拆分(商品券需要拆分,折扣卡在 applicableProductLimit > 0 时也需要拆分)
1126
- const discountType = selectedDiscount.tag || selectedDiscount.type;
1127
- const isGoodPass = discountType === 'good_pass';
1128
- const isDiscountCard = ['discount_card', 'product_discount_card'].includes(discountType);
1129
- const applicableProductLimit = selectedDiscount.config?.applicableProductLimit || 0;
1130
-
1131
- // 商品券始终需要拆分,折扣卡在 applicableProductLimit > 0 时需要拆分
1132
- const isNeedSplit = isGoodPass || isDiscountCard && applicableProductLimit > 0;
1133
-
1134
- // 需要拆分出来的数量
1007
+ const isNeedSplit = (selectedDiscount.tag || selectedDiscount.type) === "good_pass";
1135
1008
  const totalQuantity = product.quantity || product.num || 1;
1136
- const availableGoodPassCount = applicableDiscounts.filter(item => (item.tag || item.type) === 'good_pass').length;
1137
-
1138
- // 🔥 计算最大使用次数限制
1139
- let maxUsageLimit;
1140
- if (isGoodPass) {
1141
- // 商品券:使用 maxUsagePerOrder 限制
1142
- maxUsageLimit = availableGoodPassCount;
1143
- if (selectedDiscount.config && selectedDiscount.config.maxUsagePerOrder) {
1144
- maxUsageLimit = Math.min(availableGoodPassCount, selectedDiscount.config.maxUsagePerOrder);
1145
- }
1146
- } else if (isDiscountCard && applicableProductLimit > 0) {
1147
- // 折扣卡:使用 applicableProductLimit 限制(一个商品使用一次折扣卡算1次)
1148
- // 需要减去已使用次数(跨商品全局计数)
1149
- const usedLimitCount = usedDiscountCardLimitCounts.get(selectedDiscount.id) || 0;
1150
- maxUsageLimit = Math.max(0, applicableProductLimit - usedLimitCount);
1151
- } else {
1152
- // 其他情况不拆分
1153
- maxUsageLimit = 1;
1009
+ const availableGoodPassCount = applicableDiscounts.filter(
1010
+ (item) => (item.tag || item.type) === "good_pass"
1011
+ ).length;
1012
+ let maxUsageLimit = availableGoodPassCount;
1013
+ if (selectedDiscount.config && selectedDiscount.config.maxUsagePerOrder) {
1014
+ maxUsageLimit = Math.min(
1015
+ availableGoodPassCount,
1016
+ selectedDiscount.config.maxUsagePerOrder
1017
+ );
1154
1018
  }
1155
1019
  const splitCount = isNeedSplit ? Math.min(product.quantity || product.num || 1, maxUsageLimit) : 1;
1156
1020
  const arr = [];
1157
-
1158
- // 🔥 主商品和bundle子商品分别处理
1159
- if (flatItem.type === 'main') {
1160
- // 主商品:保持原有逻辑
1021
+ if (flatItem.type === "main") {
1161
1022
  if (splitCount < totalQuantity && isNeedSplit) {
1162
1023
  let total = product.origin_total ?? product.total;
1163
- if ((product.discount_list || []).some(item => item.type === 'promotion')) {
1024
+ if ((product.discount_list || []).some((item) => item.type === "promotion")) {
1164
1025
  total = product.total ?? product.origin_total;
1165
1026
  }
1166
- arr.push(this.hooks.setProduct(originProduct, {
1167
- discount_list: this.filterDiscountListByType(product.discount_list, 'promotion'),
1168
- quantity: totalQuantity - splitCount,
1169
- _id: product._id.split('___')[0],
1170
- total
1171
- }));
1027
+ arr.push(
1028
+ this.hooks.setProduct(originProduct, {
1029
+ discount_list: this.filterDiscountListByType(product.discount_list, "promotion"),
1030
+ quantity: totalQuantity - splitCount,
1031
+ _id: product._id.split("___")[0],
1032
+ total
1033
+ })
1034
+ );
1172
1035
  }
1173
1036
  for (let i = 0; i < splitCount; i++) {
1174
- // 商品券:每个拆分商品使用不同的商品券(从 applicableDiscounts 按索引取)
1175
- // 折扣卡:所有拆分商品使用同一张折扣卡(selectedDiscountCard 或 applicableDiscounts[0])
1176
- const currentSelectedDiscount = isGoodPass ? selectedDiscountCard || applicableDiscounts[i] : selectedDiscountCard || applicableDiscounts[0];
1177
- // 标记优惠券为已使用
1178
- usedDiscounts.set(currentSelectedDiscount.id, true);
1179
- // 🔥 更新 product_id 使用计数
1180
- if ((currentSelectedDiscount.tag || currentSelectedDiscount.type) === 'good_pass') {
1181
- const currentCount = usedProductIdCounts.get(currentSelectedDiscount.product_id) || 0;
1182
- usedProductIdCounts.set(currentSelectedDiscount.product_id, currentCount + 1);
1183
- }
1184
- // 🔥 更新折扣卡 applicableProductLimit 使用计数(跨商品全局)
1185
- const currentDiscountTypeForCount = currentSelectedDiscount.tag || currentSelectedDiscount.type;
1186
- if (['discount_card', 'product_discount_card'].includes(currentDiscountTypeForCount)) {
1187
- const currentLimitCount = usedDiscountCardLimitCounts.get(currentSelectedDiscount.id) || 0;
1188
- usedDiscountCardLimitCounts.set(currentSelectedDiscount.id, currentLimitCount + 1);
1037
+ const selectedDiscount2 = selectedDiscountCard || applicableDiscounts[i];
1038
+ usedDiscounts.set(selectedDiscount2.id, true);
1039
+ if ((selectedDiscount2.tag || selectedDiscount2.type) === "good_pass") {
1040
+ const currentCount = usedProductIdCounts.get(selectedDiscount2.product_id) || 0;
1041
+ usedProductIdCounts.set(selectedDiscount2.product_id, currentCount + 1);
1189
1042
  }
1190
-
1191
- // 记录实际应用了优惠券的商品信息
1192
- const appliedProducts = appliedDiscountProducts.get(currentSelectedDiscount.id) || [];
1193
-
1194
- // 优先从 origin_total拿,可能会拿不到(比如用户端预约在没有配置 original_price 的情况下)
1043
+ const appliedProducts = appliedDiscountProducts.get(selectedDiscount2.id) || [];
1195
1044
  let productOriginTotal = product.origin_total || product.total || 0;
1196
- // 如果当前 product 有 discount_list,则先从 origin_total 拿
1197
- if (this.filterDiscountListByType(product.discount_list, 'promotion').length && product.origin_total) {
1045
+ if (this.filterDiscountListByType(product.discount_list, "promotion").length && product.origin_total) {
1198
1046
  productOriginTotal = product.origin_total;
1199
1047
  }
1200
- // 如果originProduct?._productInit?.original_price为 0,product.origin_total可能为空,此时取 product.total
1201
- if (Number(originProduct?._productInit?.original_price || 0) > 0 && product.origin_total && product.total && product.origin_total !== product.total) {
1048
+ if (Number(((_z = originProduct == null ? void 0 : originProduct._productInit) == null ? void 0 : _z.original_price) || 0) > 0 && product.origin_total && product.total && product.origin_total !== product.total) {
1202
1049
  productOriginTotal = product.total;
1203
1050
  }
1204
-
1205
- // 计算使用折扣卡/商品券以后,单个商品的总 total
1206
- // 🔥 检查是否是 order_level 固定金额折扣卡
1207
- const isOrderLevel = (0, _utils.isOrderLevelFixedAmountDiscount)(selectedDiscount);
1208
- const orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount.id) : null;
1209
- const productAllocation = orderLevelAllocation?.get(flatItem._id);
1210
- const isDeductOptionPrice = !!selectedDiscount.config?.deductOptionPrice;
1211
-
1212
- // 主商品折后价(不含 option);勿与 option 合计混在同一变量,否则 main_product_selling_price 错误
1051
+ const isOrderLevel = (0, import_utils3.isOrderLevelFixedAmountDiscount)(selectedDiscount2);
1052
+ const orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount2.id) : null;
1053
+ const productAllocation = orderLevelAllocation == null ? void 0 : orderLevelAllocation.get(flatItem._id);
1054
+ const isDeductOptionPrice = !!((_A = selectedDiscount2.config) == null ? void 0 : _A.deductOptionPrice);
1213
1055
  let mainProductSellingPrice;
1214
1056
  let amount;
1215
1057
  let productDiscountDifference;
@@ -1217,166 +1059,146 @@ class RulesModule extends _BaseModule.BaseModule {
1217
1059
  let optionDiscountAmount = 0;
1218
1060
  let reapplyDiscountPercent;
1219
1061
  if (isOrderLevel && productAllocation) {
1220
- // order_level:使用预计算的分摊金额
1221
1062
  amount = productAllocation.discountAmount;
1222
1063
  productDiscountDifference = productAllocation.difference;
1223
- mainProductSellingPrice = Math.max(new _decimal.default(product.price).minus(amount).toNumber(), 0);
1224
- } else if (resolveReapplyEditModeDiscountPercent(originProduct, selectedDiscount) !== undefined) {
1225
- // Change time 重套编辑态折扣卡时,历史 par_value 不是运行时折扣口径,优先使用后端快照里的 percent。
1226
- const percent = resolveReapplyEditModeDiscountPercent(originProduct, selectedDiscount);
1227
- reapplyDiscountPercent = new _decimal.default(percent).toFixed(2);
1228
- mainProductSellingPrice = new _decimal.default(product.price || 0).mul(new _decimal.default(100).minus(percent)).div(100).toDecimalPlaces(2).toNumber();
1229
- amount = new _decimal.default(product.price).minus(mainProductSellingPrice).toNumber();
1064
+ mainProductSellingPrice = Math.max(new import_decimal.default(product.price).minus(amount).toNumber(), 0);
1065
+ } else if (resolveReapplyEditModeDiscountPercent(originProduct, selectedDiscount2) !== void 0) {
1066
+ const percent = resolveReapplyEditModeDiscountPercent(originProduct, selectedDiscount2);
1067
+ reapplyDiscountPercent = new import_decimal.default(percent).toFixed(2);
1068
+ mainProductSellingPrice = new import_decimal.default(product.price || 0).mul(new import_decimal.default(100).minus(percent)).div(100).toDecimalPlaces(2).toNumber();
1069
+ amount = new import_decimal.default(product.price).minus(mainProductSellingPrice).toNumber();
1230
1070
  } else {
1231
- // item_level 或其他类型:使用原有逻辑
1232
- mainProductSellingPrice = (0, _utils.getDiscountAmount)(selectedDiscount, product.price, product.price);
1233
- amount = new _decimal.default(product.price).minus(new _decimal.default(mainProductSellingPrice)).toNumber();
1071
+ mainProductSellingPrice = (0, import_utils.getDiscountAmount)(
1072
+ selectedDiscount2,
1073
+ product.price,
1074
+ product.price
1075
+ );
1076
+ amount = new import_decimal.default(product.price).minus(new import_decimal.default(mainProductSellingPrice)).toNumber();
1234
1077
  }
1235
- if (isDeductOptionPrice && product.options?.length) {
1236
- const optionResult = applyDiscountToOptions(product.options, selectedDiscount);
1078
+ if (isDeductOptionPrice && ((_B = product.options) == null ? void 0 : _B.length)) {
1079
+ const optionResult = applyDiscountToOptions(
1080
+ product.options,
1081
+ selectedDiscount2
1082
+ );
1237
1083
  discountedOptions = optionResult.discountedOptions;
1238
1084
  optionDiscountAmount = optionResult.optionDiscountAmount;
1239
1085
  }
1240
-
1241
- // total = 主商品折后 + option 行合计;开启 option 抵扣时必须用 discountedOptions,不能用未折扣的 product.options 再算一遍
1242
- const optionsForLineTotal = isDeductOptionPrice && product.options?.length ? discountedOptions : product.options;
1086
+ const optionsForLineTotal = isDeductOptionPrice && ((_C = product.options) == null ? void 0 : _C.length) ? discountedOptions : product.options;
1243
1087
  const optionsLineTotal = getOptionTotal(optionsForLineTotal || []);
1244
- const total = new _decimal.default(mainProductSellingPrice).plus(optionsLineTotal).toNumber();
1245
-
1246
- // discount_list.amount / fixed_amount:行级总优惠 = 主商品优惠 + option 优惠(与 total 变化一致)
1088
+ const total = new import_decimal.default(mainProductSellingPrice).plus(optionsLineTotal).toNumber();
1247
1089
  const mainProductDiscountAmount = amount;
1248
- const lineDiscountAmount = new _decimal.default(mainProductDiscountAmount).plus(optionDiscountAmount).toNumber();
1249
- const discountType = selectedDiscount.tag || selectedDiscount.type;
1250
- const currentIsGoodPass = discountType === 'good_pass';
1090
+ const lineDiscountAmount = new import_decimal.default(mainProductDiscountAmount).plus(optionDiscountAmount).toNumber();
1091
+ const discountType = selectedDiscount2.tag || selectedDiscount2.type;
1092
+ const isGoodPass = discountType === "good_pass";
1251
1093
  const discountDetail = {
1252
1094
  amount: lineDiscountAmount,
1253
- type: selectedDiscount.tag === 'product_discount_card' ? 'discount_card' : discountType,
1095
+ type: selectedDiscount2.tag === "product_discount_card" ? "discount_card" : discountType,
1254
1096
  discount: {
1255
- discount_card_type: selectedDiscount?.metadata?.discount_card_type,
1097
+ discount_card_type: (_D = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _D.discount_card_type,
1256
1098
  fixed_amount: lineDiscountAmount,
1257
- discount_calculation_mode: selectedDiscount?.metadata?.discount_calculation_mode,
1258
- resource_id: selectedDiscount.id,
1259
- title: selectedDiscount.format_title,
1099
+ discount_calculation_mode: (_E = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _E.discount_calculation_mode,
1100
+ resource_id: selectedDiscount2.id,
1101
+ title: selectedDiscount2.format_title,
1260
1102
  original_amount: product.price,
1261
1103
  product_id: originProduct.id || originProduct.product_id,
1262
- percent: reapplyDiscountPercent ?? selectedDiscount.par_value,
1263
- discount_product_id: selectedDiscount.product_id
1104
+ percent: reapplyDiscountPercent ?? selectedDiscount2.par_value,
1105
+ discount_product_id: selectedDiscount2.product_id
1264
1106
  },
1265
- // 前端使用的num数量,为了计算优惠金额(拆分时为1)
1266
- _num: isNeedSplit ? 1 : product.num,
1267
- config: currentSelectedDiscount?.config,
1107
+ // 前端使用的num数量,为了计算优惠金额
1108
+ _num: isGoodPass ? 1 : product.num,
1109
+ config: selectedDiscount2 == null ? void 0 : selectedDiscount2.config,
1268
1110
  metadata: {
1269
1111
  num: 1,
1270
- discount_rule_uncheck_flag: selectedDiscount?.discount_rule_uncheck_flag,
1112
+ discount_rule_uncheck_flag: selectedDiscount2 == null ? void 0 : selectedDiscount2.discount_rule_uncheck_flag,
1271
1113
  // 🔥 order_level 分摊差值
1272
- ...(productDiscountDifference !== undefined && {
1273
- product_discount_difference: productDiscountDifference
1274
- }),
1114
+ ...productDiscountDifference !== void 0 && { product_discount_difference: productDiscountDifference },
1275
1115
  /** 仅主商品上的优惠金额(不含 option) */
1276
1116
  mainProductDiscountAmount,
1277
1117
  optionDiscountAmount
1278
1118
  }
1279
1119
  };
1280
1120
  appliedProducts.push(discountDetail);
1281
- appliedDiscountProducts.set(selectedDiscount.id, appliedProducts);
1282
-
1283
- // 记录应用了优惠券的商品
1284
- // 后续更新价格改为 getProductTotalPrice getProductOriginTotalPrice逻辑
1121
+ appliedDiscountProducts.set(selectedDiscount2.id, appliedProducts);
1285
1122
  if (product.isClient) {
1286
- arr.push(this.hooks.setProduct(originProduct, {
1287
- discount_list: [discountDetail],
1288
- // good_pass:主商品价以折后价为准;勿用 product.price - amount(amount 含 option 优惠时会算错)
1289
- price: isGoodPass ? mainProductSellingPrice : product.price,
1290
- quantity: isNeedSplit ? 1 : product.quantity,
1291
- origin_total: (0, _utils2.getProductOriginTotalPrice)({
1292
- product: {
1293
- original_price: product.original_price
1294
- },
1295
- bundle: product.bundle,
1296
- options: restoreOptionPrices(product.options)
1297
- }),
1298
- variant: originProduct._productInit.variant,
1299
- original_price: new _decimal.default(product.price || 0).toNumber(),
1300
- total: total,
1301
- options: discountedOptions
1302
- }));
1123
+ arr.push(
1124
+ this.hooks.setProduct(originProduct, {
1125
+ discount_list: [discountDetail],
1126
+ // good_pass:主商品价以折后价为准;勿用 product.price - amount(amount 含 option 优惠时会算错)
1127
+ price: isGoodPass ? mainProductSellingPrice : product.price,
1128
+ quantity: isNeedSplit ? 1 : product.quantity,
1129
+ origin_total: (0, import_utils2.getProductOriginTotalPrice)({
1130
+ product: {
1131
+ original_price: product.original_price
1132
+ },
1133
+ bundle: product.bundle,
1134
+ options: restoreOptionPrices(product.options)
1135
+ }),
1136
+ variant: originProduct._productInit.variant,
1137
+ original_price: new import_decimal.default(product.price || 0).toNumber(),
1138
+ total,
1139
+ options: discountedOptions
1140
+ })
1141
+ );
1303
1142
  } else {
1304
- arr.push(this.hooks.setProduct(originProduct, {
1305
- discount_list: this.filterDiscountListByType(product.discount_list, 'promotion').concat([discountDetail]),
1306
- _id: product._id.split('___')[0] + '___' + currentSelectedDiscount.id + '_' + i + '_' + index,
1307
- price: currentIsGoodPass ? 0 : product.price,
1308
- quantity: isNeedSplit ? 1 : product.quantity,
1309
- total: total,
1310
- origin_total: productOriginTotal,
1311
- main_product_selling_price: mainProductSellingPrice,
1312
- options: discountedOptions
1313
- }));
1143
+ arr.push(
1144
+ this.hooks.setProduct(originProduct, {
1145
+ discount_list: this.filterDiscountListByType(product.discount_list, "promotion").concat([discountDetail]),
1146
+ _id: product._id.split("___")[0] + "___" + selectedDiscount2.id + index,
1147
+ price: selectedDiscount2.tag === "good_pass" ? 0 : product.price,
1148
+ quantity: isNeedSplit ? 1 : product.quantity,
1149
+ total,
1150
+ origin_total: productOriginTotal,
1151
+ main_product_selling_price: mainProductSellingPrice,
1152
+ options: discountedOptions
1153
+ })
1154
+ );
1314
1155
  }
1315
1156
  }
1316
1157
  processedProductsMap.set(product._id, arr);
1317
1158
  } else {
1318
- // 🔥 bundle子商品:支持拆分(商品券和折扣卡在 applicableProductLimit > 0 时都需要拆分)
1319
1159
  const processedItems = [];
1320
1160
  if (isNeedSplit) {
1321
- // 需要拆分数量(商品券或折扣卡有 applicableProductLimit 限制)
1322
1161
  const discountNum = splitCount;
1323
1162
  const normalNum = totalQuantity - discountNum;
1324
-
1325
- // 生成有折扣的商品(每个拆分商品 num: 1)
1326
1163
  for (let i = 0; i < discountNum; i++) {
1327
- // 商品券:每个拆分商品使用不同的商品券
1328
- // 折扣卡:所有拆分商品使用同一张折扣卡
1329
- const currentBundleDiscount = isGoodPass ? selectedDiscountCard || applicableDiscounts[i] : selectedDiscountCard || applicableDiscounts[0];
1330
- usedDiscounts.set(currentBundleDiscount.id, true);
1331
- // 🔥 更新 product_id 使用计数
1332
- if ((currentBundleDiscount.tag || currentBundleDiscount.type) === 'good_pass') {
1333
- const currentCount = usedProductIdCounts.get(currentBundleDiscount.product_id) || 0;
1334
- usedProductIdCounts.set(currentBundleDiscount.product_id, currentCount + 1);
1164
+ const selectedDiscount2 = applicableDiscounts[i];
1165
+ usedDiscounts.set(selectedDiscount2.id, true);
1166
+ if ((selectedDiscount2.tag || selectedDiscount2.type) === "good_pass") {
1167
+ const currentCount = usedProductIdCounts.get(selectedDiscount2.product_id) || 0;
1168
+ usedProductIdCounts.set(selectedDiscount2.product_id, currentCount + 1);
1335
1169
  }
1336
- // 🔥 更新折扣卡 applicableProductLimit 使用计数(跨商品全局)
1337
- const bundleDiscountTypeForCount = currentBundleDiscount.tag || currentBundleDiscount.type;
1338
- if (['discount_card', 'product_discount_card'].includes(bundleDiscountTypeForCount)) {
1339
- const currentBundleLimitCount = usedDiscountCardLimitCounts.get(currentBundleDiscount.id) || 0;
1340
- usedDiscountCardLimitCounts.set(currentBundleDiscount.id, currentBundleLimitCount + 1);
1341
- }
1342
-
1343
- // 🔥 生成唯一的 _id
1344
1170
  const uniqueId = `${flatItem._id}_split_${i}`;
1345
-
1346
- // 计算折扣后的价格(使用 getDiscountAmount,内部已处理 maxDeductionAmount)
1347
- const discountedPrice = (0, _utils.getDiscountAmount)(currentBundleDiscount, product.origin_total, product.origin_total);
1348
- const bundleDiscountAmount = new _decimal.default(product.origin_total || 0).minus(discountedPrice).toNumber();
1171
+ const discountedPrice = (0, import_utils.getDiscountAmount)(
1172
+ selectedDiscount2,
1173
+ product.origin_total,
1174
+ product.origin_total
1175
+ );
1176
+ const bundleDiscountAmount = new import_decimal.default(product.origin_total || 0).minus(discountedPrice).toNumber();
1349
1177
  debugger;
1350
-
1351
- // 确定折扣类型
1352
- const bundleDiscountType = currentBundleDiscount.tag === 'product_discount_card' ? 'discount_card' : currentBundleDiscount.tag;
1353
1178
  const discountDetail = {
1354
1179
  amount: bundleDiscountAmount,
1355
- type: bundleDiscountType,
1180
+ type: "good_pass",
1356
1181
  discount: {
1357
- discount_card_type: currentBundleDiscount?.metadata?.discount_card_type,
1358
- discount_calculation_mode: currentBundleDiscount?.metadata?.discount_calculation_mode,
1359
- fixed_amount: bundleDiscountAmount,
1360
- resource_id: currentBundleDiscount.id,
1361
- title: currentBundleDiscount.format_title,
1182
+ fixed_amount: product.origin_total,
1183
+ discount_calculation_mode: (_F = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _F.discount_calculation_mode,
1184
+ resource_id: selectedDiscount2.id,
1185
+ title: selectedDiscount2.format_title,
1362
1186
  original_amount: product.origin_total,
1363
1187
  product_id: product.id || product.product_id,
1364
- discount_product_id: selectedDiscount.product_id
1188
+ discount_product_id: selectedDiscount2.product_id
1365
1189
  },
1366
1190
  metadata: {
1367
1191
  // 🔥 使用拆分后的唯一 _id
1368
1192
  custom_product_bundle_map_id: uniqueId,
1369
- discount_rule_uncheck_flag: selectedDiscount?.discount_rule_uncheck_flag,
1193
+ discount_rule_uncheck_flag: selectedDiscount2 == null ? void 0 : selectedDiscount2.discount_rule_uncheck_flag,
1370
1194
  num: 1
1371
1195
  },
1372
1196
  _num: 1,
1373
- config: currentBundleDiscount?.config
1197
+ config: selectedDiscount2 == null ? void 0 : selectedDiscount2.config
1374
1198
  };
1375
-
1376
- // 记录实际应用的折扣
1377
- const appliedProducts = appliedDiscountProducts.get(currentBundleDiscount.id) || [];
1199
+ const appliedProducts = appliedDiscountProducts.get(selectedDiscount2.id) || [];
1378
1200
  appliedProducts.push(discountDetail);
1379
- appliedDiscountProducts.set(currentBundleDiscount.id, appliedProducts);
1201
+ appliedDiscountProducts.set(selectedDiscount2.id, appliedProducts);
1380
1202
  processedItems.push({
1381
1203
  ...flatItem,
1382
1204
  // 🔥 使用唯一的 _id
@@ -1388,333 +1210,100 @@ class RulesModule extends _BaseModule.BaseModule {
1388
1210
  total: discountedPrice,
1389
1211
  discount_list: [discountDetail],
1390
1212
  processed: true,
1391
- _discountId: currentBundleDiscount.id
1213
+ _discountId: selectedDiscount2.id
1392
1214
  });
1393
1215
  }
1394
-
1395
- // 🔥 对拆分后的剩余商品继续匹配其他可用折扣(而不是等到下次执行才应用)
1396
- let remainingNum = normalNum;
1397
- let continueSplitIndex = discountNum;
1398
- while (remainingNum > 0) {
1399
- // 重新查找适用于剩余商品的可用折扣(已使用的会被自动过滤掉)
1400
- const nextApplicableDiscounts = sortedDiscountList.filter(nextDiscount => {
1401
- const nextDiscountType = nextDiscount.tag || nextDiscount.type;
1402
- // 检查策略可用性
1403
- if (['good_pass', 'discount_card', 'product_discount_card'].includes(nextDiscountType)) {
1404
- if (nextDiscount.config === undefined || !nextDiscount?.config?.isAvailable) {
1405
- return false;
1406
- }
1407
- }
1408
- // 折扣卡时总价为0时不可用
1409
- if ((Number(product.total) <= 0 || !product.total) && !product.discount_list?.find(n => n.discount?.resource_id === nextDiscount.id) && nextDiscountType !== 'good_pass') return false;
1410
-
1411
- // 商品券已被使用则跳过
1412
- if (usedDiscounts.get(nextDiscount.id) && nextDiscountType === 'good_pass') return false;
1413
-
1414
- // 检查 maxUsagePerOrder 限制
1415
- if (nextDiscountType === 'good_pass') {
1416
- const maxUsagePerOrder = nextDiscount.config?.maxUsagePerOrder;
1417
- if (maxUsagePerOrder && maxUsagePerOrder > 0) {
1418
- const currentUsedCount = usedProductIdCounts.get(nextDiscount.product_id) || 0;
1419
- if (currentUsedCount >= maxUsagePerOrder) {
1420
- return false;
1421
- }
1422
- }
1423
- }
1424
-
1425
- // 检查折扣卡的 applicableProductLimit 限制
1426
- if (['discount_card', 'product_discount_card'].includes(nextDiscountType)) {
1427
- const limitConfig = nextDiscount.config?.applicableProductLimit || 0;
1428
- if (limitConfig > 0) {
1429
- const currentUsedLimitCount = usedDiscountCardLimitCounts.get(nextDiscount.id) || 0;
1430
- if (currentUsedLimitCount >= limitConfig) {
1431
- return false;
1432
- }
1433
- }
1434
- }
1435
- const limitedData = nextDiscount.limited_relation_product_data;
1436
- if (limitedData.type === 'product_all') {
1437
- if (limitedData.filter === 1 && limitedData.exclude_product_ids.includes(product.id)) {
1438
- return false;
1439
- }
1440
- if (!this.checkPackageSubItemUsageRules(nextDiscount, flatItem)) {
1441
- return false;
1442
- }
1443
- return true;
1444
- } else if (limitedData.product_ids && limitedData.product_ids.includes(product.id)) {
1445
- if (!this.checkPackageSubItemUsageRules(nextDiscount, flatItem)) {
1446
- return false;
1447
- }
1448
- return true;
1449
- }
1450
- return false;
1216
+ if (normalNum > 0) {
1217
+ processedItems.push({
1218
+ ...flatItem,
1219
+ // 🔥 为剩余商品生成唯一的 _id
1220
+ _id: `${flatItem._id}_split_rest`,
1221
+ num: normalNum,
1222
+ quantity: normalNum,
1223
+ discount_list: this.filterDiscountListByType(flatItem.discount_list, "promotion"),
1224
+ processed: true
1451
1225
  });
1452
-
1453
- // 没有更多可用折扣,剩余商品无折扣存储
1454
- if (nextApplicableDiscounts.length === 0) {
1455
- processedItems.push({
1456
- ...flatItem,
1457
- _id: `${flatItem._id}_split_rest`,
1458
- num: remainingNum,
1459
- quantity: remainingNum,
1460
- discount_list: [],
1461
- processed: true
1462
- });
1463
- break;
1464
- }
1465
-
1466
- // 选择最优折扣
1467
- const nextSelectedDiscountCard = nextApplicableDiscounts.find(n => n.isScan && n.isSelected && (n.tag || n.type) !== 'good_pass');
1468
- const nextSelectedDiscount = nextSelectedDiscountCard || nextApplicableDiscounts[0];
1469
-
1470
- // 判断新折扣是否需要拆分
1471
- const nextDiscType = nextSelectedDiscount.tag || nextSelectedDiscount.type;
1472
- const nextIsGoodPass = nextDiscType === 'good_pass';
1473
- const nextIsDiscountCard = ['discount_card', 'product_discount_card'].includes(nextDiscType);
1474
- const nextApplicableProductLimit = nextSelectedDiscount.config?.applicableProductLimit || 0;
1475
- const nextIsNeedSplit = nextIsGoodPass || nextIsDiscountCard && nextApplicableProductLimit > 0;
1476
- if (!nextIsNeedSplit) {
1477
- // 🔥 不需要拆分:直接应用折扣到所有剩余商品
1478
- const nextBundleDiscount = nextSelectedDiscountCard || nextApplicableDiscounts[0];
1479
- usedDiscounts.set(nextBundleDiscount.id, true);
1480
- if ((nextBundleDiscount.tag || nextBundleDiscount.type) === 'good_pass') {
1481
- const curCount = usedProductIdCounts.get(nextBundleDiscount.product_id) || 0;
1482
- usedProductIdCounts.set(nextBundleDiscount.product_id, curCount + 1);
1483
- }
1484
- const nextNoSplitType = nextBundleDiscount.tag || nextBundleDiscount.type;
1485
- if (['discount_card', 'product_discount_card'].includes(nextNoSplitType)) {
1486
- const curCount = usedDiscountCardLimitCounts.get(nextBundleDiscount.id) || 0;
1487
- usedDiscountCardLimitCounts.set(nextBundleDiscount.id, curCount + remainingNum);
1488
- }
1489
- const nextOriginTotal = product.original_price || product.price || 0;
1490
- const nextTargetTotal = (0, _utils.getDiscountAmount)(nextBundleDiscount, nextOriginTotal, nextOriginTotal);
1491
- const nextDiscountAmount = new _decimal.default(nextOriginTotal).minus(nextTargetTotal).toNumber();
1492
- const nextUniqueId = `${flatItem._id}_split_${continueSplitIndex}`;
1493
- const nextBundleDiscType = nextBundleDiscount.tag === 'product_discount_card' ? 'discount_card' : nextBundleDiscount.tag;
1494
- const nextDiscountDetail = {
1495
- amount: nextDiscountAmount * remainingNum,
1496
- type: nextBundleDiscType,
1497
- discount: {
1498
- discount_card_type: nextBundleDiscount?.metadata?.discount_card_type,
1499
- fixed_amount: nextDiscountAmount,
1500
- resource_id: nextBundleDiscount.id,
1501
- title: nextBundleDiscount.format_title,
1502
- original_amount: product.original_price,
1503
- product_id: product.id,
1504
- percent: nextBundleDiscount.par_value,
1505
- discount_product_id: nextBundleDiscount.product_id
1506
- },
1507
- metadata: {
1508
- custom_product_bundle_map_id: nextUniqueId,
1509
- num: remainingNum
1510
- },
1511
- config: nextBundleDiscount?.config,
1512
- _num: remainingNum * (flatItem?.parentProduct?.num || 1)
1513
- };
1514
- const nextAppliedProducts = appliedDiscountProducts.get(nextBundleDiscount.id) || [];
1515
- nextAppliedProducts.push(nextDiscountDetail);
1516
- appliedDiscountProducts.set(nextBundleDiscount.id, nextAppliedProducts);
1517
- processedItems.push({
1518
- ...flatItem,
1519
- _id: nextUniqueId,
1520
- num: remainingNum,
1521
- quantity: remainingNum,
1522
- total: nextTargetTotal,
1523
- price: new _decimal.default(nextOriginTotal || 0).minus(nextDiscountDetail.discount.fixed_amount).toNumber(),
1524
- discount_list: [nextDiscountDetail],
1525
- processed: true
1526
- });
1527
- remainingNum = 0;
1528
- break;
1529
- }
1530
-
1531
- // 🔥 需要拆分:计算最大使用次数
1532
- let nextMaxUsageLimit;
1533
- if (nextIsGoodPass) {
1534
- const nextGoodPassCount = nextApplicableDiscounts.filter(item => (item.tag || item.type) === 'good_pass').length;
1535
- nextMaxUsageLimit = nextGoodPassCount;
1536
- if (nextSelectedDiscount.config?.maxUsagePerOrder) {
1537
- const usedCount = usedProductIdCounts.get(nextSelectedDiscount.product_id) || 0;
1538
- nextMaxUsageLimit = Math.min(nextGoodPassCount, Math.max(0, nextSelectedDiscount.config.maxUsagePerOrder - usedCount));
1539
- }
1540
- } else if (nextIsDiscountCard && nextApplicableProductLimit > 0) {
1541
- const usedLimitCount = usedDiscountCardLimitCounts.get(nextSelectedDiscount.id) || 0;
1542
- nextMaxUsageLimit = Math.max(0, nextApplicableProductLimit - usedLimitCount);
1543
- } else {
1544
- nextMaxUsageLimit = 1;
1545
- }
1546
- const nextSplitCount = Math.min(remainingNum, nextMaxUsageLimit);
1547
- if (nextSplitCount === 0) {
1548
- // 已达使用上限,剩余商品无折扣存储
1549
- processedItems.push({
1550
- ...flatItem,
1551
- _id: `${flatItem._id}_split_rest`,
1552
- num: remainingNum,
1553
- quantity: remainingNum,
1554
- discount_list: [],
1555
- processed: true
1556
- });
1557
- break;
1558
- }
1559
-
1560
- // 生成有折扣的商品
1561
- for (let j = 0; j < nextSplitCount; j++) {
1562
- const nextBundleDiscount = nextIsGoodPass ? nextSelectedDiscountCard || nextApplicableDiscounts[j] : nextSelectedDiscountCard || nextApplicableDiscounts[0];
1563
- usedDiscounts.set(nextBundleDiscount.id, true);
1564
- if ((nextBundleDiscount.tag || nextBundleDiscount.type) === 'good_pass') {
1565
- const curCount = usedProductIdCounts.get(nextBundleDiscount.product_id) || 0;
1566
- usedProductIdCounts.set(nextBundleDiscount.product_id, curCount + 1);
1567
- }
1568
- const nextBundleDiscTypeForCount = nextBundleDiscount.tag || nextBundleDiscount.type;
1569
- if (['discount_card', 'product_discount_card'].includes(nextBundleDiscTypeForCount)) {
1570
- const curLimitCount = usedDiscountCardLimitCounts.get(nextBundleDiscount.id) || 0;
1571
- usedDiscountCardLimitCounts.set(nextBundleDiscount.id, curLimitCount + 1);
1572
- }
1573
- const nextUniqueId = `${flatItem._id}_split_${continueSplitIndex}`;
1574
- const nextDiscountedPrice = (0, _utils.getDiscountAmount)(nextBundleDiscount, product.origin_total, product.origin_total);
1575
- const nextBundleDiscAmount = new _decimal.default(product.origin_total || 0).minus(nextDiscountedPrice).toNumber();
1576
- const nextBundleDiscTypeStr = nextBundleDiscount.tag === 'product_discount_card' ? 'discount_card' : nextBundleDiscount.tag;
1577
- const nextDiscountDetail = {
1578
- amount: nextBundleDiscAmount,
1579
- type: nextBundleDiscTypeStr,
1580
- discount: {
1581
- discount_card_type: nextBundleDiscount?.metadata?.discount_card_type,
1582
- fixed_amount: nextBundleDiscAmount,
1583
- resource_id: nextBundleDiscount.id,
1584
- title: nextBundleDiscount.format_title,
1585
- original_amount: product.origin_total,
1586
- product_id: product.id,
1587
- percent: nextBundleDiscount.par_value,
1588
- discount_product_id: nextBundleDiscount.product_id
1589
- },
1590
- metadata: {
1591
- custom_product_bundle_map_id: nextUniqueId,
1592
- num: 1
1593
- },
1594
- _num: 1,
1595
- config: nextBundleDiscount?.config
1596
- };
1597
- const nextAppliedProducts = appliedDiscountProducts.get(nextBundleDiscount.id) || [];
1598
- nextAppliedProducts.push(nextDiscountDetail);
1599
- appliedDiscountProducts.set(nextBundleDiscount.id, nextAppliedProducts);
1600
- processedItems.push({
1601
- ...flatItem,
1602
- _id: nextUniqueId,
1603
- num: 1,
1604
- quantity: 1,
1605
- price: nextDiscountedPrice,
1606
- total: nextDiscountedPrice,
1607
- discount_list: [nextDiscountDetail],
1608
- processed: true,
1609
- _discountId: nextBundleDiscount.id
1610
- });
1611
- continueSplitIndex++;
1612
- }
1613
- remainingNum -= nextSplitCount;
1614
1226
  }
1615
1227
  } else {
1616
- // 不拆分:直接应用折扣
1617
- const currentBundleDiscount = selectedDiscountCard || applicableDiscounts[0];
1618
- usedDiscounts.set(currentBundleDiscount.id, true);
1619
- // 🔥 更新 product_id 使用计数
1620
- if ((currentBundleDiscount.tag || currentBundleDiscount.type) === 'good_pass') {
1621
- const currentCount = usedProductIdCounts.get(currentBundleDiscount.product_id) || 0;
1622
- usedProductIdCounts.set(currentBundleDiscount.product_id, currentCount + 1);
1623
- }
1624
- // 🔥 更新折扣卡 applicableProductLimit 使用计数(不拆分时按商品数量计数)
1625
- const noSplitDiscountType = currentBundleDiscount.tag || currentBundleDiscount.type;
1626
- if (['discount_card', 'product_discount_card'].includes(noSplitDiscountType)) {
1627
- const bundleQuantity = product.num || 1;
1628
- const currentNoSplitCount = usedDiscountCardLimitCounts.get(currentBundleDiscount.id) || 0;
1629
- usedDiscountCardLimitCounts.set(currentBundleDiscount.id, currentNoSplitCount + bundleQuantity);
1228
+ const selectedDiscount2 = selectedDiscountCard || applicableDiscounts[0];
1229
+ usedDiscounts.set(selectedDiscount2.id, true);
1230
+ if ((selectedDiscount2.tag || selectedDiscount2.type) === "good_pass") {
1231
+ const currentCount = usedProductIdCounts.get(selectedDiscount2.product_id) || 0;
1232
+ usedProductIdCounts.set(selectedDiscount2.product_id, currentCount + 1);
1630
1233
  }
1631
1234
  const productOriginTotal = product.original_price || product.price || 0;
1632
-
1633
- // 🔥 检查是否是 order_level 固定金额折扣卡
1634
- const isOrderLevel = (0, _utils.isOrderLevelFixedAmountDiscount)(selectedDiscount);
1635
- const orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount.id) : null;
1636
- const productAllocation = orderLevelAllocation?.get(flatItem._id);
1235
+ const isOrderLevel = (0, import_utils3.isOrderLevelFixedAmountDiscount)(selectedDiscount2);
1236
+ const orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount2.id) : null;
1237
+ const productAllocation = orderLevelAllocation == null ? void 0 : orderLevelAllocation.get(flatItem._id);
1637
1238
  let targetProductTotal;
1638
1239
  let fixedAmountPerItem;
1639
1240
  let productDiscountDifference;
1640
1241
  if (isOrderLevel && productAllocation) {
1641
- // order_level:使用预计算的单价折扣金额(已经是单价,无需再除以数量)
1642
1242
  fixedAmountPerItem = productAllocation.discountAmount;
1643
1243
  productDiscountDifference = productAllocation.difference;
1644
- targetProductTotal = Math.max(new _decimal.default(productOriginTotal).minus(fixedAmountPerItem).toNumber(), 0);
1244
+ targetProductTotal = Math.max(new import_decimal.default(productOriginTotal).minus(fixedAmountPerItem).toNumber(), 0);
1645
1245
  } else {
1646
- // item_level 或其他类型:使用原有逻辑
1647
- targetProductTotal = (0, _utils.getDiscountAmount)(currentBundleDiscount, productOriginTotal, productOriginTotal);
1648
- fixedAmountPerItem = new _decimal.default(productOriginTotal).minus(targetProductTotal).toNumber();
1246
+ targetProductTotal = (0, import_utils.getDiscountAmount)(
1247
+ selectedDiscount2,
1248
+ productOriginTotal,
1249
+ productOriginTotal
1250
+ );
1251
+ fixedAmountPerItem = new import_decimal.default(productOriginTotal).minus(targetProductTotal).toNumber();
1649
1252
  }
1650
-
1651
- // 计算实际折扣金额
1652
- const bundleActualDiscountAmount = new _decimal.default(productOriginTotal).minus(targetProductTotal).toNumber();
1653
-
1654
- // 🔥 使用当前的 _id 作为唯一标识
1655
1253
  const uniqueId = flatItem._id;
1656
1254
  debugger;
1657
1255
  const discountDetail = {
1658
- amount: bundleActualDiscountAmount * (product.num || 1),
1659
- type: currentBundleDiscount.tag === 'product_discount_card' ? 'discount_card' : currentBundleDiscount.tag,
1256
+ amount: fixedAmountPerItem * (product.num || 1),
1257
+ type: selectedDiscount2.tag === "product_discount_card" ? "discount_card" : selectedDiscount2.tag,
1660
1258
  discount: {
1661
- discount_card_type: currentBundleDiscount?.metadata?.discount_card_type,
1662
- fixed_amount: bundleActualDiscountAmount,
1663
- discount_calculation_mode: currentBundleDiscount?.metadata?.discount_calculation_mode,
1664
- resource_id: currentBundleDiscount.id,
1665
- title: currentBundleDiscount.format_title,
1259
+ discount_card_type: (_G = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _G.discount_card_type,
1260
+ fixed_amount: fixedAmountPerItem,
1261
+ discount_calculation_mode: (_H = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _H.discount_calculation_mode,
1262
+ resource_id: selectedDiscount2.id,
1263
+ title: selectedDiscount2.format_title,
1666
1264
  original_amount: product.original_price,
1667
1265
  product_id: product.id || product.product_id,
1668
- percent: selectedDiscount.par_value,
1669
- discount_product_id: selectedDiscount.product_id
1266
+ percent: selectedDiscount2.par_value,
1267
+ discount_product_id: selectedDiscount2.product_id
1670
1268
  },
1671
1269
  metadata: {
1672
1270
  // 🔥 使用唯一的 _id
1673
1271
  custom_product_bundle_map_id: uniqueId,
1674
- discount_rule_uncheck_flag: selectedDiscount?.discount_rule_uncheck_flag,
1272
+ discount_rule_uncheck_flag: selectedDiscount2 == null ? void 0 : selectedDiscount2.discount_rule_uncheck_flag,
1675
1273
  num: product.num || 1,
1676
1274
  // 🔥 order_level 分摊差值
1677
- ...(productDiscountDifference !== undefined && {
1678
- product_discount_difference: productDiscountDifference
1679
- })
1275
+ ...productDiscountDifference !== void 0 && { product_discount_difference: productDiscountDifference }
1680
1276
  },
1681
- config: currentBundleDiscount?.config,
1682
- _num: (product.num || 1) * (flatItem?.parentProduct?.num || 1)
1277
+ config: selectedDiscount2 == null ? void 0 : selectedDiscount2.config,
1278
+ _num: (product.num || 1) * (((_I = flatItem == null ? void 0 : flatItem.parentProduct) == null ? void 0 : _I.num) || 1)
1683
1279
  };
1684
-
1685
- // 记录实际应用的折扣
1686
- const appliedProducts = appliedDiscountProducts.get(currentBundleDiscount.id) || [];
1280
+ const appliedProducts = appliedDiscountProducts.get(selectedDiscount2.id) || [];
1687
1281
  appliedProducts.push(discountDetail);
1688
- appliedDiscountProducts.set(currentBundleDiscount.id, appliedProducts);
1282
+ appliedDiscountProducts.set(selectedDiscount2.id, appliedProducts);
1689
1283
  processedItems.push({
1690
1284
  ...flatItem,
1691
1285
  total: targetProductTotal,
1692
- price: new _decimal.default(productOriginTotal || 0).minus(fixedAmountPerItem).toNumber(),
1693
- discount_list: this.filterDiscountListByType(flatItem.discount_list, 'promotion').concat([discountDetail]),
1286
+ price: new import_decimal.default(productOriginTotal || 0).minus(fixedAmountPerItem).toNumber(),
1287
+ discount_list: this.filterDiscountListByType(flatItem.discount_list, "promotion").concat([discountDetail]),
1694
1288
  processed: true
1695
1289
  });
1696
1290
  }
1697
1291
  processedFlatItemsMap.set(flatItem._id, processedItems);
1698
1292
  }
1699
1293
  });
1700
-
1701
- // 🔥 重组:将处理后的bundle子商品重新组装回主商品
1702
- const reconstructProductsWithBundle = (processedProductsMap, processedFlatItemsMap, originalProductList) => {
1294
+ const reconstructProductsWithBundle = (processedProductsMap2, processedFlatItemsMap2, originalProductList) => {
1703
1295
  const result = [];
1704
- originalProductList.forEach(originProduct => {
1296
+ originalProductList.forEach((originProduct) => {
1705
1297
  const product = this.hooks.getProduct(originProduct);
1706
-
1707
- // 获取主商品处理结果
1708
- const mainProductArr = processedProductsMap.get(product._id);
1298
+ const mainProductArr = processedProductsMap2.get(product._id);
1709
1299
  if (!mainProductArr || mainProductArr.length === 0) {
1710
- // 如果没有处理结果,返回默认商品(还原 option 价格)
1711
1300
  const getDefaultProduct = () => {
1712
1301
  const restoredOptions = restoreOptionPrices(product.options);
1713
1302
  if (product.isClient) {
1714
1303
  return this.hooks.setProduct(originProduct, {
1715
- discount_list: this.filterDiscountListByType(product.discount_list, 'promotion'),
1304
+ discount_list: this.filterDiscountListByType(product.discount_list, "promotion"),
1716
1305
  price: product.price,
1717
- origin_total: (0, _utils2.getProductOriginTotalPrice)({
1306
+ origin_total: (0, import_utils2.getProductOriginTotalPrice)({
1718
1307
  product: {
1719
1308
  original_price: product.original_price
1720
1309
  },
@@ -1723,7 +1312,7 @@ class RulesModule extends _BaseModule.BaseModule {
1723
1312
  }),
1724
1313
  variant: originProduct._productInit.variant,
1725
1314
  original_price: originProduct._productInit.original_price,
1726
- total: (0, _utils2.getProductTotalPrice)({
1315
+ total: (0, import_utils2.getProductTotalPrice)({
1727
1316
  product: {
1728
1317
  price: product.price
1729
1318
  },
@@ -1734,7 +1323,7 @@ class RulesModule extends _BaseModule.BaseModule {
1734
1323
  });
1735
1324
  } else {
1736
1325
  return this.hooks.setProduct(originProduct, {
1737
- discount_list: this.filterDiscountListByType(product.discount_list, 'promotion'),
1326
+ discount_list: this.filterDiscountListByType(product.discount_list, "promotion"),
1738
1327
  total: product.total,
1739
1328
  origin_total: product.origin_total,
1740
1329
  price: product.price,
@@ -1745,359 +1334,325 @@ class RulesModule extends _BaseModule.BaseModule {
1745
1334
  result.push(getDefaultProduct());
1746
1335
  return;
1747
1336
  }
1748
-
1749
- // 检查是否有bundle子商品需要重组
1750
1337
  const hasBundle = product.bundle && Array.isArray(product.bundle) && product.bundle.length > 0;
1751
1338
  if (!hasBundle) {
1752
- // 没有bundle,直接使用主商品处理结果
1753
1339
  result.push(...mainProductArr);
1754
1340
  } else {
1755
- // 🔥 有bundle,需要检查子商品是否应用了商品券
1756
- // 1. 先收集所有bundle子商品的处理结果
1757
- const bundleProcessingInfo = new Map();
1758
- let hasGoodPassApplied = false; // 标记是否有子商品应用了商品券
1759
-
1341
+ const bundleProcessingInfo = /* @__PURE__ */ new Map();
1342
+ let hasGoodPassApplied = false;
1760
1343
  if (product.bundle && Array.isArray(product.bundle)) {
1761
1344
  product.bundle.forEach((bundleItem, bundleIndex) => {
1762
1345
  const bundleItemId = `${product._id}_bundle_${bundleIndex}`;
1763
- const processedBundleItems = processedFlatItemsMap.get(bundleItemId);
1346
+ const processedBundleItems = processedFlatItemsMap2.get(bundleItemId);
1764
1347
  if (!processedBundleItems || processedBundleItems.length === 0) {
1765
- // 未处理的bundle item,保持原样
1766
1348
  bundleProcessingInfo.set(bundleIndex, [bundleItem]);
1767
1349
  } else {
1768
- // 处理过的bundle item
1769
1350
  bundleProcessingInfo.set(bundleIndex, processedBundleItems);
1770
- // 🔥 检查是否应用了商品券(good_pass)
1771
- const hasGoodPass = processedBundleItems.some(item => item.discount_list?.some(discount => discount.type === 'good_pass' || discount.tag === 'good_pass'));
1351
+ const hasGoodPass = processedBundleItems.some(
1352
+ (item) => {
1353
+ var _a2;
1354
+ return (_a2 = item.discount_list) == null ? void 0 : _a2.some(
1355
+ (discount) => discount.type === "good_pass" || discount.tag === "good_pass"
1356
+ );
1357
+ }
1358
+ );
1772
1359
  if (hasGoodPass) {
1773
1360
  hasGoodPassApplied = true;
1774
1361
  }
1775
1362
  }
1776
1363
  });
1777
1364
  }
1778
-
1779
- // 🔥 2. 如果有子商品应用了商品券,且主商品数量大于1,需要拆分主商品
1780
1365
  const mainProductQuantity = mainProductArr[0] ? this.hooks.getProduct(mainProductArr[0]).quantity : 1;
1781
1366
  if (hasGoodPassApplied && mainProductArr.length === 1 && mainProductQuantity > 1) {
1782
1367
  const mainProduct = mainProductArr[0];
1783
1368
  const mainProductData = this.hooks.getProduct(mainProduct);
1784
-
1785
- // 🔥 方案:拆分成2个主商品
1786
- // 1. 一个主商品(qty=1)包含拆分后的bundle
1787
- // 2. 一个主商品(qty=原quantity-1)包含原始未拆分的bundle
1788
-
1789
- // 第一个:包含拆分后的bundle (qty=1)
1790
1369
  const newBundleWithDiscount = [];
1791
- (product.bundle || []).forEach((bundleItem, bundleIndex) => {
1792
- const processedItems = bundleProcessingInfo.get(bundleIndex) || [bundleItem];
1793
- if (processedItems.length > 1) {
1794
- // 被拆分的子商品,添加所有拆分项
1795
- processedItems.forEach(item => {
1796
- // 🔥 更新 discount_list 中的 num,使其与拆分后的 item.num 一致
1797
- const updatedDiscountList = (item.discount_list || []).map(discount => ({
1798
- ...discount,
1799
- metadata: {
1800
- ...discount.metadata,
1801
- num: item.num,
1802
- custom_product_bundle_map_id: item.metadata?.custom_product_bundle_map_id
1803
- }
1804
- // num: item.num, // 使用拆分后的 num
1805
- }));
1806
- newBundleWithDiscount.push({
1807
- ...bundleItem,
1808
- _id: item._id,
1809
- product_id: bundleItem.product_id,
1810
- price: item.price,
1811
- num: item.num,
1812
- quantity: item.num,
1813
- discount_list: updatedDiscountList
1814
- });
1815
- });
1816
- } else {
1817
- // 未拆分的子商品,保持原样
1818
- const item = processedItems[0];
1819
- if (item.processed) {
1820
- // 🔥 同样需要更新 discount_list 中的 num
1821
- const updatedDiscountList = (item.discount_list || []).map(discount => ({
1822
- ...discount,
1823
- metadata: {
1824
- ...discount.metadata,
1370
+ (product.bundle || []).forEach(
1371
+ (bundleItem, bundleIndex) => {
1372
+ const processedItems = bundleProcessingInfo.get(
1373
+ bundleIndex
1374
+ ) || [bundleItem];
1375
+ if (processedItems.length > 1) {
1376
+ processedItems.forEach((item) => {
1377
+ const updatedDiscountList2 = (item.discount_list || []).map((discount) => {
1378
+ var _a2;
1379
+ return {
1380
+ ...discount,
1381
+ metadata: {
1382
+ ...discount.metadata,
1383
+ num: item.num,
1384
+ custom_product_bundle_map_id: (_a2 = item.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id
1385
+ }
1386
+ // num: item.num, // 使用拆分后的 num
1387
+ };
1388
+ });
1389
+ newBundleWithDiscount.push({
1390
+ ...bundleItem,
1391
+ _id: item._id,
1392
+ product_id: bundleItem.product_id,
1393
+ price: item.price,
1825
1394
  num: item.num,
1826
- custom_product_bundle_map_id: item.metadata?.custom_product_bundle_map_id
1827
- }
1828
- // num: item.num, // 使用当前的 num
1829
- }));
1830
- newBundleWithDiscount.push({
1831
- ...bundleItem,
1832
- _id: item._id,
1833
- product_id: bundleItem.product_id,
1834
- price: item.price,
1835
- num: item.num,
1836
- quantity: item.num,
1837
- discount_list: updatedDiscountList
1395
+ discount_list: updatedDiscountList2
1396
+ });
1838
1397
  });
1839
1398
  } else {
1840
- newBundleWithDiscount.push(item);
1399
+ const item = processedItems[0];
1400
+ if (item.processed) {
1401
+ const updatedDiscountList2 = (item.discount_list || []).map((discount) => {
1402
+ var _a2;
1403
+ return {
1404
+ ...discount,
1405
+ metadata: {
1406
+ ...discount.metadata,
1407
+ num: item.num,
1408
+ custom_product_bundle_map_id: (_a2 = item.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id
1409
+ }
1410
+ // num: item.num, // 使用当前的 num
1411
+ };
1412
+ });
1413
+ newBundleWithDiscount.push({
1414
+ ...bundleItem,
1415
+ _id: item._id,
1416
+ product_id: bundleItem.product_id,
1417
+ price: item.price,
1418
+ num: item.num,
1419
+ discount_list: updatedDiscountList2
1420
+ });
1421
+ } else {
1422
+ newBundleWithDiscount.push(item);
1423
+ }
1841
1424
  }
1842
1425
  }
1843
- });
1844
-
1845
- // 计算第一个主商品的总价(包含拆分后的bundle)
1426
+ );
1846
1427
  let newTotalWithDiscount = Number(mainProductData.price || 0);
1847
- let newOriginTotalWithDiscount = Number(mainProductData.original_price || mainProductData.price || 0);
1848
-
1849
- // 🔥 更新主商品自己的 discount_list 中的 num(quantity=1)
1850
- const updatedMainDiscountList = mainProductData.discount_list.map(discount => {
1851
- if (discount?.metadata?.custom_product_bundle_map_id) {
1852
- // bundle的discount_list保持不变
1428
+ let newOriginTotalWithDiscount = Number(
1429
+ mainProductData.original_price || mainProductData.price || 0
1430
+ );
1431
+ const updatedMainDiscountList = mainProductData.discount_list.map((discount) => {
1432
+ var _a2, _b;
1433
+ if ((_a2 = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id) {
1853
1434
  return discount;
1854
1435
  }
1855
- // 主商品自己的discount,更新num为1
1856
1436
  return {
1857
1437
  ...discount,
1858
1438
  // num: 1,
1859
1439
  metadata: {
1860
1440
  ...discount.metadata,
1861
- custom_product_bundle_map_id: discount?.metadata?.custom_product_bundle_map_id,
1441
+ custom_product_bundle_map_id: (_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.custom_product_bundle_map_id,
1862
1442
  num: 1
1863
1443
  }
1864
1444
  };
1865
1445
  });
1866
-
1867
- // 🔥 使用更新后的列表计算折扣金额
1868
- const mainDiscountList = updatedMainDiscountList.filter(item => !item?.metadata?.custom_product_bundle_map_id);
1446
+ const mainDiscountList = updatedMainDiscountList.filter(
1447
+ (item) => {
1448
+ var _a2;
1449
+ return !((_a2 = item == null ? void 0 : item.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id);
1450
+ }
1451
+ );
1869
1452
  if (mainDiscountList && mainDiscountList.length > 0) {
1870
- const allDiscountAmount = (0, _utils.getDiscountListAmountTotal)(mainDiscountList);
1871
- newTotalWithDiscount = new _decimal.default(mainProductData.price || 0).minus(allDiscountAmount).toNumber() ?? newTotalWithDiscount;
1453
+ const allDiscountAmount = (0, import_utils.getDiscountListAmountTotal)(mainDiscountList);
1454
+ newTotalWithDiscount = new import_decimal.default(mainProductData.price || 0).minus(allDiscountAmount).toNumber() ?? newTotalWithDiscount;
1872
1455
  newOriginTotalWithDiscount = mainProductData.origin_total ?? newOriginTotalWithDiscount;
1873
1456
  }
1874
-
1875
- // 累加bundle的价格(只累加一次)
1876
1457
  if (newBundleWithDiscount.length > 0) {
1877
- newBundleWithDiscount.forEach(item => {
1458
+ newBundleWithDiscount.forEach((item) => {
1878
1459
  newTotalWithDiscount += Number(item.price) * Number(item.num);
1879
1460
  });
1880
- newBundleWithDiscount.forEach(item => {
1881
- const originalPrice = item.discount_list?.[0]?.discount?.original_amount || item.price;
1461
+ newBundleWithDiscount.forEach((item) => {
1462
+ var _a2, _b, _c;
1463
+ const originalPrice = ((_c = (_b = (_a2 = item.discount_list) == null ? void 0 : _a2[0]) == null ? void 0 : _b.discount) == null ? void 0 : _c.original_amount) || item.price;
1882
1464
  newOriginTotalWithDiscount += Number(originalPrice) * Number(item.num);
1883
1465
  });
1884
1466
  }
1885
-
1886
- // 累加options的价格(options不参与折扣,在最终设置total时处理)
1887
- if (product?.options) {
1467
+ if (product == null ? void 0 : product.options) {
1888
1468
  newTotalWithDiscount = product.options.reduce((accumulator, currentValue) => {
1889
- const currentPrice = new _decimal.default(currentValue.price || 0);
1890
- const currentNum = new _decimal.default(currentValue.num || 0);
1469
+ const currentPrice = new import_decimal.default(currentValue.price || 0);
1470
+ const currentNum = new import_decimal.default(currentValue.num || 0);
1891
1471
  return accumulator.add(currentPrice.mul(currentNum));
1892
- }, new _decimal.default(newTotalWithDiscount)).toNumber();
1472
+ }, new import_decimal.default(newTotalWithDiscount)).toNumber();
1893
1473
  }
1894
-
1895
- // 添加第一个主商品:qty=1,包含拆分后的bundle
1896
- result.push(this.hooks.setProduct(mainProduct, {
1897
- ...mainProductData,
1898
- _id: `${mainProductData._id.split('___')[0]}___split_discount`,
1899
- quantity: 1,
1900
- discount_list: updatedMainDiscountList,
1901
- bundle: newBundleWithDiscount,
1902
- total: new _decimal.default(newTotalWithDiscount).toDecimalPlaces(2, _decimal.default.ROUND_HALF_UP).toNumber(),
1903
- origin_total: new _decimal.default(newOriginTotalWithDiscount).toDecimalPlaces(2, _decimal.default.ROUND_HALF_UP).toNumber()
1904
- }));
1905
-
1906
- // 第二个:包含原始bundle (qty=原quantity-1)
1474
+ result.push(
1475
+ this.hooks.setProduct(mainProduct, {
1476
+ ...mainProductData,
1477
+ _id: `${mainProductData._id.split("___")[0]}___split_discount`,
1478
+ quantity: 1,
1479
+ discount_list: updatedMainDiscountList,
1480
+ bundle: newBundleWithDiscount,
1481
+ total: new import_decimal.default(newTotalWithDiscount).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber(),
1482
+ origin_total: new import_decimal.default(newOriginTotalWithDiscount).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber()
1483
+ })
1484
+ );
1907
1485
  if (mainProductQuantity > 1) {
1908
1486
  const newBundleOriginal = [];
1909
- (product.bundle || []).forEach((bundleItem, bundleIndex) => {
1910
- // 使用原始的bundle配置,不包含拆分
1911
- newBundleOriginal.push({
1912
- ...bundleItem,
1913
- discount_list: []
1914
- });
1915
- });
1916
-
1917
- // 计算第二个主商品的总价
1487
+ (product.bundle || []).forEach(
1488
+ (bundleItem, bundleIndex) => {
1489
+ newBundleOriginal.push({
1490
+ ...bundleItem,
1491
+ discount_list: []
1492
+ });
1493
+ }
1494
+ );
1918
1495
  let newTotalOriginal = Number(mainProductData.price || 0);
1919
- let newOriginTotalOriginal = Number(mainProductData.original_price || mainProductData.price || 0);
1920
-
1921
- // 🔥 更新主商品自己的 discount_list 中的 num(quantity=原quantity-1)
1922
- const updatedMainDiscountListOriginal = mainProductData.discount_list.map(discount => {
1923
- if (discount?.metadata?.custom_product_bundle_map_id) {
1924
- // bundle的discount_list保持不变
1496
+ let newOriginTotalOriginal = Number(
1497
+ mainProductData.original_price || mainProductData.price || 0
1498
+ );
1499
+ const updatedMainDiscountListOriginal = mainProductData.discount_list.map((discount) => {
1500
+ var _a2, _b;
1501
+ if ((_a2 = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id) {
1925
1502
  return discount;
1926
1503
  }
1927
- // 主商品自己的discount,更新num为 mainProductQuantity - 1
1928
1504
  return {
1929
1505
  ...discount,
1930
1506
  metadata: {
1931
1507
  ...discount.metadata,
1932
1508
  num: mainProductQuantity - 1,
1933
- custom_product_bundle_map_id: discount?.metadata?.custom_product_bundle_map_id
1509
+ custom_product_bundle_map_id: (_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.custom_product_bundle_map_id
1934
1510
  }
1935
1511
  // num: mainProductQuantity - 1,
1936
1512
  };
1937
1513
  });
1938
-
1939
- // 🔥 使用更新后的列表计算折扣金额
1940
- const mainDiscountListOriginal = updatedMainDiscountListOriginal.filter(item => !item?.metadata?.custom_product_bundle_map_id);
1514
+ const mainDiscountListOriginal = updatedMainDiscountListOriginal.filter(
1515
+ (item) => {
1516
+ var _a2;
1517
+ return !((_a2 = item == null ? void 0 : item.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id);
1518
+ }
1519
+ );
1941
1520
  if (mainDiscountListOriginal && mainDiscountListOriginal.length > 0) {
1942
- const allDiscountAmount = (0, _utils.getDiscountListAmount)(mainDiscountListOriginal);
1943
- newTotalOriginal = new _decimal.default(mainProductData.price || 0).minus(allDiscountAmount).toNumber() ?? newTotalOriginal;
1521
+ const allDiscountAmount = (0, import_utils.getDiscountListAmount)(
1522
+ mainDiscountListOriginal
1523
+ );
1524
+ newTotalOriginal = new import_decimal.default(mainProductData.price || 0).minus(allDiscountAmount).toNumber() ?? newTotalOriginal;
1944
1525
  newOriginTotalOriginal = mainProductData.origin_total ?? newOriginTotalOriginal;
1945
1526
  }
1946
-
1947
- // 累加bundle的价格(只累加一次)
1948
1527
  if (newBundleOriginal.length > 0) {
1949
- newBundleOriginal.forEach(item => {
1528
+ newBundleOriginal.forEach((item) => {
1950
1529
  newTotalOriginal += Number(item.price) * Number(item.num);
1951
1530
  newOriginTotalOriginal += Number(item.price) * Number(item.num);
1952
1531
  });
1953
1532
  }
1954
-
1955
- // 累加options的价格(options不参与折扣,在最终设置total时处理)
1956
- if (product?.options) {
1533
+ if (product == null ? void 0 : product.options) {
1957
1534
  newTotalOriginal = product.options.reduce((accumulator, currentValue) => {
1958
- const currentPrice = new _decimal.default(currentValue.price || 0);
1959
- const currentNum = new _decimal.default(currentValue.num || 0);
1535
+ const currentPrice = new import_decimal.default(currentValue.price || 0);
1536
+ const currentNum = new import_decimal.default(currentValue.num || 0);
1960
1537
  return accumulator.add(currentPrice.mul(currentNum));
1961
- }, new _decimal.default(newTotalOriginal)).toNumber();
1538
+ }, new import_decimal.default(newTotalOriginal)).toNumber();
1962
1539
  }
1963
- newTotalOriginal = new _decimal.default(newTotalOriginal).toDecimalPlaces(2, _decimal.default.ROUND_HALF_UP).toNumber();
1964
- newOriginTotalOriginal = new _decimal.default(newOriginTotalOriginal).toDecimalPlaces(2, _decimal.default.ROUND_HALF_UP).toNumber();
1965
-
1966
- // 添加第二个主商品:qty=原quantity-1,包含原始bundle
1967
- result.push(this.hooks.setProduct(mainProduct, {
1968
- ...mainProductData,
1969
- _id: `${mainProductData._id.split('___')[0]}___split_normal`,
1970
- quantity: mainProductQuantity - 1,
1971
- discount_list: updatedMainDiscountListOriginal,
1972
- bundle: newBundleOriginal,
1973
- total: newTotalOriginal,
1974
- origin_total: newOriginTotalOriginal
1975
- }));
1540
+ newTotalOriginal = new import_decimal.default(newTotalOriginal).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber();
1541
+ newOriginTotalOriginal = new import_decimal.default(newOriginTotalOriginal).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber();
1542
+ result.push(
1543
+ this.hooks.setProduct(mainProduct, {
1544
+ ...mainProductData,
1545
+ _id: `${mainProductData._id.split("___")[0]}___split_normal`,
1546
+ quantity: mainProductQuantity - 1,
1547
+ discount_list: updatedMainDiscountListOriginal,
1548
+ bundle: newBundleOriginal,
1549
+ total: newTotalOriginal,
1550
+ origin_total: newOriginTotalOriginal
1551
+ })
1552
+ );
1976
1553
  }
1977
1554
  } else {
1978
- // 🔥 没有子商品被拆分,使用原有逻辑
1979
- mainProductArr.forEach(mainProduct => {
1555
+ mainProductArr.forEach((mainProduct) => {
1556
+ var _a2, _b, _c;
1980
1557
  const mainProductData = this.hooks.getProduct(mainProduct);
1981
-
1982
- // 重组bundle
1983
1558
  const newBundle = [];
1984
1559
  if (product.bundle && Array.isArray(product.bundle)) {
1985
1560
  product.bundle.forEach((bundleItem, bundleIndex) => {
1986
1561
  const bundleItemId = `${product._id}_bundle_${bundleIndex}`;
1987
- const processedBundleItems = processedFlatItemsMap.get(bundleItemId);
1562
+ const processedBundleItems = processedFlatItemsMap2.get(bundleItemId);
1988
1563
  if (!processedBundleItems || processedBundleItems.length === 0) {
1989
- // 未处理的bundle item,保持原样
1990
1564
  newBundle.push(bundleItem);
1991
1565
  } else {
1992
- // 🔥 关键:拆分后的bundle item
1993
- processedBundleItems.forEach(item => {
1566
+ processedBundleItems.forEach((item) => {
1994
1567
  const nextBundlePrice = item.price ?? bundleItem.price;
1995
1568
  const nextBundleSellingPrice = item.bundle_selling_price ?? item.price ?? bundleItem.bundle_selling_price;
1996
- // 🔥 更新 discount_list 中的 num,使其与拆分后的 item.num 一致
1997
- const updatedDiscountList = (item.discount_list || []).map(discount => ({
1998
- ...discount,
1999
- metadata: {
2000
- ...discount.metadata,
2001
- num: item.num,
2002
- custom_product_bundle_map_id: discount?.metadata?.custom_product_bundle_map_id
2003
- }
2004
- // num: item.num, // 使用拆分后的 num
2005
- }));
1569
+ const updatedDiscountList2 = (item.discount_list || []).map((discount) => {
1570
+ var _a3;
1571
+ return {
1572
+ ...discount,
1573
+ metadata: {
1574
+ ...discount.metadata,
1575
+ num: item.num,
1576
+ custom_product_bundle_map_id: (_a3 = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a3.custom_product_bundle_map_id
1577
+ }
1578
+ // num: item.num, // 使用拆分后的 num
1579
+ };
1580
+ });
2006
1581
  newBundle.push({
2007
1582
  ...bundleItem,
2008
1583
  _id: item._id,
2009
1584
  product_id: bundleItem.product_id,
2010
1585
  price: nextBundlePrice,
2011
1586
  num: item.num,
2012
- discount_list: updatedDiscountList,
2013
- bundle_selling_price: bundleItem.bundle_selling_price !== undefined ? nextBundleSellingPrice : undefined
1587
+ discount_list: updatedDiscountList2,
1588
+ bundle_selling_price: bundleItem.bundle_selling_price !== void 0 ? nextBundleSellingPrice : void 0
2014
1589
  });
2015
1590
  });
2016
1591
  }
2017
1592
  });
2018
1593
  }
2019
-
2020
- // 主商品已经在前面的 setProduct 中应用过折扣;这里只替换 bundle,
2021
- // 避免把主商品 discount_list 再扣一次。
2022
1594
  const mainSellingPrice = mainProductData.main_product_selling_price ?? mainProductData.price ?? 0;
2023
1595
  let newTotal = Number(mainSellingPrice || 0);
2024
1596
  let newOriginTotal = Number(mainProductData.original_price || mainProductData.price || 0);
2025
-
2026
- // 判断是否是手动折扣
2027
- const isManualDiscount = typeof mainProductData.isManualDiscount === 'boolean' ? mainProductData.isManualDiscount : mainProductData.total != mainProductData.origin_total && (!mainProductData.discount_list?.length || mainProductData?.discount_list?.every?.(item => item.type === 'product'));
2028
-
2029
- // 如果是手动折扣,使用原有的total和origin_total,不重新计算
1597
+ const isManualDiscount = typeof mainProductData.isManualDiscount === "boolean" ? mainProductData.isManualDiscount : mainProductData.total != mainProductData.origin_total && (!((_a2 = mainProductData.discount_list) == null ? void 0 : _a2.length) || ((_c = (_b = mainProductData == null ? void 0 : mainProductData.discount_list) == null ? void 0 : _b.every) == null ? void 0 : _c.call(_b, (item) => item.type === "product")));
2030
1598
  if (isManualDiscount) {
2031
1599
  newTotal = mainProductData.total ?? newTotal;
2032
1600
  newOriginTotal = mainProductData.origin_total ?? newOriginTotal;
2033
1601
  } else {
2034
- // 累加bundle的折后价格(只累加一次)
2035
1602
  if (newBundle.length > 0) {
2036
- newBundle.forEach(item => {
2037
- newTotal += Number(item.price) * Number(item.num);
2038
- const originalPrice = item.discount_list?.[0]?.discount?.original_amount || item.price;
2039
- newOriginTotal += Number(originalPrice) * Number(item.num);
1603
+ newBundle.forEach((item) => {
1604
+ const bundleSellingPrice = item.bundle_selling_price ?? item.price;
1605
+ newTotal += Number(bundleSellingPrice) * Number(item.num);
2040
1606
  });
2041
- // 计算原始总价(不考虑折扣)
2042
- newBundle.forEach(item => {
2043
- const originalPrice = item.discount_list?.[0]?.discount?.original_amount || item.price;
1607
+ newBundle.forEach((item) => {
1608
+ var _a3, _b2, _c2;
1609
+ const originalPrice = ((_c2 = (_b2 = (_a3 = item.discount_list) == null ? void 0 : _a3[0]) == null ? void 0 : _b2.discount) == null ? void 0 : _c2.original_amount) || item.price;
2044
1610
  newOriginTotal += Number(originalPrice) * Number(item.num);
2045
1611
  });
2046
1612
  }
2047
1613
  }
2048
-
2049
- // 累加options的价格(options不参与折扣,在最终设置total时处理)
2050
- if (product?.options) {
1614
+ if (product == null ? void 0 : product.options) {
2051
1615
  newTotal = product.options.reduce((accumulator, currentValue) => {
2052
- const currentPrice = new _decimal.default(currentValue.price || 0);
2053
- const currentNum = new _decimal.default(currentValue.num || 0);
1616
+ const currentPrice = new import_decimal.default(currentValue.price || 0);
1617
+ const currentNum = new import_decimal.default(currentValue.num || 0);
2054
1618
  return accumulator.add(currentPrice.mul(currentNum));
2055
- }, new _decimal.default(newTotal)).toNumber();
1619
+ }, new import_decimal.default(newTotal)).toNumber();
2056
1620
  }
2057
- newTotal = new _decimal.default(newTotal).toDecimalPlaces(2, _decimal.default.ROUND_HALF_UP).toNumber();
2058
- newOriginTotal = new _decimal.default(newOriginTotal).toDecimalPlaces(2, _decimal.default.ROUND_HALF_UP).toNumber();
2059
-
2060
- // 生成最终的主商品
2061
- result.push(this.hooks.setProduct(mainProduct, {
2062
- ...mainProductData,
2063
- bundle: newBundle,
2064
- total: newTotal,
2065
- origin_total: newOriginTotal
2066
- }));
1621
+ newTotal = new import_decimal.default(newTotal).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber();
1622
+ newOriginTotal = new import_decimal.default(newOriginTotal).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber();
1623
+ result.push(
1624
+ this.hooks.setProduct(mainProduct, {
1625
+ ...mainProductData,
1626
+ bundle: newBundle,
1627
+ total: newTotal,
1628
+ origin_total: newOriginTotal
1629
+ })
1630
+ );
2067
1631
  });
2068
1632
  }
2069
1633
  }
2070
1634
  });
2071
1635
  return result;
2072
1636
  };
2073
-
2074
- // 按原始顺序构建处理后的商品列表
2075
- const processedProductList = reconstructProductsWithBundle(processedProductsMap, processedFlatItemsMap, productList);
2076
-
2077
- // 按原始顺序更新优惠券列表,标记已使用和可用的优惠券
2078
- const updatedDiscountList = addModeDiscount.map(discount => {
2079
- // 获取此优惠券适用的商品列表
1637
+ const processedProductList = reconstructProductsWithBundle(
1638
+ processedProductsMap,
1639
+ processedFlatItemsMap,
1640
+ productList
1641
+ );
1642
+ const updatedDiscountList = addModeDiscount.map((discount) => {
2080
1643
  const applicableProducts = discountApplicability.get(discount.id) || [];
2081
-
2082
- // 获取此优惠券适用的商品详情
2083
1644
  const applicableProductDetails = discountApplicableProducts.get(discount.id) || [];
2084
-
2085
- // 获取此优惠券实际应用的商品详情
2086
1645
  const appliedProductDetails = appliedDiscountProducts.get(discount.id) || [];
2087
-
2088
- // 根据是否有适用商品决定isAvailable
2089
1646
  const isAvailable = applicableProducts.length > 0;
2090
-
2091
- // 如果此优惠券被明确设置为不选中,保持其状态,但正确设置isAvailable
2092
- if (typeof discount.isSelected === 'boolean' && discount.isSelected === false && discount.isManualSelect) {
1647
+ if (typeof discount.isSelected === "boolean" && discount.isSelected === false && discount.isManualSelect) {
2093
1648
  return {
2094
1649
  ...discount,
2095
1650
  isSelected: false,
2096
- isAvailable: isAvailable,
1651
+ isAvailable,
2097
1652
  // 正确设置可用性
2098
1653
  applicableProductIds: applicableProducts,
2099
1654
  // 添加可抵扣的商品详情
2100
- applicableProductDetails: applicableProductDetails,
1655
+ applicableProductDetails,
2101
1656
  // 添加实际抵扣的商品详情(对于未选中的优惠券,为空数组)
2102
1657
  appliedProductDetails: []
2103
1658
  };
@@ -2106,20 +1661,18 @@ class RulesModule extends _BaseModule.BaseModule {
2106
1661
  return {
2107
1662
  ...discount,
2108
1663
  isSelected: true,
2109
- isManualSelect: options?.scan ? false : discount.isManualSelect,
1664
+ isManualSelect: (options == null ? void 0 : options.scan) ? false : discount.isManualSelect,
2110
1665
  // 标记为可用,因为它已被应用
2111
1666
  isAvailable: true,
2112
1667
  // 记录适用的商品IDs
2113
1668
  applicableProductIds: applicableProducts,
2114
1669
  // 添加可抵扣的商品详情
2115
- applicableProductDetails: applicableProductDetails,
1670
+ applicableProductDetails,
2116
1671
  // 添加实际抵扣的商品详情
2117
- appliedProductDetails: appliedProductDetails
1672
+ appliedProductDetails
2118
1673
  };
2119
1674
  }
2120
- let isSelected = typeof discount.isSelected === 'boolean' ? discount.isSelected : undefined;
2121
-
2122
- // 如果是可用的 并且没有手动标记 则设置为选中
1675
+ let isSelected = typeof discount.isSelected === "boolean" ? discount.isSelected : void 0;
2123
1676
  if (isAvailable && appliedProductDetails.length && !discount.isManualSelect) {
2124
1677
  isSelected = true;
2125
1678
  } else if (!appliedProductDetails.length) {
@@ -2128,14 +1681,14 @@ class RulesModule extends _BaseModule.BaseModule {
2128
1681
  return {
2129
1682
  ...discount,
2130
1683
  // 如果有适用的商品,标记为可用
2131
- isAvailable: isAvailable,
1684
+ isAvailable,
2132
1685
  isSelected,
2133
1686
  // 如果是扫码进来的,要手动设置为手动选择:false
2134
- isManualSelect: options?.scan ? false : discount.isManualSelect,
1687
+ isManualSelect: (options == null ? void 0 : options.scan) ? false : discount.isManualSelect,
2135
1688
  // 记录适用的商品IDs
2136
1689
  applicableProductIds: applicableProducts,
2137
1690
  // 添加可抵扣的商品详情
2138
- applicableProductDetails: applicableProductDetails,
1691
+ applicableProductDetails,
2139
1692
  // 添加实际抵扣的商品详情(对于未使用的优惠券,为空数组)
2140
1693
  appliedProductDetails: []
2141
1694
  };
@@ -2145,7 +1698,6 @@ class RulesModule extends _BaseModule.BaseModule {
2145
1698
  discountList: [...editModeDiscount, ...updatedDiscountList]
2146
1699
  };
2147
1700
  }
2148
-
2149
1701
  /**
2150
1702
  * 检查优惠是否符合 PackageSubItemUsageRules 配置
2151
1703
  * @param discount 优惠券
@@ -2153,229 +1705,105 @@ class RulesModule extends _BaseModule.BaseModule {
2153
1705
  * @returns 是否可用
2154
1706
  */
2155
1707
  checkPackageSubItemUsageRules(discount, flatItem) {
1708
+ var _a, _b, _c, _d, _e, _f, _g, _h;
2156
1709
  const limitedData = discount.limited_relation_product_data;
2157
- const usageRules = limitedData?.package_sub_item_usage_rules;
2158
- const rules = ['original_price', ...(usageRules?.rules || [])];
2159
-
2160
- // 如果没有配置 package_sub_item_usage_rules,则默认可用
1710
+ const usageRules = limitedData == null ? void 0 : limitedData.package_sub_item_usage_rules;
1711
+ const rules = ["original_price", ...(usageRules == null ? void 0 : usageRules.rules) || []];
2161
1712
  if (!usageRules) {
2162
1713
  return true;
2163
1714
  }
2164
1715
  const ruleType = usageRules.type;
2165
- // 套餐适用范围配置
2166
- const packageScope = usageRules?.package_scope;
2167
- const {
2168
- type: scopeType,
2169
- exclude_bundle_product_ids = [],
2170
- include_bundle_product_ids = [],
2171
- filter = 0
2172
- } = packageScope || {};
2173
- const isMainProduct = flatItem.type === 'main'; // 单独购买
2174
- const isBundleItem = flatItem.type === 'bundle'; // 套餐中购买
2175
- const bundleMainProductId = flatItem.product?.product_id;
2176
-
2177
- // 主商品直接可用
1716
+ const packageScope = usageRules == null ? void 0 : usageRules.package_scope;
1717
+ const { type: scopeType, exclude_bundle_product_ids = [], include_bundle_product_ids = [], filter = 0 } = packageScope || {};
1718
+ const isMainProduct = flatItem.type === "main";
1719
+ const isBundleItem = flatItem.type === "bundle";
1720
+ const bundleMainProductId = (_a = flatItem.product) == null ? void 0 : _a.product_id;
2178
1721
  if (isMainProduct) {
2179
1722
  return true;
2180
1723
  }
2181
-
2182
- // universal_discount: 单独购买和套餐中(子商品为原价)均可使用
2183
- if (ruleType === 'universal_discount') {
1724
+ if (ruleType === "universal_discount") {
2184
1725
  if (isMainProduct) {
2185
- return true; // 单独购买时可用
1726
+ return true;
2186
1727
  }
2187
1728
  if (isBundleItem) {
2188
- // 套餐中购买时,判断是否为原价
2189
- const priceType = flatItem.bundleItem?.price_type;
2190
- const priceTypeExt = flatItem.bundleItem?.price_type_ext;
2191
- // 主商品id
2192
- const mainProductId = flatItem?.originProduct?._productOrigin?.id || flatItem?.parentProduct?.id || 0;
2193
- // original_price 对应:
2194
- // 1. price_type: "markup" && price_type_ext: "product_price"
2195
- // markup_price 对应:
2196
- // price_type: "markup" && price_type_ext: ""
2197
- /** 原价 */
2198
- const isOriginalPrice = priceType === 'markup' && priceTypeExt === 'product_price';
2199
- /** 加价 */
2200
- const isMarkupPrice = priceType === 'markup' && (priceTypeExt === '' || !priceTypeExt);
2201
-
2202
- // 检查 rules
1729
+ const priceType = (_b = flatItem.bundleItem) == null ? void 0 : _b.price_type;
1730
+ const priceTypeExt = (_c = flatItem.bundleItem) == null ? void 0 : _c.price_type_ext;
1731
+ const mainProductId = ((_e = (_d = flatItem == null ? void 0 : flatItem.originProduct) == null ? void 0 : _d._productOrigin) == null ? void 0 : _e.id) || ((_f = flatItem == null ? void 0 : flatItem.parentProduct) == null ? void 0 : _f.id) || 0;
1732
+ const isOriginalPrice = priceType === "markup" && priceTypeExt === "product_price";
1733
+ const isMarkupPrice = priceType === "markup" && (priceTypeExt === "" || !priceTypeExt);
2203
1734
  if (rules.length > 0) {
2204
- const _isOriginalPrice = isOriginalPrice && rules.includes('original_price');
2205
- const _isMarkupPrice = isMarkupPrice && rules.includes('markup_price');
2206
- // 价格是否符合规则:原价或加价
1735
+ const _isOriginalPrice = isOriginalPrice && rules.includes("original_price");
1736
+ const _isMarkupPrice = isMarkupPrice && rules.includes("markup_price");
2207
1737
  const isPriceValid = _isOriginalPrice || _isMarkupPrice;
2208
- // 套餐适用范围校验
2209
1738
  let isScopeValid = false;
2210
-
2211
- // 排除套餐判断, product_all值兼容旧数据
2212
- if (scopeType === 'all_packages' || scopeType === 'product_all') {
2213
- // 所有套餐可用
1739
+ if (scopeType === "all_packages" || scopeType === "product_all") {
2214
1740
  if (!filter) {
2215
1741
  isScopeValid = true;
2216
1742
  } else {
2217
1743
  isScopeValid = !exclude_bundle_product_ids.includes(Number(bundleMainProductId));
2218
1744
  }
2219
1745
  }
2220
-
2221
- // 包含套餐判断, products值兼容旧数据
2222
- if (scopeType === 'specific_packages' || scopeType === 'products') {
1746
+ if (scopeType === "specific_packages" || scopeType === "products") {
2223
1747
  isScopeValid = include_bundle_product_ids.includes(Number(bundleMainProductId));
2224
1748
  }
2225
-
2226
- // 价格和套餐适用范围都符合,则可用
2227
1749
  if (isPriceValid && isScopeValid) {
2228
1750
  return true;
2229
1751
  }
2230
-
2231
- // 检查原价
2232
- // if (isOriginalPrice && rules.includes('original_price')) {
2233
- // return true;
2234
- // }
2235
-
2236
- // 检查加价
2237
- // if (isMarkupPrice && rules.includes('markup_price')) {
2238
- // return true;
2239
- // }
2240
-
2241
- // 如果都不匹配,则不可用
2242
1752
  return false;
2243
1753
  }
2244
-
2245
- // 原价包括:price_type: "markup" && price_type_ext: "product_price"
2246
1754
  return isOriginalPrice;
2247
1755
  }
2248
1756
  return true;
2249
1757
  }
2250
-
2251
- // package_exclusive: 仅在套餐中(子商品为原价)时可使用
2252
- if (ruleType === 'package_exclusive') {
1758
+ if (ruleType === "package_exclusive") {
2253
1759
  if (isMainProduct) {
2254
- return false; // 单独购买时不可用
1760
+ return false;
2255
1761
  }
2256
1762
  if (isBundleItem) {
2257
- // 套餐中购买时,判断是否为原价
2258
- const priceType = flatItem.bundleItem?.price_type;
2259
- const priceTypeExt = flatItem.bundleItem?.price_type_ext;
2260
-
2261
- // original_price 对应:
2262
- // 1. price_type: "markup" && price_type_ext: "product_price"
2263
- // markup_price 对应:
2264
- // price_type: "markup" && price_type_ext: ""
2265
- /** 原价 */
2266
- const isOriginalPrice = priceType === 'markup' && priceTypeExt === 'product_price';
2267
- /** 加价 */
2268
- const isMarkupPrice = priceType === 'markup' && (priceTypeExt === '' || !priceTypeExt);
2269
-
2270
- // 检查 rules
1763
+ const priceType = (_g = flatItem.bundleItem) == null ? void 0 : _g.price_type;
1764
+ const priceTypeExt = (_h = flatItem.bundleItem) == null ? void 0 : _h.price_type_ext;
1765
+ const isOriginalPrice = priceType === "markup" && priceTypeExt === "product_price";
1766
+ const isMarkupPrice = priceType === "markup" && (priceTypeExt === "" || !priceTypeExt);
2271
1767
  if (rules.length > 0) {
2272
- const _isOriginalPrice = isOriginalPrice && rules.includes('original_price');
2273
- const _isMarkupPrice = isMarkupPrice && rules.includes('markup_price');
2274
- // 价格是否符合规则:原价或加价
1768
+ const _isOriginalPrice = isOriginalPrice && rules.includes("original_price");
1769
+ const _isMarkupPrice = isMarkupPrice && rules.includes("markup_price");
2275
1770
  const isPriceValid = _isOriginalPrice || _isMarkupPrice;
2276
- // 套餐适用范围校验
2277
1771
  let isScopeValid = false;
2278
-
2279
- // 排除套餐判断, product_all值兼容旧数据
2280
- if (scopeType === 'all_packages' || scopeType === 'product_all') {
2281
- // 所有套餐可用
1772
+ if (scopeType === "all_packages" || scopeType === "product_all") {
2282
1773
  if (!filter) {
2283
1774
  isScopeValid = true;
2284
1775
  } else {
2285
1776
  isScopeValid = !exclude_bundle_product_ids.includes(Number(bundleMainProductId));
2286
1777
  }
2287
1778
  }
2288
-
2289
- // 包含套餐判断, products值兼容旧数据
2290
- if (scopeType === 'specific_packages' || scopeType === 'products') {
1779
+ if (scopeType === "specific_packages" || scopeType === "products") {
2291
1780
  isScopeValid = include_bundle_product_ids.includes(Number(bundleMainProductId));
2292
1781
  }
2293
-
2294
- // 价格和套餐适用范围都符合,则可用
2295
1782
  if (isPriceValid && isScopeValid) {
2296
1783
  return true;
2297
1784
  }
2298
-
2299
- // 检查原价
2300
- // if (isOriginalPrice && rules.includes('original_price')) {
2301
- // return true;
2302
- // }
2303
-
2304
- // 检查加价
2305
- // if (isMarkupPrice && rules.includes('markup_price')) {
2306
- // return true;
2307
- // }
2308
-
2309
- // 如果都不匹配,则不可用
2310
1785
  return false;
2311
1786
  }
2312
-
2313
- // 原价包括:price_type: "markup" && price_type_ext: "product_price"
2314
1787
  return isOriginalPrice;
2315
1788
  }
2316
1789
  return false;
2317
1790
  }
2318
-
2319
- // single_item_promo: 仅在单独购买时可使用
2320
- if (ruleType === 'single_item_promo') {
2321
- return isMainProduct; // 只有单独购买时可用
2322
- }
2323
-
2324
- /*
2325
- // custom_usage_rules: 根据自定义规则判断
2326
- if (ruleType === 'custom_usage_rules') {
2327
- const customRules = usageRules.custom_usage_rules;
2328
- if (!customRules) {
2329
- return true; // 如果没有自定义规则,默认可用
2330
- }
2331
- const { types, package_sub_item_rules } = customRules;
2332
- // 判断商品类型是否在允许的类型中
2333
- if (isMainProduct) {
2334
- // 主商品对应 standalone_product
2335
- if (!types.includes('standalone_product')) {
2336
- return false;
2337
- }
2338
- return true; // 主商品不需要判断 package_sub_item_rules
2339
- }
2340
- if (isBundleItem) {
2341
- // bundle子商品对应 package_sub_item
2342
- if (!types.includes('package_sub_item')) {
2343
- return false;
2344
- }
2345
- // 如果包含 package_sub_item,还需要判断 price_type
2346
- const priceType = flatItem.bundleItem?.price_type;
2347
- const priceTypeExt = flatItem.bundleItem?.price_type_ext;
2348
- // 检查 package_sub_item_rules
2349
- if (package_sub_item_rules && package_sub_item_rules.length > 0) {
2350
- // original_price 对应:
2351
- // 1. price_type: "markup" && price_type_ext: "product_price"
2352
- // markup_price 对应:
2353
- // price_type: "markup" && price_type_ext: ""
2354
- const isOriginalPrice = (priceType === 'markup' && priceTypeExt === 'product_price');
2355
- const isMarkupPrice = priceType === 'markup' && (priceTypeExt === '' || !priceTypeExt);
2356
- if (isOriginalPrice && package_sub_item_rules.includes('original_price')) {
2357
- return true;
2358
- }
2359
- if (isMarkupPrice && package_sub_item_rules.includes('markup_price')) {
2360
- return true;
2361
- }
2362
- // 如果都不匹配,则不可用
2363
- return false;
2364
- }
2365
- return true; // 如果没有 package_sub_item_rules 配置,默认可用
2366
- }
2367
- return true;
1791
+ if (ruleType === "single_item_promo") {
1792
+ return isMainProduct;
2368
1793
  }
2369
- * */
2370
-
2371
- // 默认可用
2372
1794
  return true;
2373
1795
  }
2374
1796
  async destroy() {
2375
1797
  this.core.effects.offByModuleDestroy(this.name);
2376
1798
  await this.core.effects.emit(`${this.name}:onDestroy`, {});
1799
+ console.log("[Rules] 已销毁");
2377
1800
  super.destroy();
2378
1801
  }
2379
- async clear() {}
2380
- }
2381
- exports.RulesModule = RulesModule;
1802
+ async clear() {
1803
+ console.log("[Rules] clear");
1804
+ }
1805
+ };
1806
+ // Annotate the CommonJS export names for ESM import in node:
1807
+ 0 && (module.exports = {
1808
+ RulesModule
1809
+ });