@pisell/pisellos 2.1.172 → 2.1.174

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 (238) hide show
  1. package/dist/apis/picoding.d.ts +0 -0
  2. package/dist/apis/picoding.js +1 -0
  3. package/dist/index.d.ts +0 -1
  4. package/dist/index.js +0 -1
  5. package/dist/model/strategy/adapter/promotion/evaluator.js +26 -99
  6. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  7. package/dist/model/strategy/adapter/walletPass/evaluator.d.ts +2 -2
  8. package/dist/model/strategy/adapter/walletPass/evaluator.js +12 -63
  9. package/dist/model/strategy/adapter/walletPass/locales.js +3 -12
  10. package/dist/model/strategy/engine.d.ts +5 -18
  11. package/dist/model/strategy/engine.js +45 -145
  12. package/dist/model/strategy/type.d.ts +0 -17
  13. package/dist/model/strategy/type.js +0 -4
  14. package/dist/modules/Cart/types.d.ts +0 -2
  15. package/dist/modules/Cart/utils/cartProduct.js +25 -56
  16. package/dist/modules/Cart/utils/changePrice.js +16 -9
  17. package/dist/modules/Discount/availability.d.ts +7 -0
  18. package/dist/modules/Discount/availability.js +52 -0
  19. package/dist/modules/Discount/entitlementPass.d.ts +34 -0
  20. package/dist/modules/Discount/entitlementPass.js +147 -0
  21. package/dist/modules/Discount/entitlementState.d.ts +8 -0
  22. package/dist/modules/Discount/entitlementState.js +205 -0
  23. package/dist/modules/Discount/index.d.ts +12 -3
  24. package/dist/modules/Discount/index.js +211 -17
  25. package/dist/modules/Discount/types.d.ts +42 -22
  26. package/dist/modules/Holder/index.d.ts +48 -0
  27. package/dist/modules/Holder/index.js +640 -0
  28. package/dist/modules/Holder/types.d.ts +123 -0
  29. package/dist/modules/Holder/types.js +1 -0
  30. package/dist/modules/Holder/utils.d.ts +13 -0
  31. package/dist/modules/Holder/utils.js +34 -0
  32. package/dist/modules/OpenData/index.d.ts +24 -0
  33. package/dist/modules/OpenData/index.js +173 -0
  34. package/dist/modules/OpenData/types.d.ts +73 -0
  35. package/dist/modules/OpenData/types.js +1 -0
  36. package/dist/modules/OpenData/utils.d.ts +2 -0
  37. package/dist/modules/OpenData/utils.js +75 -0
  38. package/dist/modules/Order/index.d.ts +67 -1
  39. package/dist/modules/Order/index.js +923 -30
  40. package/dist/modules/Order/types.d.ts +176 -12
  41. package/dist/modules/Order/types.js +2 -0
  42. package/dist/modules/Order/utils.d.ts +128 -0
  43. package/dist/modules/Order/utils.js +621 -5
  44. package/dist/modules/Payment/index.d.ts +1 -2
  45. package/dist/modules/Payment/index.js +7 -10
  46. package/dist/modules/Payment/utils.js +0 -3
  47. package/dist/modules/Payment/walletpass.d.ts +0 -23
  48. package/dist/modules/Payment/walletpass.js +95 -191
  49. package/dist/modules/Product/types.d.ts +7 -0
  50. package/dist/modules/Product/utils.js +2 -2
  51. package/dist/modules/ProductList/index.d.ts +1 -1
  52. package/dist/modules/ProductList/index.js +4 -3
  53. package/dist/modules/Quotation/index.d.ts +48 -0
  54. package/dist/modules/Quotation/index.js +248 -0
  55. package/dist/modules/Quotation/types.d.ts +42 -0
  56. package/dist/modules/Quotation/types.js +1 -0
  57. package/dist/modules/Rules/entitlementLines.d.ts +8 -0
  58. package/dist/modules/Rules/entitlementLines.js +157 -0
  59. package/dist/modules/Rules/index.d.ts +17 -11
  60. package/dist/modules/Rules/index.js +495 -726
  61. package/dist/modules/Rules/types.d.ts +2 -4
  62. package/dist/modules/SalesSummary/index.d.ts +63 -0
  63. package/dist/modules/SalesSummary/index.js +174 -0
  64. package/dist/modules/SalesSummary/types.d.ts +60 -0
  65. package/dist/modules/SalesSummary/types.js +1 -0
  66. package/dist/modules/SalesSummary/utils.d.ts +30 -0
  67. package/dist/modules/SalesSummary/utils.js +480 -0
  68. package/dist/modules/ScanOrderLogger/index.d.ts +23 -0
  69. package/dist/modules/ScanOrderLogger/index.js +174 -0
  70. package/dist/modules/ScanOrderLogger/providers/feishu.d.ts +2 -0
  71. package/dist/modules/ScanOrderLogger/providers/feishu.js +221 -0
  72. package/dist/modules/ScanOrderLogger/providers/grafana.d.ts +2 -0
  73. package/dist/modules/ScanOrderLogger/providers/grafana.js +50 -0
  74. package/dist/modules/ScanOrderLogger/types.d.ts +53 -0
  75. package/dist/modules/ScanOrderLogger/types.js +1 -0
  76. package/dist/modules/Schedule/getDateIsInSchedule.js +11 -18
  77. package/dist/modules/Schedule/utils.d.ts +1 -1
  78. package/dist/modules/Summary/types.d.ts +0 -2
  79. package/dist/modules/Summary/utils.d.ts +3 -9
  80. package/dist/modules/Summary/utils.js +67 -57
  81. package/dist/modules/index.d.ts +5 -0
  82. package/dist/modules/index.js +6 -1
  83. package/dist/plugins/window.d.ts +3 -2
  84. package/dist/solution/BookingByStep/index.d.ts +17 -3
  85. package/dist/solution/BookingByStep/index.js +322 -247
  86. package/dist/solution/BookingByStep/types.d.ts +4 -1
  87. package/dist/solution/BookingByStep/types.js +7 -1
  88. package/dist/solution/BookingByStep/utils/timeslots.d.ts +3 -1
  89. package/dist/solution/BookingByStep/utils/timeslots.js +19 -12
  90. package/dist/solution/Checkout/index.js +0 -2
  91. package/dist/solution/ScanOrder/index.d.ts +158 -0
  92. package/dist/solution/ScanOrder/index.js +3474 -0
  93. package/dist/solution/ScanOrder/types.d.ts +307 -0
  94. package/dist/solution/ScanOrder/types.js +35 -0
  95. package/dist/solution/ScanOrder/utils.d.ts +172 -0
  96. package/dist/solution/ScanOrder/utils.js +796 -0
  97. package/dist/solution/ShopDiscount/index.d.ts +6 -2
  98. package/dist/solution/ShopDiscount/index.js +194 -110
  99. package/dist/solution/ShopDiscount/types.d.ts +1 -1
  100. package/dist/solution/ShopDiscount/types.js +1 -2
  101. package/dist/solution/ShopDiscount/utils.d.ts +1 -0
  102. package/dist/solution/ShopDiscount/utils.js +52 -27
  103. package/dist/solution/VenueBooking/index.d.ts +225 -0
  104. package/dist/solution/VenueBooking/index.js +3749 -0
  105. package/dist/solution/VenueBooking/sales-section-4-annotated.json +343 -0
  106. package/dist/solution/VenueBooking/types.d.ts +156 -0
  107. package/dist/solution/VenueBooking/types.js +21 -0
  108. package/dist/solution/VenueBooking/utils/dateSummary.d.ts +11 -0
  109. package/dist/solution/VenueBooking/utils/dateSummary.js +104 -0
  110. package/dist/solution/VenueBooking/utils/resource.d.ts +14 -0
  111. package/dist/solution/VenueBooking/utils/resource.js +131 -0
  112. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +38 -0
  113. package/dist/solution/VenueBooking/utils/slotMerge.js +239 -0
  114. package/dist/solution/VenueBooking/utils/timeSlot.d.ts +32 -0
  115. package/dist/solution/VenueBooking/utils/timeSlot.js +453 -0
  116. package/dist/solution/VenueBooking/utils.d.ts +1 -0
  117. package/dist/solution/VenueBooking/utils.js +1 -0
  118. package/dist/solution/index.d.ts +2 -0
  119. package/dist/solution/index.js +3 -1
  120. package/dist/types/index.d.ts +1 -0
  121. package/lib/apis/picoding.d.ts +0 -0
  122. package/lib/apis/picoding.js +0 -0
  123. package/lib/index.d.ts +0 -1
  124. package/lib/index.js +1 -3
  125. package/lib/model/strategy/adapter/promotion/evaluator.js +8 -57
  126. package/lib/model/strategy/adapter/promotion/index.js +49 -0
  127. package/lib/model/strategy/adapter/walletPass/evaluator.d.ts +2 -2
  128. package/lib/model/strategy/adapter/walletPass/evaluator.js +7 -36
  129. package/lib/model/strategy/adapter/walletPass/locales.js +3 -12
  130. package/lib/model/strategy/engine.d.ts +5 -18
  131. package/lib/model/strategy/engine.js +21 -85
  132. package/lib/model/strategy/type.d.ts +0 -17
  133. package/lib/modules/Cart/types.d.ts +0 -2
  134. package/lib/modules/Cart/utils/cartProduct.js +12 -39
  135. package/lib/modules/Cart/utils/changePrice.js +13 -9
  136. package/lib/modules/Discount/availability.d.ts +7 -0
  137. package/lib/modules/Discount/availability.js +91 -0
  138. package/lib/modules/Discount/entitlementPass.d.ts +34 -0
  139. package/lib/modules/Discount/entitlementPass.js +184 -0
  140. package/lib/modules/Discount/entitlementState.d.ts +8 -0
  141. package/lib/modules/Discount/entitlementState.js +206 -0
  142. package/lib/modules/Discount/index.d.ts +12 -3
  143. package/lib/modules/Discount/index.js +123 -12
  144. package/lib/modules/Discount/types.d.ts +42 -22
  145. package/lib/modules/Holder/index.d.ts +48 -0
  146. package/lib/modules/Holder/index.js +402 -0
  147. package/lib/modules/Holder/types.d.ts +123 -0
  148. package/lib/modules/Holder/types.js +17 -0
  149. package/lib/modules/Holder/utils.d.ts +13 -0
  150. package/lib/modules/Holder/utils.js +71 -0
  151. package/lib/modules/OpenData/index.d.ts +24 -0
  152. package/lib/modules/OpenData/index.js +119 -0
  153. package/lib/modules/OpenData/types.d.ts +73 -0
  154. package/lib/modules/OpenData/types.js +17 -0
  155. package/lib/modules/OpenData/utils.d.ts +2 -0
  156. package/lib/modules/OpenData/utils.js +111 -0
  157. package/lib/modules/Order/index.d.ts +67 -1
  158. package/lib/modules/Order/index.js +529 -1
  159. package/lib/modules/Order/types.d.ts +176 -12
  160. package/lib/modules/Order/utils.d.ts +128 -0
  161. package/lib/modules/Order/utils.js +514 -2
  162. package/lib/modules/Payment/index.d.ts +1 -2
  163. package/lib/modules/Payment/index.js +0 -1
  164. package/lib/modules/Payment/utils.js +0 -3
  165. package/lib/modules/Payment/walletpass.d.ts +0 -23
  166. package/lib/modules/Payment/walletpass.js +17 -94
  167. package/lib/modules/Product/types.d.ts +7 -0
  168. package/lib/modules/Product/utils.js +2 -2
  169. package/lib/modules/ProductList/index.d.ts +1 -1
  170. package/lib/modules/ProductList/index.js +5 -4
  171. package/lib/modules/Quotation/index.d.ts +48 -0
  172. package/lib/modules/Quotation/index.js +152 -0
  173. package/lib/modules/Quotation/types.d.ts +42 -0
  174. package/lib/modules/Quotation/types.js +17 -0
  175. package/lib/modules/Rules/entitlementLines.d.ts +8 -0
  176. package/lib/modules/Rules/entitlementLines.js +158 -0
  177. package/lib/modules/Rules/index.d.ts +17 -11
  178. package/lib/modules/Rules/index.js +548 -798
  179. package/lib/modules/Rules/types.d.ts +2 -4
  180. package/lib/modules/SalesSummary/index.d.ts +63 -0
  181. package/lib/modules/SalesSummary/index.js +105 -0
  182. package/lib/modules/SalesSummary/types.d.ts +60 -0
  183. package/lib/modules/SalesSummary/types.js +17 -0
  184. package/lib/modules/SalesSummary/utils.d.ts +30 -0
  185. package/lib/modules/SalesSummary/utils.js +420 -0
  186. package/lib/modules/ScanOrderLogger/index.d.ts +23 -0
  187. package/lib/modules/ScanOrderLogger/index.js +147 -0
  188. package/lib/modules/ScanOrderLogger/providers/feishu.d.ts +2 -0
  189. package/lib/modules/ScanOrderLogger/providers/feishu.js +157 -0
  190. package/lib/modules/ScanOrderLogger/providers/grafana.d.ts +2 -0
  191. package/lib/modules/ScanOrderLogger/providers/grafana.js +52 -0
  192. package/lib/modules/ScanOrderLogger/types.d.ts +53 -0
  193. package/lib/modules/ScanOrderLogger/types.js +17 -0
  194. package/lib/modules/Schedule/getDateIsInSchedule.js +9 -11
  195. package/lib/modules/Schedule/utils.d.ts +1 -1
  196. package/lib/modules/Summary/types.d.ts +0 -2
  197. package/lib/modules/Summary/utils.d.ts +3 -9
  198. package/lib/modules/Summary/utils.js +45 -34
  199. package/lib/modules/index.d.ts +5 -0
  200. package/lib/modules/index.js +11 -1
  201. package/lib/plugins/window.d.ts +3 -2
  202. package/lib/solution/BookingByStep/index.d.ts +17 -3
  203. package/lib/solution/BookingByStep/index.js +45 -4
  204. package/lib/solution/BookingByStep/types.d.ts +4 -1
  205. package/lib/solution/BookingByStep/types.js +15 -0
  206. package/lib/solution/BookingByStep/utils/timeslots.d.ts +3 -1
  207. package/lib/solution/BookingByStep/utils/timeslots.js +19 -11
  208. package/lib/solution/Checkout/index.js +0 -2
  209. package/lib/solution/ScanOrder/index.d.ts +158 -0
  210. package/lib/solution/ScanOrder/index.js +2135 -0
  211. package/lib/solution/ScanOrder/types.d.ts +307 -0
  212. package/lib/solution/ScanOrder/types.js +36 -0
  213. package/lib/solution/ScanOrder/utils.d.ts +172 -0
  214. package/lib/solution/ScanOrder/utils.js +658 -0
  215. package/lib/solution/ShopDiscount/index.d.ts +6 -2
  216. package/lib/solution/ShopDiscount/index.js +94 -50
  217. package/lib/solution/ShopDiscount/types.d.ts +1 -1
  218. package/lib/solution/ShopDiscount/utils.d.ts +1 -0
  219. package/lib/solution/ShopDiscount/utils.js +48 -11
  220. package/lib/solution/VenueBooking/index.d.ts +225 -0
  221. package/lib/solution/VenueBooking/index.js +2073 -0
  222. package/lib/solution/VenueBooking/sales-section-4-annotated.json +343 -0
  223. package/lib/solution/VenueBooking/types.d.ts +156 -0
  224. package/lib/solution/VenueBooking/types.js +44 -0
  225. package/lib/solution/VenueBooking/utils/dateSummary.d.ts +11 -0
  226. package/lib/solution/VenueBooking/utils/dateSummary.js +110 -0
  227. package/lib/solution/VenueBooking/utils/resource.d.ts +14 -0
  228. package/lib/solution/VenueBooking/utils/resource.js +92 -0
  229. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +38 -0
  230. package/lib/solution/VenueBooking/utils/slotMerge.js +237 -0
  231. package/lib/solution/VenueBooking/utils/timeSlot.d.ts +32 -0
  232. package/lib/solution/VenueBooking/utils/timeSlot.js +339 -0
  233. package/lib/solution/VenueBooking/utils.d.ts +1 -0
  234. package/lib/solution/VenueBooking/utils.js +69 -0
  235. package/lib/solution/index.d.ts +2 -0
  236. package/lib/solution/index.js +5 -1
  237. package/lib/types/index.d.ts +1 -0
  238. package/package.json +1 -1
@@ -1,8 +1,3 @@
1
- var _excluded = ["_original_add_price"],
2
- _excluded2 = ["_original_price", "_original_add_price"];
3
- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
4
- function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
5
- function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
6
1
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
7
2
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
8
3
  function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
@@ -12,6 +7,7 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o =
12
7
  function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
13
8
  function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
14
9
  function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
10
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
15
11
  function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
16
12
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
17
13
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
@@ -35,6 +31,14 @@ import { getProductOriginTotalPrice, getProductTotalPrice } from "../Cart/utils"
35
31
  import Decimal from 'decimal.js';
36
32
  import { isBoolean } from 'lodash-es';
37
33
  import dayjs from 'dayjs';
34
+ import { WalletPassEvaluator } from "../../model/strategy/adapter/walletPass/evaluator";
35
+ import { compareEntitlementPassPriority, getRemainingEntitlementUses, isEntitlementPass, isFullCoveragePass, resolveEntitlementQuota } from "../Discount/entitlementPass";
36
+ import { getDiscountUsageBlockReason, getDiscountUsageLimitFailKey } from "../Discount/availability";
37
+ import { withCommittedEntitlementDetails, isPersistedEntitlementLine } from "../Discount/entitlementState";
38
+ import { getDiscountTimeUnavailableReason } from "../../solution/ShopDiscount/utils";
39
+ import { cloneDeep } from 'lodash-es';
40
+ import { prepareEntitlementLines, finalizeEntitlementLines, isEntitlementRuntimeLine, rebuildEntitlementLine } from "./entitlementLines";
41
+
38
42
  // 临时变量
39
43
  var flatItem;
40
44
  export var RulesModule = /*#__PURE__*/function (_BaseModule) {
@@ -47,13 +51,24 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
47
51
  _defineProperty(_assertThisInitialized(_this), "defaultName", 'rules');
48
52
  _defineProperty(_assertThisInitialized(_this), "defaultVersion", '1.0.0');
49
53
  _defineProperty(_assertThisInitialized(_this), "store", void 0);
50
- _defineProperty(_assertThisInitialized(_this), "window", void 0);
51
- // WindowPlugin 实例
52
54
  _defineProperty(_assertThisInitialized(_this), "hooks", void 0);
55
+ _defineProperty(_assertThisInitialized(_this), "entitlementPassEnabled", false);
56
+ _defineProperty(_assertThisInitialized(_this), "defaultWalletPassEvaluator", void 0);
53
57
  _this.hooks = {};
54
58
  return _this;
55
59
  }
56
60
  _createClass(RulesModule, [{
61
+ key: "setEntitlementPassEnabled",
62
+ value: function setEntitlementPassEnabled(enabled) {
63
+ this.entitlementPassEnabled = enabled;
64
+ }
65
+ }, {
66
+ key: "getWalletPassEvaluator",
67
+ value: function getWalletPassEvaluator() {
68
+ var _this$core, _this$core$getWalletP, _this$defaultWalletPa;
69
+ return ((_this$core = this.core) === null || _this$core === void 0 || (_this$core = _this$core.getPlugin('window')) === null || _this$core === void 0 || (_this$core$getWalletP = _this$core.getWalletPassEvaluator) === null || _this$core$getWalletP === void 0 ? void 0 : _this$core$getWalletP.call(_this$core)) || ((_this$defaultWalletPa = this.defaultWalletPassEvaluator) !== null && _this$defaultWalletPa !== void 0 ? _this$defaultWalletPa : this.defaultWalletPassEvaluator = new WalletPassEvaluator());
70
+ }
71
+ }, {
57
72
  key: "initialize",
58
73
  value: function () {
59
74
  var _initialize = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(core, options) {
@@ -63,8 +78,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
63
78
  this.core = core;
64
79
  this.hooks = options === null || options === void 0 ? void 0 : options.hooks;
65
80
  this.store = options === null || options === void 0 ? void 0 : options.store;
66
- this.window = core.getPlugin('window');
67
- case 4:
81
+ case 3:
68
82
  case "end":
69
83
  return _context.stop();
70
84
  }
@@ -101,42 +115,69 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
101
115
  value: function getRulesList() {
102
116
  return this.store.rulesList;
103
117
  }
118
+ }, {
119
+ key: "normalizeHolderRecordIds",
120
+ value: function normalizeHolderRecordIds(value) {
121
+ var records = Array.isArray(value) ? value : [value];
122
+ return Array.from(new Set(records.map(function (record) {
123
+ if (record && _typeof(record) === 'object') {
124
+ return record.form_record_id;
125
+ }
126
+ return record;
127
+ }).filter(function (record) {
128
+ return record !== undefined && record !== null && record !== '' && record !== 0 && record !== '0';
129
+ }).map(String)));
130
+ }
104
131
 
105
- // 商品不需要holder,则不需要判断,直接返回true,商品需要holder但是还没填写,那么暂时不使用带有holder的券,直到填写才去匹配
132
+ /**
133
+ * 商品未开启 Holder 选择时跳过匹配;已开启时,特定 form Holder 卡
134
+ * 只适用于同一 Holder Record,是否必填不影响匹配规则。
135
+ */
106
136
  }, {
107
137
  key: "checkHolderMatch",
108
- value: function checkHolderMatch(discount, product, holders) {
109
- var _discount$holder;
138
+ value: function checkHolderMatch(discount, product, holderSource, holders) {
139
+ var _discount$holder, _ref, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9, _ref10, _holderSource$holder_, _holderSource$metadat, _holderSource$origin, _holderSource$metadat2, _holderSource$_origin, _holderSource$_origin2, _holderSource$_origin3, _holderSource$_produc, _holderSource$_produc2, _holderSource$_extend, _holderSource$_extend2, _holderSource$_extend3;
110
140
  // 非表单类型 holder 视为匹配
111
141
  if (((_discount$holder = discount.holder) === null || _discount$holder === void 0 ? void 0 : _discount$holder.holder_type) !== 'form') return true;
112
- // 主预约holder, 目前(20251124)默认只考虑单个holder的情况
113
- var orderHolderId = Array.isArray(holders) && holders.length > 0 ? holders[0].form_record_id : undefined;
114
- var productHolderId = Array.isArray(product.holder_id) ? product.holder_id[0] : product.holder_id;
115
- // 商品不需要选holder,则不对比holder,直接返回true,
116
- if (!product.isNeedHolder) return true;
117
- // 商品需要holder,但父预约及商品都无holder,返回false
118
- if (!orderHolderId && !productHolderId) return false;
119
- // 最终直接匹配 holder 是否相同
120
- return (productHolderId || orderHolderId) === discount.holder.holder_id;
121
- }
122
- }, {
123
- key: "getWalletPassEvaluator",
124
- value: function getWalletPassEvaluator() {
125
- var _this$window$getWalle, _this$window;
126
- return (_this$window$getWalle = (_this$window = this.window).getWalletPassEvaluator) === null || _this$window$getWalle === void 0 ? void 0 : _this$window$getWalle.call(_this$window);
142
+
143
+ // 旧券沿用预约主体和单个 Holder 的匹配口径。
144
+ if (!isEntitlementPass(discount)) {
145
+ if (!product.isNeedHolder) return true;
146
+ var holder = holders === null || holders === void 0 ? void 0 : holders[0];
147
+ var orderHolderId = holder && _typeof(holder) === 'object' ? holder.form_record_id : holder;
148
+ var productHolderId = Array.isArray(product.holder_id) ? product.holder_id[0] : product.holder_id;
149
+ if (!orderHolderId && !productHolderId) return false;
150
+ return (productHolderId || orderHolderId) === discount.holder.holder_id;
151
+ }
152
+
153
+ // getProduct 会裁剪商品字段,从原始商品读取配置,套餐子项沿用父商品。
154
+ var holderConfig = (_ref = (_ref2 = (_ref3 = (_ref4 = (_ref5 = (_ref6 = (_ref7 = (_ref8 = (_ref9 = (_ref10 = (_holderSource$holder_ = holderSource === null || holderSource === void 0 ? void 0 : holderSource.holder_config) !== null && _holderSource$holder_ !== void 0 ? _holderSource$holder_ : holderSource === null || holderSource === void 0 || (_holderSource$metadat = holderSource.metadata) === null || _holderSource$metadat === void 0 ? void 0 : _holderSource$metadat.holder_config) !== null && _ref10 !== void 0 ? _ref10 : holderSource === null || holderSource === void 0 || (_holderSource$origin = holderSource.origin) === null || _holderSource$origin === void 0 ? void 0 : _holderSource$origin.holder_config) !== null && _ref9 !== void 0 ? _ref9 : holderSource === null || holderSource === void 0 || (_holderSource$metadat2 = holderSource.metadata) === null || _holderSource$metadat2 === void 0 || (_holderSource$metadat2 = _holderSource$metadat2.origin) === null || _holderSource$metadat2 === void 0 ? void 0 : _holderSource$metadat2.holder_config) !== null && _ref8 !== void 0 ? _ref8 : holderSource === null || holderSource === void 0 || (_holderSource$_origin = holderSource._origin) === null || _holderSource$_origin === void 0 ? void 0 : _holderSource$_origin.holder_config) !== null && _ref7 !== void 0 ? _ref7 : holderSource === null || holderSource === void 0 || (_holderSource$_origin2 = holderSource._origin) === null || _holderSource$_origin2 === void 0 || (_holderSource$_origin2 = _holderSource$_origin2.product) === null || _holderSource$_origin2 === void 0 ? void 0 : _holderSource$_origin2.holder_config) !== null && _ref6 !== void 0 ? _ref6 : holderSource === null || holderSource === void 0 || (_holderSource$_origin3 = holderSource._originData) === null || _holderSource$_origin3 === void 0 || (_holderSource$_origin3 = _holderSource$_origin3.product) === null || _holderSource$_origin3 === void 0 ? void 0 : _holderSource$_origin3.holder_config) !== null && _ref5 !== void 0 ? _ref5 : holderSource === null || holderSource === void 0 || (_holderSource$_produc = holderSource._productInit) === null || _holderSource$_produc === void 0 ? void 0 : _holderSource$_produc.holder_config) !== null && _ref4 !== void 0 ? _ref4 : holderSource === null || holderSource === void 0 || (_holderSource$_produc2 = holderSource._productOrigin) === null || _holderSource$_produc2 === void 0 ? void 0 : _holderSource$_produc2.holder_config) !== null && _ref3 !== void 0 ? _ref3 : holderSource === null || holderSource === void 0 || (_holderSource$_extend = holderSource._extend) === null || _holderSource$_extend === void 0 ? void 0 : _holderSource$_extend.holder_config) !== null && _ref2 !== void 0 ? _ref2 : holderSource === null || holderSource === void 0 || (_holderSource$_extend2 = holderSource._extend) === null || _holderSource$_extend2 === void 0 || (_holderSource$_extend2 = _holderSource$_extend2.product) === null || _holderSource$_extend2 === void 0 ? void 0 : _holderSource$_extend2.holder_config) !== null && _ref !== void 0 ? _ref : holderSource === null || holderSource === void 0 || (_holderSource$_extend3 = holderSource._extend) === null || _holderSource$_extend3 === void 0 || (_holderSource$_extend3 = _holderSource$_extend3.product) === null || _holderSource$_extend3 === void 0 || (_holderSource$_extend3 = _holderSource$_extend3.metadata) === null || _holderSource$_extend3 === void 0 ? void 0 : _holderSource$_extend3.holder_config;
155
+ var holderStatus = holderConfig === null || holderConfig === void 0 ? void 0 : holderConfig.status;
156
+ var holderEnabled = holderStatus == null || holderStatus === '' || holderStatus === true || ['enable', '1'].includes(String(holderStatus).trim().toLowerCase());
157
+ if (!holderEnabled || !(holderConfig !== null && holderConfig !== void 0 && holderConfig.resource_id)) {
158
+ return true;
159
+ }
160
+ var discountHolderIds = this.normalizeHolderRecordIds(discount.holder.holder_id);
161
+ if (!discountHolderIds.length) return false;
162
+ var productHolderIds = this.normalizeHolderRecordIds(product.holder_id);
163
+ var candidateHolderIds = productHolderIds.length || Array.isArray(product.holder_id) ? productHolderIds : this.normalizeHolderRecordIds(holders);
164
+ if (!candidateHolderIds.length) return false;
165
+ var discountHolderIdSet = new Set(discountHolderIds);
166
+ return candidateHolderIds.every(function (holderId) {
167
+ return discountHolderIdSet.has(holderId);
168
+ });
127
169
  }
128
170
 
129
171
  // 判断discountList 是否可以对当前productList生效
130
172
  }, {
131
173
  key: "isDiscountListAvailable",
132
- value: function isDiscountListAvailable(_ref) {
174
+ value: function isDiscountListAvailable(_ref11) {
133
175
  var _this2 = this;
134
- var oldDiscountList = _ref.oldDiscountList,
135
- newDiscountList = _ref.newDiscountList,
136
- productList = _ref.productList,
137
- orderTotalAmount = _ref.orderTotalAmount,
138
- holders = _ref.holders,
139
- isFormSubject = _ref.isFormSubject;
176
+ var oldDiscountList = _ref11.oldDiscountList,
177
+ newDiscountList = _ref11.newDiscountList,
178
+ productList = _ref11.productList,
179
+ holders = _ref11.holders,
180
+ isFormSubject = _ref11.isFormSubject;
140
181
  // 首先检查是否有新的优惠券可应用
141
182
  if (!newDiscountList || newDiscountList.length === 0) {
142
183
  return {
@@ -147,7 +188,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
147
188
  }
148
189
 
149
190
  // 编辑商品已有商品券
150
- if (productList.every(function (item) {
191
+ if (!newDiscountList.some(isEntitlementPass) && productList.length > 0 && productList.every(function (item) {
151
192
  var _product$discount_lis;
152
193
  var product = _this2.hooks.getProduct(item);
153
194
  return product.booking_id && (((_product$discount_lis = product.discount_list) === null || _product$discount_lis === void 0 ? void 0 : _product$discount_lis.length) || product.total == 0);
@@ -165,11 +206,10 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
165
206
  var filteredOldDiscountList = oldDiscountList.filter(function (discount) {
166
207
  return !discount.isEditMode && (discount.tag !== 'good_pass' || discount.isScan);
167
208
  });
168
- var mergedDiscountList = uniqueById([].concat(_toConsumableArray(filteredOldDiscountList), _toConsumableArray(newDiscountList)));
209
+ var mergedDiscountList = uniqueById([].concat(_toConsumableArray(newDiscountList.filter(isEntitlementPass)), _toConsumableArray(filteredOldDiscountList), _toConsumableArray(newDiscountList)));
169
210
  var result = this.calcDiscount({
170
211
  discountList: mergedDiscountList,
171
- productList: _toConsumableArray(productList),
172
- orderTotalAmount: orderTotalAmount,
212
+ productList: this.entitlementPassEnabled ? cloneDeep(productList) : _toConsumableArray(productList),
173
213
  holders: holders,
174
214
  isFormSubject: isFormSubject
175
215
  }, {
@@ -178,15 +218,16 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
178
218
 
179
219
  // 检查是否有产品使用了新折扣
180
220
  var hasApplicableDiscount = false;
181
- var newDiscountIds = newDiscountList.map(function (discount) {
182
- return discount.id;
183
- });
221
+ var newDiscountIds = new Set(newDiscountList.map(function (discount) {
222
+ return String(discount.id);
223
+ }));
184
224
 
185
225
  // 遍历处理后的产品列表,检查是否有产品使用了新折扣
186
226
  result.productList.forEach(function (product) {
187
- var _this2$hooks$getProdu = _this2.hooks.getProduct(product),
188
- discount_list = _this2$hooks$getProdu.discount_list,
189
- bundle = _this2$hooks$getProdu.bundle;
227
+ var mappedProduct = _this2.hooks.getProduct(product);
228
+ if (isPersistedEntitlementLine(product, mappedProduct)) return;
229
+ var discount_list = mappedProduct.discount_list,
230
+ bundle = mappedProduct.bundle;
190
231
  var allDiscountList = _toConsumableArray(discount_list || []);
191
232
  (bundle || []).forEach(function (item) {
192
233
  allDiscountList.push.apply(allDiscountList, _toConsumableArray((item === null || item === void 0 ? void 0 : item.discount_list) || []));
@@ -195,7 +236,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
195
236
  // 检查是否有使用新折扣的情况
196
237
  var usedNewDiscount = allDiscountList.some(function (discount) {
197
238
  var _discount$discount;
198
- return newDiscountIds.includes(discount === null || discount === void 0 || (_discount$discount = discount.discount) === null || _discount$discount === void 0 ? void 0 : _discount$discount.resource_id);
239
+ return newDiscountIds.has(String(discount === null || discount === void 0 || (_discount$discount = discount.discount) === null || _discount$discount === void 0 ? void 0 : _discount$discount.resource_id));
199
240
  });
200
241
  if (usedNewDiscount) {
201
242
  hasApplicableDiscount = true;
@@ -210,6 +251,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
210
251
  }
211
252
  return {
212
253
  isAvailable: hasApplicableDiscount,
254
+ evaluatedDiscountList: result.discountList,
213
255
  discountList: hasApplicableDiscount ? result.discountList : oldDiscountList,
214
256
  productList: hasApplicableDiscount ? result.productList : productList,
215
257
  unavailableReason: unavailableReason
@@ -239,7 +281,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
239
281
  for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
240
282
  var item = _step3.value;
241
283
  var product = this.hooks.getProduct(item);
242
- var bookingTime = ((product === null || product === void 0 ? void 0 : product.startDate) || dayjs()).format('YYYY-MM-DD HH:mm:ss');
284
+ var bookingTime = dayjs((product === null || product === void 0 ? void 0 : product.startDate) || undefined).format('YYYY-MM-DD HH:mm:ss');
243
285
  var filteredList = filterDiscountListByBookingTime([discount], bookingTime);
244
286
  if (filteredList.length === 0) {
245
287
  return UnavailableReason.TimeLimit;
@@ -264,6 +306,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
264
306
  for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
265
307
  var _discount = _step2.value;
266
308
  var limitedData = _discount.limited_relation_product_data;
309
+ if (!limitedData) return UnavailableReason.ProductNotApplicable;
267
310
  var hasApplicableProduct = false;
268
311
  var _iterator4 = _createForOfIteratorHelper(productList),
269
312
  _step4;
@@ -298,20 +341,68 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
298
341
  }
299
342
  }, {
300
343
  key: "calcDiscount",
301
- value: function calcDiscount(_ref2, options) {
344
+ value: function calcDiscount(_ref12, options) {
302
345
  var _this3 = this;
303
- var discountList = _ref2.discountList,
304
- productList = _ref2.productList,
305
- holders = _ref2.holders,
306
- isFormSubject = _ref2.isFormSubject,
307
- orderTotalAmount = _ref2.orderTotalAmount;
346
+ var discountList = _ref12.discountList,
347
+ productList = _ref12.productList,
348
+ holders = _ref12.holders,
349
+ isFormSubject = _ref12.isFormSubject;
350
+ discountList = this.entitlementPassEnabled ? withCommittedEntitlementDetails(discountList, productList, this.hooks.getProduct) : discountList.filter(function (item) {
351
+ return !isEntitlementPass(item);
352
+ });
353
+ var usableEntitlements = discountList.filter(function (discount) {
354
+ return isEntitlementPass(discount) && !discount.isEditMode && !discount.isManualSelect && !getDiscountUsageBlockReason(discount);
355
+ });
356
+ var canUseEntitlement = function canUseEntitlement(originProduct) {
357
+ var _product$original_pri;
358
+ var product = _this3.hooks.getProduct(originProduct);
359
+ // 预判任一份可用就按份拆开,实际抵扣仍逐份核对 Holder。
360
+ var holderProducts = Array.isArray(product.holder_id) && product.holder_id.length > 1 ? product.holder_id.map(function (holder_id) {
361
+ return _objectSpread(_objectSpread({}, product), {}, {
362
+ holder_id: holder_id
363
+ });
364
+ }) : [product];
365
+ var items = [{
366
+ type: 'main',
367
+ id: product.id,
368
+ price: (_product$original_pri = product.original_price) !== null && _product$original_pri !== void 0 ? _product$original_pri : product.price
369
+ }].concat(_toConsumableArray((product.bundle || []).map(function (bundleItem) {
370
+ var _ref13, _bundleItem$_bundle_p, _bundleItem$original_;
371
+ return {
372
+ type: 'bundle',
373
+ id: (_ref13 = (_bundleItem$_bundle_p = bundleItem._bundle_product_id) !== null && _bundleItem$_bundle_p !== void 0 ? _bundleItem$_bundle_p : bundleItem.bundle_product_id) !== null && _ref13 !== void 0 ? _ref13 : bundleItem.product_id,
374
+ price: (_bundleItem$original_ = bundleItem.original_price) !== null && _bundleItem$original_ !== void 0 ? _bundleItem$original_ : bundleItem.price,
375
+ bundleItem: bundleItem
376
+ };
377
+ })));
378
+ return usableEntitlements.some(function (discount) {
379
+ var scope = discount.limited_relation_product_data;
380
+ if (!scope || !holderProducts.some(function (item) {
381
+ return _this3.checkHolderMatch(discount, item, originProduct, holders);
382
+ }) || !filterDiscountListByBookingTime([discount], dayjs(product.startDate || undefined).format('YYYY-MM-DD HH:mm:ss')).length) return false;
383
+ return items.some(function (item) {
384
+ var _scope$exclude_produc, _scope$product_ids;
385
+ return Number(item.price) > 0 && (scope.type === 'product_all' ? !(scope.filter === 1 && (_scope$exclude_produc = scope.exclude_product_ids) !== null && _scope$exclude_produc !== void 0 && _scope$exclude_produc.some(function (id) {
386
+ return String(id) === String(item.id);
387
+ })) : !!((_scope$product_ids = scope.product_ids) !== null && _scope$product_ids !== void 0 && _scope$product_ids.includes(item.id))) && _this3.checkPackageSubItemUsageRules(discount, _objectSpread(_objectSpread({}, item), {}, {
388
+ originProduct: originProduct,
389
+ parentProduct: product
390
+ }));
391
+ });
392
+ });
393
+ };
394
+ if (this.entitlementPassEnabled) productList = prepareEntitlementLines(productList, this.hooks, canUseEntitlement);
308
395
  var editModeDiscount = [];
309
396
  var addModeDiscount = [];
310
397
  discountList.forEach(function (discount) {
311
398
  if (discount.isEditMode) {
312
399
  editModeDiscount.push(discount);
313
400
  } else {
314
- addModeDiscount.push(discount);
401
+ addModeDiscount.push(isEntitlementPass(discount) ? _objectSpread(_objectSpread({}, discount), {}, {
402
+ config: undefined,
403
+ reason: undefined,
404
+ reasonCode: undefined
405
+ }) : discount);
315
406
  }
316
407
  });
317
408
 
@@ -362,6 +453,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
362
453
  // 2. 展开 bundle 子商品
363
454
  if (product.bundle && Array.isArray(product.bundle) && product.bundle.length > 0) {
364
455
  product.bundle.forEach(function (bundleItem, bundleIndex) {
456
+ var _ref14, _bundleItem$_bundle_p2;
365
457
  flattened.push({
366
458
  type: 'bundle',
367
459
  originProduct: originProduct,
@@ -370,8 +462,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
370
462
  bundleIndex: bundleIndex,
371
463
  // 虚拟商品属性
372
464
  price: Number(bundleItem.price || 0),
373
- id: bundleItem._bundle_product_id,
374
- // 🔥 使用 _bundle_product_id
465
+ id: (_ref14 = (_bundleItem$_bundle_p2 = bundleItem._bundle_product_id) !== null && _bundleItem$_bundle_p2 !== void 0 ? _bundleItem$_bundle_p2 : bundleItem.bundle_product_id) !== null && _ref14 !== void 0 ? _ref14 : bundleItem.product_id,
375
466
  _id: "".concat(product._id, "_bundle_").concat(bundleIndex),
376
467
  parentId: product._id,
377
468
  num: bundleItem.num || 1,
@@ -477,6 +568,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
477
568
  }
478
569
  return 0;
479
570
  }
571
+ if (isEntitlementPass(a) || isEntitlementPass(b)) {
572
+ return isEntitlementPass(a) && isEntitlementPass(b) ? compareEntitlementPassPriority(a, b) : isEntitlementPass(a) ? -1 : 1;
573
+ }
480
574
 
481
575
  // 1. 先按优先级排序
482
576
  var priorityA = getPriority(a);
@@ -528,10 +622,10 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
528
622
 
529
623
  // 对扁平化后的列表按价格降序排序(用于应用优惠券时优先选择高价商品)
530
624
  var sortedFlattenedList = flattenedList.sort(function (a, b) {
531
- var _ref3, _a$original_price, _ref4, _b$original_price;
625
+ var _ref15, _a$original_price, _ref16, _b$original_price;
532
626
  // 子商品优先使用 original_price,主商品使用 price
533
- var priceA = new Decimal(a.type === 'bundle' ? (_ref3 = (_a$original_price = a.original_price) !== null && _a$original_price !== void 0 ? _a$original_price : a.price) !== null && _ref3 !== void 0 ? _ref3 : '0' : a.price || '0');
534
- var priceB = new Decimal(b.type === 'bundle' ? (_ref4 = (_b$original_price = b.original_price) !== null && _b$original_price !== void 0 ? _b$original_price : b.price) !== null && _ref4 !== void 0 ? _ref4 : '0' : b.price || '0');
627
+ var priceA = new Decimal(a.type === 'bundle' ? (_ref15 = (_a$original_price = a.original_price) !== null && _a$original_price !== void 0 ? _a$original_price : a.price) !== null && _ref15 !== void 0 ? _ref15 : '0' : a.price || '0');
628
+ var priceB = new Decimal(b.type === 'bundle' ? (_ref16 = (_b$original_price = b.original_price) !== null && _b$original_price !== void 0 ? _b$original_price : b.price) !== null && _ref16 !== void 0 ? _ref16 : '0' : b.price || '0');
535
629
  if (priceA.equals(priceB)) {
536
630
  // 价格相同时,主商品优先
537
631
  if (a.type !== b.type) {
@@ -553,62 +647,18 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
553
647
  return priceB.minus(priceA).toNumber();
554
648
  });
555
649
 
556
- // 🔥 为每个折扣卡/商品券执行策略检查并附加config
557
- var evaluator = this.getWalletPassEvaluator();
558
- if (evaluator) {
559
- addModeDiscount.forEach(function (discount) {
560
- var discountType = discount.tag || discount.type;
561
- // 只对 good_pass 和 discount_card 类型执行策略检查
562
- if (['good_pass', 'discount_card', 'product_discount_card'].includes(discountType)) {
563
- var _discount$limited_rel, _discount$limited_rel2;
564
- // 转换 discount 为 Voucher 格式
565
- var voucher = {
566
- id: discount.id,
567
- amount: Number(discount.par_value || 0),
568
- balance: Number(discount.balance || 0),
569
- type: discountType,
570
- product_id: discount.product_id,
571
- unified_available_status: 1,
572
- available_product_type: (_discount$limited_rel = discount.limited_relation_product_data) === null || _discount$limited_rel === void 0 ? void 0 : _discount$limited_rel.type,
573
- available_product_ids: (_discount$limited_rel2 = discount.limited_relation_product_data) === null || _discount$limited_rel2 === void 0 ? void 0 : _discount$limited_rel2.product_ids
574
- };
575
-
576
- // 转换 sortedFlattenedList 为 Product 格式
577
- var productsForEvaluate = sortedFlattenedList.map(function (item) {
578
- var _item$product;
579
- return {
580
- product_id: item.id,
581
- price: item.price || 0,
582
- quantity: item.quantity || item.num || 1,
583
- selling_price: item.price || 0,
584
- product_options: item.type === 'main' ? (_item$product = item.product) === null || _item$product === void 0 ? void 0 : _item$product.options : undefined
585
- };
586
- });
587
-
588
- // 调用策略检查
589
- var result = evaluator.checkVoucherAvailability({
590
- orderTotalAmount: orderTotalAmount,
591
- products: productsForEvaluate,
592
- vouchers: [voucher]
593
- });
594
-
595
- // 将 config 附加到 discount 对象
596
- if (result.isAvailable) {
597
- discount.config = _objectSpread(_objectSpread({}, result.config), {}, {
598
- isAvailable: true
599
- });
600
- } else {
601
- discount.config = {
602
- isAvailable: false
603
- };
604
- }
605
- }
650
+ // 检查商品是否被排除(全品类)
651
+ var isProductIncludedByLimitedData = function isProductIncludedByLimitedData(limitedData, productId) {
652
+ var excludedIds = (limitedData === null || limitedData === void 0 ? void 0 : limitedData.exclude_product_ids) || [];
653
+ var isExcluded = (limitedData === null || limitedData === void 0 ? void 0 : limitedData.filter) === 1 && excludedIds.some(function (id) {
654
+ return String(id) === String(productId);
606
655
  });
607
- }
656
+ return !isExcluded;
657
+ };
608
658
 
609
659
  /**
610
- // 对productList按价格降序排序(用于应用优惠券时优先选择高价商品) 价格相同时使用quantity 排序
611
- const sortedProductList = [...productList].sort((a, b) => {
660
+ // 对productList按价格降序排序(用于应用优惠券时优先选择高价商品) 价格相同时使用quantity 排序
661
+ const sortedProductList = [...productList].sort((a, b) => {
612
662
  const aProduct = this.hooks.getProduct(a);
613
663
  const bProduct = this.hooks.getProduct(b);
614
664
  const priceA = new Decimal((aProduct.price as string) || '0');
@@ -623,24 +673,93 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
623
673
  });
624
674
  */
625
675
 
626
- // 标记已使用的优惠券
676
+ // 旧券沿用一次性标记;多次卡按卡 ID 累计本次分配数量。
627
677
  var usedDiscounts = new Map();
628
-
629
- // 🔥 统计每个 product_id(商品券商品id)已使用的数量,用于 maxUsagePerOrder 限制
678
+ var entitlementUsageCounts = new Map();
630
679
  var usedProductIdCounts = new Map();
680
+ var markDiscountUsed = function markDiscountUsed(discount) {
681
+ if (isEntitlementPass(discount)) {
682
+ entitlementUsageCounts.set(discount.id, (entitlementUsageCounts.get(discount.id) || 0) + 1);
683
+ } else {
684
+ usedDiscounts.set(discount.id, true);
685
+ }
686
+ usedProductIdCounts.set(discount.product_id, (usedProductIdCounts.get(discount.product_id) || 0) + 1);
687
+ };
631
688
 
632
- // 🔥 统计每张折扣卡的 applicableProductLimit 已使用次数(跨商品全局计数)
633
- var usedDiscountCardLimitCounts = new Map();
634
-
635
- // 🔥 预先将 editModeDiscount 中的折扣卡计入 applicableProductLimit 已使用次数
636
- editModeDiscount.forEach(function (discount) {
637
- var discountType = discount.tag || discount.type;
638
- if (['discount_card', 'product_discount_card'].includes(discountType)) {
639
- var _discount$metadata4;
640
- var currentCount = usedDiscountCardLimitCounts.get(discount.id) || 0;
641
- usedDiscountCardLimitCounts.set(discount.id, currentCount + (((_discount$metadata4 = discount.metadata) === null || _discount$metadata4 === void 0 ? void 0 : _discount$metadata4.num) || 1));
689
+ // 沿用商品券逐份拆分,同一多次卡可重复分配,数量受本单剩余额度限制。
690
+ var getFullCoveragePasses = function getFullCoveragePasses(discounts, quantity) {
691
+ var allocated = [];
692
+ var productCounts = new Map(usedProductIdCounts);
693
+ var _iterator5 = _createForOfIteratorHelper(discounts),
694
+ _step5;
695
+ try {
696
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
697
+ var _discount$config;
698
+ var discount = _step5.value;
699
+ if (!isFullCoveragePass(discount) || allocated.length >= quantity) continue;
700
+ var count = isEntitlementPass(discount) ? getRemainingEntitlementUses(discount, entitlementUsageCounts.get(discount.id) || 0, quantity - allocated.length) : usedDiscounts.get(discount.id) ? 0 : 1;
701
+ var limit = Number(((_discount$config = discount.config) === null || _discount$config === void 0 ? void 0 : _discount$config.maxUsagePerOrder) || 0);
702
+ if (isEntitlementPass(discount) && limit > 0) {
703
+ count = Math.min(count, Math.max(0, Math.floor(limit) - (productCounts.get(discount.product_id) || 0)));
704
+ }
705
+ for (var i = 0; i < count; i++) allocated.push(discount);
706
+ productCounts.set(discount.product_id, (productCounts.get(discount.product_id) || 0) + count);
707
+ }
708
+ } catch (err) {
709
+ _iterator5.e(err);
710
+ } finally {
711
+ _iterator5.f();
712
+ }
713
+ return allocated;
714
+ };
715
+ var evaluator;
716
+ addModeDiscount.filter(isEntitlementPass).forEach(function (discount) {
717
+ var _evaluator, _discount$unified_ava, _discount$limited_rel, _discount$limited_rel2;
718
+ discount.usageLimitFailKey = getDiscountUsageLimitFailKey(discount);
719
+ discount.reasonCode = getDiscountUsageBlockReason(discount);
720
+ var quota = resolveEntitlementQuota(discount);
721
+ if (discount.reasonCode || !quota) {
722
+ discount.config = {
723
+ isAvailable: false
724
+ };
725
+ return;
726
+ }
727
+ (_evaluator = evaluator) !== null && _evaluator !== void 0 ? _evaluator : evaluator = _this3.getWalletPassEvaluator();
728
+ var result = evaluator.checkVoucherAvailability({
729
+ orderTotalAmount: productList.reduce(function (sum, item) {
730
+ var product = _this3.hooks.getProduct(item);
731
+ return sum.plus(new Decimal(product.origin_total || 0).times(product.quantity || product.num || 1));
732
+ }, new Decimal(0)).toNumber(),
733
+ // 策略按统一商品结构读主价与数量,套餐次数还需乘父商品份数。
734
+ products: sortedFlattenedList.map(function (item) {
735
+ var _item$parentProduct, _item$parentProduct2, _item$product;
736
+ return {
737
+ product_id: item.id,
738
+ price: item.price || 0,
739
+ main_product_selling_price: item.price || 0,
740
+ quantity: (item.quantity || item.num || 1) * (item.type === 'bundle' ? ((_item$parentProduct = item.parentProduct) === null || _item$parentProduct === void 0 ? void 0 : _item$parentProduct.quantity) || ((_item$parentProduct2 = item.parentProduct) === null || _item$parentProduct2 === void 0 ? void 0 : _item$parentProduct2.num) || 1 : 1),
741
+ product_options: item.type === 'main' ? (_item$product = item.product) === null || _item$product === void 0 ? void 0 : _item$product.options : undefined
742
+ };
743
+ }),
744
+ vouchers: [_objectSpread(_objectSpread({}, discount), {}, {
745
+ amount: Number(discount.par_value || 0),
746
+ balance: quota.type === 'unlimited' ? Number.MAX_SAFE_INTEGER : quota.balance,
747
+ type: 'entitlement_pass',
748
+ unified_available_status: (_discount$unified_ava = discount.unified_available_status) !== null && _discount$unified_ava !== void 0 ? _discount$unified_ava : 1,
749
+ available_product_type: (_discount$limited_rel = discount.limited_relation_product_data) === null || _discount$limited_rel === void 0 ? void 0 : _discount$limited_rel.type,
750
+ available_product_ids: (_discount$limited_rel2 = discount.limited_relation_product_data) === null || _discount$limited_rel2 === void 0 ? void 0 : _discount$limited_rel2.product_ids
751
+ })]
752
+ });
753
+ discount.config = _objectSpread(_objectSpread({}, result.config), {}, {
754
+ isAvailable: result.isAvailable
755
+ });
756
+ if (!result.isAvailable) {
757
+ discount.reason = result.reason;
758
+ discount.reasonCode = result.reasonCode || 'not_meet_the_required_conditions';
642
759
  }
643
760
  });
761
+ var entitlementTimeReasons = new Map();
762
+ var entitlementHolderMismatch = new Set();
644
763
 
645
764
  // 记录每个优惠券适用的商品ID
646
765
  var discountApplicability = new Map();
@@ -686,7 +805,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
686
805
 
687
806
  // 编辑的商品使用了优惠券不可用
688
807
  var isAvailableProduct = flatItem.type === 'main' ? !((_product2 = product) !== null && _product2 !== void 0 && _product2.booking_id && (_product3 = product) !== null && _product3 !== void 0 && (_product3 = _product3.discount_list) !== null && _product3 !== void 0 && _product3.length && (_product4 = product) !== null && _product4 !== void 0 && (_product4 = _product4.discount_list) !== null && _product4 !== void 0 && _product4.every(function (d) {
689
- return d.id && ['good_pass', 'discount_card', 'product_discount_card'].includes(d.tag || d.type);
808
+ return d.id && ['entitlement_pass', 'good_pass', 'discount_card', 'product_discount_card'].includes(d.tag || d.type);
690
809
  })) : !(flatItem !== null && flatItem !== void 0 && flatItem.booking_id && !!(flatItem !== null && flatItem !== void 0 && (_flatItem$bundleItem = flatItem.bundleItem) !== null && _flatItem$bundleItem !== void 0 && (_flatItem$bundleItem = _flatItem$bundleItem.discount_list) !== null && _flatItem$bundleItem !== void 0 && _flatItem$bundleItem.length) && flatItem !== null && flatItem !== void 0 && (_flatItem$bundleItem2 = flatItem.bundleItem) !== null && _flatItem$bundleItem2 !== void 0 && (_flatItem$bundleItem2 = _flatItem$bundleItem2.discount_list) !== null && _flatItem$bundleItem2 !== void 0 && _flatItem$bundleItem2.every(function (d) {
691
810
  return d.id;
692
811
  }));
@@ -706,7 +825,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
706
825
  var limitedData = discount.limited_relation_product_data;
707
826
 
708
827
  // 时间限制检查
709
- var timeLimit = !!filterDiscountListByBookingTime([discount], (((_product5 = product) === null || _product5 === void 0 ? void 0 : _product5.startDate) || dayjs()).format('YYYY-MM-DD HH:mm:ss')).length;
828
+ var timeLimit = !!filterDiscountListByBookingTime([discount], dayjs(((_product5 = product) === null || _product5 === void 0 ? void 0 : _product5.startDate) || undefined).format('YYYY-MM-DD HH:mm:ss')).length;
710
829
  if (!timeLimit) {
711
830
  return false;
712
831
  }
@@ -787,7 +906,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
787
906
  // 收集该折扣卡适用的商品(排除被其他专属折扣卡占用的商品)
788
907
  var applicableProducts = [];
789
908
  sortedFlattenedList.forEach(function (flatItem) {
790
- var _flatItem$parentProdu2, _flatItem$parentProdu3, _product$price, _ref5, _flatItem$original_pr;
909
+ var _flatItem$parentProdu2, _flatItem$parentProdu3, _product$price, _ref17, _flatItem$original_pr;
791
910
  // 🔥 检查该商品是否被其他专属折扣卡占用
792
911
  var occupyingDiscountId = occupiedItems.get(flatItem._id);
793
912
  if (occupyingDiscountId !== undefined && occupyingDiscountId !== discount.id) {
@@ -815,7 +934,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
815
934
 
816
935
  // 对于主商品:使用 price
817
936
  // 对于子商品:优先使用 flatItem.original_price,否则使用 flatItem.price
818
- var originalAmount = flatItem.type === 'main' ? Number((_product$price = product.price) !== null && _product$price !== void 0 ? _product$price : 0) : Number((_ref5 = (_flatItem$original_pr = flatItem.original_price) !== null && _flatItem$original_pr !== void 0 ? _flatItem$original_pr : flatItem.price) !== null && _ref5 !== void 0 ? _ref5 : 0);
937
+ var originalAmount = flatItem.type === 'main' ? Number((_product$price = product.price) !== null && _product$price !== void 0 ? _product$price : 0) : Number((_ref17 = (_flatItem$original_pr = flatItem.original_price) !== null && _flatItem$original_pr !== void 0 ? _flatItem$original_pr : flatItem.price) !== null && _ref17 !== void 0 ? _ref17 : 0);
819
938
 
820
939
  // 传递 parentQuantity 用于差值处理时判断是否是真正的"数量为1"
821
940
  var productData = {
@@ -857,7 +976,6 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
857
976
  var _flatItem$parentProdu5;
858
977
  // bundle子商品:构造虚拟商品对象
859
978
  product = {
860
- startDate: flatItem === null || flatItem === void 0 || (_flatItem$parentProdu5 = flatItem.parentProduct) === null || _flatItem$parentProdu5 === void 0 ? void 0 : _flatItem$parentProdu5.startDate,
861
979
  _id: flatItem._id,
862
980
  id: flatItem.id,
863
981
  price: flatItem.price,
@@ -866,27 +984,38 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
866
984
  total: flatItem.total,
867
985
  origin_total: flatItem.origin_total,
868
986
  booking_id: flatItem.booking_id,
869
- discount_list: flatItem.discount_list || []
987
+ discount_list: flatItem.discount_list || [],
988
+ startDate: (_flatItem$parentProdu5 = flatItem.parentProduct) === null || _flatItem$parentProdu5 === void 0 ? void 0 : _flatItem$parentProdu5.startDate
870
989
  };
871
990
  originProduct = flatItem.originProduct;
872
991
  }
873
992
  addModeDiscount.forEach(function (discount) {
874
- var _product6, _product7, _product8, _product9, _flatItem$bundleItem3, _flatItem$bundleItem4, _discount$config;
993
+ var _discount$config2, _product6, _limitedData$exclude_2, _product7, _product8, _product9, _flatItem$bundleItem3, _flatItem$bundleItem4;
875
994
  var limitedData = discount === null || discount === void 0 ? void 0 : discount.limited_relation_product_data;
995
+ if (!limitedData || isEntitlementPass(discount) && ((_discount$config2 = discount.config) === null || _discount$config2 === void 0 ? void 0 : _discount$config2.isAvailable) === false) return;
996
+
876
997
  // 拿到discount配置的holder信息 product信息 product.holder 加在 isLimitedProduct
877
998
  var _tempVar = (flatItem === null || flatItem === void 0 ? void 0 : flatItem.type) === 'bundle' ? flatItem === null || flatItem === void 0 ? void 0 : flatItem.parentProduct : flatItem === null || flatItem === void 0 ? void 0 : flatItem.product;
878
999
  var isHolderMatch = _this3.checkHolderMatch(discount, {
879
1000
  isNeedHolder: isFormSubject && !(_tempVar !== null && _tempVar !== void 0 && _tempVar.isNormalProduct),
880
1001
  holder_id: (_tempVar === null || _tempVar === void 0 ? void 0 : _tempVar.holder_id) || product.holder_id
881
- }, holders);
1002
+ }, flatItem.originProduct, holders);
882
1003
  var timeLimit = true;
883
- timeLimit = !!filterDiscountListByBookingTime([discount], (((_product6 = product) === null || _product6 === void 0 ? void 0 : _product6.startDate) || dayjs()).format('YYYY-MM-DD HH:mm:ss')).length;
1004
+ var useTime = dayjs(((_product6 = product) === null || _product6 === void 0 ? void 0 : _product6.startDate) || undefined).format('YYYY-MM-DD HH:mm:ss');
1005
+ timeLimit = !!filterDiscountListByBookingTime([discount], useTime).length;
1006
+ if (isEntitlementPass(discount)) {
1007
+ var reason = getDiscountTimeUnavailableReason(discount, useTime);
1008
+ var reasons = entitlementTimeReasons.get(discount.id) || [];
1009
+ reasons.push(reason);
1010
+ entitlementTimeReasons.set(discount.id, reasons);
1011
+ if (!isHolderMatch) entitlementHolderMismatch.add(discount.id);
1012
+ }
884
1013
  // 是符合折扣的商品
885
- var 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;
1014
+ var isLimitedProduct = (limitedData.type === 'product_all' && !(limitedData.filter === 1 && (_limitedData$exclude_2 = limitedData.exclude_product_ids) !== null && _limitedData$exclude_2 !== void 0 && _limitedData$exclude_2.includes(product.id)) || limitedData.product_ids && limitedData.product_ids.includes(product.id)) && isHolderMatch;
886
1015
 
887
1016
  // 编辑的商品 使用了优惠券不可用
888
1017
  var isAvailableProduct = flatItem.type === 'main' ? !((_product7 = product) !== null && _product7 !== void 0 && _product7.booking_id && (_product8 = product) !== null && _product8 !== void 0 && (_product8 = _product8.discount_list) !== null && _product8 !== void 0 && _product8.length && (_product9 = product) !== null && _product9 !== void 0 && (_product9 = _product9.discount_list) !== null && _product9 !== void 0 && _product9.every(function (discount) {
889
- return discount.id && ['good_pass', 'discount_card', 'product_discount_card'].includes(discount.tag || discount.type);
1018
+ return discount.id && ['entitlement_pass', 'good_pass', 'discount_card', 'product_discount_card'].includes(discount.tag || discount.type);
890
1019
  })) : !(flatItem !== null && flatItem !== void 0 && flatItem.booking_id && !!(flatItem !== null && flatItem !== void 0 && (_flatItem$bundleItem3 = flatItem.bundleItem) !== null && _flatItem$bundleItem3 !== void 0 && (_flatItem$bundleItem3 = _flatItem$bundleItem3.discount_list) !== null && _flatItem$bundleItem3 !== void 0 && _flatItem$bundleItem3.length) && flatItem !== null && flatItem !== void 0 && (_flatItem$bundleItem4 = flatItem.bundleItem) !== null && _flatItem$bundleItem4 !== void 0 && (_flatItem$bundleItem4 = _flatItem$bundleItem4.discount_list) !== null && _flatItem$bundleItem4 !== void 0 && _flatItem$bundleItem4.every(function (discount) {
891
1020
  return discount.id;
892
1021
  }));
@@ -895,15 +1024,15 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
895
1024
  var isBundleAvailable = _this3.checkPackageSubItemUsageRules(discount, flatItem);
896
1025
 
897
1026
  // 判断优惠券是否适用于该商品
898
- if (isAvailableProduct && isLimitedProduct && timeLimit && isBundleAvailable && (_discount$config = discount.config) !== null && _discount$config !== void 0 && _discount$config.isAvailable) {
899
- var _discountApplicabilit, _discount$metadata5, _discount$metadata6;
1027
+ if (isAvailableProduct && !isPersistedEntitlementLine(originProduct, flatItem.type === 'main' ? flatItem.product : flatItem.parentProduct) && isLimitedProduct && isBundleAvailable && timeLimit) {
1028
+ var _discountApplicabilit, _discount$metadata4, _discount$metadata5;
900
1029
  // 记录此优惠券适用的商品
901
1030
  (_discountApplicabilit = discountApplicability.get(discount.id)) === null || _discountApplicabilit === void 0 || _discountApplicabilit.push(product.id);
902
1031
 
903
1032
  // 记录可抵扣的商品详情
904
1033
  var applicableProducts = discountApplicableProducts.get(discount.id) || [];
905
1034
  var discountType = discount.tag || discount.type;
906
- var isGoodPass = discountType === 'good_pass';
1035
+ var isGoodPass = isFullCoveragePass(discount);
907
1036
 
908
1037
  // 使用数量
909
1038
  var num = isGoodPass || (flatItem === null || flatItem === void 0 ? void 0 : flatItem.type) === 'main' ? 1 : product.num;
@@ -912,15 +1041,14 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
912
1041
  type: discountType,
913
1042
  tag: discountType,
914
1043
  discount: {
915
- discount_card_type: discount === null || discount === void 0 || (_discount$metadata5 = discount.metadata) === null || _discount$metadata5 === void 0 ? void 0 : _discount$metadata5.discount_card_type,
1044
+ discount_card_type: discount === null || discount === void 0 || (_discount$metadata4 = discount.metadata) === null || _discount$metadata4 === void 0 ? void 0 : _discount$metadata4.discount_card_type,
916
1045
  fixed_amount: product.price,
917
- discount_calculation_mode: discount === null || discount === void 0 || (_discount$metadata6 = discount.metadata) === null || _discount$metadata6 === void 0 ? void 0 : _discount$metadata6.discount_calculation_mode,
1046
+ discount_calculation_mode: discount === null || discount === void 0 || (_discount$metadata5 = discount.metadata) === null || _discount$metadata5 === void 0 ? void 0 : _discount$metadata5.discount_calculation_mode,
918
1047
  resource_id: discount.id,
919
1048
  title: discount.format_title,
920
1049
  original_amount: product.price || product.origin_total,
921
1050
  pre_value: discount.par_value,
922
- product_id: originProduct.id,
923
- discount_product_id: discount.product_id
1051
+ product_id: product.id
924
1052
  },
925
1053
  metadata: {
926
1054
  num: num,
@@ -936,75 +1064,19 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
936
1064
  // 🔥 用于存储扁平化商品处理结果的Map
937
1065
  var processedFlatItemsMap = new Map();
938
1066
 
939
- // 🔥 Option 折扣辅助函数
940
- var applyDiscountToOptions = function applyDiscountToOptions(options, discount) {
941
- if (!(options !== null && options !== void 0 && options.length)) return {
942
- discountedOptions: options,
943
- optionDiscountAmount: 0
944
- };
945
- var optionDiscountAmount = 0;
946
- var discountedOptions = options.map(function (option) {
947
- var _ref6, _ref7, _option$_original_pri, _ref8, _option$num, _rest$price, _option$_original_pri2;
948
- // 折前单价:优先 price,缺失再 add_price;已写回折后价时用 _original_price(或旧字段 _original_add_price)
949
- var rawUnit = (_ref6 = (_ref7 = (_option$_original_pri = option._original_price) !== null && _option$_original_pri !== void 0 ? _option$_original_pri : option._original_add_price) !== null && _ref7 !== void 0 ? _ref7 : option.price) !== null && _ref6 !== void 0 ? _ref6 : option.add_price;
950
- var baseUnitNum = Number(rawUnit !== null && rawUnit !== void 0 ? rawUnit : 0);
951
- if (baseUnitNum <= 0) return option;
952
- var discountedPrice = getDiscountAmount(discount, baseUnitNum, baseUnitNum);
953
- var optQty = Number((_ref8 = (_option$num = option.num) !== null && _option$num !== void 0 ? _option$num : option.quantity) !== null && _ref8 !== void 0 ? _ref8 : 1);
954
- optionDiscountAmount = new Decimal(optionDiscountAmount).plus(new Decimal(baseUnitNum).minus(discountedPrice).mul(optQty)).toNumber();
955
- var _original_add_price = option._original_add_price,
956
- rest = _objectWithoutProperties(option, _excluded);
957
- var tmpl = (_rest$price = rest.price) !== null && _rest$price !== void 0 ? _rest$price : rest.add_price;
958
- var nextPrice = typeof tmpl === 'string' ? String(discountedPrice) : discountedPrice;
959
- return _objectSpread(_objectSpread({}, rest), {}, {
960
- _original_price: (_option$_original_pri2 = option._original_price) !== null && _option$_original_pri2 !== void 0 ? _option$_original_pri2 : _original_add_price !== undefined ? _original_add_price : rawUnit,
961
- price: nextPrice
962
- });
963
- });
964
- return {
965
- discountedOptions: discountedOptions,
966
- optionDiscountAmount: optionDiscountAmount
967
- };
968
- };
969
- var restoreOptionPrices = function restoreOptionPrices(options) {
970
- if (!(options !== null && options !== void 0 && options.length)) return options;
971
- return options.map(function (option) {
972
- var orig = option._original_price !== undefined ? option._original_price : option._original_add_price;
973
- if (orig !== undefined) {
974
- var _original_price = option._original_price,
975
- _original_add_price = option._original_add_price,
976
- rest = _objectWithoutProperties(option, _excluded2);
977
- return _objectSpread(_objectSpread({}, rest), {}, {
978
- price: orig
979
- });
980
- }
981
- return option;
982
- });
983
- };
984
- var getOptionTotal = function getOptionTotal(options) {
985
- if (!(options !== null && options !== void 0 && options.length)) return 0;
986
- return options.reduce(function (sum, opt) {
987
- var _ref9, _opt$price, _ref10, _opt$num;
988
- var unit = Number((_ref9 = (_opt$price = opt.price) !== null && _opt$price !== void 0 ? _opt$price : opt.add_price) !== null && _ref9 !== void 0 ? _ref9 : 0);
989
- var n = Number((_ref10 = (_opt$num = opt.num) !== null && _opt$num !== void 0 ? _opt$num : opt.quantity) !== null && _ref10 !== void 0 ? _ref10 : 1);
990
- return new Decimal(sum).plus(new Decimal(unit).mul(n)).toNumber();
991
- }, 0);
992
- };
993
-
994
1067
  // 然后再处理应用哪些优惠券,此时只考虑filteredDiscountList中的优惠券
995
1068
  // 🔥 使用扁平化后的列表进行处理
996
1069
  sortedFlattenedList.forEach(function (flatItem, index) {
997
- var _product10, _product$discount_lis2, _product11, _selectedDiscount$con;
1070
+ var _product10, _product$discount_lis2, _product11;
998
1071
  // 获取商品数据
999
1072
  var product, originProduct;
1000
1073
  if (flatItem.type === 'main') {
1001
1074
  product = flatItem.product;
1002
1075
  originProduct = flatItem.originProduct;
1003
1076
  } else {
1004
- var _flatItem$parentProdu6, _flatItem$bundleItem5, _flatItem$bundleItem6, _flatItem$bundleItem7;
1077
+ var _flatItem$bundleItem5, _flatItem$bundleItem6, _flatItem$bundleItem7, _flatItem$parentProdu6;
1005
1078
  // bundle子商品
1006
1079
  product = {
1007
- startDate: flatItem === null || flatItem === void 0 || (_flatItem$parentProdu6 = flatItem.parentProduct) === null || _flatItem$parentProdu6 === void 0 ? void 0 : _flatItem$parentProdu6.startDate,
1008
1080
  _id: flatItem._id,
1009
1081
  id: flatItem.id,
1010
1082
  price: flatItem.price,
@@ -1014,14 +1086,15 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1014
1086
  original_price: flatItem === null || flatItem === void 0 || (_flatItem$bundleItem5 = flatItem.bundleItem) === null || _flatItem$bundleItem5 === void 0 ? void 0 : _flatItem$bundleItem5.original_price,
1015
1087
  origin_total: flatItem === null || flatItem === void 0 || (_flatItem$bundleItem6 = flatItem.bundleItem) === null || _flatItem$bundleItem6 === void 0 ? void 0 : _flatItem$bundleItem6.original_price,
1016
1088
  booking_id: flatItem.booking_id,
1017
- discount_list: (flatItem === null || flatItem === void 0 || (_flatItem$bundleItem7 = flatItem.bundleItem) === null || _flatItem$bundleItem7 === void 0 ? void 0 : _flatItem$bundleItem7.discount_list) || []
1089
+ discount_list: (flatItem === null || flatItem === void 0 || (_flatItem$bundleItem7 = flatItem.bundleItem) === null || _flatItem$bundleItem7 === void 0 ? void 0 : _flatItem$bundleItem7.discount_list) || [],
1090
+ startDate: (_flatItem$parentProdu6 = flatItem.parentProduct) === null || _flatItem$parentProdu6 === void 0 ? void 0 : _flatItem$parentProdu6.startDate
1018
1091
  };
1019
1092
  originProduct = flatItem.originProduct;
1020
1093
  }
1021
1094
 
1022
1095
  // 已有优惠的商品跳过
1023
- if ((_product10 = product) !== null && _product10 !== void 0 && _product10.booking_id && (_product$discount_lis2 = product.discount_list) !== null && _product$discount_lis2 !== void 0 && _product$discount_lis2.length && (_product11 = product) !== null && _product11 !== void 0 && (_product11 = _product11.discount_list) !== null && _product11 !== void 0 && _product11.every(function (discount) {
1024
- return discount.id && ['good_pass', 'discount_card', 'product_discount_card'].includes(discount.tag || discount.type);
1096
+ if (isPersistedEntitlementLine(originProduct, flatItem.type === 'main' ? flatItem.product : flatItem.parentProduct) || (_product10 = product) !== null && _product10 !== void 0 && _product10.booking_id && (_product$discount_lis2 = product.discount_list) !== null && _product$discount_lis2 !== void 0 && _product$discount_lis2.length && (_product11 = product) !== null && _product11 !== void 0 && (_product11 = _product11.discount_list) !== null && _product11 !== void 0 && _product11.every(function (discount) {
1097
+ return discount.id && ['entitlement_pass', 'good_pass', 'discount_card', 'product_discount_card'].includes(discount.tag || discount.type);
1025
1098
  })) {
1026
1099
  if (flatItem.type === 'main') {
1027
1100
  processedProductsMap.set(product._id, [originProduct]);
@@ -1035,75 +1108,43 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1035
1108
 
1036
1109
  // 找到适用于此商品的所有优惠券,仅考虑isSelected不为false的优惠券
1037
1110
  var applicableDiscounts = sortedDiscountList.filter(function (discount) {
1038
- var _product$discount_lis3, _product$discount_lis4;
1039
- // 🔥 检查策略可用性(针对 good_pass 和折扣卡)
1040
- var discountType = discount.tag || discount.type;
1041
- if (['good_pass', 'discount_card', 'product_discount_card'].includes(discountType)) {
1042
- var _discount$config2;
1043
- // 如果策略检查后没有config,说明不可用
1044
- if (discount.config === undefined || !(discount !== null && discount !== void 0 && (_discount$config2 = discount.config) !== null && _discount$config2 !== void 0 && _discount$config2.isAvailable)) {
1045
- return false;
1046
- }
1047
- }
1048
-
1111
+ var _discount$config3, _discount$config4, _discount$config5, _product$discount_lis3, _product$discount_lis4;
1112
+ if (isEntitlementPass(discount) && (((_discount$config3 = discount.config) === null || _discount$config3 === void 0 ? void 0 : _discount$config3.isAvailable) === false || getRemainingEntitlementUses(discount, entitlementUsageCounts.get(discount.id) || 0, 1) <= 0 || Number((_discount$config4 = discount.config) === null || _discount$config4 === void 0 ? void 0 : _discount$config4.maxUsagePerOrder) > 0 && (usedProductIdCounts.get(discount.product_id) || 0) >= Number((_discount$config5 = discount.config) === null || _discount$config5 === void 0 ? void 0 : _discount$config5.maxUsagePerOrder))) return false;
1049
1113
  // 如果商品价格为 0,其实不需要使用任何优惠券,直接 return true
1050
1114
  // 商品券时主商品价格为0不可用
1051
- if ((Number(product.price) <= 0 || !product.price) && !((_product$discount_lis3 = product.discount_list) !== null && _product$discount_lis3 !== void 0 && _product$discount_lis3.length) && (discount.tag || discount.type) === 'good_pass') return false;
1115
+ if ((Number(product.price) <= 0 || !product.price) && !((_product$discount_lis3 = product.discount_list) !== null && _product$discount_lis3 !== void 0 && _product$discount_lis3.length) && isFullCoveragePass(discount)) return false;
1052
1116
 
1053
1117
  // 折扣卡商品价格为0时不可用
1054
- if ((Number(product.total) <= 0 || !product.total) && !((_product$discount_lis4 = product.discount_list) !== null && _product$discount_lis4 !== void 0 && _product$discount_lis4.find(function (n) {
1118
+ if ((Number(product.price) <= 0 || !product.price) && !((_product$discount_lis4 = product.discount_list) !== null && _product$discount_lis4 !== void 0 && _product$discount_lis4.find(function (n) {
1055
1119
  var _n$discount;
1056
1120
  return ((_n$discount = n.discount) === null || _n$discount === void 0 ? void 0 : _n$discount.resource_id) === discount.id;
1057
- })) && (discount.tag || discount.type) !== 'good_pass') return false;
1121
+ })) && !isFullCoveragePass(discount)) return false;
1058
1122
  // 如果优惠券已被使用,则跳过
1059
1123
  var targetUsedDiscounts = usedDiscounts.get(discount.id);
1060
1124
  if (targetUsedDiscounts && (discount.tag || discount.type) === 'good_pass') return false;
1061
-
1062
- // 🔥 检查 maxUsagePerOrder 限制:同一 product_id 的商品券使用数量不能超过配置值
1063
- if ((discount.tag || discount.type) === 'good_pass') {
1064
- var _discount$config3;
1065
- var maxUsagePerOrder = (_discount$config3 = discount.config) === null || _discount$config3 === void 0 ? void 0 : _discount$config3.maxUsagePerOrder;
1066
- if (maxUsagePerOrder && maxUsagePerOrder > 0) {
1067
- var currentUsedCount = usedProductIdCounts.get(discount.product_id) || 0;
1068
- if (currentUsedCount >= maxUsagePerOrder) {
1069
- return false;
1070
- }
1071
- }
1072
- }
1073
-
1074
- // 🔥 检查折扣卡的 applicableProductLimit 限制:折扣卡可使用的最大次数(跨商品全局)
1075
- var discountTypeForLimit = discount.tag || discount.type;
1076
- if (['discount_card', 'product_discount_card'].includes(discountTypeForLimit)) {
1077
- var _discount$config4;
1078
- var applicableProductLimitConfig = ((_discount$config4 = discount.config) === null || _discount$config4 === void 0 ? void 0 : _discount$config4.applicableProductLimit) || 0;
1079
- if (applicableProductLimitConfig > 0) {
1080
- var currentUsedLimitCount = usedDiscountCardLimitCounts.get(discount.id) || 0;
1081
- if (currentUsedLimitCount >= applicableProductLimitConfig) {
1082
- return false;
1083
- }
1084
- }
1085
- }
1086
1125
  var limitedData = discount.limited_relation_product_data;
1126
+ if (!limitedData) return false;
1087
1127
 
1088
1128
  // 拿到discount配置的holder信息 product信息 product.holder 不可用return false
1089
1129
  var _tempVar = (flatItem === null || flatItem === void 0 ? void 0 : flatItem.type) === 'bundle' ? flatItem === null || flatItem === void 0 ? void 0 : flatItem.parentProduct : flatItem === null || flatItem === void 0 ? void 0 : flatItem.product;
1090
1130
  var isHolderMatch = _this3.checkHolderMatch(discount, {
1091
1131
  isNeedHolder: isFormSubject && !(_tempVar !== null && _tempVar !== void 0 && _tempVar.isNormalProduct),
1092
1132
  holder_id: (_tempVar === null || _tempVar === void 0 ? void 0 : _tempVar.holder_id) || product.holder_id
1093
- }, holders);
1133
+ }, flatItem.originProduct, holders);
1094
1134
  // 如果 holder 不匹配,则不适用
1095
1135
  if (!isHolderMatch) return false;
1096
1136
  var timeLimit = true;
1097
- timeLimit = !!filterDiscountListByBookingTime([discount], (product.startDate || dayjs()).format('YYYY-MM-DD HH:mm:ss')).length;
1137
+ timeLimit = !!filterDiscountListByBookingTime([discount], dayjs(product.startDate || undefined).format('YYYY-MM-DD HH:mm:ss')).length;
1098
1138
  if (!timeLimit) {
1099
1139
  return false;
1100
1140
  }
1101
1141
 
1102
1142
  // 判断优惠券是否适用于该商品
1103
1143
  if (limitedData.type === 'product_all') {
1104
- if (limitedData.filter === 1 && limitedData.exclude_product_ids.includes(product.id)) {
1144
+ if (!isProductIncludedByLimitedData(limitedData, product.id)) {
1105
1145
  return false;
1106
1146
  }
1147
+
1107
1148
  // 检查 package_sub_item_usage_rules
1108
1149
  if (!_this3.checkPackageSubItemUsageRules(discount, flatItem)) {
1109
1150
  return false;
@@ -1123,9 +1164,12 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1123
1164
  // 如果有 isScan 且 isSelected 的折扣卡,则优先选中,否则再选择第一个
1124
1165
  // 用于处理:先手动扫描了一张折扣卡,扫描完以后带入客户信息,但是之前那张折扣卡不是最优惠的情况
1125
1166
  var selectedDiscountCard = applicableDiscounts.find(function (n) {
1126
- return n.isScan && n.isSelected && (n.tag || n.type) !== 'good_pass';
1167
+ return n.isScan && n.isSelected && !isFullCoveragePass(n);
1127
1168
  });
1128
- var selectedDiscount = selectedDiscountCard || applicableDiscounts[0];
1169
+ var explicitlySelected = (options === null || options === void 0 ? void 0 : options.isSelected) === true ? applicableDiscounts.find(function (item) {
1170
+ return isEntitlementPass(item) && String(item.id) === String(options.discountId);
1171
+ }) : undefined;
1172
+ var selectedDiscount = explicitlySelected || selectedDiscountCard || applicableDiscounts[0];
1129
1173
 
1130
1174
  // 如果是手动折扣,则不适用优惠券
1131
1175
  var isManualDiscount = false;
@@ -1133,22 +1177,19 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1133
1177
  var _product$discount_lis5, _product12, _product12$every;
1134
1178
  // 主商品:判断自身是否手动折扣
1135
1179
  isManualDiscount = typeof product.isManualDiscount === 'boolean' ? product.isManualDiscount : product.total != product.origin_total && (product.bundle || []).every(function (item) {
1136
- var _ref11;
1137
- return !((_ref11 = item.discount_list || []) !== null && _ref11 !== void 0 && _ref11.length);
1180
+ var _ref18;
1181
+ return !((_ref18 = item.discount_list || []) !== null && _ref18 !== void 0 && _ref18.length);
1138
1182
  }) && (!((_product$discount_lis5 = product.discount_list) !== null && _product$discount_lis5 !== void 0 && _product$discount_lis5.length) || ((_product12 = product) === null || _product12 === void 0 || (_product12 = _product12.discount_list) === null || _product12 === void 0 || (_product12$every = _product12.every) === null || _product12$every === void 0 ? void 0 : _product12$every.call(_product12, function (item) {
1139
1183
  return item.type === 'product';
1140
1184
  })));
1141
- if (product.inPromotion) {
1142
- isManualDiscount = false;
1143
- }
1144
1185
  } else {
1145
1186
  // bundle子商品:判断父主商品是否手动折扣
1146
1187
  var parentProduct = flatItem.parentProduct;
1147
1188
  if (parentProduct) {
1148
1189
  var _parentProduct$discou, _parentProduct$discou2, _parentProduct$discou3;
1149
1190
  isManualDiscount = typeof parentProduct.isManualDiscount === 'boolean' ? parentProduct.isManualDiscount : parentProduct.total != parentProduct.origin_total && (parentProduct.bundle || []).every(function (item) {
1150
- var _ref12;
1151
- return !((_ref12 = item.discount_list || []) !== null && _ref12 !== void 0 && _ref12.length);
1191
+ var _ref19;
1192
+ return !((_ref19 = item.discount_list || []) !== null && _ref19 !== void 0 && _ref19.length);
1152
1193
  }) && (!((_parentProduct$discou = parentProduct.discount_list) !== null && _parentProduct$discou !== void 0 && _parentProduct$discou.length) || (parentProduct === null || parentProduct === void 0 || (_parentProduct$discou2 = parentProduct.discount_list) === null || _parentProduct$discou2 === void 0 || (_parentProduct$discou3 = _parentProduct$discou2.every) === null || _parentProduct$discou3 === void 0 ? void 0 : _parentProduct$discou3.call(_parentProduct$discou2, function (item) {
1153
1194
  return item.type === 'product';
1154
1195
  })));
@@ -1215,8 +1256,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1215
1256
  // 如果没有适用的优惠券,或者手动折扣,则不适用优惠券
1216
1257
  if (applicableDiscounts.length === 0 || isManualDiscount || isBoolean(product.vouchersApplicable) && !product.vouchersApplicable) {
1217
1258
  if (flatItem.type === 'main') {
1218
- // 主商品:保持原有逻辑,还原 option 价格
1219
- var restoredOptions = restoreOptionPrices(product.options);
1259
+ // 主商品:保持原有逻辑
1220
1260
  if (product.isClient) {
1221
1261
  processedProductsMap.set(product._id, [_this3.hooks.setProduct(originProduct, _objectSpread(_objectSpread({}, isManualDiscount ? {} : {
1222
1262
  origin_total: getProductOriginTotalPrice({
@@ -1224,7 +1264,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1224
1264
  original_price: product.original_price
1225
1265
  },
1226
1266
  bundle: product.bundle,
1227
- options: restoredOptions
1267
+ options: product.options
1228
1268
  }),
1229
1269
  variant: originProduct._productInit.variant,
1230
1270
  original_price: originProduct._productInit.original_price,
@@ -1233,16 +1273,16 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1233
1273
  price: product.price
1234
1274
  },
1235
1275
  bundle: product.bundle,
1236
- options: restoredOptions
1276
+ options: product.options
1237
1277
  }),
1238
1278
  price: product.price,
1239
- options: restoredOptions
1279
+ options: product.options
1240
1280
  }), {}, {
1241
1281
  discount_list: _this3.filterDiscountListByType(product.discount_list, 'promotion')
1242
1282
  }))]);
1243
1283
  } else {
1244
- var _ref13, _product$_promotion$f, _product13, _product$origin_total, _product$price2;
1245
- var total = product.inPromotion ? (_ref13 = (_product$_promotion$f = (_product13 = product) === null || _product13 === void 0 || (_product13 = _product13._promotion) === null || _product13 === void 0 ? void 0 : _product13.finalPrice) !== null && _product$_promotion$f !== void 0 ? _product$_promotion$f : product.origin_total) !== null && _ref13 !== void 0 ? _ref13 : product.total : (_product$origin_total = product.origin_total) !== null && _product$origin_total !== void 0 ? _product$origin_total : product.total;
1284
+ var _ref20, _product$_promotion$f, _product13, _product$origin_total, _product$price2;
1285
+ var total = product.inPromotion ? (_ref20 = (_product$_promotion$f = (_product13 = product) === null || _product13 === void 0 || (_product13 = _product13._promotion) === null || _product13 === void 0 ? void 0 : _product13.finalPrice) !== null && _product$_promotion$f !== void 0 ? _product$_promotion$f : product.origin_total) !== null && _ref20 !== void 0 ? _ref20 : product.total : (_product$origin_total = product.origin_total) !== null && _product$origin_total !== void 0 ? _product$origin_total : product.total;
1246
1286
  var main_product_selling_price = (_product$price2 = product.price) !== null && _product$price2 !== void 0 ? _product$price2 : product.main_product_selling_price;
1247
1287
  if ((product.discount_list || []).some(function (item) {
1248
1288
  return item.type === 'promotion';
@@ -1255,10 +1295,11 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1255
1295
  price: product.price
1256
1296
  } : {
1257
1297
  _id: product._id.split('___')[0] + '___' + index,
1298
+ origin_total: product.origin_total,
1258
1299
  total: total,
1300
+ original_price: product.original_price,
1259
1301
  price: product.price,
1260
- main_product_selling_price: main_product_selling_price,
1261
- options: restoredOptions
1302
+ main_product_selling_price: main_product_selling_price
1262
1303
  }), {}, {
1263
1304
  discount_list: _this3.filterDiscountListByType(product.discount_list, 'promotion')
1264
1305
  }))]);
@@ -1278,81 +1319,37 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1278
1319
  return;
1279
1320
  }
1280
1321
 
1281
- // 是否需要拆分(商品券需要拆分,折扣卡在 applicableProductLimit > 0 时也需要拆分)
1282
- var discountType = selectedDiscount.tag || selectedDiscount.type;
1283
- var isGoodPass = discountType === 'good_pass';
1284
- var isDiscountCard = ['discount_card', 'product_discount_card'].includes(discountType);
1285
- var applicableProductLimit = ((_selectedDiscount$con = selectedDiscount.config) === null || _selectedDiscount$con === void 0 ? void 0 : _selectedDiscount$con.applicableProductLimit) || 0;
1286
-
1287
- // 商品券始终需要拆分,折扣卡在 applicableProductLimit > 0 时需要拆分
1288
- var isNeedSplit = isGoodPass || isDiscountCard && applicableProductLimit > 0;
1322
+ // 是否需要拆分(商品券需要拆分)
1323
+ var isNeedSplit = isFullCoveragePass(selectedDiscount);
1289
1324
 
1290
1325
  // 需要拆分出来的数量
1291
1326
  var totalQuantity = product.quantity || product.num || 1;
1292
- var availableGoodPassCount = applicableDiscounts.filter(function (item) {
1327
+ var prioritizedDiscounts = [selectedDiscount].concat(_toConsumableArray(applicableDiscounts.filter(function (item) {
1328
+ return item !== selectedDiscount;
1329
+ })));
1330
+ var allocatedPasses = isNeedSplit ? applicableDiscounts.some(isEntitlementPass) ? getFullCoveragePasses(prioritizedDiscounts, totalQuantity) : applicableDiscounts.slice(0, Math.min(totalQuantity, applicableDiscounts.filter(function (item) {
1293
1331
  return (item.tag || item.type) === 'good_pass';
1294
- }).length;
1295
-
1296
- // 🔥 计算最大使用次数限制
1297
- var maxUsageLimit;
1298
- if (isGoodPass) {
1299
- // 商品券:使用 maxUsagePerOrder 限制
1300
- maxUsageLimit = availableGoodPassCount;
1301
- if (selectedDiscount.config && selectedDiscount.config.maxUsagePerOrder) {
1302
- maxUsageLimit = Math.min(availableGoodPassCount, selectedDiscount.config.maxUsagePerOrder);
1303
- }
1304
- } else if (isDiscountCard && applicableProductLimit > 0) {
1305
- // 折扣卡:使用 applicableProductLimit 限制(一个商品使用一次折扣卡算1次)
1306
- // 需要减去已使用次数(跨商品全局计数)
1307
- var usedLimitCount = usedDiscountCardLimitCounts.get(selectedDiscount.id) || 0;
1308
- maxUsageLimit = Math.max(0, applicableProductLimit - usedLimitCount);
1309
- } else {
1310
- // 其他情况不拆分
1311
- maxUsageLimit = 1;
1312
- }
1313
- var splitCount = isNeedSplit ? Math.min(product.quantity || product.num || 1, maxUsageLimit) : 1;
1332
+ }).length)) : [selectedDiscount];
1333
+ var splitCount = allocatedPasses.length;
1314
1334
  var arr = [];
1315
1335
 
1316
1336
  // 🔥 主商品和bundle子商品分别处理
1317
1337
  if (flatItem.type === 'main') {
1318
1338
  // 主商品:保持原有逻辑
1319
1339
  if (splitCount < totalQuantity && isNeedSplit) {
1320
- var _product$origin_total2;
1321
- var _total = (_product$origin_total2 = product.origin_total) !== null && _product$origin_total2 !== void 0 ? _product$origin_total2 : product.total;
1322
- if ((product.discount_list || []).some(function (item) {
1323
- return item.type === 'promotion';
1324
- })) {
1325
- var _product$total2;
1326
- _total = (_product$total2 = product.total) !== null && _product$total2 !== void 0 ? _product$total2 : product.origin_total;
1327
- }
1328
1340
  arr.push(_this3.hooks.setProduct(originProduct, {
1329
1341
  discount_list: _this3.filterDiscountListByType(product.discount_list, 'promotion'),
1330
1342
  quantity: totalQuantity - splitCount,
1331
- _id: product._id.split('___')[0],
1332
- total: _total
1343
+ _id: product._id.split('___')[0]
1333
1344
  }));
1334
1345
  }
1335
1346
  for (var i = 0; i < splitCount; i++) {
1336
- var _originProduct, _selectedDiscount$con2, _product$options, _product$options2, _selectedDiscount$met, _selectedDiscount$met2;
1337
- // 商品券:每个拆分商品使用不同的商品券(从 applicableDiscounts 按索引取)
1338
- // 折扣卡:所有拆分商品使用同一张折扣卡(selectedDiscountCard 或 applicableDiscounts[0])
1339
- var currentSelectedDiscount = isGoodPass ? selectedDiscountCard || applicableDiscounts[i] : selectedDiscountCard || applicableDiscounts[0];
1340
- // 标记优惠券为已使用
1341
- usedDiscounts.set(currentSelectedDiscount.id, true);
1342
- // 🔥 更新 product_id 使用计数
1343
- if ((currentSelectedDiscount.tag || currentSelectedDiscount.type) === 'good_pass') {
1344
- var currentCount = usedProductIdCounts.get(currentSelectedDiscount.product_id) || 0;
1345
- usedProductIdCounts.set(currentSelectedDiscount.product_id, currentCount + 1);
1346
- }
1347
- // 🔥 更新折扣卡 applicableProductLimit 使用计数(跨商品全局)
1348
- var currentDiscountTypeForCount = currentSelectedDiscount.tag || currentSelectedDiscount.type;
1349
- if (['discount_card', 'product_discount_card'].includes(currentDiscountTypeForCount)) {
1350
- var currentLimitCount = usedDiscountCardLimitCounts.get(currentSelectedDiscount.id) || 0;
1351
- usedDiscountCardLimitCounts.set(currentSelectedDiscount.id, currentLimitCount + 1);
1352
- }
1347
+ var _originProduct, _selectedDiscount$met, _selectedDiscount$met2;
1348
+ var _selectedDiscount = allocatedPasses[i];
1349
+ markDiscountUsed(_selectedDiscount);
1353
1350
 
1354
1351
  // 记录实际应用了优惠券的商品信息
1355
- var appliedProducts = appliedDiscountProducts.get(currentSelectedDiscount.id) || [];
1352
+ var appliedProducts = appliedDiscountProducts.get(_selectedDiscount.id) || [];
1356
1353
 
1357
1354
  // 优先从 origin_total拿,可能会拿不到(比如用户端预约在没有配置 original_price 的情况下)
1358
1355
  var productOriginTotal = product.origin_total || product.total || 0;
@@ -1367,473 +1364,191 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1367
1364
 
1368
1365
  // 计算使用折扣卡/商品券以后,单个商品的总 total
1369
1366
  // 🔥 检查是否是 order_level 固定金额折扣卡
1370
- var isOrderLevel = isOrderLevelFixedAmountDiscount(selectedDiscount);
1371
- var orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount.id) : null;
1367
+ var isOrderLevel = isOrderLevelFixedAmountDiscount(_selectedDiscount);
1368
+ var orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(_selectedDiscount.id) : null;
1372
1369
  var productAllocation = orderLevelAllocation === null || orderLevelAllocation === void 0 ? void 0 : orderLevelAllocation.get(flatItem._id);
1373
- var isDeductOptionPrice = !!((_selectedDiscount$con2 = selectedDiscount.config) !== null && _selectedDiscount$con2 !== void 0 && _selectedDiscount$con2.deductOptionPrice);
1374
-
1375
- // 主商品折后价(不含 option);勿与 option 合计混在同一变量,否则 main_product_selling_price 错误
1376
- var mainProductSellingPrice = void 0;
1370
+ var targetProductTotal = void 0;
1377
1371
  var amount = void 0;
1378
1372
  var productDiscountDifference = void 0;
1379
- var discountedOptions = product.options;
1380
- var optionDiscountAmount = 0;
1381
1373
  if (isOrderLevel && productAllocation) {
1382
1374
  // order_level:使用预计算的分摊金额
1383
1375
  amount = productAllocation.discountAmount;
1384
1376
  productDiscountDifference = productAllocation.difference;
1385
- mainProductSellingPrice = Math.max(new Decimal(product.price).minus(amount).toNumber(), 0);
1377
+ targetProductTotal = Math.max(new Decimal(product.price).minus(amount).toNumber(), 0);
1386
1378
  } else {
1387
1379
  // item_level 或其他类型:使用原有逻辑
1388
- mainProductSellingPrice = getDiscountAmount(currentSelectedDiscount, product.price, product.price);
1389
- amount = new Decimal(product.price).minus(new Decimal(mainProductSellingPrice)).toNumber();
1390
- }
1391
- if (isDeductOptionPrice && (_product$options = product.options) !== null && _product$options !== void 0 && _product$options.length) {
1392
- var optionResult = applyDiscountToOptions(product.options, currentSelectedDiscount);
1393
- discountedOptions = optionResult.discountedOptions;
1394
- optionDiscountAmount = optionResult.optionDiscountAmount;
1380
+ targetProductTotal = getDiscountAmount(_selectedDiscount, product.price, product.price);
1381
+ amount = new Decimal(product.price).minus(new Decimal(targetProductTotal)).toNumber();
1395
1382
  }
1396
-
1397
- // total = 主商品折后 + option 行合计;开启 option 抵扣时必须用 discountedOptions,不能用未折扣的 product.options 再算一遍
1398
- var optionsForLineTotal = isDeductOptionPrice && (_product$options2 = product.options) !== null && _product$options2 !== void 0 && _product$options2.length ? discountedOptions : product.options;
1399
- var optionsLineTotal = getOptionTotal(optionsForLineTotal || []);
1400
- var _total2 = new Decimal(mainProductSellingPrice).plus(optionsLineTotal).toNumber();
1401
-
1402
- // discount_list.amount / fixed_amount:行级总优惠 = 主商品优惠 + option 优惠(与 total 变化一致)
1403
- var mainProductDiscountAmount = amount;
1404
- var lineDiscountAmount = new Decimal(mainProductDiscountAmount).plus(optionDiscountAmount).toNumber();
1405
- var currentDiscountType = currentSelectedDiscount.tag === 'product_discount_card' ? 'discount_card' : currentSelectedDiscount.tag;
1406
- var _discountType = selectedDiscount.tag || selectedDiscount.type;
1407
- var currentIsGoodPass = currentDiscountType === 'good_pass';
1383
+ var discountType = _selectedDiscount.tag || _selectedDiscount.type;
1384
+ var isGoodPass = isFullCoveragePass(_selectedDiscount);
1408
1385
  var discountDetail = {
1409
- amount: lineDiscountAmount,
1410
- type: selectedDiscount.tag === 'product_discount_card' ? 'discount_card' : _discountType,
1386
+ amount: amount,
1387
+ type: _selectedDiscount.tag === 'product_discount_card' ? 'discount_card' : discountType,
1411
1388
  discount: {
1412
- discount_card_type: selectedDiscount === null || selectedDiscount === void 0 || (_selectedDiscount$met = selectedDiscount.metadata) === null || _selectedDiscount$met === void 0 ? void 0 : _selectedDiscount$met.discount_card_type,
1413
- fixed_amount: lineDiscountAmount,
1414
- discount_calculation_mode: selectedDiscount === null || selectedDiscount === void 0 || (_selectedDiscount$met2 = selectedDiscount.metadata) === null || _selectedDiscount$met2 === void 0 ? void 0 : _selectedDiscount$met2.discount_calculation_mode,
1415
- resource_id: selectedDiscount.id,
1416
- title: selectedDiscount.format_title,
1389
+ discount_card_type: _selectedDiscount === null || _selectedDiscount === void 0 || (_selectedDiscount$met = _selectedDiscount.metadata) === null || _selectedDiscount$met === void 0 ? void 0 : _selectedDiscount$met.discount_card_type,
1390
+ fixed_amount: amount,
1391
+ discount_calculation_mode: _selectedDiscount === null || _selectedDiscount === void 0 || (_selectedDiscount$met2 = _selectedDiscount.metadata) === null || _selectedDiscount$met2 === void 0 ? void 0 : _selectedDiscount$met2.discount_calculation_mode,
1392
+ resource_id: _selectedDiscount.id,
1393
+ title: _selectedDiscount.format_title,
1417
1394
  original_amount: product.price,
1418
- product_id: originProduct.id,
1419
- percent: currentSelectedDiscount.par_value,
1420
- discount_product_id: currentSelectedDiscount.product_id
1395
+ product_id: product.id,
1396
+ percent: _selectedDiscount.par_value
1421
1397
  },
1422
- // 前端使用的num数量,为了计算优惠金额(拆分时为1)
1423
- _num: isNeedSplit ? 1 : product.num,
1424
- config: currentSelectedDiscount === null || currentSelectedDiscount === void 0 ? void 0 : currentSelectedDiscount.config,
1425
- metadata: _objectSpread(_objectSpread({
1398
+ // 前端使用的num数量,为了计算优惠金额
1399
+ _num: isGoodPass ? 1 : product.num,
1400
+ metadata: _objectSpread({
1426
1401
  num: 1,
1427
- discount_rule_uncheck_flag: selectedDiscount === null || selectedDiscount === void 0 ? void 0 : selectedDiscount.discount_rule_uncheck_flag
1402
+ discount_rule_uncheck_flag: _selectedDiscount === null || _selectedDiscount === void 0 ? void 0 : _selectedDiscount.discount_rule_uncheck_flag
1428
1403
  }, productDiscountDifference !== undefined && {
1429
1404
  product_discount_difference: productDiscountDifference
1430
- }), {}, {
1431
- /** 仅主商品上的优惠金额(不含 option) */
1432
- mainProductDiscountAmount: mainProductDiscountAmount,
1433
- optionDiscountAmount: optionDiscountAmount
1434
1405
  })
1435
1406
  };
1436
1407
  appliedProducts.push(discountDetail);
1437
- appliedDiscountProducts.set(currentSelectedDiscount.id, appliedProducts);
1408
+ appliedDiscountProducts.set(_selectedDiscount.id, appliedProducts);
1409
+ var _total = targetProductTotal;
1410
+ if (product.options) {
1411
+ _total = product.options.reduce(function (accumulator, currentValue) {
1412
+ var currentPrice = new Decimal(currentValue.price || 0);
1413
+ var currentNum = new Decimal(currentValue.num || 0);
1414
+ return accumulator.add(currentPrice.mul(currentNum));
1415
+ }, new Decimal(_total)).toNumber();
1416
+ }
1438
1417
 
1439
1418
  // 记录应用了优惠券的商品
1440
1419
  // 后续更新价格改为 getProductTotalPrice getProductOriginTotalPrice逻辑
1441
1420
  if (product.isClient) {
1442
1421
  arr.push(_this3.hooks.setProduct(originProduct, {
1443
1422
  discount_list: [discountDetail],
1444
- // good_pass:主商品价以折后价为准;勿用 product.price - amount(amount 含 option 优惠时会算错)
1445
- price: currentIsGoodPass ? mainProductSellingPrice : product.price,
1423
+ price: isGoodPass ? 0 : product.price,
1446
1424
  quantity: isNeedSplit ? 1 : product.quantity,
1447
1425
  origin_total: getProductOriginTotalPrice({
1448
1426
  product: {
1449
1427
  original_price: product.original_price
1450
1428
  },
1451
1429
  bundle: product.bundle,
1452
- options: restoreOptionPrices(product.options)
1430
+ options: product.options
1453
1431
  }),
1454
1432
  variant: originProduct._productInit.variant,
1455
1433
  original_price: new Decimal(product.price || 0).toNumber(),
1456
- total: _total2,
1457
- options: discountedOptions
1434
+ total: _total
1458
1435
  }));
1459
1436
  } else {
1460
1437
  arr.push(_this3.hooks.setProduct(originProduct, {
1461
1438
  discount_list: _this3.filterDiscountListByType(product.discount_list, 'promotion').concat([discountDetail]),
1462
- _id: product._id.split('___')[0] + '___' + currentSelectedDiscount.id + '_' + i + '_' + index,
1463
- price: currentIsGoodPass ? 0 : product.price,
1439
+ _id: product._id.split('___')[0] + "___" + _selectedDiscount.id + index + (isEntitlementPass(_selectedDiscount) ? "_".concat(i) : ''),
1440
+ price: isGoodPass ? 0 : product.price,
1464
1441
  quantity: isNeedSplit ? 1 : product.quantity,
1465
- total: _total2,
1442
+ total: _total,
1466
1443
  origin_total: productOriginTotal,
1467
- main_product_selling_price: mainProductSellingPrice,
1468
- options: discountedOptions
1444
+ main_product_selling_price: targetProductTotal
1469
1445
  }));
1470
1446
  }
1471
1447
  }
1472
1448
  processedProductsMap.set(product._id, arr);
1473
1449
  } else {
1474
- // 🔥 bundle子商品:支持拆分(商品券和折扣卡在 applicableProductLimit > 0 时都需要拆分)
1450
+ // 🔥 bundle子商品:支持拆分
1475
1451
  var processedItems = [];
1476
1452
  if (isNeedSplit) {
1477
- // 需要拆分数量(商品券或折扣卡有 applicableProductLimit 限制)
1453
+ // 商品券:需要拆分数量
1478
1454
  var discountNum = splitCount;
1479
1455
  var normalNum = totalQuantity - discountNum;
1480
1456
 
1481
- // 生成有折扣的商品(每个拆分商品 num: 1)
1457
+ // 生成有折扣的商品(每张商品券对应 num: 1)
1482
1458
  for (var _i = 0; _i < discountNum; _i++) {
1483
- var _currentBundleDiscoun, _currentBundleDiscoun2;
1484
- // 商品券:每个拆分商品使用不同的商品券
1485
- // 折扣卡:所有拆分商品使用同一张折扣卡
1486
- var currentBundleDiscount = isGoodPass ? selectedDiscountCard || applicableDiscounts[_i] : selectedDiscountCard || applicableDiscounts[0];
1487
- usedDiscounts.set(currentBundleDiscount.id, true);
1488
- // 🔥 更新 product_id 使用计数
1489
- if ((currentBundleDiscount.tag || currentBundleDiscount.type) === 'good_pass') {
1490
- var _currentCount = usedProductIdCounts.get(currentBundleDiscount.product_id) || 0;
1491
- usedProductIdCounts.set(currentBundleDiscount.product_id, _currentCount + 1);
1492
- }
1493
- // 🔥 更新折扣卡 applicableProductLimit 使用计数(跨商品全局)
1494
- var bundleDiscountTypeForCount = currentBundleDiscount.tag || currentBundleDiscount.type;
1495
- if (['discount_card', 'product_discount_card'].includes(bundleDiscountTypeForCount)) {
1496
- var currentBundleLimitCount = usedDiscountCardLimitCounts.get(currentBundleDiscount.id) || 0;
1497
- usedDiscountCardLimitCounts.set(currentBundleDiscount.id, currentBundleLimitCount + 1);
1498
- }
1459
+ var _selectedDiscount2$me;
1460
+ var _selectedDiscount2 = allocatedPasses[_i];
1461
+ markDiscountUsed(_selectedDiscount2);
1499
1462
 
1500
1463
  // 🔥 生成唯一的 _id
1501
1464
  var uniqueId = "".concat(flatItem._id, "_split_").concat(_i);
1502
-
1503
- // 计算折扣后的价格(使用 getDiscountAmount,内部已处理 maxDeductionAmount)
1504
- var discountedPrice = getDiscountAmount(currentBundleDiscount, product.origin_total, product.origin_total);
1505
- var bundleDiscountAmount = new Decimal(product.origin_total || 0).minus(discountedPrice).toNumber();
1506
-
1507
- // 确定折扣类型
1508
- var bundleDiscountType = currentBundleDiscount.tag === 'product_discount_card' ? 'discount_card' : currentBundleDiscount.tag;
1509
1465
  var _discountDetail = {
1510
- amount: bundleDiscountAmount,
1511
- type: bundleDiscountType,
1466
+ amount: product.origin_total || product.price || 0,
1467
+ type: _selectedDiscount2.tag || _selectedDiscount2.type,
1512
1468
  discount: {
1513
- discount_card_type: currentBundleDiscount === null || currentBundleDiscount === void 0 || (_currentBundleDiscoun = currentBundleDiscount.metadata) === null || _currentBundleDiscoun === void 0 ? void 0 : _currentBundleDiscoun.discount_card_type,
1514
- discount_calculation_mode: currentBundleDiscount === null || currentBundleDiscount === void 0 || (_currentBundleDiscoun2 = currentBundleDiscount.metadata) === null || _currentBundleDiscoun2 === void 0 ? void 0 : _currentBundleDiscoun2.discount_calculation_mode,
1515
- fixed_amount: bundleDiscountAmount,
1516
- resource_id: currentBundleDiscount.id,
1517
- title: currentBundleDiscount.format_title,
1469
+ fixed_amount: product.origin_total || product.price || 0,
1470
+ discount_calculation_mode: _selectedDiscount2 === null || _selectedDiscount2 === void 0 || (_selectedDiscount2$me = _selectedDiscount2.metadata) === null || _selectedDiscount2$me === void 0 ? void 0 : _selectedDiscount2$me.discount_calculation_mode,
1471
+ resource_id: _selectedDiscount2.id,
1472
+ title: _selectedDiscount2.format_title,
1518
1473
  original_amount: product.origin_total,
1519
- product_id: product.id,
1520
- percent: currentBundleDiscount.par_value,
1521
- discount_product_id: currentBundleDiscount.product_id
1474
+ product_id: product.id
1522
1475
  },
1523
1476
  metadata: {
1524
1477
  // 🔥 使用拆分后的唯一 _id
1525
1478
  custom_product_bundle_map_id: uniqueId,
1526
- discount_rule_uncheck_flag: selectedDiscount === null || selectedDiscount === void 0 ? void 0 : selectedDiscount.discount_rule_uncheck_flag,
1479
+ discount_rule_uncheck_flag: _selectedDiscount2 === null || _selectedDiscount2 === void 0 ? void 0 : _selectedDiscount2.discount_rule_uncheck_flag,
1527
1480
  num: 1
1528
1481
  },
1529
- _num: 1,
1530
- config: currentBundleDiscount === null || currentBundleDiscount === void 0 ? void 0 : currentBundleDiscount.config
1482
+ _num: 1
1531
1483
  };
1532
1484
 
1533
1485
  // 记录实际应用的折扣
1534
- var _appliedProducts = appliedDiscountProducts.get(currentBundleDiscount.id) || [];
1486
+ var _appliedProducts = appliedDiscountProducts.get(_selectedDiscount2.id) || [];
1535
1487
  _appliedProducts.push(_discountDetail);
1536
- appliedDiscountProducts.set(currentBundleDiscount.id, _appliedProducts);
1488
+ appliedDiscountProducts.set(_selectedDiscount2.id, _appliedProducts);
1537
1489
  processedItems.push(_objectSpread(_objectSpread({}, flatItem), {}, {
1538
1490
  // 🔥 使用唯一的 _id
1539
1491
  _id: uniqueId,
1540
1492
  num: 1,
1541
1493
  quantity: 1,
1542
- price: discountedPrice,
1543
- // 折扣后的价格
1544
- total: discountedPrice,
1494
+ price: 0,
1495
+ // 商品券价格为0
1496
+ total: 0,
1545
1497
  discount_list: _this3.filterDiscountListByType(flatItem.discount_list, 'promotion').concat([_discountDetail]),
1546
1498
  processed: true,
1547
- _discountId: currentBundleDiscount.id
1499
+ _discountId: _selectedDiscount2.id
1548
1500
  }));
1549
1501
  }
1550
1502
 
1551
- // 🔥 对拆分后的剩余商品继续匹配其他可用折扣(而不是等到下次执行才应用)
1552
- var remainingNum = normalNum;
1553
- var continueSplitIndex = discountNum;
1554
- while (remainingNum > 0) {
1555
- var _nextSelectedDiscount;
1556
- // 重新查找适用于剩余商品的可用折扣(已使用的会被自动过滤掉)
1557
- var nextApplicableDiscounts = sortedDiscountList.filter(function (nextDiscount) {
1558
- var _product$discount_lis10;
1559
- var nextDiscountType = nextDiscount.tag || nextDiscount.type;
1560
- // 检查策略可用性
1561
- if (['good_pass', 'discount_card', 'product_discount_card'].includes(nextDiscountType)) {
1562
- var _nextDiscount$config;
1563
- if (nextDiscount.config === undefined || !(nextDiscount !== null && nextDiscount !== void 0 && (_nextDiscount$config = nextDiscount.config) !== null && _nextDiscount$config !== void 0 && _nextDiscount$config.isAvailable)) {
1564
- return false;
1565
- }
1566
- }
1567
- // 折扣卡时总价为0时不可用
1568
- if ((Number(product.total) <= 0 || !product.total) && !((_product$discount_lis10 = product.discount_list) !== null && _product$discount_lis10 !== void 0 && _product$discount_lis10.find(function (n) {
1569
- var _n$discount2;
1570
- return ((_n$discount2 = n.discount) === null || _n$discount2 === void 0 ? void 0 : _n$discount2.resource_id) === nextDiscount.id;
1571
- })) && nextDiscountType !== 'good_pass') return false;
1572
-
1573
- // 商品券已被使用则跳过
1574
- if (usedDiscounts.get(nextDiscount.id) && nextDiscountType === 'good_pass') return false;
1575
-
1576
- // 检查 maxUsagePerOrder 限制
1577
- if (nextDiscountType === 'good_pass') {
1578
- var _nextDiscount$config2;
1579
- var maxUsagePerOrder = (_nextDiscount$config2 = nextDiscount.config) === null || _nextDiscount$config2 === void 0 ? void 0 : _nextDiscount$config2.maxUsagePerOrder;
1580
- if (maxUsagePerOrder && maxUsagePerOrder > 0) {
1581
- var currentUsedCount = usedProductIdCounts.get(nextDiscount.product_id) || 0;
1582
- if (currentUsedCount >= maxUsagePerOrder) {
1583
- return false;
1584
- }
1585
- }
1586
- }
1587
-
1588
- // 检查折扣卡的 applicableProductLimit 限制
1589
- if (['discount_card', 'product_discount_card'].includes(nextDiscountType)) {
1590
- var _nextDiscount$config3;
1591
- var limitConfig = ((_nextDiscount$config3 = nextDiscount.config) === null || _nextDiscount$config3 === void 0 ? void 0 : _nextDiscount$config3.applicableProductLimit) || 0;
1592
- if (limitConfig > 0) {
1593
- var currentUsedLimitCount = usedDiscountCardLimitCounts.get(nextDiscount.id) || 0;
1594
- if (currentUsedLimitCount >= limitConfig) {
1595
- return false;
1596
- }
1597
- }
1598
- }
1599
- var limitedData = nextDiscount.limited_relation_product_data;
1600
- if (limitedData.type === 'product_all') {
1601
- if (limitedData.filter === 1 && limitedData.exclude_product_ids.includes(product.id)) {
1602
- return false;
1603
- }
1604
- if (!_this3.checkPackageSubItemUsageRules(nextDiscount, flatItem)) {
1605
- return false;
1606
- }
1607
- return true;
1608
- } else if (limitedData.product_ids && limitedData.product_ids.includes(product.id)) {
1609
- if (!_this3.checkPackageSubItemUsageRules(nextDiscount, flatItem)) {
1610
- return false;
1611
- }
1612
- return true;
1613
- }
1614
- return false;
1615
- });
1616
-
1617
- // 没有更多可用折扣,剩余商品无折扣存储
1618
- if (nextApplicableDiscounts.length === 0) {
1619
- processedItems.push(_objectSpread(_objectSpread({}, flatItem), {}, {
1620
- _id: "".concat(flatItem._id, "_split_rest"),
1621
- num: remainingNum,
1622
- quantity: remainingNum,
1623
- discount_list: [],
1624
- processed: true
1625
- }));
1626
- break;
1627
- }
1628
-
1629
- // 选择最优折扣
1630
- var nextSelectedDiscountCard = nextApplicableDiscounts.find(function (n) {
1631
- return n.isScan && n.isSelected && (n.tag || n.type) !== 'good_pass';
1632
- });
1633
- var nextSelectedDiscount = nextSelectedDiscountCard || nextApplicableDiscounts[0];
1634
-
1635
- // 判断新折扣是否需要拆分
1636
- var nextDiscType = nextSelectedDiscount.tag || nextSelectedDiscount.type;
1637
- var nextIsGoodPass = nextDiscType === 'good_pass';
1638
- var nextIsDiscountCard = ['discount_card', 'product_discount_card'].includes(nextDiscType);
1639
- var nextApplicableProductLimit = ((_nextSelectedDiscount = nextSelectedDiscount.config) === null || _nextSelectedDiscount === void 0 ? void 0 : _nextSelectedDiscount.applicableProductLimit) || 0;
1640
- var nextIsNeedSplit = nextIsGoodPass || nextIsDiscountCard && nextApplicableProductLimit > 0;
1641
- if (!nextIsNeedSplit) {
1642
- var _nextBundleDiscount$m, _flatItem$parentProdu9;
1643
- // 🔥 不需要拆分:直接应用折扣到所有剩余商品
1644
- var nextBundleDiscount = nextSelectedDiscountCard || nextApplicableDiscounts[0];
1645
- usedDiscounts.set(nextBundleDiscount.id, true);
1646
- if ((nextBundleDiscount.tag || nextBundleDiscount.type) === 'good_pass') {
1647
- var curCount = usedProductIdCounts.get(nextBundleDiscount.product_id) || 0;
1648
- usedProductIdCounts.set(nextBundleDiscount.product_id, curCount + 1);
1649
- }
1650
- var nextNoSplitType = nextBundleDiscount.tag || nextBundleDiscount.type;
1651
- if (['discount_card', 'product_discount_card'].includes(nextNoSplitType)) {
1652
- var _curCount = usedDiscountCardLimitCounts.get(nextBundleDiscount.id) || 0;
1653
- usedDiscountCardLimitCounts.set(nextBundleDiscount.id, _curCount + remainingNum);
1654
- }
1655
- var nextOriginTotal = product.original_price || product.price || 0;
1656
- var nextTargetTotal = getDiscountAmount(nextBundleDiscount, nextOriginTotal, nextOriginTotal);
1657
- var nextDiscountAmount = new Decimal(nextOriginTotal).minus(nextTargetTotal).toNumber();
1658
- var nextUniqueId = "".concat(flatItem._id, "_split_").concat(continueSplitIndex);
1659
- var nextBundleDiscType = nextBundleDiscount.tag === 'product_discount_card' ? 'discount_card' : nextBundleDiscount.tag;
1660
- var nextDiscountDetail = {
1661
- amount: nextDiscountAmount * remainingNum,
1662
- type: nextBundleDiscType,
1663
- discount: {
1664
- discount_card_type: nextBundleDiscount === null || nextBundleDiscount === void 0 || (_nextBundleDiscount$m = nextBundleDiscount.metadata) === null || _nextBundleDiscount$m === void 0 ? void 0 : _nextBundleDiscount$m.discount_card_type,
1665
- fixed_amount: nextDiscountAmount,
1666
- resource_id: nextBundleDiscount.id,
1667
- title: nextBundleDiscount.format_title,
1668
- original_amount: product.original_price,
1669
- product_id: product.id,
1670
- percent: nextBundleDiscount.par_value,
1671
- discount_product_id: nextBundleDiscount.product_id
1672
- },
1673
- metadata: {
1674
- custom_product_bundle_map_id: nextUniqueId,
1675
- num: remainingNum
1676
- },
1677
- config: nextBundleDiscount === null || nextBundleDiscount === void 0 ? void 0 : nextBundleDiscount.config,
1678
- _num: remainingNum * ((flatItem === null || flatItem === void 0 || (_flatItem$parentProdu9 = flatItem.parentProduct) === null || _flatItem$parentProdu9 === void 0 ? void 0 : _flatItem$parentProdu9.num) || 1)
1679
- };
1680
- var nextAppliedProducts = appliedDiscountProducts.get(nextBundleDiscount.id) || [];
1681
- nextAppliedProducts.push(nextDiscountDetail);
1682
- appliedDiscountProducts.set(nextBundleDiscount.id, nextAppliedProducts);
1683
- processedItems.push(_objectSpread(_objectSpread({}, flatItem), {}, {
1684
- _id: nextUniqueId,
1685
- num: remainingNum,
1686
- quantity: remainingNum,
1687
- total: nextTargetTotal,
1688
- price: new Decimal(nextOriginTotal || 0).minus(nextDiscountDetail.discount.fixed_amount).toNumber(),
1689
- discount_list: [nextDiscountDetail],
1690
- processed: true
1691
- }));
1692
- remainingNum = 0;
1693
- break;
1694
- }
1695
-
1696
- // 🔥 需要拆分:计算最大使用次数
1697
- var nextMaxUsageLimit = void 0;
1698
- if (nextIsGoodPass) {
1699
- var _nextSelectedDiscount2;
1700
- var nextGoodPassCount = nextApplicableDiscounts.filter(function (item) {
1701
- return (item.tag || item.type) === 'good_pass';
1702
- }).length;
1703
- nextMaxUsageLimit = nextGoodPassCount;
1704
- if ((_nextSelectedDiscount2 = nextSelectedDiscount.config) !== null && _nextSelectedDiscount2 !== void 0 && _nextSelectedDiscount2.maxUsagePerOrder) {
1705
- var usedCount = usedProductIdCounts.get(nextSelectedDiscount.product_id) || 0;
1706
- nextMaxUsageLimit = Math.min(nextGoodPassCount, Math.max(0, nextSelectedDiscount.config.maxUsagePerOrder - usedCount));
1707
- }
1708
- } else if (nextIsDiscountCard && nextApplicableProductLimit > 0) {
1709
- var _usedLimitCount = usedDiscountCardLimitCounts.get(nextSelectedDiscount.id) || 0;
1710
- nextMaxUsageLimit = Math.max(0, nextApplicableProductLimit - _usedLimitCount);
1711
- } else {
1712
- nextMaxUsageLimit = 1;
1713
- }
1714
- var nextSplitCount = Math.min(remainingNum, nextMaxUsageLimit);
1715
- if (nextSplitCount === 0) {
1716
- // 已达使用上限,剩余商品无折扣存储
1717
- processedItems.push(_objectSpread(_objectSpread({}, flatItem), {}, {
1718
- _id: "".concat(flatItem._id, "_split_rest"),
1719
- num: remainingNum,
1720
- quantity: remainingNum,
1721
- discount_list: _this3.filterDiscountListByType(flatItem.discount_list, 'promotion'),
1722
- processed: true
1723
- }));
1724
- break;
1725
- }
1726
-
1727
- // 生成有折扣的商品
1728
- for (var j = 0; j < nextSplitCount; j++) {
1729
- var _nextBundleDiscount$m2;
1730
- var _nextBundleDiscount = nextIsGoodPass ? nextSelectedDiscountCard || nextApplicableDiscounts[j] : nextSelectedDiscountCard || nextApplicableDiscounts[0];
1731
- usedDiscounts.set(_nextBundleDiscount.id, true);
1732
- if ((_nextBundleDiscount.tag || _nextBundleDiscount.type) === 'good_pass') {
1733
- var _curCount2 = usedProductIdCounts.get(_nextBundleDiscount.product_id) || 0;
1734
- usedProductIdCounts.set(_nextBundleDiscount.product_id, _curCount2 + 1);
1735
- }
1736
- var nextBundleDiscTypeForCount = _nextBundleDiscount.tag || _nextBundleDiscount.type;
1737
- if (['discount_card', 'product_discount_card'].includes(nextBundleDiscTypeForCount)) {
1738
- var curLimitCount = usedDiscountCardLimitCounts.get(_nextBundleDiscount.id) || 0;
1739
- usedDiscountCardLimitCounts.set(_nextBundleDiscount.id, curLimitCount + 1);
1740
- }
1741
- var _nextUniqueId = "".concat(flatItem._id, "_split_").concat(continueSplitIndex);
1742
- var nextDiscountedPrice = getDiscountAmount(_nextBundleDiscount, product.origin_total, product.origin_total);
1743
- var nextBundleDiscAmount = new Decimal(product.origin_total || 0).minus(nextDiscountedPrice).toNumber();
1744
- var nextBundleDiscTypeStr = _nextBundleDiscount.tag === 'product_discount_card' ? 'discount_card' : _nextBundleDiscount.tag;
1745
- var _nextDiscountDetail = {
1746
- amount: nextBundleDiscAmount,
1747
- type: nextBundleDiscTypeStr,
1748
- discount: {
1749
- discount_card_type: _nextBundleDiscount === null || _nextBundleDiscount === void 0 || (_nextBundleDiscount$m2 = _nextBundleDiscount.metadata) === null || _nextBundleDiscount$m2 === void 0 ? void 0 : _nextBundleDiscount$m2.discount_card_type,
1750
- fixed_amount: nextBundleDiscAmount,
1751
- resource_id: _nextBundleDiscount.id,
1752
- title: _nextBundleDiscount.format_title,
1753
- original_amount: product.origin_total,
1754
- product_id: product.id,
1755
- percent: _nextBundleDiscount.par_value,
1756
- discount_product_id: _nextBundleDiscount.product_id
1757
- },
1758
- metadata: {
1759
- custom_product_bundle_map_id: _nextUniqueId,
1760
- num: 1
1761
- },
1762
- _num: 1,
1763
- config: _nextBundleDiscount === null || _nextBundleDiscount === void 0 ? void 0 : _nextBundleDiscount.config
1764
- };
1765
- var _nextAppliedProducts = appliedDiscountProducts.get(_nextBundleDiscount.id) || [];
1766
- _nextAppliedProducts.push(_nextDiscountDetail);
1767
- appliedDiscountProducts.set(_nextBundleDiscount.id, _nextAppliedProducts);
1768
- processedItems.push(_objectSpread(_objectSpread({}, flatItem), {}, {
1769
- _id: _nextUniqueId,
1770
- num: 1,
1771
- quantity: 1,
1772
- price: nextDiscountedPrice,
1773
- total: nextDiscountedPrice,
1774
- discount_list: [_nextDiscountDetail],
1775
- processed: true,
1776
- _discountId: _nextBundleDiscount.id
1777
- }));
1778
- continueSplitIndex++;
1779
- }
1780
- remainingNum -= nextSplitCount;
1503
+ // 生成无折扣的商品(剩余数量)
1504
+ if (normalNum > 0) {
1505
+ processedItems.push(_objectSpread(_objectSpread({}, flatItem), {}, {
1506
+ // 🔥 为剩余商品生成唯一的 _id
1507
+ _id: "".concat(flatItem._id, "_split_rest"),
1508
+ num: normalNum,
1509
+ quantity: normalNum,
1510
+ discount_list: _this3.filterDiscountListByType(flatItem.discount_list, 'promotion'),
1511
+ processed: true
1512
+ }));
1781
1513
  }
1782
1514
  } else {
1783
- var _currentBundleDiscoun3, _currentBundleDiscoun4, _flatItem$parentProdu10;
1784
- // 不拆分:直接应用折扣
1785
- var _currentBundleDiscount = selectedDiscountCard || applicableDiscounts[0];
1786
- usedDiscounts.set(_currentBundleDiscount.id, true);
1787
- // 🔥 更新 product_id 使用计数
1788
- if ((_currentBundleDiscount.tag || _currentBundleDiscount.type) === 'good_pass') {
1789
- var _currentCount2 = usedProductIdCounts.get(_currentBundleDiscount.product_id) || 0;
1790
- usedProductIdCounts.set(_currentBundleDiscount.product_id, _currentCount2 + 1);
1791
- }
1792
- // 🔥 更新折扣卡 applicableProductLimit 使用计数(不拆分时按商品数量计数)
1793
- var noSplitDiscountType = _currentBundleDiscount.tag || _currentBundleDiscount.type;
1794
- if (['discount_card', 'product_discount_card'].includes(noSplitDiscountType)) {
1795
- var bundleQuantity = product.num || 1;
1796
- var currentNoSplitCount = usedDiscountCardLimitCounts.get(_currentBundleDiscount.id) || 0;
1797
- usedDiscountCardLimitCounts.set(_currentBundleDiscount.id, currentNoSplitCount + bundleQuantity);
1798
- }
1515
+ var _selectedDiscount$met3, _selectedDiscount$met4, _flatItem$parentProdu9;
1516
+ // 折扣卡:不拆分数量,直接应用
1517
+ usedDiscounts.set(selectedDiscount.id, true);
1799
1518
  var _productOriginTotal = product.original_price || product.price || 0;
1800
1519
 
1801
1520
  // 🔥 检查是否是 order_level 固定金额折扣卡
1802
1521
  var _isOrderLevel = isOrderLevelFixedAmountDiscount(selectedDiscount);
1803
1522
  var _orderLevelAllocation = _isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount.id) : null;
1804
1523
  var _productAllocation = _orderLevelAllocation === null || _orderLevelAllocation === void 0 ? void 0 : _orderLevelAllocation.get(flatItem._id);
1805
- var targetProductTotal;
1524
+ var _targetProductTotal;
1806
1525
  var fixedAmountPerItem;
1807
1526
  var _productDiscountDifference;
1808
1527
  if (_isOrderLevel && _productAllocation) {
1809
1528
  // order_level:使用预计算的单价折扣金额(已经是单价,无需再除以数量)
1810
1529
  fixedAmountPerItem = _productAllocation.discountAmount;
1811
1530
  _productDiscountDifference = _productAllocation.difference;
1812
- targetProductTotal = Math.max(new Decimal(_productOriginTotal).minus(fixedAmountPerItem).toNumber(), 0);
1531
+ _targetProductTotal = Math.max(new Decimal(_productOriginTotal).minus(fixedAmountPerItem).toNumber(), 0);
1813
1532
  } else {
1814
1533
  // item_level 或其他类型:使用原有逻辑
1815
- targetProductTotal = getDiscountAmount(_currentBundleDiscount, _productOriginTotal, _productOriginTotal);
1816
- fixedAmountPerItem = new Decimal(_productOriginTotal).minus(targetProductTotal).toNumber();
1534
+ _targetProductTotal = getDiscountAmount(selectedDiscount, _productOriginTotal, _productOriginTotal);
1535
+ fixedAmountPerItem = new Decimal(_productOriginTotal).minus(_targetProductTotal).toNumber();
1817
1536
  }
1818
1537
 
1819
- // 计算实际折扣金额
1820
- var bundleActualDiscountAmount = new Decimal(_productOriginTotal).minus(targetProductTotal).toNumber();
1821
-
1822
1538
  // 🔥 使用当前的 _id 作为唯一标识
1823
1539
  var _uniqueId = flatItem._id;
1824
1540
  var _discountDetail2 = {
1825
- amount: bundleActualDiscountAmount * (product.num || 1),
1826
- type: _currentBundleDiscount.tag === 'product_discount_card' ? 'discount_card' : _currentBundleDiscount.tag,
1541
+ amount: fixedAmountPerItem * (product.num || 1),
1542
+ type: selectedDiscount.tag === 'product_discount_card' ? 'discount_card' : selectedDiscount.tag,
1827
1543
  discount: {
1828
- discount_card_type: _currentBundleDiscount === null || _currentBundleDiscount === void 0 || (_currentBundleDiscoun3 = _currentBundleDiscount.metadata) === null || _currentBundleDiscoun3 === void 0 ? void 0 : _currentBundleDiscoun3.discount_card_type,
1829
- fixed_amount: bundleActualDiscountAmount,
1830
- discount_calculation_mode: _currentBundleDiscount === null || _currentBundleDiscount === void 0 || (_currentBundleDiscoun4 = _currentBundleDiscount.metadata) === null || _currentBundleDiscoun4 === void 0 ? void 0 : _currentBundleDiscoun4.discount_calculation_mode,
1831
- resource_id: _currentBundleDiscount.id,
1832
- title: _currentBundleDiscount.format_title,
1544
+ discount_card_type: selectedDiscount === null || selectedDiscount === void 0 || (_selectedDiscount$met3 = selectedDiscount.metadata) === null || _selectedDiscount$met3 === void 0 ? void 0 : _selectedDiscount$met3.discount_card_type,
1545
+ fixed_amount: fixedAmountPerItem,
1546
+ discount_calculation_mode: selectedDiscount === null || selectedDiscount === void 0 || (_selectedDiscount$met4 = selectedDiscount.metadata) === null || _selectedDiscount$met4 === void 0 ? void 0 : _selectedDiscount$met4.discount_calculation_mode,
1547
+ resource_id: selectedDiscount.id,
1548
+ title: selectedDiscount.format_title,
1833
1549
  original_amount: product.original_price,
1834
1550
  product_id: product.id,
1835
- percent: _currentBundleDiscount.par_value,
1836
- discount_product_id: _currentBundleDiscount.product_id
1551
+ percent: selectedDiscount.par_value
1837
1552
  },
1838
1553
  metadata: _objectSpread({
1839
1554
  // 🔥 使用唯一的 _id
@@ -1843,16 +1558,15 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1843
1558
  }, _productDiscountDifference !== undefined && {
1844
1559
  product_discount_difference: _productDiscountDifference
1845
1560
  }),
1846
- config: _currentBundleDiscount === null || _currentBundleDiscount === void 0 ? void 0 : _currentBundleDiscount.config,
1847
- _num: (product.num || 1) * ((flatItem === null || flatItem === void 0 || (_flatItem$parentProdu10 = flatItem.parentProduct) === null || _flatItem$parentProdu10 === void 0 ? void 0 : _flatItem$parentProdu10.num) || 1)
1561
+ _num: (product.num || 1) * ((flatItem === null || flatItem === void 0 || (_flatItem$parentProdu9 = flatItem.parentProduct) === null || _flatItem$parentProdu9 === void 0 ? void 0 : _flatItem$parentProdu9.num) || 1)
1848
1562
  };
1849
1563
 
1850
1564
  // 记录实际应用的折扣
1851
- var _appliedProducts2 = appliedDiscountProducts.get(_currentBundleDiscount.id) || [];
1565
+ var _appliedProducts2 = appliedDiscountProducts.get(selectedDiscount.id) || [];
1852
1566
  _appliedProducts2.push(_discountDetail2);
1853
- appliedDiscountProducts.set(_currentBundleDiscount.id, _appliedProducts2);
1567
+ appliedDiscountProducts.set(selectedDiscount.id, _appliedProducts2);
1854
1568
  processedItems.push(_objectSpread(_objectSpread({}, flatItem), {}, {
1855
- total: targetProductTotal,
1569
+ total: _targetProductTotal,
1856
1570
  price: new Decimal(_productOriginTotal || 0).minus(fixedAmountPerItem).toNumber(),
1857
1571
  discount_list: _this3.filterDiscountListByType(flatItem.discount_list, 'promotion').concat([_discountDetail2]),
1858
1572
  processed: true
@@ -1868,12 +1582,43 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1868
1582
  originalProductList.forEach(function (originProduct) {
1869
1583
  var product = _this3.hooks.getProduct(originProduct);
1870
1584
 
1585
+ // 已提交的扣次不参与运行时重组,避免价格或使用明细被二次改写。
1586
+ if (isPersistedEntitlementLine(originProduct, product)) {
1587
+ result.push(originProduct);
1588
+ return;
1589
+ }
1590
+
1871
1591
  // 获取主商品处理结果
1872
1592
  var mainProductArr = processedProductsMap.get(product._id);
1593
+ if (isEntitlementRuntimeLine(originProduct, product) && !product.isManualDiscount && mainProductArr !== null && mainProductArr !== void 0 && mainProductArr.length) {
1594
+ var bundle = (product.bundle || []).flatMap(function (item, index) {
1595
+ var processed = processedFlatItemsMap.get("".concat(product._id, "_bundle_").concat(index));
1596
+ if (!(processed !== null && processed !== void 0 && processed.length)) return [item];
1597
+ return processed.map(function (child) {
1598
+ return _objectSpread(_objectSpread({}, item), {}, {
1599
+ _id: child._id,
1600
+ price: child.price,
1601
+ bundle_selling_price: child.price,
1602
+ num: child.num,
1603
+ discount_list: (child.discount_list || []).map(function (detail) {
1604
+ return _objectSpread(_objectSpread({}, detail), {}, {
1605
+ metadata: _objectSpread(_objectSpread({}, detail.metadata), {}, {
1606
+ num: child.num,
1607
+ custom_product_bundle_map_id: child._id
1608
+ })
1609
+ });
1610
+ })
1611
+ });
1612
+ });
1613
+ });
1614
+ result.push.apply(result, _toConsumableArray(mainProductArr.map(function (item) {
1615
+ return rebuildEntitlementLine(item, bundle, _this3.hooks);
1616
+ })));
1617
+ return;
1618
+ }
1873
1619
  if (!mainProductArr || mainProductArr.length === 0) {
1874
- // 如果没有处理结果,返回默认商品(还原 option 价格)
1620
+ // 如果没有处理结果,返回默认商品
1875
1621
  var getDefaultProduct = function getDefaultProduct() {
1876
- var restoredOptions = restoreOptionPrices(product.options);
1877
1622
  if (product.isClient) {
1878
1623
  return _this3.hooks.setProduct(originProduct, {
1879
1624
  discount_list: _this3.filterDiscountListByType(product.discount_list, 'promotion'),
@@ -1883,7 +1628,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1883
1628
  original_price: product.original_price
1884
1629
  },
1885
1630
  bundle: product.bundle,
1886
- options: restoredOptions
1631
+ options: product.options
1887
1632
  }),
1888
1633
  variant: originProduct._productInit.variant,
1889
1634
  original_price: originProduct._productInit.original_price,
@@ -1892,17 +1637,15 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1892
1637
  price: product.price
1893
1638
  },
1894
1639
  bundle: product.bundle,
1895
- options: restoredOptions
1896
- }),
1897
- options: restoredOptions
1640
+ options: product.options
1641
+ })
1898
1642
  });
1899
1643
  } else {
1900
1644
  return _this3.hooks.setProduct(originProduct, {
1901
1645
  discount_list: _this3.filterDiscountListByType(product.discount_list, 'promotion'),
1902
1646
  total: product.total,
1903
1647
  origin_total: product.origin_total,
1904
- price: product.price,
1905
- options: restoreOptionPrices(product.options)
1648
+ price: product.price
1906
1649
  });
1907
1650
  }
1908
1651
  };
@@ -1935,7 +1678,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1935
1678
  var hasGoodPass = processedBundleItems.some(function (item) {
1936
1679
  var _item$discount_list;
1937
1680
  return (_item$discount_list = item.discount_list) === null || _item$discount_list === void 0 ? void 0 : _item$discount_list.some(function (discount) {
1938
- return discount.type === 'good_pass' || discount.tag === 'good_pass';
1681
+ return isFullCoveragePass(discount);
1939
1682
  });
1940
1683
  });
1941
1684
  if (hasGoodPass) {
@@ -1978,7 +1721,6 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1978
1721
  product_id: bundleItem.product_id,
1979
1722
  price: item.price,
1980
1723
  num: item.num,
1981
- quantity: item.num,
1982
1724
  discount_list: updatedDiscountList
1983
1725
  }));
1984
1726
  });
@@ -2002,7 +1744,6 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2002
1744
  product_id: bundleItem.product_id,
2003
1745
  price: item.price,
2004
1746
  num: item.num,
2005
- quantity: item.num,
2006
1747
  discount_list: _updatedDiscountList
2007
1748
  }));
2008
1749
  } else {
@@ -2017,8 +1758,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2017
1758
 
2018
1759
  // 🔥 更新主商品自己的 discount_list 中的 num(quantity=1)
2019
1760
  var updatedMainDiscountList = mainProductData.discount_list.map(function (discount) {
2020
- var _discount$metadata7, _discount$metadata8;
2021
- if (discount !== null && discount !== void 0 && (_discount$metadata7 = discount.metadata) !== null && _discount$metadata7 !== void 0 && _discount$metadata7.custom_product_bundle_map_id) {
1761
+ var _discount$metadata6, _discount$metadata7;
1762
+ if (discount !== null && discount !== void 0 && (_discount$metadata6 = discount.metadata) !== null && _discount$metadata6 !== void 0 && _discount$metadata6.custom_product_bundle_map_id) {
2022
1763
  // bundle的discount_list保持不变
2023
1764
  return discount;
2024
1765
  }
@@ -2026,7 +1767,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2026
1767
  return _objectSpread(_objectSpread({}, discount), {}, {
2027
1768
  // num: 1,
2028
1769
  metadata: _objectSpread(_objectSpread({}, discount.metadata), {}, {
2029
- custom_product_bundle_map_id: discount === null || discount === void 0 || (_discount$metadata8 = discount.metadata) === null || _discount$metadata8 === void 0 ? void 0 : _discount$metadata8.custom_product_bundle_map_id,
1770
+ custom_product_bundle_map_id: discount === null || discount === void 0 || (_discount$metadata7 = discount.metadata) === null || _discount$metadata7 === void 0 ? void 0 : _discount$metadata7.custom_product_bundle_map_id,
2030
1771
  num: 1
2031
1772
  })
2032
1773
  });
@@ -2071,8 +1812,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2071
1812
  quantity: 1,
2072
1813
  discount_list: updatedMainDiscountList,
2073
1814
  bundle: newBundleWithDiscount,
2074
- total: newTotalWithDiscount,
2075
- origin_total: newOriginTotalWithDiscount
1815
+ total: new Decimal(newTotalWithDiscount).toDecimalPlaces(2, Decimal.ROUND_HALF_UP).toNumber(),
1816
+ origin_total: new Decimal(newOriginTotalWithDiscount).toDecimalPlaces(2, Decimal.ROUND_HALF_UP).toNumber()
2076
1817
  })));
2077
1818
 
2078
1819
  // 第二个:包含原始bundle (qty=原quantity-1)
@@ -2091,8 +1832,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2091
1832
 
2092
1833
  // 🔥 更新主商品自己的 discount_list 中的 num(quantity=原quantity-1)
2093
1834
  var updatedMainDiscountListOriginal = mainProductData.discount_list.map(function (discount) {
2094
- var _discount$metadata9, _discount$metadata10;
2095
- if (discount !== null && discount !== void 0 && (_discount$metadata9 = discount.metadata) !== null && _discount$metadata9 !== void 0 && _discount$metadata9.custom_product_bundle_map_id) {
1835
+ var _discount$metadata8, _discount$metadata9;
1836
+ if (discount !== null && discount !== void 0 && (_discount$metadata8 = discount.metadata) !== null && _discount$metadata8 !== void 0 && _discount$metadata8.custom_product_bundle_map_id) {
2096
1837
  // bundle的discount_list保持不变
2097
1838
  return discount;
2098
1839
  }
@@ -2100,7 +1841,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2100
1841
  return _objectSpread(_objectSpread({}, discount), {}, {
2101
1842
  metadata: _objectSpread(_objectSpread({}, discount.metadata), {}, {
2102
1843
  num: mainProductQuantity - 1,
2103
- custom_product_bundle_map_id: discount === null || discount === void 0 || (_discount$metadata10 = discount.metadata) === null || _discount$metadata10 === void 0 ? void 0 : _discount$metadata10.custom_product_bundle_map_id
1844
+ custom_product_bundle_map_id: discount === null || discount === void 0 || (_discount$metadata9 = discount.metadata) === null || _discount$metadata9 === void 0 ? void 0 : _discount$metadata9.custom_product_bundle_map_id
2104
1845
  })
2105
1846
  // num: mainProductQuantity - 1,
2106
1847
  });
@@ -2167,11 +1908,11 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2167
1908
  processedBundleItems.forEach(function (item) {
2168
1909
  // 🔥 更新 discount_list 中的 num,使其与拆分后的 item.num 一致
2169
1910
  var updatedDiscountList = (item.discount_list || []).map(function (discount) {
2170
- var _discount$metadata11;
1911
+ var _discount$metadata10;
2171
1912
  return _objectSpread(_objectSpread({}, discount), {}, {
2172
1913
  metadata: _objectSpread(_objectSpread({}, discount.metadata), {}, {
2173
1914
  num: item.num,
2174
- custom_product_bundle_map_id: discount === null || discount === void 0 || (_discount$metadata11 = discount.metadata) === null || _discount$metadata11 === void 0 ? void 0 : _discount$metadata11.custom_product_bundle_map_id
1915
+ custom_product_bundle_map_id: discount === null || discount === void 0 || (_discount$metadata10 = discount.metadata) === null || _discount$metadata10 === void 0 ? void 0 : _discount$metadata10.custom_product_bundle_map_id
2175
1916
  })
2176
1917
  // num: item.num, // 使用拆分后的 num
2177
1918
  });
@@ -2181,9 +1922,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2181
1922
  product_id: bundleItem.product_id,
2182
1923
  price: item.price,
2183
1924
  num: item.num,
2184
- quantity: item.num,
2185
- discount_list: updatedDiscountList,
2186
- bundle_selling_price: bundleItem.bundle_selling_price !== undefined ? item.price : undefined
1925
+ discount_list: updatedDiscountList
2187
1926
  }));
2188
1927
  });
2189
1928
  }
@@ -2222,8 +1961,12 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2222
1961
  // 累加bundle的价格(只累加一次)
2223
1962
  if (newBundle.length > 0) {
2224
1963
  newBundle.forEach(function (item) {
2225
- var _item$discount_list3;
2226
1964
  newTotal += Number(item.price) * Number(item.num);
1965
+ });
1966
+
1967
+ // 计算原始总价(不考虑折扣)
1968
+ newBundle.forEach(function (item) {
1969
+ var _item$discount_list3;
2227
1970
  var originalPrice = ((_item$discount_list3 = item.discount_list) === null || _item$discount_list3 === void 0 || (_item$discount_list3 = _item$discount_list3[0]) === null || _item$discount_list3 === void 0 || (_item$discount_list3 = _item$discount_list3.discount) === null || _item$discount_list3 === void 0 ? void 0 : _item$discount_list3.original_amount) || item.price;
2228
1971
  newOriginTotal += Number(originalPrice) * Number(item.num);
2229
1972
  });
@@ -2238,6 +1981,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2238
1981
  return accumulator.add(currentPrice.mul(currentNum));
2239
1982
  }, new Decimal(newTotal)).toNumber();
2240
1983
  }
1984
+ newTotal = new Decimal(newTotal).toDecimalPlaces(2, Decimal.ROUND_HALF_UP).toNumber();
1985
+ newOriginTotal = new Decimal(newOriginTotal).toDecimalPlaces(2, Decimal.ROUND_HALF_UP).toNumber();
2241
1986
 
2242
1987
  // 生成最终的主商品
2243
1988
  result.push(_this3.hooks.setProduct(mainProduct, _objectSpread(_objectSpread({}, mainProductData), {}, {
@@ -2265,6 +2010,29 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2265
2010
 
2266
2011
  // 获取此优惠券实际应用的商品详情
2267
2012
  var appliedProductDetails = appliedDiscountProducts.get(discount.id) || [];
2013
+ if (isEntitlementPass(discount)) {
2014
+ var committed = discount.committedAppliedProductDetails || [];
2015
+ var details = [].concat(_toConsumableArray(committed), _toConsumableArray(appliedProductDetails));
2016
+ var _isAvailable = applicableProducts.length > 0;
2017
+ var timeReasons = entitlementTimeReasons.get(discount.id) || [];
2018
+ var timeReason = timeReasons.length ? timeReasons.every(Boolean) ? timeReasons[0] : undefined : getDiscountTimeUnavailableReason(discount, dayjs().format('YYYY-MM-DD HH:mm:ss'));
2019
+ var reasonCode = _isAvailable ? undefined : discount.reasonCode || timeReason || (entitlementHolderMismatch.has(discount.id) ? 'holder_not_matched' : 'product_not_applicable');
2020
+ return _objectSpread(_objectSpread({}, discount), {}, {
2021
+ isAvailable: _isAvailable || committed.length > 0,
2022
+ isSelected: details.length > 0,
2023
+ isUsed: details.length > 0,
2024
+ reasonCode: reasonCode,
2025
+ reason: reasonCode === discount.reasonCode ? discount.reason : undefined,
2026
+ isManualSelect: options !== null && options !== void 0 && options.scan ? false : discount.isManualSelect,
2027
+ applicableProductIds: applicableProducts,
2028
+ applicableProductDetails: applicableProductDetails,
2029
+ appliedProductDetails: details,
2030
+ savedAmount: details.reduce(function (sum, detail) {
2031
+ var _detail$discount;
2032
+ return new Decimal(sum).plus(new Decimal(((_detail$discount = detail.discount) === null || _detail$discount === void 0 ? void 0 : _detail$discount.fixed_amount) || 0).mul(detail._num || 1)).toNumber();
2033
+ }, 0)
2034
+ });
2035
+ }
2268
2036
 
2269
2037
  // 根据是否有适用商品决定isAvailable
2270
2038
  var isAvailable = applicableProducts.length > 0;
@@ -2320,7 +2088,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2320
2088
  });
2321
2089
  console.log(processedProductList, 'processedProductList');
2322
2090
  return {
2323
- productList: processedProductList,
2091
+ productList: this.entitlementPassEnabled ? finalizeEntitlementLines(processedProductList, this.hooks) : processedProductList,
2324
2092
  discountList: [].concat(editModeDiscount, _toConsumableArray(updatedDiscountList))
2325
2093
  };
2326
2094
  }
@@ -2345,14 +2113,15 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2345
2113
  var ruleType = usageRules.type;
2346
2114
  // 套餐适用范围配置
2347
2115
  var packageScope = usageRules === null || usageRules === void 0 ? void 0 : usageRules.package_scope;
2348
- var _ref14 = packageScope || {},
2349
- scopeType = _ref14.type,
2350
- _ref14$exclude_bundle = _ref14.exclude_bundle_product_ids,
2351
- exclude_bundle_product_ids = _ref14$exclude_bundle === void 0 ? [] : _ref14$exclude_bundle,
2352
- _ref14$include_bundle = _ref14.include_bundle_product_ids,
2353
- include_bundle_product_ids = _ref14$include_bundle === void 0 ? [] : _ref14$include_bundle,
2354
- _ref14$filter = _ref14.filter,
2355
- filter = _ref14$filter === void 0 ? 0 : _ref14$filter;
2116
+ var _ref21 = packageScope || {},
2117
+ _ref21$type = _ref21.type,
2118
+ scopeType = _ref21$type === void 0 ? 'product_all' : _ref21$type,
2119
+ _ref21$exclude_bundle = _ref21.exclude_bundle_product_ids,
2120
+ exclude_bundle_product_ids = _ref21$exclude_bundle === void 0 ? [] : _ref21$exclude_bundle,
2121
+ _ref21$include_bundle = _ref21.include_bundle_product_ids,
2122
+ include_bundle_product_ids = _ref21$include_bundle === void 0 ? [] : _ref21$include_bundle,
2123
+ _ref21$filter = _ref21.filter,
2124
+ filter = _ref21$filter === void 0 ? 0 : _ref21$filter;
2356
2125
  var isMainProduct = flatItem.type === 'main'; // 单独购买
2357
2126
  var isBundleItem = flatItem.type === 'bundle'; // 套餐中购买
2358
2127
 
@@ -2367,12 +2136,12 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2367
2136
  return true; // 单独购买时可用
2368
2137
  }
2369
2138
  if (isBundleItem) {
2370
- var _flatItem$bundleItem9, _flatItem$bundleItem10, _flatItem$originProdu, _flatItem$parentProdu11;
2139
+ var _flatItem$bundleItem9, _flatItem$bundleItem10, _flatItem$originProdu, _flatItem$parentProdu10;
2371
2140
  // 套餐中购买时,判断是否为原价
2372
2141
  var priceType = (_flatItem$bundleItem9 = flatItem.bundleItem) === null || _flatItem$bundleItem9 === void 0 ? void 0 : _flatItem$bundleItem9.price_type;
2373
2142
  var priceTypeExt = (_flatItem$bundleItem10 = flatItem.bundleItem) === null || _flatItem$bundleItem10 === void 0 ? void 0 : _flatItem$bundleItem10.price_type_ext;
2374
2143
  // 主商品id
2375
- var mainProductId = (flatItem === null || flatItem === void 0 || (_flatItem$originProdu = flatItem.originProduct) === null || _flatItem$originProdu === void 0 || (_flatItem$originProdu = _flatItem$originProdu._productOrigin) === null || _flatItem$originProdu === void 0 ? void 0 : _flatItem$originProdu.id) || (flatItem === null || flatItem === void 0 || (_flatItem$parentProdu11 = flatItem.parentProduct) === null || _flatItem$parentProdu11 === void 0 ? void 0 : _flatItem$parentProdu11.id) || 0;
2144
+ var mainProductId = (flatItem === null || flatItem === void 0 || (_flatItem$originProdu = flatItem.originProduct) === null || _flatItem$originProdu === void 0 || (_flatItem$originProdu = _flatItem$originProdu._productOrigin) === null || _flatItem$originProdu === void 0 ? void 0 : _flatItem$originProdu.id) || (flatItem === null || flatItem === void 0 || (_flatItem$parentProdu10 = flatItem.parentProduct) === null || _flatItem$parentProdu10 === void 0 ? void 0 : _flatItem$parentProdu10.id) || 0;
2376
2145
  // original_price 对应:
2377
2146
  // 1. price_type: "markup" && price_type_ext: "product_price"
2378
2147
  // markup_price 对应: