@pisell/pisellos 2.1.173 → 2.1.174

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  2. package/dist/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
  3. package/dist/model/strategy/adapter/walletPass/evaluator.js +4 -2
  4. package/dist/modules/Discount/availability.d.ts +7 -0
  5. package/dist/modules/Discount/availability.js +52 -0
  6. package/dist/modules/Discount/entitlementPass.d.ts +34 -0
  7. package/dist/modules/Discount/entitlementPass.js +147 -0
  8. package/dist/modules/Discount/entitlementState.d.ts +8 -0
  9. package/dist/modules/Discount/entitlementState.js +205 -0
  10. package/dist/modules/Discount/index.d.ts +6 -3
  11. package/dist/modules/Discount/index.js +125 -23
  12. package/dist/modules/Discount/types.d.ts +34 -5
  13. package/dist/modules/Holder/index.d.ts +48 -0
  14. package/dist/modules/Holder/index.js +640 -0
  15. package/dist/modules/Holder/types.d.ts +123 -0
  16. package/dist/modules/Holder/types.js +1 -0
  17. package/dist/modules/Holder/utils.d.ts +13 -0
  18. package/dist/modules/Holder/utils.js +34 -0
  19. package/dist/modules/Order/index.d.ts +1 -0
  20. package/dist/modules/Order/index.js +18 -1
  21. package/dist/modules/Order/types.d.ts +2 -0
  22. package/dist/modules/Order/utils.d.ts +10 -0
  23. package/dist/modules/Order/utils.js +35 -3
  24. package/dist/modules/Product/types.d.ts +7 -0
  25. package/dist/modules/Rules/entitlementLines.d.ts +8 -0
  26. package/dist/modules/Rules/entitlementLines.js +157 -0
  27. package/dist/modules/Rules/index.d.ts +12 -2
  28. package/dist/modules/Rules/index.js +377 -112
  29. package/dist/modules/Rules/types.d.ts +2 -2
  30. package/dist/modules/index.d.ts +1 -0
  31. package/dist/modules/index.js +2 -1
  32. package/dist/plugins/window.d.ts +3 -0
  33. package/dist/solution/BookingByStep/index.d.ts +17 -2
  34. package/dist/solution/BookingByStep/index.js +276 -204
  35. package/dist/solution/BookingByStep/types.d.ts +2 -1
  36. package/dist/solution/BookingByStep/types.js +3 -1
  37. package/dist/solution/ScanOrder/index.js +1 -1
  38. package/dist/solution/ScanOrder/types.d.ts +1 -0
  39. package/dist/solution/ShopDiscount/index.d.ts +3 -0
  40. package/dist/solution/ShopDiscount/index.js +161 -78
  41. package/dist/solution/ShopDiscount/utils.d.ts +1 -0
  42. package/dist/solution/ShopDiscount/utils.js +40 -1
  43. package/dist/solution/VenueBooking/index.d.ts +19 -0
  44. package/dist/solution/VenueBooking/index.js +978 -748
  45. package/dist/solution/VenueBooking/types.d.ts +2 -0
  46. package/dist/types/index.d.ts +1 -0
  47. package/lib/model/strategy/adapter/promotion/index.js +49 -0
  48. package/lib/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
  49. package/lib/model/strategy/adapter/walletPass/evaluator.js +4 -2
  50. package/lib/modules/Discount/availability.d.ts +7 -0
  51. package/lib/modules/Discount/availability.js +91 -0
  52. package/lib/modules/Discount/entitlementPass.d.ts +34 -0
  53. package/lib/modules/Discount/entitlementPass.js +184 -0
  54. package/lib/modules/Discount/entitlementState.d.ts +8 -0
  55. package/lib/modules/Discount/entitlementState.js +206 -0
  56. package/lib/modules/Discount/index.d.ts +6 -3
  57. package/lib/modules/Discount/index.js +66 -16
  58. package/lib/modules/Discount/types.d.ts +34 -5
  59. package/lib/modules/Holder/index.d.ts +48 -0
  60. package/lib/modules/Holder/index.js +402 -0
  61. package/lib/modules/Holder/types.d.ts +123 -0
  62. package/lib/modules/Holder/types.js +17 -0
  63. package/lib/modules/Holder/utils.d.ts +13 -0
  64. package/lib/modules/Holder/utils.js +71 -0
  65. package/lib/modules/Order/index.d.ts +1 -0
  66. package/lib/modules/Order/index.js +14 -0
  67. package/lib/modules/Order/types.d.ts +2 -0
  68. package/lib/modules/Order/utils.d.ts +10 -0
  69. package/lib/modules/Order/utils.js +36 -5
  70. package/lib/modules/Product/types.d.ts +7 -0
  71. package/lib/modules/Rules/entitlementLines.d.ts +8 -0
  72. package/lib/modules/Rules/entitlementLines.js +158 -0
  73. package/lib/modules/Rules/index.d.ts +12 -2
  74. package/lib/modules/Rules/index.js +304 -70
  75. package/lib/modules/Rules/types.d.ts +2 -2
  76. package/lib/modules/index.d.ts +1 -0
  77. package/lib/modules/index.js +3 -1
  78. package/lib/plugins/window.d.ts +3 -0
  79. package/lib/solution/BookingByStep/index.d.ts +17 -2
  80. package/lib/solution/BookingByStep/index.js +39 -0
  81. package/lib/solution/BookingByStep/types.d.ts +2 -1
  82. package/lib/solution/BookingByStep/types.js +5 -0
  83. package/lib/solution/ScanOrder/index.js +1 -1
  84. package/lib/solution/ScanOrder/types.d.ts +1 -0
  85. package/lib/solution/ShopDiscount/index.d.ts +3 -0
  86. package/lib/solution/ShopDiscount/index.js +78 -28
  87. package/lib/solution/ShopDiscount/utils.d.ts +1 -0
  88. package/lib/solution/ShopDiscount/utils.js +42 -1
  89. package/lib/solution/VenueBooking/index.d.ts +19 -0
  90. package/lib/solution/VenueBooking/index.js +134 -16
  91. package/lib/solution/VenueBooking/types.d.ts +2 -0
  92. package/lib/types/index.d.ts +1 -0
  93. package/package.json +1 -1
@@ -1,4 +1,3 @@
1
- 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); }
2
1
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
2
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
3
  function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
@@ -8,6 +7,7 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o =
8
7
  function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
9
8
  function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
10
9
  function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
10
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
11
11
  function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
12
12
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
13
13
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
@@ -31,6 +31,13 @@ import { getProductOriginTotalPrice, getProductTotalPrice } from "../Cart/utils"
31
31
  import Decimal from 'decimal.js';
32
32
  import { isBoolean } from 'lodash-es';
33
33
  import dayjs from 'dayjs';
34
+ import { WalletPassEvaluator } from "../../model/strategy/adapter/walletPass/evaluator";
35
+ import { compareEntitlementPassPriority, getRemainingEntitlementUses, isEntitlementPass, isFullCoveragePass, resolveEntitlementQuota } from "../Discount/entitlementPass";
36
+ import { getDiscountUsageBlockReason, getDiscountUsageLimitFailKey } from "../Discount/availability";
37
+ import { withCommittedEntitlementDetails, isPersistedEntitlementLine } from "../Discount/entitlementState";
38
+ import { getDiscountTimeUnavailableReason } from "../../solution/ShopDiscount/utils";
39
+ import { cloneDeep } from 'lodash-es';
40
+ import { prepareEntitlementLines, finalizeEntitlementLines, isEntitlementRuntimeLine, rebuildEntitlementLine } from "./entitlementLines";
34
41
 
35
42
  // 临时变量
36
43
  var flatItem;
@@ -45,10 +52,23 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
45
52
  _defineProperty(_assertThisInitialized(_this), "defaultVersion", '1.0.0');
46
53
  _defineProperty(_assertThisInitialized(_this), "store", void 0);
47
54
  _defineProperty(_assertThisInitialized(_this), "hooks", void 0);
55
+ _defineProperty(_assertThisInitialized(_this), "entitlementPassEnabled", false);
56
+ _defineProperty(_assertThisInitialized(_this), "defaultWalletPassEvaluator", void 0);
48
57
  _this.hooks = {};
49
58
  return _this;
50
59
  }
51
60
  _createClass(RulesModule, [{
61
+ key: "setEntitlementPassEnabled",
62
+ value: function setEntitlementPassEnabled(enabled) {
63
+ this.entitlementPassEnabled = enabled;
64
+ }
65
+ }, {
66
+ key: "getWalletPassEvaluator",
67
+ value: function getWalletPassEvaluator() {
68
+ var _this$core, _this$core$getWalletP, _this$defaultWalletPa;
69
+ return ((_this$core = this.core) === null || _this$core === void 0 || (_this$core = _this$core.getPlugin('window')) === null || _this$core === void 0 || (_this$core$getWalletP = _this$core.getWalletPassEvaluator) === null || _this$core$getWalletP === void 0 ? void 0 : _this$core$getWalletP.call(_this$core)) || ((_this$defaultWalletPa = this.defaultWalletPassEvaluator) !== null && _this$defaultWalletPa !== void 0 ? _this$defaultWalletPa : this.defaultWalletPassEvaluator = new WalletPassEvaluator());
70
+ }
71
+ }, {
52
72
  key: "initialize",
53
73
  value: function () {
54
74
  var _initialize = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(core, options) {
@@ -95,35 +115,69 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
95
115
  value: function getRulesList() {
96
116
  return this.store.rulesList;
97
117
  }
118
+ }, {
119
+ key: "normalizeHolderRecordIds",
120
+ value: function normalizeHolderRecordIds(value) {
121
+ var records = Array.isArray(value) ? value : [value];
122
+ return Array.from(new Set(records.map(function (record) {
123
+ if (record && _typeof(record) === 'object') {
124
+ return record.form_record_id;
125
+ }
126
+ return record;
127
+ }).filter(function (record) {
128
+ return record !== undefined && record !== null && record !== '' && record !== 0 && record !== '0';
129
+ }).map(String)));
130
+ }
98
131
 
99
- // 商品不需要holder,则不需要判断,直接返回true,商品需要holder但是还没填写,那么暂时不使用带有holder的券,直到填写才去匹配
132
+ /**
133
+ * 商品未开启 Holder 选择时跳过匹配;已开启时,特定 form Holder 卡
134
+ * 只适用于同一 Holder Record,是否必填不影响匹配规则。
135
+ */
100
136
  }, {
101
137
  key: "checkHolderMatch",
102
- value: function checkHolderMatch(discount, product, holders) {
103
- var _discount$holder;
138
+ value: function checkHolderMatch(discount, product, holderSource, holders) {
139
+ var _discount$holder, _ref, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9, _ref10, _holderSource$holder_, _holderSource$metadat, _holderSource$origin, _holderSource$metadat2, _holderSource$_origin, _holderSource$_origin2, _holderSource$_origin3, _holderSource$_produc, _holderSource$_produc2, _holderSource$_extend, _holderSource$_extend2, _holderSource$_extend3;
104
140
  // 非表单类型 holder 视为匹配
105
141
  if (((_discount$holder = discount.holder) === null || _discount$holder === void 0 ? void 0 : _discount$holder.holder_type) !== 'form') return true;
106
- // 主预约holder, 目前(20251124)默认只考虑单个holder的情况
107
- var orderHolderId = Array.isArray(holders) && holders.length > 0 ? holders[0].form_record_id : undefined;
108
- var productHolderId = Array.isArray(product.holder_id) ? product.holder_id[0] : product.holder_id;
109
- // 商品不需要选holder,则不对比holder,直接返回true
110
- if (!product.isNeedHolder) return true;
111
- // 商品需要holder,但父预约及商品都无holder,返回false
112
- if (!orderHolderId && !productHolderId) return false;
113
- // 最终直接匹配 holder 是否相同
114
- return (productHolderId || orderHolderId) === discount.holder.holder_id;
142
+
143
+ // 旧券沿用预约主体和单个 Holder 的匹配口径。
144
+ if (!isEntitlementPass(discount)) {
145
+ if (!product.isNeedHolder) return true;
146
+ var holder = holders === null || holders === void 0 ? void 0 : holders[0];
147
+ var orderHolderId = holder && _typeof(holder) === 'object' ? holder.form_record_id : holder;
148
+ var productHolderId = Array.isArray(product.holder_id) ? product.holder_id[0] : product.holder_id;
149
+ if (!orderHolderId && !productHolderId) return false;
150
+ return (productHolderId || orderHolderId) === discount.holder.holder_id;
151
+ }
152
+
153
+ // getProduct 会裁剪商品字段,从原始商品读取配置,套餐子项沿用父商品。
154
+ var holderConfig = (_ref = (_ref2 = (_ref3 = (_ref4 = (_ref5 = (_ref6 = (_ref7 = (_ref8 = (_ref9 = (_ref10 = (_holderSource$holder_ = holderSource === null || holderSource === void 0 ? void 0 : holderSource.holder_config) !== null && _holderSource$holder_ !== void 0 ? _holderSource$holder_ : holderSource === null || holderSource === void 0 || (_holderSource$metadat = holderSource.metadata) === null || _holderSource$metadat === void 0 ? void 0 : _holderSource$metadat.holder_config) !== null && _ref10 !== void 0 ? _ref10 : holderSource === null || holderSource === void 0 || (_holderSource$origin = holderSource.origin) === null || _holderSource$origin === void 0 ? void 0 : _holderSource$origin.holder_config) !== null && _ref9 !== void 0 ? _ref9 : holderSource === null || holderSource === void 0 || (_holderSource$metadat2 = holderSource.metadata) === null || _holderSource$metadat2 === void 0 || (_holderSource$metadat2 = _holderSource$metadat2.origin) === null || _holderSource$metadat2 === void 0 ? void 0 : _holderSource$metadat2.holder_config) !== null && _ref8 !== void 0 ? _ref8 : holderSource === null || holderSource === void 0 || (_holderSource$_origin = holderSource._origin) === null || _holderSource$_origin === void 0 ? void 0 : _holderSource$_origin.holder_config) !== null && _ref7 !== void 0 ? _ref7 : holderSource === null || holderSource === void 0 || (_holderSource$_origin2 = holderSource._origin) === null || _holderSource$_origin2 === void 0 || (_holderSource$_origin2 = _holderSource$_origin2.product) === null || _holderSource$_origin2 === void 0 ? void 0 : _holderSource$_origin2.holder_config) !== null && _ref6 !== void 0 ? _ref6 : holderSource === null || holderSource === void 0 || (_holderSource$_origin3 = holderSource._originData) === null || _holderSource$_origin3 === void 0 || (_holderSource$_origin3 = _holderSource$_origin3.product) === null || _holderSource$_origin3 === void 0 ? void 0 : _holderSource$_origin3.holder_config) !== null && _ref5 !== void 0 ? _ref5 : holderSource === null || holderSource === void 0 || (_holderSource$_produc = holderSource._productInit) === null || _holderSource$_produc === void 0 ? void 0 : _holderSource$_produc.holder_config) !== null && _ref4 !== void 0 ? _ref4 : holderSource === null || holderSource === void 0 || (_holderSource$_produc2 = holderSource._productOrigin) === null || _holderSource$_produc2 === void 0 ? void 0 : _holderSource$_produc2.holder_config) !== null && _ref3 !== void 0 ? _ref3 : holderSource === null || holderSource === void 0 || (_holderSource$_extend = holderSource._extend) === null || _holderSource$_extend === void 0 ? void 0 : _holderSource$_extend.holder_config) !== null && _ref2 !== void 0 ? _ref2 : holderSource === null || holderSource === void 0 || (_holderSource$_extend2 = holderSource._extend) === null || _holderSource$_extend2 === void 0 || (_holderSource$_extend2 = _holderSource$_extend2.product) === null || _holderSource$_extend2 === void 0 ? void 0 : _holderSource$_extend2.holder_config) !== null && _ref !== void 0 ? _ref : holderSource === null || holderSource === void 0 || (_holderSource$_extend3 = holderSource._extend) === null || _holderSource$_extend3 === void 0 || (_holderSource$_extend3 = _holderSource$_extend3.product) === null || _holderSource$_extend3 === void 0 || (_holderSource$_extend3 = _holderSource$_extend3.metadata) === null || _holderSource$_extend3 === void 0 ? void 0 : _holderSource$_extend3.holder_config;
155
+ var holderStatus = holderConfig === null || holderConfig === void 0 ? void 0 : holderConfig.status;
156
+ var holderEnabled = holderStatus == null || holderStatus === '' || holderStatus === true || ['enable', '1'].includes(String(holderStatus).trim().toLowerCase());
157
+ if (!holderEnabled || !(holderConfig !== null && holderConfig !== void 0 && holderConfig.resource_id)) {
158
+ return true;
159
+ }
160
+ var discountHolderIds = this.normalizeHolderRecordIds(discount.holder.holder_id);
161
+ if (!discountHolderIds.length) return false;
162
+ var productHolderIds = this.normalizeHolderRecordIds(product.holder_id);
163
+ var candidateHolderIds = productHolderIds.length || Array.isArray(product.holder_id) ? productHolderIds : this.normalizeHolderRecordIds(holders);
164
+ if (!candidateHolderIds.length) return false;
165
+ var discountHolderIdSet = new Set(discountHolderIds);
166
+ return candidateHolderIds.every(function (holderId) {
167
+ return discountHolderIdSet.has(holderId);
168
+ });
115
169
  }
116
170
 
117
171
  // 判断discountList 是否可以对当前productList生效
118
172
  }, {
119
173
  key: "isDiscountListAvailable",
120
- value: function isDiscountListAvailable(_ref) {
174
+ value: function isDiscountListAvailable(_ref11) {
121
175
  var _this2 = this;
122
- var oldDiscountList = _ref.oldDiscountList,
123
- newDiscountList = _ref.newDiscountList,
124
- productList = _ref.productList,
125
- holders = _ref.holders,
126
- isFormSubject = _ref.isFormSubject;
176
+ var oldDiscountList = _ref11.oldDiscountList,
177
+ newDiscountList = _ref11.newDiscountList,
178
+ productList = _ref11.productList,
179
+ holders = _ref11.holders,
180
+ isFormSubject = _ref11.isFormSubject;
127
181
  // 首先检查是否有新的优惠券可应用
128
182
  if (!newDiscountList || newDiscountList.length === 0) {
129
183
  return {
@@ -134,7 +188,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
134
188
  }
135
189
 
136
190
  // 编辑商品已有商品券
137
- if (productList.every(function (item) {
191
+ if (!newDiscountList.some(isEntitlementPass) && productList.length > 0 && productList.every(function (item) {
138
192
  var _product$discount_lis;
139
193
  var product = _this2.hooks.getProduct(item);
140
194
  return product.booking_id && (((_product$discount_lis = product.discount_list) === null || _product$discount_lis === void 0 ? void 0 : _product$discount_lis.length) || product.total == 0);
@@ -152,10 +206,10 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
152
206
  var filteredOldDiscountList = oldDiscountList.filter(function (discount) {
153
207
  return !discount.isEditMode && (discount.tag !== 'good_pass' || discount.isScan);
154
208
  });
155
- var mergedDiscountList = uniqueById([].concat(_toConsumableArray(filteredOldDiscountList), _toConsumableArray(newDiscountList)));
209
+ var mergedDiscountList = uniqueById([].concat(_toConsumableArray(newDiscountList.filter(isEntitlementPass)), _toConsumableArray(filteredOldDiscountList), _toConsumableArray(newDiscountList)));
156
210
  var result = this.calcDiscount({
157
211
  discountList: mergedDiscountList,
158
- productList: _toConsumableArray(productList),
212
+ productList: this.entitlementPassEnabled ? cloneDeep(productList) : _toConsumableArray(productList),
159
213
  holders: holders,
160
214
  isFormSubject: isFormSubject
161
215
  }, {
@@ -164,15 +218,16 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
164
218
 
165
219
  // 检查是否有产品使用了新折扣
166
220
  var hasApplicableDiscount = false;
167
- var newDiscountIds = newDiscountList.map(function (discount) {
168
- return discount.id;
169
- });
221
+ var newDiscountIds = new Set(newDiscountList.map(function (discount) {
222
+ return String(discount.id);
223
+ }));
170
224
 
171
225
  // 遍历处理后的产品列表,检查是否有产品使用了新折扣
172
226
  result.productList.forEach(function (product) {
173
- var _this2$hooks$getProdu = _this2.hooks.getProduct(product),
174
- discount_list = _this2$hooks$getProdu.discount_list,
175
- bundle = _this2$hooks$getProdu.bundle;
227
+ var mappedProduct = _this2.hooks.getProduct(product);
228
+ if (isPersistedEntitlementLine(product, mappedProduct)) return;
229
+ var discount_list = mappedProduct.discount_list,
230
+ bundle = mappedProduct.bundle;
176
231
  var allDiscountList = _toConsumableArray(discount_list || []);
177
232
  (bundle || []).forEach(function (item) {
178
233
  allDiscountList.push.apply(allDiscountList, _toConsumableArray((item === null || item === void 0 ? void 0 : item.discount_list) || []));
@@ -181,7 +236,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
181
236
  // 检查是否有使用新折扣的情况
182
237
  var usedNewDiscount = allDiscountList.some(function (discount) {
183
238
  var _discount$discount;
184
- return newDiscountIds.includes(discount === null || discount === void 0 || (_discount$discount = discount.discount) === null || _discount$discount === void 0 ? void 0 : _discount$discount.resource_id);
239
+ return newDiscountIds.has(String(discount === null || discount === void 0 || (_discount$discount = discount.discount) === null || _discount$discount === void 0 ? void 0 : _discount$discount.resource_id));
185
240
  });
186
241
  if (usedNewDiscount) {
187
242
  hasApplicableDiscount = true;
@@ -196,6 +251,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
196
251
  }
197
252
  return {
198
253
  isAvailable: hasApplicableDiscount,
254
+ evaluatedDiscountList: result.discountList,
199
255
  discountList: hasApplicableDiscount ? result.discountList : oldDiscountList,
200
256
  productList: hasApplicableDiscount ? result.productList : productList,
201
257
  unavailableReason: unavailableReason
@@ -225,7 +281,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
225
281
  for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
226
282
  var item = _step3.value;
227
283
  var product = this.hooks.getProduct(item);
228
- var bookingTime = ((product === null || product === void 0 ? void 0 : product.startDate) || dayjs()).format('YYYY-MM-DD HH:mm:ss');
284
+ var bookingTime = dayjs((product === null || product === void 0 ? void 0 : product.startDate) || undefined).format('YYYY-MM-DD HH:mm:ss');
229
285
  var filteredList = filterDiscountListByBookingTime([discount], bookingTime);
230
286
  if (filteredList.length === 0) {
231
287
  return UnavailableReason.TimeLimit;
@@ -250,6 +306,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
250
306
  for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
251
307
  var _discount = _step2.value;
252
308
  var limitedData = _discount.limited_relation_product_data;
309
+ if (!limitedData) return UnavailableReason.ProductNotApplicable;
253
310
  var hasApplicableProduct = false;
254
311
  var _iterator4 = _createForOfIteratorHelper(productList),
255
312
  _step4;
@@ -284,19 +341,68 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
284
341
  }
285
342
  }, {
286
343
  key: "calcDiscount",
287
- value: function calcDiscount(_ref2, options) {
344
+ value: function calcDiscount(_ref12, options) {
288
345
  var _this3 = this;
289
- var discountList = _ref2.discountList,
290
- productList = _ref2.productList,
291
- holders = _ref2.holders,
292
- isFormSubject = _ref2.isFormSubject;
346
+ var discountList = _ref12.discountList,
347
+ productList = _ref12.productList,
348
+ holders = _ref12.holders,
349
+ isFormSubject = _ref12.isFormSubject;
350
+ discountList = this.entitlementPassEnabled ? withCommittedEntitlementDetails(discountList, productList, this.hooks.getProduct) : discountList.filter(function (item) {
351
+ return !isEntitlementPass(item);
352
+ });
353
+ var usableEntitlements = discountList.filter(function (discount) {
354
+ return isEntitlementPass(discount) && !discount.isEditMode && !discount.isManualSelect && !getDiscountUsageBlockReason(discount);
355
+ });
356
+ var canUseEntitlement = function canUseEntitlement(originProduct) {
357
+ var _product$original_pri;
358
+ var product = _this3.hooks.getProduct(originProduct);
359
+ // 预判任一份可用就按份拆开,实际抵扣仍逐份核对 Holder。
360
+ var holderProducts = Array.isArray(product.holder_id) && product.holder_id.length > 1 ? product.holder_id.map(function (holder_id) {
361
+ return _objectSpread(_objectSpread({}, product), {}, {
362
+ holder_id: holder_id
363
+ });
364
+ }) : [product];
365
+ var items = [{
366
+ type: 'main',
367
+ id: product.id,
368
+ price: (_product$original_pri = product.original_price) !== null && _product$original_pri !== void 0 ? _product$original_pri : product.price
369
+ }].concat(_toConsumableArray((product.bundle || []).map(function (bundleItem) {
370
+ var _ref13, _bundleItem$_bundle_p, _bundleItem$original_;
371
+ return {
372
+ type: 'bundle',
373
+ id: (_ref13 = (_bundleItem$_bundle_p = bundleItem._bundle_product_id) !== null && _bundleItem$_bundle_p !== void 0 ? _bundleItem$_bundle_p : bundleItem.bundle_product_id) !== null && _ref13 !== void 0 ? _ref13 : bundleItem.product_id,
374
+ price: (_bundleItem$original_ = bundleItem.original_price) !== null && _bundleItem$original_ !== void 0 ? _bundleItem$original_ : bundleItem.price,
375
+ bundleItem: bundleItem
376
+ };
377
+ })));
378
+ return usableEntitlements.some(function (discount) {
379
+ var scope = discount.limited_relation_product_data;
380
+ if (!scope || !holderProducts.some(function (item) {
381
+ return _this3.checkHolderMatch(discount, item, originProduct, holders);
382
+ }) || !filterDiscountListByBookingTime([discount], dayjs(product.startDate || undefined).format('YYYY-MM-DD HH:mm:ss')).length) return false;
383
+ return items.some(function (item) {
384
+ var _scope$exclude_produc, _scope$product_ids;
385
+ return Number(item.price) > 0 && (scope.type === 'product_all' ? !(scope.filter === 1 && (_scope$exclude_produc = scope.exclude_product_ids) !== null && _scope$exclude_produc !== void 0 && _scope$exclude_produc.some(function (id) {
386
+ return String(id) === String(item.id);
387
+ })) : !!((_scope$product_ids = scope.product_ids) !== null && _scope$product_ids !== void 0 && _scope$product_ids.includes(item.id))) && _this3.checkPackageSubItemUsageRules(discount, _objectSpread(_objectSpread({}, item), {}, {
388
+ originProduct: originProduct,
389
+ parentProduct: product
390
+ }));
391
+ });
392
+ });
393
+ };
394
+ if (this.entitlementPassEnabled) productList = prepareEntitlementLines(productList, this.hooks, canUseEntitlement);
293
395
  var editModeDiscount = [];
294
396
  var addModeDiscount = [];
295
397
  discountList.forEach(function (discount) {
296
398
  if (discount.isEditMode) {
297
399
  editModeDiscount.push(discount);
298
400
  } else {
299
- addModeDiscount.push(discount);
401
+ addModeDiscount.push(isEntitlementPass(discount) ? _objectSpread(_objectSpread({}, discount), {}, {
402
+ config: undefined,
403
+ reason: undefined,
404
+ reasonCode: undefined
405
+ }) : discount);
300
406
  }
301
407
  });
302
408
 
@@ -347,6 +453,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
347
453
  // 2. 展开 bundle 子商品
348
454
  if (product.bundle && Array.isArray(product.bundle) && product.bundle.length > 0) {
349
455
  product.bundle.forEach(function (bundleItem, bundleIndex) {
456
+ var _ref14, _bundleItem$_bundle_p2;
350
457
  flattened.push({
351
458
  type: 'bundle',
352
459
  originProduct: originProduct,
@@ -355,8 +462,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
355
462
  bundleIndex: bundleIndex,
356
463
  // 虚拟商品属性
357
464
  price: Number(bundleItem.price || 0),
358
- id: bundleItem._bundle_product_id,
359
- // 🔥 使用 _bundle_product_id
465
+ id: (_ref14 = (_bundleItem$_bundle_p2 = bundleItem._bundle_product_id) !== null && _bundleItem$_bundle_p2 !== void 0 ? _bundleItem$_bundle_p2 : bundleItem.bundle_product_id) !== null && _ref14 !== void 0 ? _ref14 : bundleItem.product_id,
360
466
  _id: "".concat(product._id, "_bundle_").concat(bundleIndex),
361
467
  parentId: product._id,
362
468
  num: bundleItem.num || 1,
@@ -462,6 +568,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
462
568
  }
463
569
  return 0;
464
570
  }
571
+ if (isEntitlementPass(a) || isEntitlementPass(b)) {
572
+ return isEntitlementPass(a) && isEntitlementPass(b) ? compareEntitlementPassPriority(a, b) : isEntitlementPass(a) ? -1 : 1;
573
+ }
465
574
 
466
575
  // 1. 先按优先级排序
467
576
  var priorityA = getPriority(a);
@@ -513,10 +622,10 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
513
622
 
514
623
  // 对扁平化后的列表按价格降序排序(用于应用优惠券时优先选择高价商品)
515
624
  var sortedFlattenedList = flattenedList.sort(function (a, b) {
516
- var _ref3, _a$original_price, _ref4, _b$original_price;
625
+ var _ref15, _a$original_price, _ref16, _b$original_price;
517
626
  // 子商品优先使用 original_price,主商品使用 price
518
- 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');
519
- var priceB = new Decimal(b.type === 'bundle' ? (_ref4 = (_b$original_price = b.original_price) !== null && _b$original_price !== void 0 ? _b$original_price : b.price) !== null && _ref4 !== void 0 ? _ref4 : '0' : b.price || '0');
627
+ var priceA = new Decimal(a.type === 'bundle' ? (_ref15 = (_a$original_price = a.original_price) !== null && _a$original_price !== void 0 ? _a$original_price : a.price) !== null && _ref15 !== void 0 ? _ref15 : '0' : a.price || '0');
628
+ var priceB = new Decimal(b.type === 'bundle' ? (_ref16 = (_b$original_price = b.original_price) !== null && _b$original_price !== void 0 ? _b$original_price : b.price) !== null && _ref16 !== void 0 ? _ref16 : '0' : b.price || '0');
520
629
  if (priceA.equals(priceB)) {
521
630
  // 价格相同时,主商品优先
522
631
  if (a.type !== b.type) {
@@ -564,8 +673,93 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
564
673
  });
565
674
  */
566
675
 
567
- // 标记已使用的优惠券
676
+ // 旧券沿用一次性标记;多次卡按卡 ID 累计本次分配数量。
568
677
  var usedDiscounts = new Map();
678
+ var entitlementUsageCounts = new Map();
679
+ var usedProductIdCounts = new Map();
680
+ var markDiscountUsed = function markDiscountUsed(discount) {
681
+ if (isEntitlementPass(discount)) {
682
+ entitlementUsageCounts.set(discount.id, (entitlementUsageCounts.get(discount.id) || 0) + 1);
683
+ } else {
684
+ usedDiscounts.set(discount.id, true);
685
+ }
686
+ usedProductIdCounts.set(discount.product_id, (usedProductIdCounts.get(discount.product_id) || 0) + 1);
687
+ };
688
+
689
+ // 沿用商品券逐份拆分,同一多次卡可重复分配,数量受本单剩余额度限制。
690
+ var getFullCoveragePasses = function getFullCoveragePasses(discounts, quantity) {
691
+ var allocated = [];
692
+ var productCounts = new Map(usedProductIdCounts);
693
+ var _iterator5 = _createForOfIteratorHelper(discounts),
694
+ _step5;
695
+ try {
696
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
697
+ var _discount$config;
698
+ var discount = _step5.value;
699
+ if (!isFullCoveragePass(discount) || allocated.length >= quantity) continue;
700
+ var count = isEntitlementPass(discount) ? getRemainingEntitlementUses(discount, entitlementUsageCounts.get(discount.id) || 0, quantity - allocated.length) : usedDiscounts.get(discount.id) ? 0 : 1;
701
+ var limit = Number(((_discount$config = discount.config) === null || _discount$config === void 0 ? void 0 : _discount$config.maxUsagePerOrder) || 0);
702
+ if (isEntitlementPass(discount) && limit > 0) {
703
+ count = Math.min(count, Math.max(0, Math.floor(limit) - (productCounts.get(discount.product_id) || 0)));
704
+ }
705
+ for (var i = 0; i < count; i++) allocated.push(discount);
706
+ productCounts.set(discount.product_id, (productCounts.get(discount.product_id) || 0) + count);
707
+ }
708
+ } catch (err) {
709
+ _iterator5.e(err);
710
+ } finally {
711
+ _iterator5.f();
712
+ }
713
+ return allocated;
714
+ };
715
+ var evaluator;
716
+ addModeDiscount.filter(isEntitlementPass).forEach(function (discount) {
717
+ var _evaluator, _discount$unified_ava, _discount$limited_rel, _discount$limited_rel2;
718
+ discount.usageLimitFailKey = getDiscountUsageLimitFailKey(discount);
719
+ discount.reasonCode = getDiscountUsageBlockReason(discount);
720
+ var quota = resolveEntitlementQuota(discount);
721
+ if (discount.reasonCode || !quota) {
722
+ discount.config = {
723
+ isAvailable: false
724
+ };
725
+ return;
726
+ }
727
+ (_evaluator = evaluator) !== null && _evaluator !== void 0 ? _evaluator : evaluator = _this3.getWalletPassEvaluator();
728
+ var result = evaluator.checkVoucherAvailability({
729
+ orderTotalAmount: productList.reduce(function (sum, item) {
730
+ var product = _this3.hooks.getProduct(item);
731
+ return sum.plus(new Decimal(product.origin_total || 0).times(product.quantity || product.num || 1));
732
+ }, new Decimal(0)).toNumber(),
733
+ // 策略按统一商品结构读主价与数量,套餐次数还需乘父商品份数。
734
+ products: sortedFlattenedList.map(function (item) {
735
+ var _item$parentProduct, _item$parentProduct2, _item$product;
736
+ return {
737
+ product_id: item.id,
738
+ price: item.price || 0,
739
+ main_product_selling_price: item.price || 0,
740
+ quantity: (item.quantity || item.num || 1) * (item.type === 'bundle' ? ((_item$parentProduct = item.parentProduct) === null || _item$parentProduct === void 0 ? void 0 : _item$parentProduct.quantity) || ((_item$parentProduct2 = item.parentProduct) === null || _item$parentProduct2 === void 0 ? void 0 : _item$parentProduct2.num) || 1 : 1),
741
+ product_options: item.type === 'main' ? (_item$product = item.product) === null || _item$product === void 0 ? void 0 : _item$product.options : undefined
742
+ };
743
+ }),
744
+ vouchers: [_objectSpread(_objectSpread({}, discount), {}, {
745
+ amount: Number(discount.par_value || 0),
746
+ balance: quota.type === 'unlimited' ? Number.MAX_SAFE_INTEGER : quota.balance,
747
+ type: 'entitlement_pass',
748
+ unified_available_status: (_discount$unified_ava = discount.unified_available_status) !== null && _discount$unified_ava !== void 0 ? _discount$unified_ava : 1,
749
+ available_product_type: (_discount$limited_rel = discount.limited_relation_product_data) === null || _discount$limited_rel === void 0 ? void 0 : _discount$limited_rel.type,
750
+ available_product_ids: (_discount$limited_rel2 = discount.limited_relation_product_data) === null || _discount$limited_rel2 === void 0 ? void 0 : _discount$limited_rel2.product_ids
751
+ })]
752
+ });
753
+ discount.config = _objectSpread(_objectSpread({}, result.config), {}, {
754
+ isAvailable: result.isAvailable
755
+ });
756
+ if (!result.isAvailable) {
757
+ discount.reason = result.reason;
758
+ discount.reasonCode = result.reasonCode || 'not_meet_the_required_conditions';
759
+ }
760
+ });
761
+ var entitlementTimeReasons = new Map();
762
+ var entitlementHolderMismatch = new Set();
569
763
 
570
764
  // 记录每个优惠券适用的商品ID
571
765
  var discountApplicability = new Map();
@@ -611,7 +805,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
611
805
 
612
806
  // 编辑的商品使用了优惠券不可用
613
807
  var isAvailableProduct = flatItem.type === 'main' ? !((_product2 = product) !== null && _product2 !== void 0 && _product2.booking_id && (_product3 = product) !== null && _product3 !== void 0 && (_product3 = _product3.discount_list) !== null && _product3 !== void 0 && _product3.length && (_product4 = product) !== null && _product4 !== void 0 && (_product4 = _product4.discount_list) !== null && _product4 !== void 0 && _product4.every(function (d) {
614
- return d.id && ['good_pass', 'discount_card', 'product_discount_card'].includes(d.tag || d.type);
808
+ return d.id && ['entitlement_pass', 'good_pass', 'discount_card', 'product_discount_card'].includes(d.tag || d.type);
615
809
  })) : !(flatItem !== null && flatItem !== void 0 && flatItem.booking_id && !!(flatItem !== null && flatItem !== void 0 && (_flatItem$bundleItem = flatItem.bundleItem) !== null && _flatItem$bundleItem !== void 0 && (_flatItem$bundleItem = _flatItem$bundleItem.discount_list) !== null && _flatItem$bundleItem !== void 0 && _flatItem$bundleItem.length) && flatItem !== null && flatItem !== void 0 && (_flatItem$bundleItem2 = flatItem.bundleItem) !== null && _flatItem$bundleItem2 !== void 0 && (_flatItem$bundleItem2 = _flatItem$bundleItem2.discount_list) !== null && _flatItem$bundleItem2 !== void 0 && _flatItem$bundleItem2.every(function (d) {
616
810
  return d.id;
617
811
  }));
@@ -631,7 +825,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
631
825
  var limitedData = discount.limited_relation_product_data;
632
826
 
633
827
  // 时间限制检查
634
- var timeLimit = !!filterDiscountListByBookingTime([discount], (((_product5 = product) === null || _product5 === void 0 ? void 0 : _product5.startDate) || dayjs()).format('YYYY-MM-DD HH:mm:ss')).length;
828
+ var timeLimit = !!filterDiscountListByBookingTime([discount], dayjs(((_product5 = product) === null || _product5 === void 0 ? void 0 : _product5.startDate) || undefined).format('YYYY-MM-DD HH:mm:ss')).length;
635
829
  if (!timeLimit) {
636
830
  return false;
637
831
  }
@@ -712,7 +906,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
712
906
  // 收集该折扣卡适用的商品(排除被其他专属折扣卡占用的商品)
713
907
  var applicableProducts = [];
714
908
  sortedFlattenedList.forEach(function (flatItem) {
715
- var _flatItem$parentProdu2, _flatItem$parentProdu3, _product$price, _ref5, _flatItem$original_pr;
909
+ var _flatItem$parentProdu2, _flatItem$parentProdu3, _product$price, _ref17, _flatItem$original_pr;
716
910
  // 🔥 检查该商品是否被其他专属折扣卡占用
717
911
  var occupyingDiscountId = occupiedItems.get(flatItem._id);
718
912
  if (occupyingDiscountId !== undefined && occupyingDiscountId !== discount.id) {
@@ -740,7 +934,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
740
934
 
741
935
  // 对于主商品:使用 price
742
936
  // 对于子商品:优先使用 flatItem.original_price,否则使用 flatItem.price
743
- var originalAmount = flatItem.type === 'main' ? Number((_product$price = product.price) !== null && _product$price !== void 0 ? _product$price : 0) : Number((_ref5 = (_flatItem$original_pr = flatItem.original_price) !== null && _flatItem$original_pr !== void 0 ? _flatItem$original_pr : flatItem.price) !== null && _ref5 !== void 0 ? _ref5 : 0);
937
+ var originalAmount = flatItem.type === 'main' ? Number((_product$price = product.price) !== null && _product$price !== void 0 ? _product$price : 0) : Number((_ref17 = (_flatItem$original_pr = flatItem.original_price) !== null && _flatItem$original_pr !== void 0 ? _flatItem$original_pr : flatItem.price) !== null && _ref17 !== void 0 ? _ref17 : 0);
744
938
 
745
939
  // 传递 parentQuantity 用于差值处理时判断是否是真正的"数量为1"
746
940
  var productData = {
@@ -796,22 +990,32 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
796
990
  originProduct = flatItem.originProduct;
797
991
  }
798
992
  addModeDiscount.forEach(function (discount) {
799
- var _product6, _product7, _product8, _product9, _flatItem$bundleItem3, _flatItem$bundleItem4;
993
+ var _discount$config2, _product6, _limitedData$exclude_2, _product7, _product8, _product9, _flatItem$bundleItem3, _flatItem$bundleItem4;
800
994
  var limitedData = discount === null || discount === void 0 ? void 0 : discount.limited_relation_product_data;
995
+ if (!limitedData || isEntitlementPass(discount) && ((_discount$config2 = discount.config) === null || _discount$config2 === void 0 ? void 0 : _discount$config2.isAvailable) === false) return;
996
+
801
997
  // 拿到discount配置的holder信息 product信息 product.holder 加在 isLimitedProduct
802
998
  var _tempVar = (flatItem === null || flatItem === void 0 ? void 0 : flatItem.type) === 'bundle' ? flatItem === null || flatItem === void 0 ? void 0 : flatItem.parentProduct : flatItem === null || flatItem === void 0 ? void 0 : flatItem.product;
803
999
  var isHolderMatch = _this3.checkHolderMatch(discount, {
804
1000
  isNeedHolder: isFormSubject && !(_tempVar !== null && _tempVar !== void 0 && _tempVar.isNormalProduct),
805
1001
  holder_id: (_tempVar === null || _tempVar === void 0 ? void 0 : _tempVar.holder_id) || product.holder_id
806
- }, holders);
1002
+ }, flatItem.originProduct, holders);
807
1003
  var timeLimit = true;
808
- timeLimit = !!filterDiscountListByBookingTime([discount], (((_product6 = product) === null || _product6 === void 0 ? void 0 : _product6.startDate) || dayjs()).format('YYYY-MM-DD HH:mm:ss')).length;
1004
+ var useTime = dayjs(((_product6 = product) === null || _product6 === void 0 ? void 0 : _product6.startDate) || undefined).format('YYYY-MM-DD HH:mm:ss');
1005
+ timeLimit = !!filterDiscountListByBookingTime([discount], useTime).length;
1006
+ if (isEntitlementPass(discount)) {
1007
+ var reason = getDiscountTimeUnavailableReason(discount, useTime);
1008
+ var reasons = entitlementTimeReasons.get(discount.id) || [];
1009
+ reasons.push(reason);
1010
+ entitlementTimeReasons.set(discount.id, reasons);
1011
+ if (!isHolderMatch) entitlementHolderMismatch.add(discount.id);
1012
+ }
809
1013
  // 是符合折扣的商品
810
- var isLimitedProduct = (limitedData.type === 'product_all' || limitedData.product_ids && limitedData.product_ids.includes(product.id)) && isHolderMatch;
1014
+ var isLimitedProduct = (limitedData.type === 'product_all' && !(limitedData.filter === 1 && (_limitedData$exclude_2 = limitedData.exclude_product_ids) !== null && _limitedData$exclude_2 !== void 0 && _limitedData$exclude_2.includes(product.id)) || limitedData.product_ids && limitedData.product_ids.includes(product.id)) && isHolderMatch;
811
1015
 
812
1016
  // 编辑的商品 使用了优惠券不可用
813
1017
  var isAvailableProduct = flatItem.type === 'main' ? !((_product7 = product) !== null && _product7 !== void 0 && _product7.booking_id && (_product8 = product) !== null && _product8 !== void 0 && (_product8 = _product8.discount_list) !== null && _product8 !== void 0 && _product8.length && (_product9 = product) !== null && _product9 !== void 0 && (_product9 = _product9.discount_list) !== null && _product9 !== void 0 && _product9.every(function (discount) {
814
- return discount.id && ['good_pass', 'discount_card', 'product_discount_card'].includes(discount.tag || discount.type);
1018
+ return discount.id && ['entitlement_pass', 'good_pass', 'discount_card', 'product_discount_card'].includes(discount.tag || discount.type);
815
1019
  })) : !(flatItem !== null && flatItem !== void 0 && flatItem.booking_id && !!(flatItem !== null && flatItem !== void 0 && (_flatItem$bundleItem3 = flatItem.bundleItem) !== null && _flatItem$bundleItem3 !== void 0 && (_flatItem$bundleItem3 = _flatItem$bundleItem3.discount_list) !== null && _flatItem$bundleItem3 !== void 0 && _flatItem$bundleItem3.length) && flatItem !== null && flatItem !== void 0 && (_flatItem$bundleItem4 = flatItem.bundleItem) !== null && _flatItem$bundleItem4 !== void 0 && (_flatItem$bundleItem4 = _flatItem$bundleItem4.discount_list) !== null && _flatItem$bundleItem4 !== void 0 && _flatItem$bundleItem4.every(function (discount) {
816
1020
  return discount.id;
817
1021
  }));
@@ -820,7 +1024,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
820
1024
  var isBundleAvailable = _this3.checkPackageSubItemUsageRules(discount, flatItem);
821
1025
 
822
1026
  // 判断优惠券是否适用于该商品
823
- if (isAvailableProduct && isLimitedProduct && timeLimit && isBundleAvailable) {
1027
+ if (isAvailableProduct && !isPersistedEntitlementLine(originProduct, flatItem.type === 'main' ? flatItem.product : flatItem.parentProduct) && isLimitedProduct && isBundleAvailable && timeLimit) {
824
1028
  var _discountApplicabilit, _discount$metadata4, _discount$metadata5;
825
1029
  // 记录此优惠券适用的商品
826
1030
  (_discountApplicabilit = discountApplicability.get(discount.id)) === null || _discountApplicabilit === void 0 || _discountApplicabilit.push(product.id);
@@ -828,7 +1032,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
828
1032
  // 记录可抵扣的商品详情
829
1033
  var applicableProducts = discountApplicableProducts.get(discount.id) || [];
830
1034
  var discountType = discount.tag || discount.type;
831
- var isGoodPass = discountType === 'good_pass';
1035
+ var isGoodPass = isFullCoveragePass(discount);
832
1036
 
833
1037
  // 使用数量
834
1038
  var num = isGoodPass || (flatItem === null || flatItem === void 0 ? void 0 : flatItem.type) === 'main' ? 1 : product.num;
@@ -844,7 +1048,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
844
1048
  title: discount.format_title,
845
1049
  original_amount: product.price || product.origin_total,
846
1050
  pre_value: discount.par_value,
847
- product_id: originProduct.id
1051
+ product_id: product.id
848
1052
  },
849
1053
  metadata: {
850
1054
  num: num,
@@ -889,8 +1093,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
889
1093
  }
890
1094
 
891
1095
  // 已有优惠的商品跳过
892
- if ((_product10 = product) !== null && _product10 !== void 0 && _product10.booking_id && (_product$discount_lis2 = product.discount_list) !== null && _product$discount_lis2 !== void 0 && _product$discount_lis2.length && (_product11 = product) !== null && _product11 !== void 0 && (_product11 = _product11.discount_list) !== null && _product11 !== void 0 && _product11.every(function (discount) {
893
- return discount.id && ['good_pass', 'discount_card', 'product_discount_card'].includes(discount.tag || discount.type);
1096
+ if (isPersistedEntitlementLine(originProduct, flatItem.type === 'main' ? flatItem.product : flatItem.parentProduct) || (_product10 = product) !== null && _product10 !== void 0 && _product10.booking_id && (_product$discount_lis2 = product.discount_list) !== null && _product$discount_lis2 !== void 0 && _product$discount_lis2.length && (_product11 = product) !== null && _product11 !== void 0 && (_product11 = _product11.discount_list) !== null && _product11 !== void 0 && _product11.every(function (discount) {
1097
+ return discount.id && ['entitlement_pass', 'good_pass', 'discount_card', 'product_discount_card'].includes(discount.tag || discount.type);
894
1098
  })) {
895
1099
  if (flatItem.type === 'main') {
896
1100
  processedProductsMap.set(product._id, [originProduct]);
@@ -904,31 +1108,33 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
904
1108
 
905
1109
  // 找到适用于此商品的所有优惠券,仅考虑isSelected不为false的优惠券
906
1110
  var applicableDiscounts = sortedDiscountList.filter(function (discount) {
907
- var _product$discount_lis3, _product$discount_lis4;
1111
+ var _discount$config3, _discount$config4, _discount$config5, _product$discount_lis3, _product$discount_lis4;
1112
+ if (isEntitlementPass(discount) && (((_discount$config3 = discount.config) === null || _discount$config3 === void 0 ? void 0 : _discount$config3.isAvailable) === false || getRemainingEntitlementUses(discount, entitlementUsageCounts.get(discount.id) || 0, 1) <= 0 || Number((_discount$config4 = discount.config) === null || _discount$config4 === void 0 ? void 0 : _discount$config4.maxUsagePerOrder) > 0 && (usedProductIdCounts.get(discount.product_id) || 0) >= Number((_discount$config5 = discount.config) === null || _discount$config5 === void 0 ? void 0 : _discount$config5.maxUsagePerOrder))) return false;
908
1113
  // 如果商品价格为 0,其实不需要使用任何优惠券,直接 return true
909
1114
  // 商品券时主商品价格为0不可用
910
- if ((Number(product.price) <= 0 || !product.price) && !((_product$discount_lis3 = product.discount_list) !== null && _product$discount_lis3 !== void 0 && _product$discount_lis3.length) && (discount.tag || discount.type) === 'good_pass') return false;
1115
+ if ((Number(product.price) <= 0 || !product.price) && !((_product$discount_lis3 = product.discount_list) !== null && _product$discount_lis3 !== void 0 && _product$discount_lis3.length) && isFullCoveragePass(discount)) return false;
911
1116
 
912
1117
  // 折扣卡商品价格为0时不可用
913
1118
  if ((Number(product.price) <= 0 || !product.price) && !((_product$discount_lis4 = product.discount_list) !== null && _product$discount_lis4 !== void 0 && _product$discount_lis4.find(function (n) {
914
1119
  var _n$discount;
915
1120
  return ((_n$discount = n.discount) === null || _n$discount === void 0 ? void 0 : _n$discount.resource_id) === discount.id;
916
- })) && (discount.tag || discount.type) !== 'good_pass') return false;
1121
+ })) && !isFullCoveragePass(discount)) return false;
917
1122
  // 如果优惠券已被使用,则跳过
918
1123
  var targetUsedDiscounts = usedDiscounts.get(discount.id);
919
1124
  if (targetUsedDiscounts && (discount.tag || discount.type) === 'good_pass') return false;
920
1125
  var limitedData = discount.limited_relation_product_data;
1126
+ if (!limitedData) return false;
921
1127
 
922
1128
  // 拿到discount配置的holder信息 product信息 product.holder 不可用return false
923
1129
  var _tempVar = (flatItem === null || flatItem === void 0 ? void 0 : flatItem.type) === 'bundle' ? flatItem === null || flatItem === void 0 ? void 0 : flatItem.parentProduct : flatItem === null || flatItem === void 0 ? void 0 : flatItem.product;
924
1130
  var isHolderMatch = _this3.checkHolderMatch(discount, {
925
1131
  isNeedHolder: isFormSubject && !(_tempVar !== null && _tempVar !== void 0 && _tempVar.isNormalProduct),
926
1132
  holder_id: (_tempVar === null || _tempVar === void 0 ? void 0 : _tempVar.holder_id) || product.holder_id
927
- }, holders);
1133
+ }, flatItem.originProduct, holders);
928
1134
  // 如果 holder 不匹配,则不适用
929
1135
  if (!isHolderMatch) return false;
930
1136
  var timeLimit = true;
931
- timeLimit = !!filterDiscountListByBookingTime([discount], (product.startDate || dayjs()).format('YYYY-MM-DD HH:mm:ss')).length;
1137
+ timeLimit = !!filterDiscountListByBookingTime([discount], dayjs(product.startDate || undefined).format('YYYY-MM-DD HH:mm:ss')).length;
932
1138
  if (!timeLimit) {
933
1139
  return false;
934
1140
  }
@@ -958,9 +1164,12 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
958
1164
  // 如果有 isScan 且 isSelected 的折扣卡,则优先选中,否则再选择第一个
959
1165
  // 用于处理:先手动扫描了一张折扣卡,扫描完以后带入客户信息,但是之前那张折扣卡不是最优惠的情况
960
1166
  var selectedDiscountCard = applicableDiscounts.find(function (n) {
961
- return n.isScan && n.isSelected && (n.tag || n.type) !== 'good_pass';
1167
+ return n.isScan && n.isSelected && !isFullCoveragePass(n);
962
1168
  });
963
- var selectedDiscount = selectedDiscountCard || applicableDiscounts[0];
1169
+ var explicitlySelected = (options === null || options === void 0 ? void 0 : options.isSelected) === true ? applicableDiscounts.find(function (item) {
1170
+ return isEntitlementPass(item) && String(item.id) === String(options.discountId);
1171
+ }) : undefined;
1172
+ var selectedDiscount = explicitlySelected || selectedDiscountCard || applicableDiscounts[0];
964
1173
 
965
1174
  // 如果是手动折扣,则不适用优惠券
966
1175
  var isManualDiscount = false;
@@ -968,8 +1177,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
968
1177
  var _product$discount_lis5, _product12, _product12$every;
969
1178
  // 主商品:判断自身是否手动折扣
970
1179
  isManualDiscount = typeof product.isManualDiscount === 'boolean' ? product.isManualDiscount : product.total != product.origin_total && (product.bundle || []).every(function (item) {
971
- var _ref6;
972
- return !((_ref6 = item.discount_list || []) !== null && _ref6 !== void 0 && _ref6.length);
1180
+ var _ref18;
1181
+ return !((_ref18 = item.discount_list || []) !== null && _ref18 !== void 0 && _ref18.length);
973
1182
  }) && (!((_product$discount_lis5 = product.discount_list) !== null && _product$discount_lis5 !== void 0 && _product$discount_lis5.length) || ((_product12 = product) === null || _product12 === void 0 || (_product12 = _product12.discount_list) === null || _product12 === void 0 || (_product12$every = _product12.every) === null || _product12$every === void 0 ? void 0 : _product12$every.call(_product12, function (item) {
974
1183
  return item.type === 'product';
975
1184
  })));
@@ -979,8 +1188,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
979
1188
  if (parentProduct) {
980
1189
  var _parentProduct$discou, _parentProduct$discou2, _parentProduct$discou3;
981
1190
  isManualDiscount = typeof parentProduct.isManualDiscount === 'boolean' ? parentProduct.isManualDiscount : parentProduct.total != parentProduct.origin_total && (parentProduct.bundle || []).every(function (item) {
982
- var _ref7;
983
- return !((_ref7 = item.discount_list || []) !== null && _ref7 !== void 0 && _ref7.length);
1191
+ var _ref19;
1192
+ return !((_ref19 = item.discount_list || []) !== null && _ref19 !== void 0 && _ref19.length);
984
1193
  }) && (!((_parentProduct$discou = parentProduct.discount_list) !== null && _parentProduct$discou !== void 0 && _parentProduct$discou.length) || (parentProduct === null || parentProduct === void 0 || (_parentProduct$discou2 = parentProduct.discount_list) === null || _parentProduct$discou2 === void 0 || (_parentProduct$discou3 = _parentProduct$discou2.every) === null || _parentProduct$discou3 === void 0 ? void 0 : _parentProduct$discou3.call(_parentProduct$discou2, function (item) {
985
1194
  return item.type === 'product';
986
1195
  })));
@@ -1072,8 +1281,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1072
1281
  discount_list: _this3.filterDiscountListByType(product.discount_list, 'promotion')
1073
1282
  }))]);
1074
1283
  } else {
1075
- var _ref8, _product$_promotion$f, _product13, _product$origin_total, _product$price2;
1076
- var total = product.inPromotion ? (_ref8 = (_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 && _ref8 !== void 0 ? _ref8 : product.total : (_product$origin_total = product.origin_total) !== null && _product$origin_total !== void 0 ? _product$origin_total : product.total;
1284
+ var _ref20, _product$_promotion$f, _product13, _product$origin_total, _product$price2;
1285
+ var total = product.inPromotion ? (_ref20 = (_product$_promotion$f = (_product13 = product) === null || _product13 === void 0 || (_product13 = _product13._promotion) === null || _product13 === void 0 ? void 0 : _product13.finalPrice) !== null && _product$_promotion$f !== void 0 ? _product$_promotion$f : product.origin_total) !== null && _ref20 !== void 0 ? _ref20 : product.total : (_product$origin_total = product.origin_total) !== null && _product$origin_total !== void 0 ? _product$origin_total : product.total;
1077
1286
  var main_product_selling_price = (_product$price2 = product.price) !== null && _product$price2 !== void 0 ? _product$price2 : product.main_product_selling_price;
1078
1287
  if ((product.discount_list || []).some(function (item) {
1079
1288
  return item.type === 'promotion';
@@ -1111,14 +1320,17 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1111
1320
  }
1112
1321
 
1113
1322
  // 是否需要拆分(商品券需要拆分)
1114
- var isNeedSplit = (selectedDiscount.tag || selectedDiscount.type) === 'good_pass';
1323
+ var isNeedSplit = isFullCoveragePass(selectedDiscount);
1115
1324
 
1116
1325
  // 需要拆分出来的数量
1117
1326
  var totalQuantity = product.quantity || product.num || 1;
1118
- var availableGoodPassCount = applicableDiscounts.filter(function (item) {
1327
+ var prioritizedDiscounts = [selectedDiscount].concat(_toConsumableArray(applicableDiscounts.filter(function (item) {
1328
+ return item !== selectedDiscount;
1329
+ })));
1330
+ var allocatedPasses = isNeedSplit ? applicableDiscounts.some(isEntitlementPass) ? getFullCoveragePasses(prioritizedDiscounts, totalQuantity) : applicableDiscounts.slice(0, Math.min(totalQuantity, applicableDiscounts.filter(function (item) {
1119
1331
  return (item.tag || item.type) === 'good_pass';
1120
- }).length;
1121
- var splitCount = isNeedSplit ? Math.min(totalQuantity, availableGoodPassCount) : 1;
1332
+ }).length)) : [selectedDiscount];
1333
+ var splitCount = allocatedPasses.length;
1122
1334
  var arr = [];
1123
1335
 
1124
1336
  // 🔥 主商品和bundle子商品分别处理
@@ -1133,10 +1345,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1133
1345
  }
1134
1346
  for (var i = 0; i < splitCount; i++) {
1135
1347
  var _originProduct, _selectedDiscount$met, _selectedDiscount$met2;
1136
- // 如果用过折扣卡,也就不存在拆分的情况了,这里直接使用上面计算出来的折扣卡
1137
- var _selectedDiscount = selectedDiscountCard || applicableDiscounts[i];
1138
- // 标记优惠券为已使用
1139
- usedDiscounts.set(_selectedDiscount.id, true);
1348
+ var _selectedDiscount = allocatedPasses[i];
1349
+ markDiscountUsed(_selectedDiscount);
1140
1350
 
1141
1351
  // 记录实际应用了优惠券的商品信息
1142
1352
  var appliedProducts = appliedDiscountProducts.get(_selectedDiscount.id) || [];
@@ -1171,7 +1381,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1171
1381
  amount = new Decimal(product.price).minus(new Decimal(targetProductTotal)).toNumber();
1172
1382
  }
1173
1383
  var discountType = _selectedDiscount.tag || _selectedDiscount.type;
1174
- var isGoodPass = discountType === 'good_pass';
1384
+ var isGoodPass = isFullCoveragePass(_selectedDiscount);
1175
1385
  var discountDetail = {
1176
1386
  amount: amount,
1177
1387
  type: _selectedDiscount.tag === 'product_discount_card' ? 'discount_card' : discountType,
@@ -1182,7 +1392,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1182
1392
  resource_id: _selectedDiscount.id,
1183
1393
  title: _selectedDiscount.format_title,
1184
1394
  original_amount: product.price,
1185
- product_id: originProduct.id,
1395
+ product_id: product.id,
1186
1396
  percent: _selectedDiscount.par_value
1187
1397
  },
1188
1398
  // 前端使用的num数量,为了计算优惠金额
@@ -1210,7 +1420,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1210
1420
  if (product.isClient) {
1211
1421
  arr.push(_this3.hooks.setProduct(originProduct, {
1212
1422
  discount_list: [discountDetail],
1213
- price: _selectedDiscount.tag === 'good_pass' ? 0 : product.price,
1423
+ price: isGoodPass ? 0 : product.price,
1214
1424
  quantity: isNeedSplit ? 1 : product.quantity,
1215
1425
  origin_total: getProductOriginTotalPrice({
1216
1426
  product: {
@@ -1226,8 +1436,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1226
1436
  } else {
1227
1437
  arr.push(_this3.hooks.setProduct(originProduct, {
1228
1438
  discount_list: _this3.filterDiscountListByType(product.discount_list, 'promotion').concat([discountDetail]),
1229
- _id: product._id.split('___')[0] + "___" + _selectedDiscount.id + index,
1230
- price: _selectedDiscount.tag === 'good_pass' ? 0 : product.price,
1439
+ _id: product._id.split('___')[0] + "___" + _selectedDiscount.id + index + (isEntitlementPass(_selectedDiscount) ? "_".concat(i) : ''),
1440
+ price: isGoodPass ? 0 : product.price,
1231
1441
  quantity: isNeedSplit ? 1 : product.quantity,
1232
1442
  total: _total,
1233
1443
  origin_total: productOriginTotal,
@@ -1247,16 +1457,16 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1247
1457
  // 生成有折扣的商品(每张商品券对应 num: 1)
1248
1458
  for (var _i = 0; _i < discountNum; _i++) {
1249
1459
  var _selectedDiscount2$me;
1250
- var _selectedDiscount2 = applicableDiscounts[_i];
1251
- usedDiscounts.set(_selectedDiscount2.id, true);
1460
+ var _selectedDiscount2 = allocatedPasses[_i];
1461
+ markDiscountUsed(_selectedDiscount2);
1252
1462
 
1253
1463
  // 🔥 生成唯一的 _id
1254
1464
  var uniqueId = "".concat(flatItem._id, "_split_").concat(_i);
1255
1465
  var _discountDetail = {
1256
- amount: product.origin_total,
1257
- type: 'good_pass',
1466
+ amount: product.origin_total || product.price || 0,
1467
+ type: _selectedDiscount2.tag || _selectedDiscount2.type,
1258
1468
  discount: {
1259
- fixed_amount: product.origin_total,
1469
+ fixed_amount: product.origin_total || product.price || 0,
1260
1470
  discount_calculation_mode: _selectedDiscount2 === null || _selectedDiscount2 === void 0 || (_selectedDiscount2$me = _selectedDiscount2.metadata) === null || _selectedDiscount2$me === void 0 ? void 0 : _selectedDiscount2$me.discount_calculation_mode,
1261
1471
  resource_id: _selectedDiscount2.id,
1262
1472
  title: _selectedDiscount2.format_title,
@@ -1302,15 +1512,14 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1302
1512
  }));
1303
1513
  }
1304
1514
  } else {
1305
- var _selectedDiscount3$me, _selectedDiscount3$me2, _flatItem$parentProdu9;
1515
+ var _selectedDiscount$met3, _selectedDiscount$met4, _flatItem$parentProdu9;
1306
1516
  // 折扣卡:不拆分数量,直接应用
1307
- var _selectedDiscount3 = selectedDiscountCard || applicableDiscounts[0];
1308
- usedDiscounts.set(_selectedDiscount3.id, true);
1517
+ usedDiscounts.set(selectedDiscount.id, true);
1309
1518
  var _productOriginTotal = product.original_price || product.price || 0;
1310
1519
 
1311
1520
  // 🔥 检查是否是 order_level 固定金额折扣卡
1312
- var _isOrderLevel = isOrderLevelFixedAmountDiscount(_selectedDiscount3);
1313
- var _orderLevelAllocation = _isOrderLevel ? orderLevelDiscountAllocations.get(_selectedDiscount3.id) : null;
1521
+ var _isOrderLevel = isOrderLevelFixedAmountDiscount(selectedDiscount);
1522
+ var _orderLevelAllocation = _isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount.id) : null;
1314
1523
  var _productAllocation = _orderLevelAllocation === null || _orderLevelAllocation === void 0 ? void 0 : _orderLevelAllocation.get(flatItem._id);
1315
1524
  var _targetProductTotal;
1316
1525
  var fixedAmountPerItem;
@@ -1322,7 +1531,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1322
1531
  _targetProductTotal = Math.max(new Decimal(_productOriginTotal).minus(fixedAmountPerItem).toNumber(), 0);
1323
1532
  } else {
1324
1533
  // item_level 或其他类型:使用原有逻辑
1325
- _targetProductTotal = getDiscountAmount(_selectedDiscount3, _productOriginTotal, _productOriginTotal);
1534
+ _targetProductTotal = getDiscountAmount(selectedDiscount, _productOriginTotal, _productOriginTotal);
1326
1535
  fixedAmountPerItem = new Decimal(_productOriginTotal).minus(_targetProductTotal).toNumber();
1327
1536
  }
1328
1537
 
@@ -1330,21 +1539,21 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1330
1539
  var _uniqueId = flatItem._id;
1331
1540
  var _discountDetail2 = {
1332
1541
  amount: fixedAmountPerItem * (product.num || 1),
1333
- type: _selectedDiscount3.tag === 'product_discount_card' ? 'discount_card' : _selectedDiscount3.tag,
1542
+ type: selectedDiscount.tag === 'product_discount_card' ? 'discount_card' : selectedDiscount.tag,
1334
1543
  discount: {
1335
- discount_card_type: _selectedDiscount3 === null || _selectedDiscount3 === void 0 || (_selectedDiscount3$me = _selectedDiscount3.metadata) === null || _selectedDiscount3$me === void 0 ? void 0 : _selectedDiscount3$me.discount_card_type,
1544
+ discount_card_type: selectedDiscount === null || selectedDiscount === void 0 || (_selectedDiscount$met3 = selectedDiscount.metadata) === null || _selectedDiscount$met3 === void 0 ? void 0 : _selectedDiscount$met3.discount_card_type,
1336
1545
  fixed_amount: fixedAmountPerItem,
1337
- discount_calculation_mode: _selectedDiscount3 === null || _selectedDiscount3 === void 0 || (_selectedDiscount3$me2 = _selectedDiscount3.metadata) === null || _selectedDiscount3$me2 === void 0 ? void 0 : _selectedDiscount3$me2.discount_calculation_mode,
1338
- resource_id: _selectedDiscount3.id,
1339
- title: _selectedDiscount3.format_title,
1546
+ discount_calculation_mode: selectedDiscount === null || selectedDiscount === void 0 || (_selectedDiscount$met4 = selectedDiscount.metadata) === null || _selectedDiscount$met4 === void 0 ? void 0 : _selectedDiscount$met4.discount_calculation_mode,
1547
+ resource_id: selectedDiscount.id,
1548
+ title: selectedDiscount.format_title,
1340
1549
  original_amount: product.original_price,
1341
1550
  product_id: product.id,
1342
- percent: _selectedDiscount3.par_value
1551
+ percent: selectedDiscount.par_value
1343
1552
  },
1344
1553
  metadata: _objectSpread({
1345
1554
  // 🔥 使用唯一的 _id
1346
1555
  custom_product_bundle_map_id: _uniqueId,
1347
- discount_rule_uncheck_flag: _selectedDiscount3 === null || _selectedDiscount3 === void 0 ? void 0 : _selectedDiscount3.discount_rule_uncheck_flag,
1556
+ discount_rule_uncheck_flag: selectedDiscount === null || selectedDiscount === void 0 ? void 0 : selectedDiscount.discount_rule_uncheck_flag,
1348
1557
  num: product.num || 1
1349
1558
  }, _productDiscountDifference !== undefined && {
1350
1559
  product_discount_difference: _productDiscountDifference
@@ -1353,9 +1562,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1353
1562
  };
1354
1563
 
1355
1564
  // 记录实际应用的折扣
1356
- var _appliedProducts2 = appliedDiscountProducts.get(_selectedDiscount3.id) || [];
1565
+ var _appliedProducts2 = appliedDiscountProducts.get(selectedDiscount.id) || [];
1357
1566
  _appliedProducts2.push(_discountDetail2);
1358
- appliedDiscountProducts.set(_selectedDiscount3.id, _appliedProducts2);
1567
+ appliedDiscountProducts.set(selectedDiscount.id, _appliedProducts2);
1359
1568
  processedItems.push(_objectSpread(_objectSpread({}, flatItem), {}, {
1360
1569
  total: _targetProductTotal,
1361
1570
  price: new Decimal(_productOriginTotal || 0).minus(fixedAmountPerItem).toNumber(),
@@ -1373,8 +1582,40 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1373
1582
  originalProductList.forEach(function (originProduct) {
1374
1583
  var product = _this3.hooks.getProduct(originProduct);
1375
1584
 
1585
+ // 已提交的扣次不参与运行时重组,避免价格或使用明细被二次改写。
1586
+ if (isPersistedEntitlementLine(originProduct, product)) {
1587
+ result.push(originProduct);
1588
+ return;
1589
+ }
1590
+
1376
1591
  // 获取主商品处理结果
1377
1592
  var mainProductArr = processedProductsMap.get(product._id);
1593
+ if (isEntitlementRuntimeLine(originProduct, product) && !product.isManualDiscount && mainProductArr !== null && mainProductArr !== void 0 && mainProductArr.length) {
1594
+ var bundle = (product.bundle || []).flatMap(function (item, index) {
1595
+ var processed = processedFlatItemsMap.get("".concat(product._id, "_bundle_").concat(index));
1596
+ if (!(processed !== null && processed !== void 0 && processed.length)) return [item];
1597
+ return processed.map(function (child) {
1598
+ return _objectSpread(_objectSpread({}, item), {}, {
1599
+ _id: child._id,
1600
+ price: child.price,
1601
+ bundle_selling_price: child.price,
1602
+ num: child.num,
1603
+ discount_list: (child.discount_list || []).map(function (detail) {
1604
+ return _objectSpread(_objectSpread({}, detail), {}, {
1605
+ metadata: _objectSpread(_objectSpread({}, detail.metadata), {}, {
1606
+ num: child.num,
1607
+ custom_product_bundle_map_id: child._id
1608
+ })
1609
+ });
1610
+ })
1611
+ });
1612
+ });
1613
+ });
1614
+ result.push.apply(result, _toConsumableArray(mainProductArr.map(function (item) {
1615
+ return rebuildEntitlementLine(item, bundle, _this3.hooks);
1616
+ })));
1617
+ return;
1618
+ }
1378
1619
  if (!mainProductArr || mainProductArr.length === 0) {
1379
1620
  // 如果没有处理结果,返回默认商品
1380
1621
  var getDefaultProduct = function getDefaultProduct() {
@@ -1437,7 +1678,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1437
1678
  var hasGoodPass = processedBundleItems.some(function (item) {
1438
1679
  var _item$discount_list;
1439
1680
  return (_item$discount_list = item.discount_list) === null || _item$discount_list === void 0 ? void 0 : _item$discount_list.some(function (discount) {
1440
- return discount.type === 'good_pass' || discount.tag === 'good_pass';
1681
+ return isFullCoveragePass(discount);
1441
1682
  });
1442
1683
  });
1443
1684
  if (hasGoodPass) {
@@ -1769,6 +2010,29 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1769
2010
 
1770
2011
  // 获取此优惠券实际应用的商品详情
1771
2012
  var appliedProductDetails = appliedDiscountProducts.get(discount.id) || [];
2013
+ if (isEntitlementPass(discount)) {
2014
+ var committed = discount.committedAppliedProductDetails || [];
2015
+ var details = [].concat(_toConsumableArray(committed), _toConsumableArray(appliedProductDetails));
2016
+ var _isAvailable = applicableProducts.length > 0;
2017
+ var timeReasons = entitlementTimeReasons.get(discount.id) || [];
2018
+ var timeReason = timeReasons.length ? timeReasons.every(Boolean) ? timeReasons[0] : undefined : getDiscountTimeUnavailableReason(discount, dayjs().format('YYYY-MM-DD HH:mm:ss'));
2019
+ var reasonCode = _isAvailable ? undefined : discount.reasonCode || timeReason || (entitlementHolderMismatch.has(discount.id) ? 'holder_not_matched' : 'product_not_applicable');
2020
+ return _objectSpread(_objectSpread({}, discount), {}, {
2021
+ isAvailable: _isAvailable || committed.length > 0,
2022
+ isSelected: details.length > 0,
2023
+ isUsed: details.length > 0,
2024
+ reasonCode: reasonCode,
2025
+ reason: reasonCode === discount.reasonCode ? discount.reason : undefined,
2026
+ isManualSelect: options !== null && options !== void 0 && options.scan ? false : discount.isManualSelect,
2027
+ applicableProductIds: applicableProducts,
2028
+ applicableProductDetails: applicableProductDetails,
2029
+ appliedProductDetails: details,
2030
+ savedAmount: details.reduce(function (sum, detail) {
2031
+ var _detail$discount;
2032
+ return new Decimal(sum).plus(new Decimal(((_detail$discount = detail.discount) === null || _detail$discount === void 0 ? void 0 : _detail$discount.fixed_amount) || 0).mul(detail._num || 1)).toNumber();
2033
+ }, 0)
2034
+ });
2035
+ }
1772
2036
 
1773
2037
  // 根据是否有适用商品决定isAvailable
1774
2038
  var isAvailable = applicableProducts.length > 0;
@@ -1824,7 +2088,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1824
2088
  });
1825
2089
  console.log(processedProductList, 'processedProductList');
1826
2090
  return {
1827
- productList: processedProductList,
2091
+ productList: this.entitlementPassEnabled ? finalizeEntitlementLines(processedProductList, this.hooks) : processedProductList,
1828
2092
  discountList: [].concat(editModeDiscount, _toConsumableArray(updatedDiscountList))
1829
2093
  };
1830
2094
  }
@@ -1849,14 +2113,15 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1849
2113
  var ruleType = usageRules.type;
1850
2114
  // 套餐适用范围配置
1851
2115
  var packageScope = usageRules === null || usageRules === void 0 ? void 0 : usageRules.package_scope;
1852
- var _ref9 = packageScope || {},
1853
- scopeType = _ref9.type,
1854
- _ref9$exclude_bundle_ = _ref9.exclude_bundle_product_ids,
1855
- exclude_bundle_product_ids = _ref9$exclude_bundle_ === void 0 ? [] : _ref9$exclude_bundle_,
1856
- _ref9$include_bundle_ = _ref9.include_bundle_product_ids,
1857
- include_bundle_product_ids = _ref9$include_bundle_ === void 0 ? [] : _ref9$include_bundle_,
1858
- _ref9$filter = _ref9.filter,
1859
- filter = _ref9$filter === void 0 ? 0 : _ref9$filter;
2116
+ var _ref21 = packageScope || {},
2117
+ _ref21$type = _ref21.type,
2118
+ scopeType = _ref21$type === void 0 ? 'product_all' : _ref21$type,
2119
+ _ref21$exclude_bundle = _ref21.exclude_bundle_product_ids,
2120
+ exclude_bundle_product_ids = _ref21$exclude_bundle === void 0 ? [] : _ref21$exclude_bundle,
2121
+ _ref21$include_bundle = _ref21.include_bundle_product_ids,
2122
+ include_bundle_product_ids = _ref21$include_bundle === void 0 ? [] : _ref21$include_bundle,
2123
+ _ref21$filter = _ref21.filter,
2124
+ filter = _ref21$filter === void 0 ? 0 : _ref21$filter;
1860
2125
  var isMainProduct = flatItem.type === 'main'; // 单独购买
1861
2126
  var isBundleItem = flatItem.type === 'bundle'; // 套餐中购买
1862
2127