@pisell/pisellos 0.0.571 → 0.0.572

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 (143) hide show
  1. package/dist/effects/index.d.ts +2 -2
  2. package/dist/model/strategy/adapter/dataVariant/type.d.ts +3 -3
  3. package/dist/model/strategy/adapter/itemRule/type.d.ts +6 -6
  4. package/dist/model/strategy/adapter/promotion/index.d.ts +4 -0
  5. package/dist/model/strategy/adapter/promotion/type.d.ts +5 -5
  6. package/dist/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
  7. package/dist/model/strategy/adapter/walletPass/evaluator.js +4 -2
  8. package/dist/model/strategy/type.d.ts +1 -1
  9. package/dist/modules/BookingContext/types.d.ts +4 -4
  10. package/dist/modules/BookingContext/utils/resourceErrors.d.ts +1 -1
  11. package/dist/modules/Customer/types.d.ts +1 -1
  12. package/dist/modules/Discount/availability.d.ts +7 -0
  13. package/dist/modules/Discount/availability.js +52 -0
  14. package/dist/modules/Discount/entitlementPass.d.ts +34 -0
  15. package/dist/modules/Discount/entitlementPass.js +147 -0
  16. package/dist/modules/Discount/entitlementState.d.ts +8 -0
  17. package/dist/modules/Discount/entitlementState.js +205 -0
  18. package/dist/modules/Discount/index.d.ts +5 -2
  19. package/dist/modules/Discount/index.js +124 -25
  20. package/dist/modules/Discount/types.d.ts +29 -6
  21. package/dist/modules/Holder/types.d.ts +1 -1
  22. package/dist/modules/OpenData/types.d.ts +1 -1
  23. package/dist/modules/Order/types.d.ts +5 -5
  24. package/dist/modules/Order/utils/bundleDiscountHydration.d.ts +1 -1
  25. package/dist/modules/Order/utils/orderCollectionIdentity.d.ts +1 -1
  26. package/dist/modules/Order/utils.d.ts +1 -1
  27. package/dist/modules/Payment/types.d.ts +7 -7
  28. package/dist/modules/Product/index.d.ts +1 -1
  29. package/dist/modules/ResourcePlanner/types.d.ts +4 -4
  30. package/dist/modules/Rules/entitlementLines.d.ts +8 -0
  31. package/dist/modules/Rules/entitlementLines.js +159 -0
  32. package/dist/modules/Rules/index.d.ts +13 -3
  33. package/dist/modules/Rules/index.js +617 -342
  34. package/dist/modules/Rules/types.d.ts +4 -4
  35. package/dist/modules/ScanOrderLogger/types.d.ts +2 -2
  36. package/dist/modules/Schedule/getDateIsInSchedule.d.ts +1 -1
  37. package/dist/modules/Schedule/type.d.ts +7 -7
  38. package/dist/modules/Schedule/types.d.ts +9 -9
  39. package/dist/plugins/app.d.ts +1 -1
  40. package/dist/plugins/request.d.ts +2 -2
  41. package/dist/plugins/window.d.ts +2 -2
  42. package/dist/server/modules/floor-plan/types.d.ts +1 -1
  43. package/dist/server/modules/menu/types.d.ts +1 -1
  44. package/dist/server/modules/order/types.d.ts +16 -16
  45. package/dist/server/modules/products/types.d.ts +1 -1
  46. package/dist/server/modules/resource/types.d.ts +1 -1
  47. package/dist/server/modules/schedule/utils.d.ts +1 -1
  48. package/dist/server/types.d.ts +4 -4
  49. package/dist/server/utils/small-ticket.d.ts +1 -1
  50. package/dist/solution/BaseSales/index.d.ts +1 -1
  51. package/dist/solution/BaseSales/types.d.ts +7 -7
  52. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -1
  53. package/dist/solution/BookingByStep/index.d.ts +1 -1
  54. package/dist/solution/BookingByStep/utils/resources.d.ts +1 -1
  55. package/dist/solution/BookingTicket/index.d.ts +13 -1
  56. package/dist/solution/BookingTicket/types.d.ts +3 -3
  57. package/dist/solution/BookingTicket/utils/addProductDecision.d.ts +1 -1
  58. package/dist/solution/BookingTicket/utils/bookingStatus.d.ts +1 -1
  59. package/dist/solution/BookingTicket/utils/scan/formatGlobalScan.d.ts +1 -1
  60. package/dist/solution/Sales/types.d.ts +4 -4
  61. package/dist/solution/ScanOrder/types.d.ts +5 -5
  62. package/dist/solution/ShopDiscount/index.d.ts +3 -0
  63. package/dist/solution/ShopDiscount/index.js +161 -78
  64. package/dist/solution/ShopDiscount/types.d.ts +1 -1
  65. package/dist/solution/ShopDiscount/utils.d.ts +3 -2
  66. package/dist/solution/ShopDiscount/utils.js +40 -1
  67. package/dist/solution/UnifiedBookingSales/types.d.ts +1 -1
  68. package/dist/solution/VenueBooking/types.d.ts +1 -1
  69. package/dist/types/index.d.ts +1 -1
  70. package/dist/utils/task.d.ts +2 -2
  71. package/dist/utils/watch.d.ts +2 -2
  72. package/lib/effects/index.d.ts +2 -2
  73. package/lib/model/strategy/adapter/dataVariant/type.d.ts +3 -3
  74. package/lib/model/strategy/adapter/itemRule/type.d.ts +6 -6
  75. package/lib/model/strategy/adapter/promotion/index.d.ts +4 -0
  76. package/lib/model/strategy/adapter/promotion/type.d.ts +5 -5
  77. package/lib/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
  78. package/lib/model/strategy/adapter/walletPass/evaluator.js +2 -0
  79. package/lib/model/strategy/type.d.ts +1 -1
  80. package/lib/modules/BookingContext/types.d.ts +4 -4
  81. package/lib/modules/BookingContext/utils/resourceErrors.d.ts +1 -1
  82. package/lib/modules/Customer/types.d.ts +1 -1
  83. package/lib/modules/Discount/availability.d.ts +7 -0
  84. package/lib/modules/Discount/availability.js +46 -0
  85. package/lib/modules/Discount/entitlementPass.d.ts +34 -0
  86. package/lib/modules/Discount/entitlementPass.js +141 -0
  87. package/lib/modules/Discount/entitlementState.d.ts +8 -0
  88. package/lib/modules/Discount/entitlementState.js +150 -0
  89. package/lib/modules/Discount/index.d.ts +5 -2
  90. package/lib/modules/Discount/index.js +59 -14
  91. package/lib/modules/Discount/types.d.ts +29 -6
  92. package/lib/modules/Holder/types.d.ts +1 -1
  93. package/lib/modules/OpenData/types.d.ts +1 -1
  94. package/lib/modules/Order/types.d.ts +5 -5
  95. package/lib/modules/Order/utils/bundleDiscountHydration.d.ts +1 -1
  96. package/lib/modules/Order/utils/orderCollectionIdentity.d.ts +1 -1
  97. package/lib/modules/Order/utils.d.ts +1 -1
  98. package/lib/modules/Payment/types.d.ts +7 -7
  99. package/lib/modules/Product/index.d.ts +1 -1
  100. package/lib/modules/ResourcePlanner/types.d.ts +4 -4
  101. package/lib/modules/Rules/entitlementLines.d.ts +8 -0
  102. package/lib/modules/Rules/entitlementLines.js +128 -0
  103. package/lib/modules/Rules/index.d.ts +13 -3
  104. package/lib/modules/Rules/index.js +284 -61
  105. package/lib/modules/Rules/types.d.ts +4 -4
  106. package/lib/modules/ScanOrderLogger/types.d.ts +2 -2
  107. package/lib/modules/Schedule/getDateIsInSchedule.d.ts +1 -1
  108. package/lib/modules/Schedule/type.d.ts +7 -7
  109. package/lib/modules/Schedule/types.d.ts +9 -9
  110. package/lib/plugins/app.d.ts +1 -1
  111. package/lib/plugins/request.d.ts +2 -2
  112. package/lib/plugins/window.d.ts +2 -2
  113. package/lib/server/modules/floor-plan/types.d.ts +1 -1
  114. package/lib/server/modules/menu/types.d.ts +1 -1
  115. package/lib/server/modules/order/types.d.ts +16 -16
  116. package/lib/server/modules/products/types.d.ts +1 -1
  117. package/lib/server/modules/resource/types.d.ts +1 -1
  118. package/lib/server/modules/schedule/utils.d.ts +1 -1
  119. package/lib/server/types.d.ts +4 -4
  120. package/lib/server/utils/small-ticket.d.ts +1 -1
  121. package/lib/solution/BaseSales/index.d.ts +1 -1
  122. package/lib/solution/BaseSales/types.d.ts +7 -7
  123. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -1
  124. package/lib/solution/BookingByStep/index.d.ts +1 -1
  125. package/lib/solution/BookingByStep/utils/resources.d.ts +1 -1
  126. package/lib/solution/BookingTicket/index.d.ts +13 -1
  127. package/lib/solution/BookingTicket/types.d.ts +3 -3
  128. package/lib/solution/BookingTicket/utils/addProductDecision.d.ts +1 -1
  129. package/lib/solution/BookingTicket/utils/bookingStatus.d.ts +1 -1
  130. package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.d.ts +1 -1
  131. package/lib/solution/Sales/types.d.ts +4 -4
  132. package/lib/solution/ScanOrder/types.d.ts +5 -5
  133. package/lib/solution/ShopDiscount/index.d.ts +3 -0
  134. package/lib/solution/ShopDiscount/index.js +55 -18
  135. package/lib/solution/ShopDiscount/types.d.ts +1 -1
  136. package/lib/solution/ShopDiscount/utils.d.ts +3 -2
  137. package/lib/solution/ShopDiscount/utils.js +39 -3
  138. package/lib/solution/UnifiedBookingSales/types.d.ts +1 -1
  139. package/lib/solution/VenueBooking/types.d.ts +1 -1
  140. package/lib/types/index.d.ts +1 -1
  141. package/lib/utils/task.d.ts +2 -2
  142. package/lib/utils/watch.d.ts +2 -2
  143. package/package.json +19 -18
@@ -1,6 +1,5 @@
1
1
  var _excluded = ["_original_add_price"],
2
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
3
  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
4
  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
5
  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; }
@@ -12,6 +11,7 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o =
12
11
  function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
13
12
  function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
14
13
  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; }
14
+ 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
15
  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
16
  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
17
  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,8 +35,14 @@ import { UnavailableReason } from "./types";
35
35
  import { uniqueById, getDiscountAmount, getDiscountListAmountTotal, getDiscountListAmount, filterDiscountListByBookingTime } from "../../solution/ShopDiscount/utils";
36
36
  import { getProductOriginTotalPrice, getProductTotalPrice } from "../Cart/utils";
37
37
  import Decimal from 'decimal.js';
38
- import { isBoolean } from 'lodash-es';
38
+ import { isBoolean, cloneDeep } from 'lodash-es';
39
39
  import dayjs from 'dayjs';
40
+ import { WalletPassEvaluator } from "../../model/strategy/adapter/walletPass/evaluator";
41
+ import { compareEntitlementPassPriority, getRemainingEntitlementUses, isEntitlementPass, isFullCoveragePass, resolveEntitlementQuota } from "../Discount/entitlementPass";
42
+ import { getDiscountUsageBlockReason, getDiscountUsageLimitFailKey } from "../Discount/availability";
43
+ import { withCommittedEntitlementDetails, isPersistedEntitlementLine } from "../Discount/entitlementState";
44
+ import { getDiscountTimeUnavailableReason } from "../../solution/ShopDiscount/utils";
45
+ import { prepareEntitlementLines, finalizeEntitlementLines, isEntitlementRuntimeLine, rebuildEntitlementLine } from "./entitlementLines";
40
46
  import { isOrderLevelFixedAmountDiscount } from "../../solution/ShopDiscount/utils";
41
47
  import { calculateOrderLevelDiscountAllocation } from "../../solution/ShopDiscount/utils";
42
48
  export var RulesModule = /*#__PURE__*/function (_BaseModule) {
@@ -52,10 +58,17 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
52
58
  _defineProperty(_assertThisInitialized(_this), "window", void 0);
53
59
  // WindowPlugin 实例
54
60
  _defineProperty(_assertThisInitialized(_this), "hooks", void 0);
61
+ _defineProperty(_assertThisInitialized(_this), "entitlementPassEnabled", false);
62
+ _defineProperty(_assertThisInitialized(_this), "defaultWalletPassEvaluator", void 0);
55
63
  _this.hooks = {};
56
64
  return _this;
57
65
  }
58
66
  _createClass(RulesModule, [{
67
+ key: "setEntitlementPassEnabled",
68
+ value: function setEntitlementPassEnabled(enabled) {
69
+ this.entitlementPassEnabled = enabled;
70
+ }
71
+ }, {
59
72
  key: "initialize",
60
73
  value: function () {
61
74
  var _initialize = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(core, options) {
@@ -109,37 +122,70 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
109
122
  var _this$window$getWalle, _this$window;
110
123
  return (_this$window$getWalle = (_this$window = this.window).getWalletPassEvaluator) === null || _this$window$getWalle === void 0 ? void 0 : _this$window$getWalle.call(_this$window);
111
124
  }
125
+ }, {
126
+ key: "normalizeHolderRecordIds",
127
+ value: function normalizeHolderRecordIds(value) {
128
+ var records = Array.isArray(value) ? value : [value];
129
+ return Array.from(new Set(records.map(function (record) {
130
+ if (record && _typeof(record) === 'object') {
131
+ return record.form_record_id;
132
+ }
133
+ return record;
134
+ }).filter(function (record) {
135
+ return record !== undefined && record !== null && record !== '' && record !== 0 && record !== '0';
136
+ }).map(String)));
137
+ }
112
138
 
113
- // 商品不需要holder,则不需要判断,直接返回true,商品需要holder但是还没填写,那么暂时不使用带有holder的券,直到填写才去匹配
139
+ /**
140
+ * 商品未开启 Holder 选择时跳过匹配;已开启时,特定 form Holder 卡
141
+ * 只适用于同一 Holder Record,是否必填不影响匹配规则。
142
+ */
114
143
  }, {
115
144
  key: "checkHolderMatch",
116
- value: function checkHolderMatch(discount, product, holders) {
117
- var _discount$holder;
145
+ value: function checkHolderMatch(discount, product, holderSource, holders) {
146
+ 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;
118
147
  // 非表单类型 holder 视为匹配
119
148
  if (((_discount$holder = discount.holder) === null || _discount$holder === void 0 ? void 0 : _discount$holder.holder_type) !== 'form') return true;
120
- // 主预约holder, 目前(20251124)默认只考虑单个holder的情况
121
- // 旧版 holders[0].form_record_id 新版 holders[0]
122
- var orderHolderId = Array.isArray(holders) && holders.length > 0 ? holders[0].form_record_id || holders[0] : undefined;
123
- var productHolderId = Array.isArray(product.holder_id) ? product.holder_id[0] : product.holder_id;
124
- // 商品不需要选holder,则不对比holder,直接返回true,
125
- if (!product.isNeedHolder) return true;
126
- // 商品需要holder,但父预约及商品都无holder,返回false
127
- if (!orderHolderId && !productHolderId) return false;
128
- // 最终直接匹配 holder 是否相同
129
- return (productHolderId || orderHolderId) === discount.holder.holder_id;
149
+
150
+ // 旧券沿用预约主体和单个 Holder 的匹配口径。
151
+ if (!isEntitlementPass(discount)) {
152
+ if (!product.isNeedHolder) return true;
153
+ var holder = holders === null || holders === void 0 ? void 0 : holders[0];
154
+ var orderHolderId = holder && _typeof(holder) === 'object' ? holder.form_record_id : holder;
155
+ var productHolderId = Array.isArray(product.holder_id) ? product.holder_id[0] : product.holder_id;
156
+ if (!orderHolderId && !productHolderId) return false;
157
+ return (productHolderId || orderHolderId) === discount.holder.holder_id;
158
+ }
159
+
160
+ // getProduct 会裁剪商品字段,从原始商品读取配置,套餐子项沿用父商品。
161
+ 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;
162
+ var holderStatus = holderConfig === null || holderConfig === void 0 ? void 0 : holderConfig.status;
163
+ var holderEnabled = holderStatus == null || holderStatus === '' || holderStatus === true || ['enable', '1'].includes(String(holderStatus).trim().toLowerCase());
164
+ if (!holderEnabled || !(holderConfig !== null && holderConfig !== void 0 && holderConfig.resource_id)) {
165
+ return true;
166
+ }
167
+ var discountHolderIds = this.normalizeHolderRecordIds(discount.holder.holder_id);
168
+ if (!discountHolderIds.length) return false;
169
+ var productHolderIds = this.normalizeHolderRecordIds(product.holder_id);
170
+ var candidateHolderIds = productHolderIds.length || Array.isArray(product.holder_id) ? productHolderIds : this.normalizeHolderRecordIds(holders);
171
+ if (!candidateHolderIds.length) return false;
172
+ var discountHolderIdSet = new Set(discountHolderIds);
173
+ return candidateHolderIds.every(function (holderId) {
174
+ return discountHolderIdSet.has(holderId);
175
+ });
130
176
  }
131
177
 
132
178
  // 判断discountList 是否可以对当前productList生效
133
179
  }, {
134
180
  key: "isDiscountListAvailable",
135
- value: function isDiscountListAvailable(_ref) {
181
+ value: function isDiscountListAvailable(_ref11) {
136
182
  var _this2 = this;
137
- var oldDiscountList = _ref.oldDiscountList,
138
- newDiscountList = _ref.newDiscountList,
139
- productList = _ref.productList,
140
- orderTotalAmount = _ref.orderTotalAmount,
141
- holders = _ref.holders,
142
- isFormSubject = _ref.isFormSubject;
183
+ var oldDiscountList = _ref11.oldDiscountList,
184
+ newDiscountList = _ref11.newDiscountList,
185
+ productList = _ref11.productList,
186
+ orderTotalAmount = _ref11.orderTotalAmount,
187
+ holders = _ref11.holders,
188
+ isFormSubject = _ref11.isFormSubject;
143
189
  // 首先检查是否有新的优惠券可应用
144
190
  if (!newDiscountList || newDiscountList.length === 0) {
145
191
  return {
@@ -150,7 +196,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
150
196
  }
151
197
 
152
198
  // 编辑商品已有商品券
153
- if (productList.every(function (item) {
199
+ if (!newDiscountList.some(isEntitlementPass) && productList.length > 0 && productList.every(function (item) {
154
200
  var _product$discount_lis;
155
201
  var product = _this2.hooks.getProduct(item);
156
202
  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);
@@ -168,10 +214,10 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
168
214
  var filteredOldDiscountList = oldDiscountList.filter(function (discount) {
169
215
  return !discount.isEditMode && (discount.tag !== 'good_pass' || discount.isScan);
170
216
  });
171
- var mergedDiscountList = uniqueById([].concat(_toConsumableArray(filteredOldDiscountList), _toConsumableArray(newDiscountList)));
217
+ var mergedDiscountList = uniqueById([].concat(_toConsumableArray(newDiscountList.filter(isEntitlementPass)), _toConsumableArray(filteredOldDiscountList), _toConsumableArray(newDiscountList)));
172
218
  var result = this.calcDiscount({
173
219
  discountList: mergedDiscountList,
174
- productList: _toConsumableArray(productList),
220
+ productList: this.entitlementPassEnabled ? cloneDeep(productList) : _toConsumableArray(productList),
175
221
  orderTotalAmount: orderTotalAmount,
176
222
  holders: holders,
177
223
  isFormSubject: isFormSubject
@@ -181,15 +227,16 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
181
227
 
182
228
  // 检查是否有产品使用了新折扣
183
229
  var hasApplicableDiscount = false;
184
- var newDiscountIds = newDiscountList.map(function (discount) {
185
- return discount.id;
186
- });
230
+ var newDiscountIds = new Set(newDiscountList.map(function (discount) {
231
+ return String(discount.id);
232
+ }));
187
233
 
188
234
  // 遍历处理后的产品列表,检查是否有产品使用了新折扣
189
235
  result.productList.forEach(function (product) {
190
- var _this2$hooks$getProdu = _this2.hooks.getProduct(product),
191
- discount_list = _this2$hooks$getProdu.discount_list,
192
- bundle = _this2$hooks$getProdu.bundle;
236
+ var mappedProduct = _this2.hooks.getProduct(product);
237
+ if (isPersistedEntitlementLine(product, mappedProduct)) return;
238
+ var discount_list = mappedProduct.discount_list,
239
+ bundle = mappedProduct.bundle;
193
240
  var allDiscountList = _toConsumableArray(discount_list || []);
194
241
  (bundle || []).forEach(function (item) {
195
242
  allDiscountList.push.apply(allDiscountList, _toConsumableArray((item === null || item === void 0 ? void 0 : item.discount_list) || []));
@@ -198,7 +245,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
198
245
  // 检查是否有使用新折扣的情况
199
246
  var usedNewDiscount = allDiscountList.some(function (discount) {
200
247
  var _discount$discount;
201
- return newDiscountIds.includes(discount === null || discount === void 0 || (_discount$discount = discount.discount) === null || _discount$discount === void 0 ? void 0 : _discount$discount.resource_id);
248
+ return newDiscountIds.has(String(discount === null || discount === void 0 || (_discount$discount = discount.discount) === null || _discount$discount === void 0 ? void 0 : _discount$discount.resource_id));
202
249
  });
203
250
  if (usedNewDiscount) {
204
251
  hasApplicableDiscount = true;
@@ -213,6 +260,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
213
260
  }
214
261
  return {
215
262
  isAvailable: hasApplicableDiscount,
263
+ evaluatedDiscountList: result.discountList,
216
264
  discountList: hasApplicableDiscount ? result.discountList : oldDiscountList,
217
265
  productList: hasApplicableDiscount ? result.productList : productList,
218
266
  unavailableReason: unavailableReason
@@ -257,7 +305,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
257
305
  for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
258
306
  var item = _step3.value;
259
307
  var product = this.hooks.getProduct(item);
260
- var bookingTime = ((product === null || product === void 0 ? void 0 : product.startDate) || dayjs()).format('YYYY-MM-DD HH:mm:ss');
308
+ var bookingTime = dayjs((product === null || product === void 0 ? void 0 : product.startDate) || undefined).format('YYYY-MM-DD HH:mm:ss');
261
309
  var filteredList = filterDiscountListByBookingTime([discount], bookingTime);
262
310
  if (filteredList.length === 0) {
263
311
  return UnavailableReason.TimeLimit;
@@ -282,6 +330,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
282
330
  for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
283
331
  var _discount = _step2.value;
284
332
  var limitedData = _discount.limited_relation_product_data;
333
+ if (!limitedData) return UnavailableReason.ProductNotApplicable;
285
334
  var hasApplicableProduct = false;
286
335
  var _iterator4 = _createForOfIteratorHelper(productList),
287
336
  _step4;
@@ -316,17 +365,63 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
316
365
  }
317
366
  }, {
318
367
  key: "calcDiscount",
319
- value: function calcDiscount(_ref2, options) {
320
- var _options$selectedList,
321
- _this3 = this;
322
- var discountList = _ref2.discountList,
323
- productList = _ref2.productList,
324
- holders = _ref2.holders,
325
- isFormSubject = _ref2.isFormSubject,
326
- orderTotalAmount = _ref2.orderTotalAmount;
368
+ value: function calcDiscount(_ref12, options) {
369
+ var _this3 = this,
370
+ _options$selectedList;
371
+ var discountList = _ref12.discountList,
372
+ productList = _ref12.productList,
373
+ holders = _ref12.holders,
374
+ isFormSubject = _ref12.isFormSubject,
375
+ orderTotalAmount = _ref12.orderTotalAmount;
327
376
  var resolveIsFormSubject = function resolveIsFormSubject(product) {
328
377
  return typeof isFormSubject === 'function' ? Boolean(isFormSubject(product)) : Boolean(isFormSubject);
329
378
  };
379
+ discountList = this.entitlementPassEnabled ? withCommittedEntitlementDetails(discountList, productList, this.hooks.getProduct) : discountList.filter(function (item) {
380
+ return !isEntitlementPass(item);
381
+ });
382
+ var usableEntitlements = discountList.filter(function (discount) {
383
+ return isEntitlementPass(discount) && !discount.isEditMode && !discount.isManualSelect && !getDiscountUsageBlockReason(discount);
384
+ });
385
+ var canUseEntitlement = function canUseEntitlement(originProduct) {
386
+ var _product$original_pri;
387
+ var product = _this3.hooks.getProduct(originProduct);
388
+ if (product.vouchersApplicable === false) return false;
389
+ // 预判任一份可用就按份拆开,实际抵扣仍逐份核对 Holder。
390
+ var holderProducts = Array.isArray(product.holder_id) && product.holder_id.length > 1 ? product.holder_id.map(function (holder_id) {
391
+ return _objectSpread(_objectSpread({}, product), {}, {
392
+ holder_id: holder_id
393
+ });
394
+ }) : [product];
395
+ var items = [{
396
+ type: 'main',
397
+ id: product.id,
398
+ price: (_product$original_pri = product.original_price) !== null && _product$original_pri !== void 0 ? _product$original_pri : product.price
399
+ }].concat(_toConsumableArray((product.bundle || []).map(function (bundleItem) {
400
+ var _ref13, _bundleItem$_bundle_p, _bundleItem$original_;
401
+ return {
402
+ type: 'bundle',
403
+ 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,
404
+ price: (_bundleItem$original_ = bundleItem.original_price) !== null && _bundleItem$original_ !== void 0 ? _bundleItem$original_ : bundleItem.price,
405
+ bundleItem: bundleItem
406
+ };
407
+ })));
408
+ return usableEntitlements.some(function (discount) {
409
+ var scope = discount.limited_relation_product_data;
410
+ if (!scope || !holderProducts.some(function (item) {
411
+ return _this3.checkHolderMatch(discount, item, originProduct, holders);
412
+ }) || !filterDiscountListByBookingTime([discount], dayjs(product.startDate || undefined).format('YYYY-MM-DD HH:mm:ss')).length) return false;
413
+ return items.some(function (item) {
414
+ var _scope$exclude_produc, _scope$product_ids;
415
+ 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) {
416
+ return String(id) === String(item.id);
417
+ })) : !!((_scope$product_ids = scope.product_ids) !== null && _scope$product_ids !== void 0 && _scope$product_ids.includes(item.id))) && _this3.checkPackageSubItemUsageRules(discount, _objectSpread(_objectSpread({}, item), {}, {
418
+ originProduct: originProduct,
419
+ parentProduct: product
420
+ }));
421
+ });
422
+ });
423
+ };
424
+ if (this.entitlementPassEnabled) productList = prepareEntitlementLines(productList, this.hooks, canUseEntitlement);
330
425
 
331
426
  // 识别出来是不是在编辑的界面里又新增了商品
332
427
  // 这种情况下,如果有可用的优惠券,也会自动勾选上
@@ -367,7 +462,11 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
367
462
  if (discount.isEditMode) {
368
463
  editModeDiscount.push(discount);
369
464
  } else {
370
- addModeDiscount.push(discount);
465
+ addModeDiscount.push(isEntitlementPass(discount) ? _objectSpread(_objectSpread({}, discount), {}, {
466
+ config: undefined,
467
+ reason: undefined,
468
+ reasonCode: undefined
469
+ }) : discount);
371
470
  }
372
471
  });
373
472
 
@@ -430,6 +529,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
430
529
  // 2. 展开 bundle 子商品
431
530
  if (product.bundle && Array.isArray(product.bundle) && product.bundle.length > 0) {
432
531
  product.bundle.forEach(function (bundleItem, bundleIndex) {
532
+ var _ref14, _bundleItem$_bundle_p2;
433
533
  flattened.push({
434
534
  type: 'bundle',
435
535
  originProduct: originProduct,
@@ -438,8 +538,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
438
538
  bundleIndex: bundleIndex,
439
539
  // 虚拟商品属性
440
540
  price: Number(bundleItem.price || 0),
441
- id: bundleItem._bundle_product_id,
442
- // 🔥 使用 _bundle_product_id
541
+ 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,
443
542
  _id: "".concat(product._id, "_bundle_").concat(bundleIndex),
444
543
  parentId: product._id,
445
544
  num: bundleItem.num || 1,
@@ -545,6 +644,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
545
644
  }
546
645
  return 0;
547
646
  }
647
+ if (isEntitlementPass(a) || isEntitlementPass(b)) {
648
+ return isEntitlementPass(a) && isEntitlementPass(b) ? compareEntitlementPassPriority(a, b) : isEntitlementPass(a) ? -1 : 1;
649
+ }
548
650
 
549
651
  // 1. 先按优先级排序
550
652
  var priorityA = getPriority(a);
@@ -588,10 +690,10 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
588
690
 
589
691
  // 对扁平化后的列表按价格降序排序(用于应用优惠券时优先选择高价商品)
590
692
  var sortedFlattenedList = flattenedList.sort(function (a, b) {
591
- var _ref3, _a$original_price, _ref4, _b$original_price;
693
+ var _ref15, _a$original_price, _ref16, _b$original_price;
592
694
  // 子商品优先使用 original_price,主商品使用 price
593
- 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');
594
- 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');
695
+ 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');
696
+ 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');
595
697
  if (priceA.equals(priceB)) {
596
698
  // 价格相同时,主商品优先
597
699
  if (a.type !== b.type) {
@@ -709,6 +811,90 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
709
811
  usedDiscountCardLimitCounts.set(discount.id, currentCount + (((_discount$metadata4 = discount.metadata) === null || _discount$metadata4 === void 0 ? void 0 : _discount$metadata4.num) || 1));
710
812
  }
711
813
  });
814
+ var entitlementUsageCounts = new Map();
815
+ var markDiscountUsed = function markDiscountUsed(discount) {
816
+ if (isEntitlementPass(discount)) {
817
+ entitlementUsageCounts.set(discount.id, (entitlementUsageCounts.get(discount.id) || 0) + 1);
818
+ usedProductIdCounts.set(discount.product_id, (usedProductIdCounts.get(discount.product_id) || 0) + 1);
819
+ } else {
820
+ usedDiscounts.set(discount.id, true);
821
+ }
822
+ };
823
+
824
+ // 沿用商品券逐份拆分,同一多次卡可重复分配,数量受本单剩余额度限制。
825
+ var getFullCoveragePasses = function getFullCoveragePasses(discounts, quantity) {
826
+ var allocated = [];
827
+ var productCounts = new Map(usedProductIdCounts);
828
+ var _iterator5 = _createForOfIteratorHelper(discounts),
829
+ _step5;
830
+ try {
831
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
832
+ var _discount$config;
833
+ var discount = _step5.value;
834
+ if (!isFullCoveragePass(discount) || allocated.length >= quantity) continue;
835
+ var count = isEntitlementPass(discount) ? getRemainingEntitlementUses(discount, entitlementUsageCounts.get(discount.id) || 0, quantity - allocated.length) : usedDiscounts.get(discount.id) ? 0 : 1;
836
+ var limit = Number(((_discount$config = discount.config) === null || _discount$config === void 0 ? void 0 : _discount$config.maxUsagePerOrder) || 0);
837
+ if (limit > 0) {
838
+ count = Math.min(count, Math.max(0, Math.floor(limit) - (productCounts.get(discount.product_id) || 0)));
839
+ }
840
+ for (var i = 0; i < count; i++) allocated.push(discount);
841
+ productCounts.set(discount.product_id, (productCounts.get(discount.product_id) || 0) + count);
842
+ }
843
+ } catch (err) {
844
+ _iterator5.e(err);
845
+ } finally {
846
+ _iterator5.f();
847
+ }
848
+ return allocated;
849
+ };
850
+ addModeDiscount.filter(isEntitlementPass).forEach(function (discount) {
851
+ var _this3$defaultWalletP, _discount$unified_ava, _discount$limited_rel3, _discount$limited_rel4;
852
+ discount.usageLimitFailKey = getDiscountUsageLimitFailKey(discount);
853
+ discount.reasonCode = getDiscountUsageBlockReason(discount);
854
+ var quota = resolveEntitlementQuota(discount);
855
+ if (discount.reasonCode || !quota) {
856
+ discount.config = {
857
+ isAvailable: false
858
+ };
859
+ return;
860
+ }
861
+ var entitlementEvaluator = evaluator || ((_this3$defaultWalletP = _this3.defaultWalletPassEvaluator) !== null && _this3$defaultWalletP !== void 0 ? _this3$defaultWalletP : _this3.defaultWalletPassEvaluator = new WalletPassEvaluator());
862
+ var result = entitlementEvaluator.checkVoucherAvailability({
863
+ // 兼容尚未传入订单总额的预约组件,保留多次卡原有的金额计算。
864
+ orderTotalAmount: orderTotalAmount || productList.reduce(function (sum, item) {
865
+ var product = _this3.hooks.getProduct(item);
866
+ return sum.plus(new Decimal(product.origin_total || 0).times(product.quantity || product.num || 1));
867
+ }, new Decimal(0)).toNumber(),
868
+ // 策略按统一商品结构读主价与数量,套餐次数还需乘父商品份数。
869
+ products: sortedFlattenedList.map(function (item) {
870
+ var _item$parentProduct, _item$parentProduct2, _item$product2;
871
+ return {
872
+ product_id: item.id,
873
+ price: item.price || 0,
874
+ main_product_selling_price: item.price || 0,
875
+ 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),
876
+ product_options: item.type === 'main' ? (_item$product2 = item.product) === null || _item$product2 === void 0 ? void 0 : _item$product2.options : undefined
877
+ };
878
+ }),
879
+ vouchers: [_objectSpread(_objectSpread({}, discount), {}, {
880
+ amount: Number(discount.par_value || 0),
881
+ balance: quota.type === 'unlimited' ? Number.MAX_SAFE_INTEGER : quota.balance,
882
+ type: 'entitlement_pass',
883
+ unified_available_status: (_discount$unified_ava = discount.unified_available_status) !== null && _discount$unified_ava !== void 0 ? _discount$unified_ava : 1,
884
+ available_product_type: (_discount$limited_rel3 = discount.limited_relation_product_data) === null || _discount$limited_rel3 === void 0 ? void 0 : _discount$limited_rel3.type,
885
+ available_product_ids: (_discount$limited_rel4 = discount.limited_relation_product_data) === null || _discount$limited_rel4 === void 0 ? void 0 : _discount$limited_rel4.product_ids
886
+ })]
887
+ });
888
+ discount.config = _objectSpread(_objectSpread({}, result.config), {}, {
889
+ isAvailable: result.isAvailable
890
+ });
891
+ if (!result.isAvailable) {
892
+ discount.reason = result.reason;
893
+ discount.reasonCode = result.reasonCode || 'not_meet_the_required_conditions';
894
+ }
895
+ });
896
+ var entitlementTimeReasons = new Map();
897
+ var entitlementHolderMismatch = new Set();
712
898
 
713
899
  // 记录每个优惠券适用的商品ID
714
900
  var discountApplicability = new Map();
@@ -754,7 +940,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
754
940
 
755
941
  // 编辑的商品使用了优惠券不可用
756
942
  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) {
757
- return d.id && ['good_pass', 'discount_card', 'product_discount_card'].includes(d.tag || d.type);
943
+ return d.id && ['entitlement_pass', 'good_pass', 'discount_card', 'product_discount_card'].includes(d.tag || d.type);
758
944
  })) : !(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) {
759
945
  return d.id;
760
946
  }));
@@ -774,7 +960,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
774
960
  var limitedData = discount.limited_relation_product_data;
775
961
 
776
962
  // 时间限制检查
777
- var timeLimit = !!filterDiscountListByBookingTime([discount], (((_product5 = product) === null || _product5 === void 0 ? void 0 : _product5.startDate) || dayjs()).format('YYYY-MM-DD HH:mm:ss')).length;
963
+ var timeLimit = !!filterDiscountListByBookingTime([discount], dayjs(((_product5 = product) === null || _product5 === void 0 ? void 0 : _product5.startDate) || undefined).format('YYYY-MM-DD HH:mm:ss')).length;
778
964
  if (!timeLimit) {
779
965
  return false;
780
966
  }
@@ -854,7 +1040,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
854
1040
  // 收集该折扣卡适用的商品(排除被其他专属折扣卡占用的商品)
855
1041
  var applicableProducts = [];
856
1042
  sortedFlattenedList.forEach(function (flatItem) {
857
- var _flatItem$parentProdu2, _flatItem$parentProdu3, _product$price, _ref5, _flatItem$original_pr;
1043
+ var _flatItem$parentProdu2, _flatItem$parentProdu3, _product$price, _ref17, _flatItem$original_pr;
858
1044
  // 🔥 检查该商品是否被其他专属折扣卡占用
859
1045
  var occupyingDiscountId = occupiedItems.get(flatItem._id);
860
1046
  if (occupyingDiscountId !== undefined && occupyingDiscountId !== discount.id) {
@@ -882,7 +1068,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
882
1068
 
883
1069
  // 对于主商品:使用 price
884
1070
  // 对于子商品:优先使用 flatItem.original_price,否则使用 flatItem.price
885
- 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);
1071
+ 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);
886
1072
 
887
1073
  // 传递 parentQuantity 用于差值处理时判断是否是真正的"数量为1"
888
1074
  var productData = {
@@ -938,18 +1124,26 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
938
1124
  originProduct = flatItem.originProduct;
939
1125
  }
940
1126
  addModeDiscount.forEach(function (discount) {
941
- var _product6, _product7, _product8, _product9, _flatItem$bundleItem3, _flatItem$bundleItem4, _discount$config;
1127
+ var _discount$config2, _product6, _product7, _product8, _product9, _flatItem$bundleItem3, _flatItem$bundleItem4, _ref18, _discount$config3;
942
1128
  var limitedData = discount === null || discount === void 0 ? void 0 : discount.limited_relation_product_data;
1129
+ if (!limitedData || isEntitlementPass(discount) && ((_discount$config2 = discount.config) === null || _discount$config2 === void 0 ? void 0 : _discount$config2.isAvailable) === false) return;
943
1130
  // 拿到discount配置的holder信息 product信息 product.holder 加在 isLimitedProduct
944
1131
  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;
945
1132
  var isHolderMatch = _this3.checkHolderMatch(discount, {
946
1133
  isNeedHolder: resolveIsFormSubject(_tempVar) && !(_tempVar !== null && _tempVar !== void 0 && _tempVar.isNormalProduct),
947
1134
  holder_id: (_tempVar === null || _tempVar === void 0 ? void 0 : _tempVar.holder_id) || product.holder_id
948
- }, holders);
1135
+ }, flatItem.originProduct, holders);
949
1136
  var timeLimit = true;
950
- timeLimit = !!filterDiscountListByBookingTime([discount], (((_product6 = product) === null || _product6 === void 0 ? void 0 : _product6.startDate) || dayjs()).format('YYYY-MM-DD HH:mm:ss')).length;
1137
+ var useTime = dayjs(((_product6 = product) === null || _product6 === void 0 ? void 0 : _product6.startDate) || undefined).format('YYYY-MM-DD HH:mm:ss');
1138
+ timeLimit = !!filterDiscountListByBookingTime([discount], useTime).length;
1139
+ if (isEntitlementPass(discount)) {
1140
+ var reasons = entitlementTimeReasons.get(discount.id) || [];
1141
+ reasons.push(getDiscountTimeUnavailableReason(discount, useTime));
1142
+ entitlementTimeReasons.set(discount.id, reasons);
1143
+ if (!isHolderMatch) entitlementHolderMismatch.add(discount.id);
1144
+ }
951
1145
  // 是符合折扣的商品
952
- 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;
1146
+ var isLimitedProduct = (limitedData.type === 'product_all' && isProductIncludedByLimitedData(limitedData, product.id) || limitedData.product_ids && limitedData.product_ids.includes(product.id)) && isHolderMatch;
953
1147
 
954
1148
  // 编辑的商品 使用了优惠券不可用
955
1149
  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) {
@@ -962,7 +1156,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
962
1156
  var isBundleAvailable = _this3.checkPackageSubItemUsageRules(discount, flatItem);
963
1157
 
964
1158
  // 判断优惠券是否适用于该商品
965
- if (isAvailableProduct && isLimitedProduct && timeLimit && isBundleAvailable && (_discount$config = discount.config) !== null && _discount$config !== void 0 && _discount$config.isAvailable) {
1159
+ if (isAvailableProduct && !isPersistedEntitlementLine(originProduct, flatItem.type === 'main' ? flatItem.product : flatItem.parentProduct) && (!isEntitlementPass(discount) || ((_ref18 = flatItem.type === 'main' ? flatItem.product : flatItem.parentProduct) === null || _ref18 === void 0 ? void 0 : _ref18.vouchersApplicable) !== false) && isLimitedProduct && timeLimit && isBundleAvailable && (_discount$config3 = discount.config) !== null && _discount$config3 !== void 0 && _discount$config3.isAvailable) {
966
1160
  var _discountApplicabilit, _discount$metadata5, _discount$metadata6;
967
1161
  // 记录此优惠券适用的商品
968
1162
  (_discountApplicabilit = discountApplicability.get(discount.id)) === null || _discountApplicabilit === void 0 || _discountApplicabilit.push(product.id);
@@ -970,7 +1164,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
970
1164
  // 记录可抵扣的商品详情
971
1165
  var applicableProducts = discountApplicableProducts.get(discount.id) || [];
972
1166
  var discountType = discount.tag || discount.type;
973
- var isGoodPass = discountType === 'good_pass';
1167
+ var isGoodPass = isFullCoveragePass(discount);
974
1168
 
975
1169
  // 使用数量
976
1170
  var num = isGoodPass || (flatItem === null || flatItem === void 0 ? void 0 : flatItem.type) === 'main' ? 1 : product.num;
@@ -986,7 +1180,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
986
1180
  title: discount.format_title,
987
1181
  original_amount: product.price || product.origin_total,
988
1182
  pre_value: discount.par_value,
989
- product_id: originProduct.id || originProduct.product_id,
1183
+ product_id: isEntitlementPass(discount) ? product.id : originProduct.id || originProduct.product_id,
990
1184
  discount_product_id: discount.product_id
991
1185
  },
992
1186
  metadata: {
@@ -1011,13 +1205,13 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1011
1205
  };
1012
1206
  var optionDiscountAmount = 0;
1013
1207
  var discountedOptions = options.map(function (option) {
1014
- var _ref6, _ref7, _option$_original_pri, _ref8, _option$num, _rest$price, _option$_original_pri2;
1208
+ var _ref19, _ref20, _option$_original_pri, _ref21, _option$num, _rest$price, _option$_original_pri2;
1015
1209
  // 折前单价:优先 price,缺失再 add_price;已写回折后价时用 _original_price(或旧字段 _original_add_price)
1016
- 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;
1210
+ var rawUnit = (_ref19 = (_ref20 = (_option$_original_pri = option._original_price) !== null && _option$_original_pri !== void 0 ? _option$_original_pri : option._original_add_price) !== null && _ref20 !== void 0 ? _ref20 : option.price) !== null && _ref19 !== void 0 ? _ref19 : option.add_price;
1017
1211
  var baseUnitNum = Number(rawUnit !== null && rawUnit !== void 0 ? rawUnit : 0);
1018
1212
  if (baseUnitNum <= 0) return option;
1019
1213
  var discountedPrice = getDiscountAmount(discount, baseUnitNum, baseUnitNum);
1020
- var optQty = Number((_ref8 = (_option$num = option.num) !== null && _option$num !== void 0 ? _option$num : option.quantity) !== null && _ref8 !== void 0 ? _ref8 : 1);
1214
+ var optQty = Number((_ref21 = (_option$num = option.num) !== null && _option$num !== void 0 ? _option$num : option.quantity) !== null && _ref21 !== void 0 ? _ref21 : 1);
1021
1215
  optionDiscountAmount = new Decimal(optionDiscountAmount).plus(new Decimal(baseUnitNum).minus(discountedPrice).mul(optQty)).toNumber();
1022
1216
  var _original_add_price = option._original_add_price,
1023
1217
  rest = _objectWithoutProperties(option, _excluded);
@@ -1051,9 +1245,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1051
1245
  var getOptionTotal = function getOptionTotal(options) {
1052
1246
  if (!(options !== null && options !== void 0 && options.length)) return 0;
1053
1247
  return options.reduce(function (sum, opt) {
1054
- var _ref9, _opt$price, _ref10, _opt$num;
1055
- var unit = Number((_ref9 = (_opt$price = opt.price) !== null && _opt$price !== void 0 ? _opt$price : opt.add_price) !== null && _ref9 !== void 0 ? _ref9 : 0);
1056
- var n = Number((_ref10 = (_opt$num = opt.num) !== null && _opt$num !== void 0 ? _opt$num : opt.quantity) !== null && _ref10 !== void 0 ? _ref10 : 1);
1248
+ var _ref22, _opt$price, _ref23, _opt$num;
1249
+ var unit = Number((_ref22 = (_opt$price = opt.price) !== null && _opt$price !== void 0 ? _opt$price : opt.add_price) !== null && _ref22 !== void 0 ? _ref22 : 0);
1250
+ var n = Number((_ref23 = (_opt$num = opt.num) !== null && _opt$num !== void 0 ? _opt$num : opt.quantity) !== null && _ref23 !== void 0 ? _ref23 : 1);
1057
1251
  return new Decimal(sum).plus(new Decimal(unit).mul(n)).toNumber();
1058
1252
  }, 0);
1059
1253
  };
@@ -1094,7 +1288,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1094
1288
  }));
1095
1289
 
1096
1290
  // 已持久化且已有钱包券/折扣卡的商品行跳过,保留后端历史折扣结果。
1097
- if (isPersistedProduct && hasExistingWalletDiscount) {
1291
+ if (isPersistedEntitlementLine(originProduct, flatItem.type === 'main' ? flatItem.product : flatItem.parentProduct) || isPersistedProduct && hasExistingWalletDiscount) {
1098
1292
  if (flatItem.type === 'main') {
1099
1293
  processedProductsMap.set(product._id, [originProduct]);
1100
1294
  } else {
@@ -1107,7 +1301,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1107
1301
 
1108
1302
  // 找到适用于此商品的所有优惠券,仅考虑isSelected不为false的优惠券
1109
1303
  var applicableDiscounts = sortedDiscountList.filter(function (discount) {
1110
- var _product$discount_lis3, _product$discount_lis4;
1304
+ var _discount$config4, _ref24, _product$discount_lis3, _product$discount_lis4;
1305
+ if (isEntitlementPass(discount) && (((_discount$config4 = discount.config) === null || _discount$config4 === void 0 ? void 0 : _discount$config4.isAvailable) !== true || ((_ref24 = flatItem.type === 'main' ? flatItem.product : flatItem.parentProduct) === null || _ref24 === void 0 ? void 0 : _ref24.vouchersApplicable) === false || getRemainingEntitlementUses(discount, entitlementUsageCounts.get(discount.id) || 0, 1) <= 0)) return false;
1111
1306
  // 🔥 检查策略可用性(针对 good_pass 和折扣卡)
1112
1307
  var discountType = discount.tag || discount.type;
1113
1308
  var currentOriginUid = getOriginProductUid(originProduct);
@@ -1118,30 +1313,30 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1118
1313
  if (!discount.isSelected) return false;
1119
1314
  }
1120
1315
  if (['good_pass', 'discount_card', 'product_discount_card'].includes(discountType) && !isReapplyEditModeDiscountForProduct) {
1121
- var _discount$config2;
1316
+ var _discount$config5;
1122
1317
  // 如果策略检查后没有config,说明不可用
1123
- if (discount.config === undefined || !(discount !== null && discount !== void 0 && (_discount$config2 = discount.config) !== null && _discount$config2 !== void 0 && _discount$config2.isAvailable)) {
1318
+ if (discount.config === undefined || !(discount !== null && discount !== void 0 && (_discount$config5 = discount.config) !== null && _discount$config5 !== void 0 && _discount$config5.isAvailable)) {
1124
1319
  return false;
1125
1320
  }
1126
1321
  }
1127
1322
 
1128
1323
  // 如果商品价格为 0,其实不需要使用任何优惠券,直接 return true
1129
1324
  // 商品券时主商品价格为0不可用
1130
- 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;
1325
+ 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;
1131
1326
 
1132
1327
  // 折扣卡商品价格为0时不可用
1133
1328
  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) {
1134
1329
  var _n$discount;
1135
1330
  return ((_n$discount = n.discount) === null || _n$discount === void 0 ? void 0 : _n$discount.resource_id) === discount.id;
1136
- })) && (discount.tag || discount.type) !== 'good_pass') return false;
1331
+ })) && !isFullCoveragePass(discount)) return false;
1137
1332
  // 如果优惠券已被使用,则跳过
1138
1333
  var targetUsedDiscounts = usedDiscounts.get(discount.id);
1139
1334
  if (targetUsedDiscounts && (discount.tag || discount.type) === 'good_pass') return false;
1140
1335
 
1141
1336
  // 🔥 检查 maxUsagePerOrder 限制:同一 product_id 的商品券使用数量不能超过配置值
1142
- if ((discount.tag || discount.type) === 'good_pass') {
1143
- var _discount$config3;
1144
- var maxUsagePerOrder = (_discount$config3 = discount.config) === null || _discount$config3 === void 0 ? void 0 : _discount$config3.maxUsagePerOrder;
1337
+ if (isFullCoveragePass(discount)) {
1338
+ var _discount$config6;
1339
+ var maxUsagePerOrder = (_discount$config6 = discount.config) === null || _discount$config6 === void 0 ? void 0 : _discount$config6.maxUsagePerOrder;
1145
1340
  if (maxUsagePerOrder && maxUsagePerOrder > 0) {
1146
1341
  var currentUsedCount = usedProductIdCounts.get(discount.product_id) || 0;
1147
1342
  if (currentUsedCount >= maxUsagePerOrder) {
@@ -1153,8 +1348,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1153
1348
  // 🔥 检查折扣卡的 applicableProductLimit 限制:折扣卡可使用的最大次数(跨商品全局)
1154
1349
  var discountTypeForLimit = discount.tag || discount.type;
1155
1350
  if (['discount_card', 'product_discount_card'].includes(discountTypeForLimit)) {
1156
- var _discount$config4;
1157
- var applicableProductLimitConfig = ((_discount$config4 = discount.config) === null || _discount$config4 === void 0 ? void 0 : _discount$config4.applicableProductLimit) || 0;
1351
+ var _discount$config7;
1352
+ var applicableProductLimitConfig = ((_discount$config7 = discount.config) === null || _discount$config7 === void 0 ? void 0 : _discount$config7.applicableProductLimit) || 0;
1158
1353
  if (applicableProductLimitConfig > 0) {
1159
1354
  var currentUsedLimitCount = usedDiscountCardLimitCounts.get(discount.id) || 0;
1160
1355
  if (currentUsedLimitCount >= applicableProductLimitConfig) {
@@ -1163,17 +1358,18 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1163
1358
  }
1164
1359
  }
1165
1360
  var limitedData = discount.limited_relation_product_data;
1361
+ if (!limitedData) return false;
1166
1362
 
1167
1363
  // 拿到discount配置的holder信息 product信息 product.holder 不可用return false
1168
1364
  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;
1169
1365
  var isHolderMatch = _this3.checkHolderMatch(discount, {
1170
1366
  isNeedHolder: resolveIsFormSubject(_tempVar) && !(_tempVar !== null && _tempVar !== void 0 && _tempVar.isNormalProduct),
1171
1367
  holder_id: (_tempVar === null || _tempVar === void 0 ? void 0 : _tempVar.holder_id) || product.holder_id
1172
- }, holders);
1368
+ }, flatItem.originProduct, holders);
1173
1369
  // 如果 holder 不匹配,则不适用
1174
1370
  if (!isHolderMatch) return false;
1175
1371
  var timeLimit = true;
1176
- timeLimit = !!filterDiscountListByBookingTime([discount], (product.startDate || dayjs()).format('YYYY-MM-DD HH:mm:ss')).length;
1372
+ timeLimit = !!filterDiscountListByBookingTime([discount], dayjs(product.startDate || undefined).format('YYYY-MM-DD HH:mm:ss')).length;
1177
1373
  if (!timeLimit) {
1178
1374
  return false;
1179
1375
  }
@@ -1203,9 +1399,12 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1203
1399
  // 如果有 isScan 且 isSelected 的折扣卡,则优先选中,否则再选择第一个
1204
1400
  // 用于处理:先手动扫描了一张折扣卡,扫描完以后带入客户信息,但是之前那张折扣卡不是最优惠的情况
1205
1401
  var selectedDiscountCard = applicableDiscounts.find(function (n) {
1206
- return n.isScan && n.isSelected && (n.tag || n.type) !== 'good_pass';
1402
+ return n.isScan && n.isSelected && !isFullCoveragePass(n);
1207
1403
  });
1208
- var selectedDiscount = selectedDiscountCard || applicableDiscounts[0];
1404
+ var explicitlySelected = (options === null || options === void 0 ? void 0 : options.isSelected) === true ? applicableDiscounts.find(function (item) {
1405
+ return isEntitlementPass(item) && String(item.id) === String(options.discountId);
1406
+ }) : undefined;
1407
+ var selectedDiscount = explicitlySelected || selectedDiscountCard || applicableDiscounts[0];
1209
1408
 
1210
1409
  // 如果是手动折扣,则不适用优惠券
1211
1410
  var isManualDiscount = false;
@@ -1215,8 +1414,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1215
1414
  isManualDiscount = typeof product.isManualDiscount === 'boolean' ? product.isManualDiscount : ((_product$discount_lis5 = product.discount_list) === null || _product$discount_lis5 === void 0 ? void 0 : _product$discount_lis5.some(function (item) {
1216
1415
  return item.type === 'product';
1217
1416
  })) || product.total != product.origin_total && (product.bundle || []).every(function (item) {
1218
- var _ref11;
1219
- return !((_ref11 = item.discount_list || []) !== null && _ref11 !== void 0 && _ref11.length);
1417
+ var _ref25;
1418
+ return !((_ref25 = item.discount_list || []) !== null && _ref25 !== void 0 && _ref25.length);
1220
1419
  }) && (!((_product$discount_lis6 = product.discount_list) !== null && _product$discount_lis6 !== void 0 && _product$discount_lis6.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) {
1221
1420
  return item.type === 'product';
1222
1421
  })));
@@ -1231,8 +1430,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1231
1430
  isManualDiscount = typeof parentProduct.isManualDiscount === 'boolean' ? parentProduct.isManualDiscount : ((_parentProduct$discou = parentProduct.discount_list) === null || _parentProduct$discou === void 0 ? void 0 : _parentProduct$discou.some(function (item) {
1232
1431
  return item.type === 'product';
1233
1432
  })) || parentProduct.total != parentProduct.origin_total && (parentProduct.bundle || []).every(function (item) {
1234
- var _ref12;
1235
- return !((_ref12 = item.discount_list || []) !== null && _ref12 !== void 0 && _ref12.length);
1433
+ var _ref26;
1434
+ return !((_ref26 = item.discount_list || []) !== null && _ref26 !== void 0 && _ref26.length);
1236
1435
  }) && (!((_parentProduct$discou2 = parentProduct.discount_list) !== null && _parentProduct$discou2 !== void 0 && _parentProduct$discou2.length) || (parentProduct === null || parentProduct === void 0 || (_parentProduct$discou3 = parentProduct.discount_list) === null || _parentProduct$discou3 === void 0 || (_parentProduct$discou4 = _parentProduct$discou3.every) === null || _parentProduct$discou4 === void 0 ? void 0 : _parentProduct$discou4.call(_parentProduct$discou3, function (item) {
1237
1436
  return item.type === 'product';
1238
1437
  })));
@@ -1325,8 +1524,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1325
1524
  discount_list: isManualDiscount ? _this3.resolveDiscountListForManualOverride(product.discount_list) : _this3.filterDiscountListByType(product.discount_list, 'promotion')
1326
1525
  }))]);
1327
1526
  } else {
1328
- var _ref13, _product$_promotion$f, _product13, _product$origin_total, _product$price2;
1329
- 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;
1527
+ var _ref27, _product$_promotion$f, _product13, _product$origin_total, _product$price2;
1528
+ var total = product.inPromotion ? (_ref27 = (_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 && _ref27 !== void 0 ? _ref27 : product.total : (_product$origin_total = product.origin_total) !== null && _product$origin_total !== void 0 ? _product$origin_total : product.total;
1330
1529
  var main_product_selling_price = (_product$price2 = product.price) !== null && _product$price2 !== void 0 ? _product$price2 : product.main_product_selling_price;
1331
1530
  if ((product.discount_list || []).some(function (item) {
1332
1531
  return item.type === 'promotion';
@@ -1365,7 +1564,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1365
1564
 
1366
1565
  // 是否需要拆分(商品券需要拆分,折扣卡在 applicableProductLimit > 0 时也需要拆分)
1367
1566
  var discountType = selectedDiscount.tag || selectedDiscount.type;
1368
- var isGoodPass = discountType === 'good_pass';
1567
+ var isGoodPass = isFullCoveragePass(selectedDiscount);
1369
1568
  var isDiscountCard = ['discount_card', 'product_discount_card'].includes(discountType);
1370
1569
  var applicableProductLimit = ((_selectedDiscount$con = selectedDiscount.config) === null || _selectedDiscount$con === void 0 ? void 0 : _selectedDiscount$con.applicableProductLimit) || 0;
1371
1570
 
@@ -1377,10 +1576,15 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1377
1576
  var availableGoodPassCount = applicableDiscounts.filter(function (item) {
1378
1577
  return (item.tag || item.type) === 'good_pass';
1379
1578
  }).length;
1579
+ var allocatedPasses = isGoodPass && applicableDiscounts.some(isEntitlementPass) ? getFullCoveragePasses([selectedDiscount].concat(_toConsumableArray(applicableDiscounts.filter(function (item) {
1580
+ return item !== selectedDiscount;
1581
+ }))), totalQuantity) : undefined;
1380
1582
 
1381
1583
  // 🔥 计算最大使用次数限制
1382
1584
  var maxUsageLimit;
1383
- if (isGoodPass) {
1585
+ if (allocatedPasses) {
1586
+ maxUsageLimit = allocatedPasses.length;
1587
+ } else if (isGoodPass) {
1384
1588
  // 商品券:使用 maxUsagePerOrder 限制
1385
1589
  maxUsageLimit = availableGoodPassCount;
1386
1590
  if (selectedDiscount.config && selectedDiscount.config.maxUsagePerOrder) {
@@ -1421,9 +1625,10 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1421
1625
  var _originProduct4, _selectedDiscount$con2, _product$options, _product$options2, _selectedDiscount$met, _selectedDiscount$met2, _reapplyDiscountPerce;
1422
1626
  // 商品券:每个拆分商品使用不同的商品券(从 applicableDiscounts 按索引取)
1423
1627
  // 折扣卡:所有拆分商品使用同一张折扣卡(selectedDiscountCard 或 applicableDiscounts[0])
1424
- var currentSelectedDiscount = isGoodPass ? selectedDiscountCard || applicableDiscounts[i] : selectedDiscountCard || applicableDiscounts[0];
1628
+ var currentSelectedDiscount = (allocatedPasses === null || allocatedPasses === void 0 ? void 0 : allocatedPasses[i]) || (isGoodPass ? selectedDiscountCard || applicableDiscounts[i] : selectedDiscountCard || applicableDiscounts[0]);
1629
+ var _selectedDiscount = currentSelectedDiscount;
1425
1630
  // 标记优惠券为已使用
1426
- usedDiscounts.set(currentSelectedDiscount.id, true);
1631
+ markDiscountUsed(currentSelectedDiscount);
1427
1632
  // 🔥 更新 product_id 使用计数
1428
1633
  if ((currentSelectedDiscount.tag || currentSelectedDiscount.type) === 'good_pass') {
1429
1634
  var currentCount = usedProductIdCounts.get(currentSelectedDiscount.product_id) || 0;
@@ -1452,10 +1657,10 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1452
1657
 
1453
1658
  // 计算使用折扣卡/商品券以后,单个商品的总 total
1454
1659
  // 🔥 检查是否是 order_level 固定金额折扣卡
1455
- var isOrderLevel = isOrderLevelFixedAmountDiscount(selectedDiscount);
1456
- var orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount.id) : null;
1660
+ var isOrderLevel = isOrderLevelFixedAmountDiscount(_selectedDiscount);
1661
+ var orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(_selectedDiscount.id) : null;
1457
1662
  var productAllocation = orderLevelAllocation === null || orderLevelAllocation === void 0 ? void 0 : orderLevelAllocation.get(flatItem._id);
1458
- var isDeductOptionPrice = !!((_selectedDiscount$con2 = selectedDiscount.config) !== null && _selectedDiscount$con2 !== void 0 && _selectedDiscount$con2.deductOptionPrice);
1663
+ var isDeductOptionPrice = !!((_selectedDiscount$con2 = _selectedDiscount.config) !== null && _selectedDiscount$con2 !== void 0 && _selectedDiscount$con2.deductOptionPrice);
1459
1664
 
1460
1665
  // 主商品折后价(不含 option);勿与 option 合计混在同一变量,否则 main_product_selling_price 错误
1461
1666
  var mainProductSellingPrice = void 0;
@@ -1469,19 +1674,19 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1469
1674
  amount = productAllocation.discountAmount;
1470
1675
  productDiscountDifference = productAllocation.difference;
1471
1676
  mainProductSellingPrice = Math.max(new Decimal(product.price).minus(amount).toNumber(), 0);
1472
- } else if (resolveReapplyEditModeDiscountPercent(originProduct, selectedDiscount) !== undefined) {
1677
+ } else if (resolveReapplyEditModeDiscountPercent(originProduct, _selectedDiscount) !== undefined) {
1473
1678
  // Change time 重套编辑态折扣卡时,历史 par_value 不是运行时折扣口径,优先使用后端快照里的 percent。
1474
- var percent = resolveReapplyEditModeDiscountPercent(originProduct, selectedDiscount);
1679
+ var percent = resolveReapplyEditModeDiscountPercent(originProduct, _selectedDiscount);
1475
1680
  reapplyDiscountPercent = new Decimal(percent).toFixed(2);
1476
1681
  mainProductSellingPrice = new Decimal(product.price || 0).mul(new Decimal(100).minus(percent)).div(100).toDecimalPlaces(2).toNumber();
1477
1682
  amount = new Decimal(product.price).minus(mainProductSellingPrice).toNumber();
1478
1683
  } else {
1479
1684
  // item_level 或其他类型:使用原有逻辑
1480
- mainProductSellingPrice = getDiscountAmount(selectedDiscount, product.price, product.price);
1685
+ mainProductSellingPrice = getDiscountAmount(_selectedDiscount, product.price, product.price);
1481
1686
  amount = new Decimal(product.price).minus(new Decimal(mainProductSellingPrice)).toNumber();
1482
1687
  }
1483
1688
  if (isDeductOptionPrice && (_product$options = product.options) !== null && _product$options !== void 0 && _product$options.length) {
1484
- var optionResult = applyDiscountToOptions(product.options, selectedDiscount);
1689
+ var optionResult = applyDiscountToOptions(product.options, _selectedDiscount);
1485
1690
  discountedOptions = optionResult.discountedOptions;
1486
1691
  optionDiscountAmount = optionResult.optionDiscountAmount;
1487
1692
  }
@@ -1494,28 +1699,28 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1494
1699
  // discount_list.amount / fixed_amount:行级总优惠 = 主商品优惠 + option 优惠(与 total 变化一致)
1495
1700
  var mainProductDiscountAmount = amount;
1496
1701
  var lineDiscountAmount = new Decimal(mainProductDiscountAmount).plus(optionDiscountAmount).toNumber();
1497
- var _discountType = selectedDiscount.tag || selectedDiscount.type;
1498
- var currentIsGoodPass = _discountType === 'good_pass';
1702
+ var _discountType = _selectedDiscount.tag || _selectedDiscount.type;
1703
+ var currentIsGoodPass = isFullCoveragePass(_selectedDiscount);
1499
1704
  var discountDetail = {
1500
1705
  amount: lineDiscountAmount,
1501
- type: selectedDiscount.tag === 'product_discount_card' ? 'discount_card' : _discountType,
1706
+ type: _selectedDiscount.tag === 'product_discount_card' ? 'discount_card' : _discountType,
1502
1707
  discount: {
1503
- discount_card_type: selectedDiscount === null || selectedDiscount === void 0 || (_selectedDiscount$met = selectedDiscount.metadata) === null || _selectedDiscount$met === void 0 ? void 0 : _selectedDiscount$met.discount_card_type,
1708
+ discount_card_type: _selectedDiscount === null || _selectedDiscount === void 0 || (_selectedDiscount$met = _selectedDiscount.metadata) === null || _selectedDiscount$met === void 0 ? void 0 : _selectedDiscount$met.discount_card_type,
1504
1709
  fixed_amount: lineDiscountAmount,
1505
- discount_calculation_mode: selectedDiscount === null || selectedDiscount === void 0 || (_selectedDiscount$met2 = selectedDiscount.metadata) === null || _selectedDiscount$met2 === void 0 ? void 0 : _selectedDiscount$met2.discount_calculation_mode,
1506
- resource_id: selectedDiscount.id,
1507
- title: selectedDiscount.format_title,
1710
+ discount_calculation_mode: _selectedDiscount === null || _selectedDiscount === void 0 || (_selectedDiscount$met2 = _selectedDiscount.metadata) === null || _selectedDiscount$met2 === void 0 ? void 0 : _selectedDiscount$met2.discount_calculation_mode,
1711
+ resource_id: _selectedDiscount.id,
1712
+ title: _selectedDiscount.format_title,
1508
1713
  original_amount: product.price,
1509
- product_id: originProduct.id || originProduct.product_id,
1510
- percent: (_reapplyDiscountPerce = reapplyDiscountPercent) !== null && _reapplyDiscountPerce !== void 0 ? _reapplyDiscountPerce : selectedDiscount.par_value,
1511
- discount_product_id: selectedDiscount.product_id
1714
+ product_id: isEntitlementPass(_selectedDiscount) ? product.id : originProduct.id || originProduct.product_id,
1715
+ percent: (_reapplyDiscountPerce = reapplyDiscountPercent) !== null && _reapplyDiscountPerce !== void 0 ? _reapplyDiscountPerce : _selectedDiscount.par_value,
1716
+ discount_product_id: _selectedDiscount.product_id
1512
1717
  },
1513
1718
  // 前端使用的num数量,为了计算优惠金额(拆分时为1)
1514
1719
  _num: isNeedSplit ? 1 : product.num,
1515
1720
  config: currentSelectedDiscount === null || currentSelectedDiscount === void 0 ? void 0 : currentSelectedDiscount.config,
1516
1721
  metadata: _objectSpread(_objectSpread({
1517
1722
  num: 1,
1518
- discount_rule_uncheck_flag: selectedDiscount === null || selectedDiscount === void 0 ? void 0 : selectedDiscount.discount_rule_uncheck_flag
1723
+ discount_rule_uncheck_flag: _selectedDiscount === null || _selectedDiscount === void 0 ? void 0 : _selectedDiscount.discount_rule_uncheck_flag
1519
1724
  }, productDiscountDifference !== undefined && {
1520
1725
  product_discount_difference: productDiscountDifference
1521
1726
  }), {}, {
@@ -1525,7 +1730,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1525
1730
  })
1526
1731
  };
1527
1732
  appliedProducts.push(discountDetail);
1528
- appliedDiscountProducts.set(selectedDiscount.id, appliedProducts);
1733
+ appliedDiscountProducts.set(_selectedDiscount.id, appliedProducts);
1529
1734
 
1530
1735
  // 记录应用了优惠券的商品
1531
1736
  // 后续更新价格改为 getProductTotalPrice getProductOriginTotalPrice逻辑
@@ -1574,8 +1779,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1574
1779
  var _currentBundleDiscoun, _currentBundleDiscoun2;
1575
1780
  // 商品券:每个拆分商品使用不同的商品券
1576
1781
  // 折扣卡:所有拆分商品使用同一张折扣卡
1577
- var currentBundleDiscount = isGoodPass ? selectedDiscountCard || applicableDiscounts[_i] : selectedDiscountCard || applicableDiscounts[0];
1578
- usedDiscounts.set(currentBundleDiscount.id, true);
1782
+ var currentBundleDiscount = (allocatedPasses === null || allocatedPasses === void 0 ? void 0 : allocatedPasses[_i]) || (isGoodPass ? selectedDiscountCard || applicableDiscounts[_i] : selectedDiscountCard || applicableDiscounts[0]);
1783
+ markDiscountUsed(currentBundleDiscount);
1579
1784
  // 🔥 更新 product_id 使用计数
1580
1785
  if ((currentBundleDiscount.tag || currentBundleDiscount.type) === 'good_pass') {
1581
1786
  var _currentCount = usedProductIdCounts.get(currentBundleDiscount.product_id) || 0;
@@ -1597,7 +1802,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1597
1802
  debugger;
1598
1803
 
1599
1804
  // 确定折扣类型
1600
- var bundleDiscountType = currentBundleDiscount.tag === 'product_discount_card' ? 'discount_card' : currentBundleDiscount.tag;
1805
+ var bundleDiscountType = currentBundleDiscount.tag === 'product_discount_card' ? 'discount_card' : currentBundleDiscount.tag || currentBundleDiscount.type;
1601
1806
  var _discountDetail = {
1602
1807
  amount: bundleDiscountAmount,
1603
1808
  type: bundleDiscountType,
@@ -1609,12 +1814,12 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1609
1814
  title: currentBundleDiscount.format_title,
1610
1815
  original_amount: product.origin_total,
1611
1816
  product_id: product.id || product.product_id,
1612
- discount_product_id: selectedDiscount.product_id
1817
+ discount_product_id: currentBundleDiscount.product_id
1613
1818
  },
1614
1819
  metadata: {
1615
1820
  // 🔥 使用拆分后的唯一 _id
1616
1821
  custom_product_bundle_map_id: uniqueId,
1617
- discount_rule_uncheck_flag: selectedDiscount === null || selectedDiscount === void 0 ? void 0 : selectedDiscount.discount_rule_uncheck_flag,
1822
+ discount_rule_uncheck_flag: currentBundleDiscount === null || currentBundleDiscount === void 0 ? void 0 : currentBundleDiscount.discount_rule_uncheck_flag,
1618
1823
  num: 1
1619
1824
  },
1620
1825
  _num: 1,
@@ -1642,236 +1847,251 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1642
1847
  // 🔥 对拆分后的剩余商品继续匹配其他可用折扣(而不是等到下次执行才应用)
1643
1848
  var remainingNum = normalNum;
1644
1849
  var continueSplitIndex = discountNum;
1645
- while (remainingNum > 0) {
1646
- var _nextSelectedDiscount;
1647
- // 重新查找适用于剩余商品的可用折扣(已使用的会被自动过滤掉)
1648
- var nextApplicableDiscounts = sortedDiscountList.filter(function (nextDiscount) {
1649
- var _product$discount_lis11;
1650
- var nextDiscountType = nextDiscount.tag || nextDiscount.type;
1651
- // 检查策略可用性
1652
- if (['good_pass', 'discount_card', 'product_discount_card'].includes(nextDiscountType)) {
1653
- var _nextDiscount$config;
1654
- if (nextDiscount.config === undefined || !(nextDiscount !== null && nextDiscount !== void 0 && (_nextDiscount$config = nextDiscount.config) !== null && _nextDiscount$config !== void 0 && _nextDiscount$config.isAvailable)) {
1655
- return false;
1850
+ var _loop = function _loop() {
1851
+ var _nextSelectedDiscount;
1852
+ // 重新查找适用于剩余商品的可用折扣(已使用的会被自动过滤掉)
1853
+ var nextApplicableDiscounts = sortedDiscountList.filter(function (nextDiscount) {
1854
+ var _product$discount_lis11;
1855
+ var nextDiscountType = nextDiscount.tag || nextDiscount.type;
1856
+ if (isEntitlementPass(nextDiscount)) {
1857
+ var _nextDiscount$config, _flatItem$parentProdu9;
1858
+ if (((_nextDiscount$config = nextDiscount.config) === null || _nextDiscount$config === void 0 ? void 0 : _nextDiscount$config.isAvailable) !== true || ((_flatItem$parentProdu9 = flatItem.parentProduct) === null || _flatItem$parentProdu9 === void 0 ? void 0 : _flatItem$parentProdu9.vouchersApplicable) === false || getRemainingEntitlementUses(nextDiscount, entitlementUsageCounts.get(nextDiscount.id) || 0, 1) <= 0 || !_this3.checkHolderMatch(nextDiscount, flatItem.parentProduct, originProduct, holders) || !filterDiscountListByBookingTime([nextDiscount], dayjs(product.startDate || undefined).format('YYYY-MM-DD HH:mm:ss')).length) return false;
1656
1859
  }
1657
- }
1658
- // 折扣卡时总价为0时不可用
1659
- if ((Number(product.total) <= 0 || !product.total) && !((_product$discount_lis11 = product.discount_list) !== null && _product$discount_lis11 !== void 0 && _product$discount_lis11.find(function (n) {
1660
- var _n$discount2;
1661
- return ((_n$discount2 = n.discount) === null || _n$discount2 === void 0 ? void 0 : _n$discount2.resource_id) === nextDiscount.id;
1662
- })) && nextDiscountType !== 'good_pass') return false;
1663
-
1664
- // 商品券已被使用则跳过
1665
- if (usedDiscounts.get(nextDiscount.id) && nextDiscountType === 'good_pass') return false;
1666
-
1667
- // 检查 maxUsagePerOrder 限制
1668
- if (nextDiscountType === 'good_pass') {
1669
- var _nextDiscount$config2;
1670
- var maxUsagePerOrder = (_nextDiscount$config2 = nextDiscount.config) === null || _nextDiscount$config2 === void 0 ? void 0 : _nextDiscount$config2.maxUsagePerOrder;
1671
- if (maxUsagePerOrder && maxUsagePerOrder > 0) {
1672
- var currentUsedCount = usedProductIdCounts.get(nextDiscount.product_id) || 0;
1673
- if (currentUsedCount >= maxUsagePerOrder) {
1860
+ // 检查策略可用性
1861
+ if (['good_pass', 'discount_card', 'product_discount_card'].includes(nextDiscountType)) {
1862
+ var _nextDiscount$config2;
1863
+ if (nextDiscount.config === undefined || !(nextDiscount !== null && nextDiscount !== void 0 && (_nextDiscount$config2 = nextDiscount.config) !== null && _nextDiscount$config2 !== void 0 && _nextDiscount$config2.isAvailable)) {
1674
1864
  return false;
1675
1865
  }
1676
1866
  }
1677
- }
1867
+ // 折扣卡时总价为0时不可用
1868
+ if ((Number(product.total) <= 0 || !product.total) && !((_product$discount_lis11 = product.discount_list) !== null && _product$discount_lis11 !== void 0 && _product$discount_lis11.find(function (n) {
1869
+ var _n$discount2;
1870
+ return ((_n$discount2 = n.discount) === null || _n$discount2 === void 0 ? void 0 : _n$discount2.resource_id) === nextDiscount.id;
1871
+ })) && !isFullCoveragePass(nextDiscount)) return false;
1872
+
1873
+ // 商品券已被使用则跳过
1874
+ if (usedDiscounts.get(nextDiscount.id) && nextDiscountType === 'good_pass') return false;
1875
+
1876
+ // 检查 maxUsagePerOrder 限制
1877
+ if (isFullCoveragePass(nextDiscount)) {
1878
+ var _nextDiscount$config3;
1879
+ var maxUsagePerOrder = (_nextDiscount$config3 = nextDiscount.config) === null || _nextDiscount$config3 === void 0 ? void 0 : _nextDiscount$config3.maxUsagePerOrder;
1880
+ if (maxUsagePerOrder && maxUsagePerOrder > 0) {
1881
+ var currentUsedCount = usedProductIdCounts.get(nextDiscount.product_id) || 0;
1882
+ if (currentUsedCount >= maxUsagePerOrder) {
1883
+ return false;
1884
+ }
1885
+ }
1886
+ }
1678
1887
 
1679
- // 检查折扣卡的 applicableProductLimit 限制
1680
- if (['discount_card', 'product_discount_card'].includes(nextDiscountType)) {
1681
- var _nextDiscount$config3;
1682
- var limitConfig = ((_nextDiscount$config3 = nextDiscount.config) === null || _nextDiscount$config3 === void 0 ? void 0 : _nextDiscount$config3.applicableProductLimit) || 0;
1683
- if (limitConfig > 0) {
1684
- var currentUsedLimitCount = usedDiscountCardLimitCounts.get(nextDiscount.id) || 0;
1685
- if (currentUsedLimitCount >= limitConfig) {
1888
+ // 检查折扣卡的 applicableProductLimit 限制
1889
+ if (['discount_card', 'product_discount_card'].includes(nextDiscountType)) {
1890
+ var _nextDiscount$config4;
1891
+ var limitConfig = ((_nextDiscount$config4 = nextDiscount.config) === null || _nextDiscount$config4 === void 0 ? void 0 : _nextDiscount$config4.applicableProductLimit) || 0;
1892
+ if (limitConfig > 0) {
1893
+ var currentUsedLimitCount = usedDiscountCardLimitCounts.get(nextDiscount.id) || 0;
1894
+ if (currentUsedLimitCount >= limitConfig) {
1895
+ return false;
1896
+ }
1897
+ }
1898
+ }
1899
+ var limitedData = nextDiscount.limited_relation_product_data;
1900
+ if (!limitedData) return false;
1901
+ if (limitedData.type === 'product_all') {
1902
+ if (!isProductIncludedByLimitedData(limitedData, product.id)) {
1903
+ return false;
1904
+ }
1905
+ if (!_this3.checkPackageSubItemUsageRules(nextDiscount, flatItem)) {
1686
1906
  return false;
1687
1907
  }
1908
+ return true;
1909
+ } else if (limitedData.product_ids && limitedData.product_ids.includes(product.id)) {
1910
+ if (!_this3.checkPackageSubItemUsageRules(nextDiscount, flatItem)) {
1911
+ return false;
1912
+ }
1913
+ return true;
1688
1914
  }
1915
+ return false;
1916
+ });
1917
+
1918
+ // 没有更多可用折扣,剩余商品无折扣存储
1919
+ if (nextApplicableDiscounts.length === 0) {
1920
+ processedItems.push(_objectSpread(_objectSpread({}, flatItem), {}, {
1921
+ _id: "".concat(flatItem._id, "_split_rest"),
1922
+ num: remainingNum,
1923
+ quantity: remainingNum,
1924
+ discount_list: [],
1925
+ processed: true
1926
+ }));
1927
+ return 0; // break
1689
1928
  }
1690
- var limitedData = nextDiscount.limited_relation_product_data;
1691
- if (limitedData.type === 'product_all') {
1692
- if (limitedData.filter === 1 && limitedData.exclude_product_ids.includes(product.id)) {
1693
- return false;
1694
- }
1695
- if (!_this3.checkPackageSubItemUsageRules(nextDiscount, flatItem)) {
1696
- return false;
1929
+
1930
+ // 选择最优折扣
1931
+ var nextSelectedDiscountCard = nextApplicableDiscounts.find(function (n) {
1932
+ return n.isScan && n.isSelected && !isFullCoveragePass(n);
1933
+ });
1934
+ var nextSelectedDiscount = nextSelectedDiscountCard || nextApplicableDiscounts[0];
1935
+
1936
+ // 判断新折扣是否需要拆分
1937
+ var nextDiscType = nextSelectedDiscount.tag || nextSelectedDiscount.type;
1938
+ var nextIsGoodPass = isFullCoveragePass(nextSelectedDiscount);
1939
+ var nextIsDiscountCard = ['discount_card', 'product_discount_card'].includes(nextDiscType);
1940
+ var nextApplicableProductLimit = ((_nextSelectedDiscount = nextSelectedDiscount.config) === null || _nextSelectedDiscount === void 0 ? void 0 : _nextSelectedDiscount.applicableProductLimit) || 0;
1941
+ var nextIsNeedSplit = nextIsGoodPass || nextIsDiscountCard && nextApplicableProductLimit > 0;
1942
+ if (!nextIsNeedSplit) {
1943
+ var _nextBundleDiscount$m, _flatItem$parentProdu10;
1944
+ // 🔥 不需要拆分:直接应用折扣到所有剩余商品
1945
+ var nextBundleDiscount = nextSelectedDiscountCard || nextApplicableDiscounts[0];
1946
+ usedDiscounts.set(nextBundleDiscount.id, true);
1947
+ if ((nextBundleDiscount.tag || nextBundleDiscount.type) === 'good_pass') {
1948
+ var curCount = usedProductIdCounts.get(nextBundleDiscount.product_id) || 0;
1949
+ usedProductIdCounts.set(nextBundleDiscount.product_id, curCount + 1);
1697
1950
  }
1698
- return true;
1699
- } else if (limitedData.product_ids && limitedData.product_ids.includes(product.id)) {
1700
- if (!_this3.checkPackageSubItemUsageRules(nextDiscount, flatItem)) {
1701
- return false;
1951
+ var nextNoSplitType = nextBundleDiscount.tag || nextBundleDiscount.type;
1952
+ if (['discount_card', 'product_discount_card'].includes(nextNoSplitType)) {
1953
+ var _curCount = usedDiscountCardLimitCounts.get(nextBundleDiscount.id) || 0;
1954
+ usedDiscountCardLimitCounts.set(nextBundleDiscount.id, _curCount + remainingNum);
1702
1955
  }
1703
- return true;
1956
+ var nextOriginTotal = product.original_price || product.price || 0;
1957
+ var nextTargetTotal = getDiscountAmount(nextBundleDiscount, nextOriginTotal, nextOriginTotal);
1958
+ var nextDiscountAmount = new Decimal(nextOriginTotal).minus(nextTargetTotal).toNumber();
1959
+ var nextUniqueId = "".concat(flatItem._id, "_split_").concat(continueSplitIndex);
1960
+ var nextBundleDiscType = nextBundleDiscount.tag === 'product_discount_card' ? 'discount_card' : nextBundleDiscount.tag || nextBundleDiscount.type;
1961
+ var nextDiscountDetail = {
1962
+ amount: nextDiscountAmount * remainingNum,
1963
+ type: nextBundleDiscType,
1964
+ discount: {
1965
+ discount_card_type: nextBundleDiscount === null || nextBundleDiscount === void 0 || (_nextBundleDiscount$m = nextBundleDiscount.metadata) === null || _nextBundleDiscount$m === void 0 ? void 0 : _nextBundleDiscount$m.discount_card_type,
1966
+ fixed_amount: nextDiscountAmount,
1967
+ resource_id: nextBundleDiscount.id,
1968
+ title: nextBundleDiscount.format_title,
1969
+ original_amount: product.original_price,
1970
+ product_id: product.id,
1971
+ percent: nextBundleDiscount.par_value,
1972
+ discount_product_id: nextBundleDiscount.product_id
1973
+ },
1974
+ metadata: {
1975
+ custom_product_bundle_map_id: nextUniqueId,
1976
+ num: remainingNum
1977
+ },
1978
+ config: nextBundleDiscount === null || nextBundleDiscount === void 0 ? void 0 : nextBundleDiscount.config,
1979
+ _num: remainingNum * ((flatItem === null || flatItem === void 0 || (_flatItem$parentProdu10 = flatItem.parentProduct) === null || _flatItem$parentProdu10 === void 0 ? void 0 : _flatItem$parentProdu10.num) || 1)
1980
+ };
1981
+ var nextAppliedProducts = appliedDiscountProducts.get(nextBundleDiscount.id) || [];
1982
+ nextAppliedProducts.push(nextDiscountDetail);
1983
+ appliedDiscountProducts.set(nextBundleDiscount.id, nextAppliedProducts);
1984
+ processedItems.push(_objectSpread(_objectSpread({}, flatItem), {}, {
1985
+ _id: nextUniqueId,
1986
+ num: remainingNum,
1987
+ quantity: remainingNum,
1988
+ total: nextTargetTotal,
1989
+ price: new Decimal(nextOriginTotal || 0).minus(nextDiscountDetail.discount.fixed_amount).toNumber(),
1990
+ discount_list: [nextDiscountDetail],
1991
+ processed: true
1992
+ }));
1993
+ remainingNum = 0;
1994
+ return 0; // break
1704
1995
  }
1705
- return false;
1706
- });
1707
1996
 
1708
- // 没有更多可用折扣,剩余商品无折扣存储
1709
- if (nextApplicableDiscounts.length === 0) {
1710
- processedItems.push(_objectSpread(_objectSpread({}, flatItem), {}, {
1711
- _id: "".concat(flatItem._id, "_split_rest"),
1712
- num: remainingNum,
1713
- quantity: remainingNum,
1714
- discount_list: [],
1715
- processed: true
1716
- }));
1717
- break;
1718
- }
1719
-
1720
- // 选择最优折扣
1721
- var nextSelectedDiscountCard = nextApplicableDiscounts.find(function (n) {
1722
- return n.isScan && n.isSelected && (n.tag || n.type) !== 'good_pass';
1723
- });
1724
- var nextSelectedDiscount = nextSelectedDiscountCard || nextApplicableDiscounts[0];
1725
-
1726
- // 判断新折扣是否需要拆分
1727
- var nextDiscType = nextSelectedDiscount.tag || nextSelectedDiscount.type;
1728
- var nextIsGoodPass = nextDiscType === 'good_pass';
1729
- var nextIsDiscountCard = ['discount_card', 'product_discount_card'].includes(nextDiscType);
1730
- var nextApplicableProductLimit = ((_nextSelectedDiscount = nextSelectedDiscount.config) === null || _nextSelectedDiscount === void 0 ? void 0 : _nextSelectedDiscount.applicableProductLimit) || 0;
1731
- var nextIsNeedSplit = nextIsGoodPass || nextIsDiscountCard && nextApplicableProductLimit > 0;
1732
- if (!nextIsNeedSplit) {
1733
- var _nextBundleDiscount$m, _flatItem$parentProdu9;
1734
- // 🔥 不需要拆分:直接应用折扣到所有剩余商品
1735
- var nextBundleDiscount = nextSelectedDiscountCard || nextApplicableDiscounts[0];
1736
- usedDiscounts.set(nextBundleDiscount.id, true);
1737
- if ((nextBundleDiscount.tag || nextBundleDiscount.type) === 'good_pass') {
1738
- var curCount = usedProductIdCounts.get(nextBundleDiscount.product_id) || 0;
1739
- usedProductIdCounts.set(nextBundleDiscount.product_id, curCount + 1);
1740
- }
1741
- var nextNoSplitType = nextBundleDiscount.tag || nextBundleDiscount.type;
1742
- if (['discount_card', 'product_discount_card'].includes(nextNoSplitType)) {
1743
- var _curCount = usedDiscountCardLimitCounts.get(nextBundleDiscount.id) || 0;
1744
- usedDiscountCardLimitCounts.set(nextBundleDiscount.id, _curCount + remainingNum);
1997
+ // 🔥 需要拆分:计算最大使用次数
1998
+ var nextAllocatedPasses = nextIsGoodPass && nextApplicableDiscounts.some(isEntitlementPass) ? getFullCoveragePasses([nextSelectedDiscount].concat(_toConsumableArray(nextApplicableDiscounts.filter(function (item) {
1999
+ return item !== nextSelectedDiscount;
2000
+ }))), remainingNum) : undefined;
2001
+ var nextMaxUsageLimit;
2002
+ if (nextAllocatedPasses) {
2003
+ nextMaxUsageLimit = nextAllocatedPasses.length;
2004
+ } else if (nextIsGoodPass) {
2005
+ var _nextSelectedDiscount2;
2006
+ var nextGoodPassCount = nextApplicableDiscounts.filter(function (item) {
2007
+ return (item.tag || item.type) === 'good_pass';
2008
+ }).length;
2009
+ nextMaxUsageLimit = nextGoodPassCount;
2010
+ if ((_nextSelectedDiscount2 = nextSelectedDiscount.config) !== null && _nextSelectedDiscount2 !== void 0 && _nextSelectedDiscount2.maxUsagePerOrder) {
2011
+ var usedCount = usedProductIdCounts.get(nextSelectedDiscount.product_id) || 0;
2012
+ nextMaxUsageLimit = Math.min(nextGoodPassCount, Math.max(0, nextSelectedDiscount.config.maxUsagePerOrder - usedCount));
2013
+ }
2014
+ } else if (nextIsDiscountCard && nextApplicableProductLimit > 0) {
2015
+ var _usedLimitCount = usedDiscountCardLimitCounts.get(nextSelectedDiscount.id) || 0;
2016
+ nextMaxUsageLimit = Math.max(0, nextApplicableProductLimit - _usedLimitCount);
2017
+ } else {
2018
+ nextMaxUsageLimit = 1;
1745
2019
  }
1746
- var nextOriginTotal = product.original_price || product.price || 0;
1747
- var nextTargetTotal = getDiscountAmount(nextBundleDiscount, nextOriginTotal, nextOriginTotal);
1748
- var nextDiscountAmount = new Decimal(nextOriginTotal).minus(nextTargetTotal).toNumber();
1749
- var nextUniqueId = "".concat(flatItem._id, "_split_").concat(continueSplitIndex);
1750
- var nextBundleDiscType = nextBundleDiscount.tag === 'product_discount_card' ? 'discount_card' : nextBundleDiscount.tag;
1751
- var nextDiscountDetail = {
1752
- amount: nextDiscountAmount * remainingNum,
1753
- type: nextBundleDiscType,
1754
- discount: {
1755
- discount_card_type: nextBundleDiscount === null || nextBundleDiscount === void 0 || (_nextBundleDiscount$m = nextBundleDiscount.metadata) === null || _nextBundleDiscount$m === void 0 ? void 0 : _nextBundleDiscount$m.discount_card_type,
1756
- fixed_amount: nextDiscountAmount,
1757
- resource_id: nextBundleDiscount.id,
1758
- title: nextBundleDiscount.format_title,
1759
- original_amount: product.original_price,
1760
- product_id: product.id,
1761
- percent: nextBundleDiscount.par_value,
1762
- discount_product_id: nextBundleDiscount.product_id
1763
- },
1764
- metadata: {
1765
- custom_product_bundle_map_id: nextUniqueId,
1766
- num: remainingNum
1767
- },
1768
- config: nextBundleDiscount === null || nextBundleDiscount === void 0 ? void 0 : nextBundleDiscount.config,
1769
- _num: remainingNum * ((flatItem === null || flatItem === void 0 || (_flatItem$parentProdu9 = flatItem.parentProduct) === null || _flatItem$parentProdu9 === void 0 ? void 0 : _flatItem$parentProdu9.num) || 1)
1770
- };
1771
- var nextAppliedProducts = appliedDiscountProducts.get(nextBundleDiscount.id) || [];
1772
- nextAppliedProducts.push(nextDiscountDetail);
1773
- appliedDiscountProducts.set(nextBundleDiscount.id, nextAppliedProducts);
1774
- processedItems.push(_objectSpread(_objectSpread({}, flatItem), {}, {
1775
- _id: nextUniqueId,
1776
- num: remainingNum,
1777
- quantity: remainingNum,
1778
- total: nextTargetTotal,
1779
- price: new Decimal(nextOriginTotal || 0).minus(nextDiscountDetail.discount.fixed_amount).toNumber(),
1780
- discount_list: [nextDiscountDetail],
1781
- processed: true
1782
- }));
1783
- remainingNum = 0;
1784
- break;
1785
- }
1786
-
1787
- // 🔥 需要拆分:计算最大使用次数
1788
- var nextMaxUsageLimit = void 0;
1789
- if (nextIsGoodPass) {
1790
- var _nextSelectedDiscount2;
1791
- var nextGoodPassCount = nextApplicableDiscounts.filter(function (item) {
1792
- return (item.tag || item.type) === 'good_pass';
1793
- }).length;
1794
- nextMaxUsageLimit = nextGoodPassCount;
1795
- if ((_nextSelectedDiscount2 = nextSelectedDiscount.config) !== null && _nextSelectedDiscount2 !== void 0 && _nextSelectedDiscount2.maxUsagePerOrder) {
1796
- var usedCount = usedProductIdCounts.get(nextSelectedDiscount.product_id) || 0;
1797
- nextMaxUsageLimit = Math.min(nextGoodPassCount, Math.max(0, nextSelectedDiscount.config.maxUsagePerOrder - usedCount));
2020
+ var nextSplitCount = Math.min(remainingNum, nextMaxUsageLimit);
2021
+ if (nextSplitCount === 0) {
2022
+ // 已达使用上限,剩余商品无折扣存储
2023
+ processedItems.push(_objectSpread(_objectSpread({}, flatItem), {}, {
2024
+ _id: "".concat(flatItem._id, "_split_rest"),
2025
+ num: remainingNum,
2026
+ quantity: remainingNum,
2027
+ discount_list: [],
2028
+ processed: true
2029
+ }));
2030
+ return 0; // break
1798
2031
  }
1799
- } else if (nextIsDiscountCard && nextApplicableProductLimit > 0) {
1800
- var _usedLimitCount = usedDiscountCardLimitCounts.get(nextSelectedDiscount.id) || 0;
1801
- nextMaxUsageLimit = Math.max(0, nextApplicableProductLimit - _usedLimitCount);
1802
- } else {
1803
- nextMaxUsageLimit = 1;
1804
- }
1805
- var nextSplitCount = Math.min(remainingNum, nextMaxUsageLimit);
1806
- if (nextSplitCount === 0) {
1807
- // 已达使用上限,剩余商品无折扣存储
1808
- processedItems.push(_objectSpread(_objectSpread({}, flatItem), {}, {
1809
- _id: "".concat(flatItem._id, "_split_rest"),
1810
- num: remainingNum,
1811
- quantity: remainingNum,
1812
- discount_list: [],
1813
- processed: true
1814
- }));
1815
- break;
1816
- }
1817
2032
 
1818
- // 生成有折扣的商品
1819
- for (var j = 0; j < nextSplitCount; j++) {
1820
- var _nextBundleDiscount$m2;
1821
- var _nextBundleDiscount = nextIsGoodPass ? nextSelectedDiscountCard || nextApplicableDiscounts[j] : nextSelectedDiscountCard || nextApplicableDiscounts[0];
1822
- usedDiscounts.set(_nextBundleDiscount.id, true);
1823
- if ((_nextBundleDiscount.tag || _nextBundleDiscount.type) === 'good_pass') {
1824
- var _curCount2 = usedProductIdCounts.get(_nextBundleDiscount.product_id) || 0;
1825
- usedProductIdCounts.set(_nextBundleDiscount.product_id, _curCount2 + 1);
1826
- }
1827
- var nextBundleDiscTypeForCount = _nextBundleDiscount.tag || _nextBundleDiscount.type;
1828
- if (['discount_card', 'product_discount_card'].includes(nextBundleDiscTypeForCount)) {
1829
- var curLimitCount = usedDiscountCardLimitCounts.get(_nextBundleDiscount.id) || 0;
1830
- usedDiscountCardLimitCounts.set(_nextBundleDiscount.id, curLimitCount + 1);
2033
+ // 生成有折扣的商品
2034
+ for (var j = 0; j < nextSplitCount; j++) {
2035
+ var _nextBundleDiscount$m2;
2036
+ var _nextBundleDiscount = (nextAllocatedPasses === null || nextAllocatedPasses === void 0 ? void 0 : nextAllocatedPasses[j]) || (nextIsGoodPass ? nextSelectedDiscountCard || nextApplicableDiscounts[j] : nextSelectedDiscountCard || nextApplicableDiscounts[0]);
2037
+ markDiscountUsed(_nextBundleDiscount);
2038
+ if ((_nextBundleDiscount.tag || _nextBundleDiscount.type) === 'good_pass') {
2039
+ var _curCount2 = usedProductIdCounts.get(_nextBundleDiscount.product_id) || 0;
2040
+ usedProductIdCounts.set(_nextBundleDiscount.product_id, _curCount2 + 1);
2041
+ }
2042
+ var nextBundleDiscTypeForCount = _nextBundleDiscount.tag || _nextBundleDiscount.type;
2043
+ if (['discount_card', 'product_discount_card'].includes(nextBundleDiscTypeForCount)) {
2044
+ var curLimitCount = usedDiscountCardLimitCounts.get(_nextBundleDiscount.id) || 0;
2045
+ usedDiscountCardLimitCounts.set(_nextBundleDiscount.id, curLimitCount + 1);
2046
+ }
2047
+ var _nextUniqueId = "".concat(flatItem._id, "_split_").concat(continueSplitIndex);
2048
+ var nextDiscountedPrice = getDiscountAmount(_nextBundleDiscount, product.origin_total, product.origin_total);
2049
+ var nextBundleDiscAmount = new Decimal(product.origin_total || 0).minus(nextDiscountedPrice).toNumber();
2050
+ var nextBundleDiscTypeStr = _nextBundleDiscount.tag === 'product_discount_card' ? 'discount_card' : _nextBundleDiscount.tag || _nextBundleDiscount.type;
2051
+ var _nextDiscountDetail = {
2052
+ amount: nextBundleDiscAmount,
2053
+ type: nextBundleDiscTypeStr,
2054
+ discount: {
2055
+ discount_card_type: _nextBundleDiscount === null || _nextBundleDiscount === void 0 || (_nextBundleDiscount$m2 = _nextBundleDiscount.metadata) === null || _nextBundleDiscount$m2 === void 0 ? void 0 : _nextBundleDiscount$m2.discount_card_type,
2056
+ fixed_amount: nextBundleDiscAmount,
2057
+ resource_id: _nextBundleDiscount.id,
2058
+ title: _nextBundleDiscount.format_title,
2059
+ original_amount: product.origin_total,
2060
+ product_id: product.id,
2061
+ percent: _nextBundleDiscount.par_value,
2062
+ discount_product_id: _nextBundleDiscount.product_id
2063
+ },
2064
+ metadata: {
2065
+ custom_product_bundle_map_id: _nextUniqueId,
2066
+ num: 1
2067
+ },
2068
+ _num: 1,
2069
+ config: _nextBundleDiscount === null || _nextBundleDiscount === void 0 ? void 0 : _nextBundleDiscount.config
2070
+ };
2071
+ var _nextAppliedProducts = appliedDiscountProducts.get(_nextBundleDiscount.id) || [];
2072
+ _nextAppliedProducts.push(_nextDiscountDetail);
2073
+ appliedDiscountProducts.set(_nextBundleDiscount.id, _nextAppliedProducts);
2074
+ processedItems.push(_objectSpread(_objectSpread({}, flatItem), {}, {
2075
+ _id: _nextUniqueId,
2076
+ num: 1,
2077
+ quantity: 1,
2078
+ price: nextDiscountedPrice,
2079
+ total: nextDiscountedPrice,
2080
+ discount_list: [_nextDiscountDetail],
2081
+ processed: true,
2082
+ _discountId: _nextBundleDiscount.id
2083
+ }));
2084
+ continueSplitIndex++;
1831
2085
  }
1832
- var _nextUniqueId = "".concat(flatItem._id, "_split_").concat(continueSplitIndex);
1833
- var nextDiscountedPrice = getDiscountAmount(_nextBundleDiscount, product.origin_total, product.origin_total);
1834
- var nextBundleDiscAmount = new Decimal(product.origin_total || 0).minus(nextDiscountedPrice).toNumber();
1835
- var nextBundleDiscTypeStr = _nextBundleDiscount.tag === 'product_discount_card' ? 'discount_card' : _nextBundleDiscount.tag;
1836
- var _nextDiscountDetail = {
1837
- amount: nextBundleDiscAmount,
1838
- type: nextBundleDiscTypeStr,
1839
- discount: {
1840
- discount_card_type: _nextBundleDiscount === null || _nextBundleDiscount === void 0 || (_nextBundleDiscount$m2 = _nextBundleDiscount.metadata) === null || _nextBundleDiscount$m2 === void 0 ? void 0 : _nextBundleDiscount$m2.discount_card_type,
1841
- fixed_amount: nextBundleDiscAmount,
1842
- resource_id: _nextBundleDiscount.id,
1843
- title: _nextBundleDiscount.format_title,
1844
- original_amount: product.origin_total,
1845
- product_id: product.id,
1846
- percent: _nextBundleDiscount.par_value,
1847
- discount_product_id: _nextBundleDiscount.product_id
1848
- },
1849
- metadata: {
1850
- custom_product_bundle_map_id: _nextUniqueId,
1851
- num: 1
1852
- },
1853
- _num: 1,
1854
- config: _nextBundleDiscount === null || _nextBundleDiscount === void 0 ? void 0 : _nextBundleDiscount.config
1855
- };
1856
- var _nextAppliedProducts = appliedDiscountProducts.get(_nextBundleDiscount.id) || [];
1857
- _nextAppliedProducts.push(_nextDiscountDetail);
1858
- appliedDiscountProducts.set(_nextBundleDiscount.id, _nextAppliedProducts);
1859
- processedItems.push(_objectSpread(_objectSpread({}, flatItem), {}, {
1860
- _id: _nextUniqueId,
1861
- num: 1,
1862
- quantity: 1,
1863
- price: nextDiscountedPrice,
1864
- total: nextDiscountedPrice,
1865
- discount_list: [_nextDiscountDetail],
1866
- processed: true,
1867
- _discountId: _nextBundleDiscount.id
1868
- }));
1869
- continueSplitIndex++;
1870
- }
1871
- remainingNum -= nextSplitCount;
2086
+ remainingNum -= nextSplitCount;
2087
+ },
2088
+ _ret;
2089
+ while (remainingNum > 0) {
2090
+ _ret = _loop();
2091
+ if (_ret === 0) break;
1872
2092
  }
1873
2093
  } else {
1874
- var _currentBundleDiscoun3, _currentBundleDiscoun4, _flatItem$parentProdu10;
2094
+ var _currentBundleDiscoun3, _currentBundleDiscoun4, _flatItem$parentProdu11;
1875
2095
  // 不拆分:直接应用折扣
1876
2096
  var _currentBundleDiscount = selectedDiscountCard || applicableDiscounts[0];
1877
2097
  usedDiscounts.set(_currentBundleDiscount.id, true);
@@ -1936,7 +2156,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1936
2156
  product_discount_difference: _productDiscountDifference
1937
2157
  }),
1938
2158
  config: _currentBundleDiscount === null || _currentBundleDiscount === void 0 ? void 0 : _currentBundleDiscount.config,
1939
- _num: (product.num || 1) * ((flatItem === null || flatItem === void 0 || (_flatItem$parentProdu10 = flatItem.parentProduct) === null || _flatItem$parentProdu10 === void 0 ? void 0 : _flatItem$parentProdu10.num) || 1)
2159
+ _num: (product.num || 1) * ((flatItem === null || flatItem === void 0 || (_flatItem$parentProdu11 = flatItem.parentProduct) === null || _flatItem$parentProdu11 === void 0 ? void 0 : _flatItem$parentProdu11.num) || 1)
1940
2160
  };
1941
2161
 
1942
2162
  // 记录实际应用的折扣
@@ -1960,8 +2180,40 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1960
2180
  originalProductList.forEach(function (originProduct) {
1961
2181
  var product = _this3.hooks.getProduct(originProduct);
1962
2182
 
2183
+ // 已提交的扣次不参与运行时重组,避免价格或使用明细被二次改写。
2184
+ if (isPersistedEntitlementLine(originProduct, product)) {
2185
+ result.push(originProduct);
2186
+ return;
2187
+ }
2188
+
1963
2189
  // 获取主商品处理结果
1964
2190
  var mainProductArr = processedProductsMap.get(product._id);
2191
+ if (isEntitlementRuntimeLine(originProduct, product) && !product.isManualDiscount && mainProductArr !== null && mainProductArr !== void 0 && mainProductArr.length) {
2192
+ var bundle = (product.bundle || []).flatMap(function (item, index) {
2193
+ var processed = processedFlatItemsMap.get("".concat(product._id, "_bundle_").concat(index));
2194
+ if (!(processed !== null && processed !== void 0 && processed.length)) return [item];
2195
+ return processed.map(function (child) {
2196
+ return _objectSpread(_objectSpread({}, item), {}, {
2197
+ _id: child._id,
2198
+ price: child.price,
2199
+ bundle_selling_price: child.price,
2200
+ num: child.num,
2201
+ discount_list: (child.discount_list || []).map(function (detail) {
2202
+ return _objectSpread(_objectSpread({}, detail), {}, {
2203
+ metadata: _objectSpread(_objectSpread({}, detail.metadata), {}, {
2204
+ num: child.num,
2205
+ custom_product_bundle_map_id: child._id
2206
+ })
2207
+ });
2208
+ })
2209
+ });
2210
+ });
2211
+ });
2212
+ result.push.apply(result, _toConsumableArray(mainProductArr.map(function (item) {
2213
+ return rebuildEntitlementLine(item, bundle, _this3.hooks);
2214
+ })));
2215
+ return;
2216
+ }
1965
2217
  if (!mainProductArr || mainProductArr.length === 0) {
1966
2218
  // 如果没有处理结果,返回默认商品(还原 option 价格)
1967
2219
  var getDefaultProduct = function getDefaultProduct() {
@@ -2027,7 +2279,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2027
2279
  var hasGoodPass = processedBundleItems.some(function (item) {
2028
2280
  var _item$discount_list;
2029
2281
  return (_item$discount_list = item.discount_list) === null || _item$discount_list === void 0 ? void 0 : _item$discount_list.some(function (discount) {
2030
- return discount.type === 'good_pass' || discount.tag === 'good_pass';
2282
+ return isFullCoveragePass(discount);
2031
2283
  });
2032
2284
  });
2033
2285
  if (hasGoodPass) {
@@ -2242,7 +2494,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2242
2494
  } else {
2243
2495
  // 🔥 没有子商品被拆分,使用原有逻辑
2244
2496
  mainProductArr.forEach(function (mainProduct) {
2245
- var _ref15, _mainProductData$main, _mainProductData$disc, _mainProductData$disc2, _mainProductData$disc3;
2497
+ var _ref29, _mainProductData$main, _mainProductData$disc, _mainProductData$disc2, _mainProductData$disc3;
2246
2498
  var mainProductData = _this3.hooks.getProduct(mainProduct);
2247
2499
 
2248
2500
  // 重组bundle
@@ -2257,9 +2509,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2257
2509
  } else {
2258
2510
  // 🔥 关键:拆分后的bundle item
2259
2511
  processedBundleItems.forEach(function (item) {
2260
- var _item$price, _ref14, _item$bundle_selling_;
2512
+ var _item$price, _ref28, _item$bundle_selling_;
2261
2513
  var nextBundlePrice = (_item$price = item.price) !== null && _item$price !== void 0 ? _item$price : bundleItem.price;
2262
- var nextBundleSellingPrice = (_ref14 = (_item$bundle_selling_ = item.bundle_selling_price) !== null && _item$bundle_selling_ !== void 0 ? _item$bundle_selling_ : item.price) !== null && _ref14 !== void 0 ? _ref14 : bundleItem.bundle_selling_price;
2514
+ var nextBundleSellingPrice = (_ref28 = (_item$bundle_selling_ = item.bundle_selling_price) !== null && _item$bundle_selling_ !== void 0 ? _item$bundle_selling_ : item.price) !== null && _ref28 !== void 0 ? _ref28 : bundleItem.bundle_selling_price;
2263
2515
  // 🔥 更新 discount_list 中的 num,使其与拆分后的 item.num 一致
2264
2516
  var updatedDiscountList = (item.discount_list || []).map(function (discount) {
2265
2517
  var _discount$metadata11;
@@ -2286,7 +2538,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2286
2538
 
2287
2539
  // 主商品已经在前面的 setProduct 中应用过折扣;这里只替换 bundle,
2288
2540
  // 避免把主商品 discount_list 再扣一次。
2289
- var mainSellingPrice = (_ref15 = (_mainProductData$main = mainProductData.main_product_selling_price) !== null && _mainProductData$main !== void 0 ? _mainProductData$main : mainProductData.price) !== null && _ref15 !== void 0 ? _ref15 : 0;
2541
+ var mainSellingPrice = (_ref29 = (_mainProductData$main = mainProductData.main_product_selling_price) !== null && _mainProductData$main !== void 0 ? _mainProductData$main : mainProductData.price) !== null && _ref29 !== void 0 ? _ref29 : 0;
2290
2542
  var newTotal = Number(mainSellingPrice || 0);
2291
2543
  var newOriginTotal = Number(mainProductData.original_price || mainProductData.price || 0);
2292
2544
 
@@ -2355,6 +2607,29 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2355
2607
 
2356
2608
  // 获取此优惠券实际应用的商品详情
2357
2609
  var appliedProductDetails = appliedDiscountProducts.get(discount.id) || [];
2610
+ if (isEntitlementPass(discount)) {
2611
+ var committed = discount.committedAppliedProductDetails || [];
2612
+ var details = [].concat(_toConsumableArray(committed), _toConsumableArray(appliedProductDetails));
2613
+ var _isAvailable = applicableProducts.length > 0;
2614
+ var timeReasons = entitlementTimeReasons.get(discount.id) || [];
2615
+ var timeReason = timeReasons.length ? timeReasons.every(Boolean) ? timeReasons[0] : undefined : getDiscountTimeUnavailableReason(discount, dayjs().format('YYYY-MM-DD HH:mm:ss'));
2616
+ var reasonCode = _isAvailable ? undefined : discount.reasonCode || timeReason || (entitlementHolderMismatch.has(discount.id) ? 'holder_not_matched' : 'product_not_applicable');
2617
+ return _objectSpread(_objectSpread({}, discount), {}, {
2618
+ isAvailable: _isAvailable || committed.length > 0,
2619
+ isSelected: details.length > 0,
2620
+ isUsed: details.length > 0,
2621
+ reasonCode: reasonCode,
2622
+ reason: reasonCode === discount.reasonCode ? discount.reason : undefined,
2623
+ isManualSelect: options !== null && options !== void 0 && options.scan ? false : discount.isManualSelect,
2624
+ applicableProductIds: applicableProducts,
2625
+ applicableProductDetails: applicableProductDetails,
2626
+ appliedProductDetails: details,
2627
+ savedAmount: details.reduce(function (sum, detail) {
2628
+ var _detail$discount;
2629
+ 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();
2630
+ }, 0)
2631
+ });
2632
+ }
2358
2633
 
2359
2634
  // 根据是否有适用商品决定isAvailable
2360
2635
  var isAvailable = applicableProducts.length > 0;
@@ -2409,7 +2684,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2409
2684
  });
2410
2685
  });
2411
2686
  return {
2412
- productList: processedProductList,
2687
+ productList: this.entitlementPassEnabled ? finalizeEntitlementLines(processedProductList, this.hooks) : processedProductList,
2413
2688
  discountList: [].concat(editModeDiscount, _toConsumableArray(updatedDiscountList))
2414
2689
  };
2415
2690
  }
@@ -2435,15 +2710,15 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2435
2710
  var ruleType = usageRules.type;
2436
2711
  // 套餐适用范围配置
2437
2712
  var packageScope = usageRules === null || usageRules === void 0 ? void 0 : usageRules.package_scope;
2438
- var _ref16 = packageScope || {},
2439
- _ref16$type = _ref16.type,
2440
- scopeType = _ref16$type === void 0 ? 'product_all' : _ref16$type,
2441
- _ref16$exclude_bundle = _ref16.exclude_bundle_product_ids,
2442
- exclude_bundle_product_ids = _ref16$exclude_bundle === void 0 ? [] : _ref16$exclude_bundle,
2443
- _ref16$include_bundle = _ref16.include_bundle_product_ids,
2444
- include_bundle_product_ids = _ref16$include_bundle === void 0 ? [] : _ref16$include_bundle,
2445
- _ref16$filter = _ref16.filter,
2446
- filter = _ref16$filter === void 0 ? 0 : _ref16$filter;
2713
+ var _ref30 = packageScope || {},
2714
+ _ref30$type = _ref30.type,
2715
+ scopeType = _ref30$type === void 0 ? 'product_all' : _ref30$type,
2716
+ _ref30$exclude_bundle = _ref30.exclude_bundle_product_ids,
2717
+ exclude_bundle_product_ids = _ref30$exclude_bundle === void 0 ? [] : _ref30$exclude_bundle,
2718
+ _ref30$include_bundle = _ref30.include_bundle_product_ids,
2719
+ include_bundle_product_ids = _ref30$include_bundle === void 0 ? [] : _ref30$include_bundle,
2720
+ _ref30$filter = _ref30.filter,
2721
+ filter = _ref30$filter === void 0 ? 0 : _ref30$filter;
2447
2722
  var isMainProduct = flatItem.type === 'main'; // 单独购买
2448
2723
  var isBundleItem = flatItem.type === 'bundle'; // 套餐中购买
2449
2724
  var bundleMainProductId = (_flatItem$product = flatItem.product) === null || _flatItem$product === void 0 ? void 0 : _flatItem$product.product_id;
@@ -2459,12 +2734,12 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2459
2734
  return true; // 单独购买时可用
2460
2735
  }
2461
2736
  if (isBundleItem) {
2462
- var _flatItem$bundleItem10, _flatItem$bundleItem11, _flatItem$originProdu, _flatItem$parentProdu11;
2737
+ var _flatItem$bundleItem10, _flatItem$bundleItem11, _flatItem$originProdu, _flatItem$parentProdu12;
2463
2738
  // 套餐中购买时,判断是否为原价
2464
2739
  var priceType = (_flatItem$bundleItem10 = flatItem.bundleItem) === null || _flatItem$bundleItem10 === void 0 ? void 0 : _flatItem$bundleItem10.price_type;
2465
2740
  var priceTypeExt = (_flatItem$bundleItem11 = flatItem.bundleItem) === null || _flatItem$bundleItem11 === void 0 ? void 0 : _flatItem$bundleItem11.price_type_ext;
2466
2741
  // 主商品id
2467
- 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;
2742
+ 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$parentProdu12 = flatItem.parentProduct) === null || _flatItem$parentProdu12 === void 0 ? void 0 : _flatItem$parentProdu12.id) || 0;
2468
2743
  // original_price 对应:
2469
2744
  // 1. price_type: "markup" && price_type_ext: "product_price"
2470
2745
  // markup_price 对应: