@pisell/pisellos 2.1.170 → 2.1.172

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 (231) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +1 -3
  3. package/dist/model/strategy/adapter/index.d.ts +0 -4
  4. package/dist/model/strategy/adapter/index.js +1 -5
  5. package/dist/model/strategy/adapter/promotion/evaluator.js +99 -26
  6. package/dist/model/strategy/adapter/promotion/index.js +0 -9
  7. package/dist/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
  8. package/dist/model/strategy/adapter/walletPass/evaluator.js +61 -8
  9. package/dist/model/strategy/adapter/walletPass/locales.js +12 -3
  10. package/dist/model/strategy/engine.d.ts +18 -5
  11. package/dist/model/strategy/engine.js +145 -45
  12. package/dist/model/strategy/type.d.ts +17 -0
  13. package/dist/model/strategy/type.js +4 -0
  14. package/dist/modules/Cart/types.d.ts +2 -0
  15. package/dist/modules/Cart/utils/cartProduct.js +56 -25
  16. package/dist/modules/Cart/utils/changePrice.js +9 -16
  17. package/dist/modules/Discount/index.d.ts +4 -13
  18. package/dist/modules/Discount/index.js +12 -124
  19. package/dist/modules/Discount/types.d.ts +18 -13
  20. package/dist/modules/Order/index.d.ts +1 -67
  21. package/dist/modules/Order/index.js +30 -918
  22. package/dist/modules/Order/types.d.ts +12 -176
  23. package/dist/modules/Order/types.js +0 -2
  24. package/dist/modules/Order/utils.d.ts +0 -118
  25. package/dist/modules/Order/utils.js +2 -586
  26. package/dist/modules/Payment/index.d.ts +2 -1
  27. package/dist/modules/Payment/index.js +10 -7
  28. package/dist/modules/Payment/utils.js +3 -0
  29. package/dist/modules/Payment/walletpass.d.ts +23 -0
  30. package/dist/modules/Payment/walletpass.js +191 -95
  31. package/dist/modules/Product/utils.js +2 -2
  32. package/dist/modules/ProductList/index.d.ts +2 -4
  33. package/dist/modules/ProductList/index.js +12 -24
  34. package/dist/modules/Rules/index.d.ts +9 -5
  35. package/dist/modules/Rules/index.js +669 -173
  36. package/dist/modules/Rules/types.d.ts +2 -0
  37. package/dist/modules/Schedule/getDateIsInSchedule.js +18 -16
  38. package/dist/modules/Schedule/utils.d.ts +1 -1
  39. package/dist/modules/Summary/types.d.ts +2 -0
  40. package/dist/modules/Summary/utils.d.ts +9 -3
  41. package/dist/modules/Summary/utils.js +57 -67
  42. package/dist/modules/index.d.ts +0 -4
  43. package/dist/modules/index.js +1 -5
  44. package/dist/plugins/window.d.ts +2 -0
  45. package/dist/solution/BookingByStep/index.d.ts +3 -2
  46. package/dist/solution/BookingByStep/index.js +43 -46
  47. package/dist/solution/BookingByStep/types.d.ts +1 -3
  48. package/dist/solution/BookingByStep/types.js +1 -5
  49. package/dist/solution/BookingByStep/utils/timeslots.d.ts +1 -3
  50. package/dist/solution/BookingByStep/utils/timeslots.js +12 -19
  51. package/dist/solution/Checkout/index.js +2 -0
  52. package/dist/solution/ShopDiscount/index.d.ts +2 -3
  53. package/dist/solution/ShopDiscount/index.js +60 -62
  54. package/dist/solution/ShopDiscount/types.d.ts +1 -1
  55. package/dist/solution/ShopDiscount/types.js +2 -1
  56. package/dist/solution/ShopDiscount/utils.js +26 -12
  57. package/dist/solution/index.d.ts +0 -2
  58. package/dist/solution/index.js +1 -3
  59. package/lib/index.d.ts +1 -1
  60. package/lib/index.js +3 -4
  61. package/lib/model/strategy/adapter/index.d.ts +0 -4
  62. package/lib/model/strategy/adapter/index.js +2 -13
  63. package/lib/model/strategy/adapter/promotion/evaluator.js +57 -8
  64. package/lib/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
  65. package/lib/model/strategy/adapter/walletPass/evaluator.js +34 -3
  66. package/lib/model/strategy/adapter/walletPass/locales.js +12 -3
  67. package/lib/model/strategy/engine.d.ts +18 -5
  68. package/lib/model/strategy/engine.js +85 -21
  69. package/lib/model/strategy/type.d.ts +17 -0
  70. package/lib/modules/Cart/types.d.ts +2 -0
  71. package/lib/modules/Cart/utils/cartProduct.js +39 -12
  72. package/lib/modules/Cart/utils/changePrice.js +9 -13
  73. package/lib/modules/Discount/index.d.ts +4 -13
  74. package/lib/modules/Discount/index.js +5 -76
  75. package/lib/modules/Discount/types.d.ts +18 -13
  76. package/lib/modules/Order/index.d.ts +1 -67
  77. package/lib/modules/Order/index.js +1 -525
  78. package/lib/modules/Order/types.d.ts +12 -176
  79. package/lib/modules/Order/utils.d.ts +0 -118
  80. package/lib/modules/Order/utils.js +2 -483
  81. package/lib/modules/Payment/index.d.ts +2 -1
  82. package/lib/modules/Payment/index.js +1 -0
  83. package/lib/modules/Payment/utils.js +3 -0
  84. package/lib/modules/Payment/walletpass.d.ts +23 -0
  85. package/lib/modules/Payment/walletpass.js +94 -17
  86. package/lib/modules/Product/utils.js +2 -2
  87. package/lib/modules/ProductList/index.d.ts +2 -4
  88. package/lib/modules/ProductList/index.js +39 -46
  89. package/lib/modules/Rules/index.d.ts +9 -5
  90. package/lib/modules/Rules/index.js +776 -292
  91. package/lib/modules/Rules/types.d.ts +2 -0
  92. package/lib/modules/Schedule/getDateIsInSchedule.js +11 -13
  93. package/lib/modules/Schedule/utils.d.ts +1 -1
  94. package/lib/modules/Summary/types.d.ts +2 -0
  95. package/lib/modules/Summary/utils.d.ts +9 -3
  96. package/lib/modules/Summary/utils.js +34 -45
  97. package/lib/modules/index.d.ts +0 -4
  98. package/lib/modules/index.js +1 -9
  99. package/lib/plugins/window.d.ts +2 -0
  100. package/lib/solution/BookingByStep/index.d.ts +3 -2
  101. package/lib/solution/BookingByStep/index.js +4 -6
  102. package/lib/solution/BookingByStep/types.d.ts +1 -3
  103. package/lib/solution/BookingByStep/types.js +0 -10
  104. package/lib/solution/BookingByStep/utils/timeslots.d.ts +1 -3
  105. package/lib/solution/BookingByStep/utils/timeslots.js +11 -19
  106. package/lib/solution/Checkout/index.js +2 -0
  107. package/lib/solution/ShopDiscount/index.d.ts +2 -3
  108. package/lib/solution/ShopDiscount/index.js +27 -22
  109. package/lib/solution/ShopDiscount/types.d.ts +1 -1
  110. package/lib/solution/ShopDiscount/utils.js +10 -6
  111. package/lib/solution/index.d.ts +0 -2
  112. package/lib/solution/index.js +1 -5
  113. package/package.json +2 -2
  114. package/dist/apis/picoding.d.ts +0 -0
  115. package/dist/apis/picoding.js +0 -1
  116. package/dist/model/strategy/adapter/dataVariant/adapter.d.ts +0 -50
  117. package/dist/model/strategy/adapter/dataVariant/adapter.js +0 -167
  118. package/dist/model/strategy/adapter/dataVariant/evaluator.d.ts +0 -89
  119. package/dist/model/strategy/adapter/dataVariant/evaluator.js +0 -867
  120. package/dist/model/strategy/adapter/dataVariant/examples.d.ts +0 -39
  121. package/dist/model/strategy/adapter/dataVariant/examples.js +0 -277
  122. package/dist/model/strategy/adapter/dataVariant/index.d.ts +0 -4
  123. package/dist/model/strategy/adapter/dataVariant/index.js +0 -4
  124. package/dist/model/strategy/adapter/dataVariant/type.d.ts +0 -149
  125. package/dist/model/strategy/adapter/dataVariant/type.js +0 -54
  126. package/dist/modules/OpenData/index.d.ts +0 -24
  127. package/dist/modules/OpenData/index.js +0 -173
  128. package/dist/modules/OpenData/types.d.ts +0 -73
  129. package/dist/modules/OpenData/types.js +0 -1
  130. package/dist/modules/OpenData/utils.d.ts +0 -2
  131. package/dist/modules/OpenData/utils.js +0 -75
  132. package/dist/modules/Quotation/index.d.ts +0 -48
  133. package/dist/modules/Quotation/index.js +0 -248
  134. package/dist/modules/Quotation/types.d.ts +0 -42
  135. package/dist/modules/Quotation/types.js +0 -1
  136. package/dist/modules/SalesSummary/index.d.ts +0 -63
  137. package/dist/modules/SalesSummary/index.js +0 -174
  138. package/dist/modules/SalesSummary/types.d.ts +0 -60
  139. package/dist/modules/SalesSummary/types.js +0 -1
  140. package/dist/modules/SalesSummary/utils.d.ts +0 -30
  141. package/dist/modules/SalesSummary/utils.js +0 -480
  142. package/dist/modules/ScanOrderLogger/index.d.ts +0 -23
  143. package/dist/modules/ScanOrderLogger/index.js +0 -174
  144. package/dist/modules/ScanOrderLogger/providers/feishu.d.ts +0 -2
  145. package/dist/modules/ScanOrderLogger/providers/feishu.js +0 -221
  146. package/dist/modules/ScanOrderLogger/providers/grafana.d.ts +0 -2
  147. package/dist/modules/ScanOrderLogger/providers/grafana.js +0 -50
  148. package/dist/modules/ScanOrderLogger/types.d.ts +0 -53
  149. package/dist/modules/ScanOrderLogger/types.js +0 -1
  150. package/dist/solution/ScanOrder/index.d.ts +0 -158
  151. package/dist/solution/ScanOrder/index.js +0 -3474
  152. package/dist/solution/ScanOrder/types.d.ts +0 -306
  153. package/dist/solution/ScanOrder/types.js +0 -35
  154. package/dist/solution/ScanOrder/utils.d.ts +0 -172
  155. package/dist/solution/ScanOrder/utils.js +0 -796
  156. package/dist/solution/VenueBooking/index.d.ts +0 -252
  157. package/dist/solution/VenueBooking/index.js +0 -3769
  158. package/dist/solution/VenueBooking/sales-section-4-annotated.json +0 -343
  159. package/dist/solution/VenueBooking/types.d.ts +0 -156
  160. package/dist/solution/VenueBooking/types.js +0 -22
  161. package/dist/solution/VenueBooking/utils/dateSummary.d.ts +0 -11
  162. package/dist/solution/VenueBooking/utils/dateSummary.js +0 -91
  163. package/dist/solution/VenueBooking/utils/resource.d.ts +0 -14
  164. package/dist/solution/VenueBooking/utils/resource.js +0 -131
  165. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +0 -32
  166. package/dist/solution/VenueBooking/utils/slotMerge.js +0 -233
  167. package/dist/solution/VenueBooking/utils/smartPricing.d.ts +0 -71
  168. package/dist/solution/VenueBooking/utils/smartPricing.js +0 -302
  169. package/dist/solution/VenueBooking/utils/timeSlot.d.ts +0 -34
  170. package/dist/solution/VenueBooking/utils/timeSlot.js +0 -458
  171. package/dist/solution/VenueBooking/utils.d.ts +0 -1
  172. package/dist/solution/VenueBooking/utils.js +0 -1
  173. package/lib/apis/picoding.d.ts +0 -0
  174. package/lib/apis/picoding.js +0 -0
  175. package/lib/model/strategy/adapter/dataVariant/adapter.d.ts +0 -50
  176. package/lib/model/strategy/adapter/dataVariant/adapter.js +0 -149
  177. package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +0 -89
  178. package/lib/model/strategy/adapter/dataVariant/evaluator.js +0 -666
  179. package/lib/model/strategy/adapter/dataVariant/examples.d.ts +0 -39
  180. package/lib/model/strategy/adapter/dataVariant/examples.js +0 -293
  181. package/lib/model/strategy/adapter/dataVariant/index.d.ts +0 -4
  182. package/lib/model/strategy/adapter/dataVariant/index.js +0 -38
  183. package/lib/model/strategy/adapter/dataVariant/type.d.ts +0 -149
  184. package/lib/model/strategy/adapter/dataVariant/type.js +0 -31
  185. package/lib/modules/OpenData/index.d.ts +0 -24
  186. package/lib/modules/OpenData/index.js +0 -119
  187. package/lib/modules/OpenData/types.d.ts +0 -73
  188. package/lib/modules/OpenData/types.js +0 -17
  189. package/lib/modules/OpenData/utils.d.ts +0 -2
  190. package/lib/modules/OpenData/utils.js +0 -111
  191. package/lib/modules/Quotation/index.d.ts +0 -48
  192. package/lib/modules/Quotation/index.js +0 -152
  193. package/lib/modules/Quotation/types.d.ts +0 -42
  194. package/lib/modules/Quotation/types.js +0 -17
  195. package/lib/modules/SalesSummary/index.d.ts +0 -63
  196. package/lib/modules/SalesSummary/index.js +0 -105
  197. package/lib/modules/SalesSummary/types.d.ts +0 -60
  198. package/lib/modules/SalesSummary/types.js +0 -17
  199. package/lib/modules/SalesSummary/utils.d.ts +0 -30
  200. package/lib/modules/SalesSummary/utils.js +0 -420
  201. package/lib/modules/ScanOrderLogger/index.d.ts +0 -23
  202. package/lib/modules/ScanOrderLogger/index.js +0 -147
  203. package/lib/modules/ScanOrderLogger/providers/feishu.d.ts +0 -2
  204. package/lib/modules/ScanOrderLogger/providers/feishu.js +0 -157
  205. package/lib/modules/ScanOrderLogger/providers/grafana.d.ts +0 -2
  206. package/lib/modules/ScanOrderLogger/providers/grafana.js +0 -52
  207. package/lib/modules/ScanOrderLogger/types.d.ts +0 -53
  208. package/lib/modules/ScanOrderLogger/types.js +0 -17
  209. package/lib/solution/ScanOrder/index.d.ts +0 -158
  210. package/lib/solution/ScanOrder/index.js +0 -2135
  211. package/lib/solution/ScanOrder/types.d.ts +0 -306
  212. package/lib/solution/ScanOrder/types.js +0 -36
  213. package/lib/solution/ScanOrder/utils.d.ts +0 -172
  214. package/lib/solution/ScanOrder/utils.js +0 -658
  215. package/lib/solution/VenueBooking/index.d.ts +0 -252
  216. package/lib/solution/VenueBooking/index.js +0 -2204
  217. package/lib/solution/VenueBooking/sales-section-4-annotated.json +0 -343
  218. package/lib/solution/VenueBooking/types.d.ts +0 -156
  219. package/lib/solution/VenueBooking/types.js +0 -45
  220. package/lib/solution/VenueBooking/utils/dateSummary.d.ts +0 -11
  221. package/lib/solution/VenueBooking/utils/dateSummary.js +0 -105
  222. package/lib/solution/VenueBooking/utils/resource.d.ts +0 -14
  223. package/lib/solution/VenueBooking/utils/resource.js +0 -92
  224. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +0 -32
  225. package/lib/solution/VenueBooking/utils/slotMerge.js +0 -236
  226. package/lib/solution/VenueBooking/utils/smartPricing.d.ts +0 -71
  227. package/lib/solution/VenueBooking/utils/smartPricing.js +0 -225
  228. package/lib/solution/VenueBooking/utils/timeSlot.d.ts +0 -34
  229. package/lib/solution/VenueBooking/utils/timeSlot.js +0 -343
  230. package/lib/solution/VenueBooking/utils.d.ts +0 -1
  231. package/lib/solution/VenueBooking/utils.js +0 -69
@@ -45,10 +45,27 @@ var defaultStrategyMetadataCustom = {
45
45
  maxPassesPerItem: 0,
46
46
  deductOptionPrice: false
47
47
  };
48
+ var FIELD_REASON_CODE_MAP = {
49
+ orderTotalAmount: "order_total_amount_not_enough",
50
+ applicableProductTotalAmount: "applicable_product_total_amount_not_enough",
51
+ applicableProductCount: "applicable_product_count_not_enough"
52
+ };
53
+ var AMOUNT_FIELDS = /* @__PURE__ */ new Set([
54
+ "orderTotalAmount",
55
+ "applicableProductTotalAmount"
56
+ ]);
57
+ function formatReason(template, value, currency = "") {
58
+ if (!template)
59
+ return template;
60
+ const v = value === void 0 || value === null ? "" : String(value);
61
+ const c = currency === void 0 || currency === null ? "" : String(currency);
62
+ return template.replace(/\$\{value\}/g, () => v).replace(/\{value\}/g, () => v).replace(/\{currency\}/g, () => c);
63
+ }
48
64
  var WalletPassEvaluator = class {
49
65
  constructor() {
50
66
  this.strategyConfigs = [];
51
67
  this.locale = "en";
68
+ this.otherParams = {};
52
69
  this.engine = new import__.StrategyEngine({
53
70
  debug: false,
54
71
  enableTrace: false
@@ -64,6 +81,9 @@ var WalletPassEvaluator = class {
64
81
  setLocale(locale) {
65
82
  this.locale = locale;
66
83
  }
84
+ setOtherParams(otherParams) {
85
+ this.otherParams = otherParams;
86
+ }
67
87
  getText(key) {
68
88
  var _a, _b;
69
89
  return (_b = (_a = import_locales.locales) == null ? void 0 : _a[this.locale]) == null ? void 0 : _b[key];
@@ -101,7 +121,7 @@ var WalletPassEvaluator = class {
101
121
  * 评估可用的 vouchers
102
122
  */
103
123
  evaluate(input) {
104
- var _a, _b;
124
+ var _a, _b, _c, _d, _e, _f, _g;
105
125
  const { orderTotalAmount, products, vouchers, strategyConfigs } = input;
106
126
  const productIds = products.map((p) => p.product_id);
107
127
  const results = [];
@@ -176,7 +196,13 @@ var WalletPassEvaluator = class {
176
196
  });
177
197
  } else {
178
198
  let reasonCode = "not_meet_the_required_conditions";
179
- if (evaluationResult.code) {
199
+ let thresholdValue = void 0;
200
+ const failedField = (_c = evaluationResult.matched) == null ? void 0 : _c.failedField;
201
+ const failedRule = (_e = (_d = evaluationResult.matched) == null ? void 0 : _d.failedRules) == null ? void 0 : _e[0];
202
+ if (failedField && FIELD_REASON_CODE_MAP[failedField]) {
203
+ reasonCode = FIELD_REASON_CODE_MAP[failedField];
204
+ thresholdValue = failedRule == null ? void 0 : failedRule.value;
205
+ } else if (evaluationResult.code) {
180
206
  const codeMapping = {
181
207
  INSUFFICIENT_AMOUNT: "not_meet_the_required_conditions",
182
208
  USAGE_LIMIT_EXCEEDED: "usage_limit_reached",
@@ -186,6 +212,10 @@ var WalletPassEvaluator = class {
186
212
  };
187
213
  reasonCode = codeMapping[evaluationResult.code] || "not_meet_the_required_conditions";
188
214
  }
215
+ const rawText = this.getText(reasonCode);
216
+ const currency = failedField && AMOUNT_FIELDS.has(failedField) ? ((_g = (_f = this.otherParams) == null ? void 0 : _f.getData) == null ? void 0 : _g.call(_f, "shop_symbol")) || "" : "";
217
+ console.log(currency, "currency12345");
218
+ const reason = thresholdValue !== void 0 ? formatReason(rawText, thresholdValue, currency) : rawText;
189
219
  results.push({
190
220
  voucher,
191
221
  isApplicable: false,
@@ -193,7 +223,7 @@ var WalletPassEvaluator = class {
193
223
  maxDeduction: 0,
194
224
  deductTaxAndFee: false,
195
225
  applicableProductIds: [],
196
- reason: this.getText(reasonCode),
226
+ reason,
197
227
  reasonCode,
198
228
  strategyResult: evaluationResult
199
229
  });
@@ -386,6 +416,7 @@ var WalletPassEvaluator = class {
386
416
  * 计算适用商品的总金额和数量
387
417
  */
388
418
  calculateApplicableProducts(products, applicableProductIds, deductTaxAndFee) {
419
+ console.log(products, "products1234");
389
420
  let total = 0;
390
421
  let count = 0;
391
422
  if (applicableProductIds !== null && applicableProductIds.length === 0) {
@@ -29,7 +29,10 @@ var locales = {
29
29
  "usage_limit_reached": "已达到使用次数上限",
30
30
  "max_passes_per_item_reached": "该商品已达到卡券使用上限",
31
31
  "not_available_for_this_channel": "当前渠道不可使用",
32
- "not_valid_for_this_order_type": "当前订单类型不适用"
32
+ "not_valid_for_this_order_type": "当前订单类型不适用",
33
+ "order_total_amount_not_enough": "满 {currency}{value} 可用",
34
+ "applicable_product_total_amount_not_enough": "满 {currency}{value} 可用",
35
+ "applicable_product_count_not_enough": "至少 {value} 件"
33
36
  },
34
37
  "en": {
35
38
  "not_meet_the_required_conditions": "Not meet the required conditions.",
@@ -37,7 +40,10 @@ var locales = {
37
40
  "usage_limit_reached": "Usage limit reached.",
38
41
  "max_passes_per_item_reached": "Max passes per item reached.",
39
42
  "not_available_for_this_channel": "Not available for this channel.",
40
- "not_valid_for_this_order_type": "Not valid for this order type."
43
+ "not_valid_for_this_order_type": "Not valid for this order type.",
44
+ "order_total_amount_not_enough": "Spend {currency}{value} to use",
45
+ "applicable_product_total_amount_not_enough": "Spend {currency}{value} to use",
46
+ "applicable_product_count_not_enough": "Min. Qty {value}"
41
47
  },
42
48
  "zh-HK": {
43
49
  "not_meet_the_required_conditions": "未達使用條件",
@@ -45,7 +51,10 @@ var locales = {
45
51
  "usage_limit_reached": "已達使用次數上限",
46
52
  "max_passes_per_item_reached": "該商品已達卡券使用上限",
47
53
  "not_available_for_this_channel": "當前渠道不可使用",
48
- "not_valid_for_this_order_type": "當前訂單類型不適用"
54
+ "not_valid_for_this_order_type": "當前訂單類型不適用",
55
+ "order_total_amount_not_enough": "滿 {currency}{value} 可用",
56
+ "applicable_product_total_amount_not_enough": "滿 {currency}{value} 可用",
57
+ "applicable_product_count_not_enough": "至少 {value} 件"
49
58
  }
50
59
  };
51
60
  // Annotate the CommonJS export names for ESM import in node:
@@ -27,17 +27,30 @@ export declare class StrategyEngine {
27
27
  *
28
28
  * @param group 条件组
29
29
  * @param context 运行时上下文
30
- * @returns 评估结果对象,包含条件是否满足和收集到的 actionIds
30
+ * @returns 评估结果对象,包含条件是否满足、收集到的 actionIds、以及失败的原子规则信息
31
31
  */
32
32
  private evaluateConditionGroup;
33
33
  /**
34
- * 评估条件组的逻辑运算
34
+ * 评估条件组的逻辑运算(带失败规则收集)
35
+ *
36
+ * 失败规则收集策略:
37
+ * - `and`:返回第一个失败的原子规则(嵌套 group 递归取其首个失败原子规则)
38
+ * - `or`:所有分支失败时,聚合每个分支的失败规则
39
+ * - `not`:被取反规则实际通过时,记录该规则
40
+ */
41
+ private evaluateGroupLogicDetailed;
42
+ /**
43
+ * 评估单个规则(带失败规则收集)
44
+ */
45
+ private evaluateRuleDetailed;
46
+ /**
47
+ * 评估原子规则(不收集失败信息,仅返回布尔结果)
35
48
  */
36
- private evaluateGroupLogic;
49
+ private evaluateAtomicRule;
37
50
  /**
38
- * 评估单个规则
51
+ * 构建失败规则信息
39
52
  */
40
- private evaluateRule;
53
+ private buildFailedRuleInfo;
41
54
  /**
42
55
  * 评估代码模式条件
43
56
  */
@@ -42,7 +42,7 @@ var StrategyEngine = class {
42
42
  * 评估策略
43
43
  */
44
44
  evaluate(config, context) {
45
- var _a;
45
+ var _a, _b;
46
46
  const startTime = Date.now();
47
47
  const trace = {
48
48
  steps: [],
@@ -105,7 +105,11 @@ var StrategyEngine = class {
105
105
  matched: {
106
106
  conditions: applicable,
107
107
  actionIds: evaluationResult.actionIds,
108
- details: {}
108
+ details: {},
109
+ ...applicable ? {} : {
110
+ failedField: (_a = evaluationResult.failedRules[0]) == null ? void 0 : _a.field,
111
+ failedRules: evaluationResult.failedRules
112
+ }
109
113
  },
110
114
  matchedActions: sortedActions,
111
115
  outputs: {},
@@ -119,7 +123,7 @@ var StrategyEngine = class {
119
123
  } catch (error) {
120
124
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
121
125
  if (this.options.enableTrace) {
122
- (_a = trace.errors) == null ? void 0 : _a.push({
126
+ (_b = trace.errors) == null ? void 0 : _b.push({
123
127
  step: "evaluation",
124
128
  error: errorMessage,
125
129
  timestamp: Date.now()
@@ -149,12 +153,15 @@ var StrategyEngine = class {
149
153
  *
150
154
  * @param group 条件组
151
155
  * @param context 运行时上下文
152
- * @returns 评估结果对象,包含条件是否满足和收集到的 actionIds
156
+ * @returns 评估结果对象,包含条件是否满足、收集到的 actionIds、以及失败的原子规则信息
153
157
  */
154
158
  evaluateConditionGroup(group, context) {
155
159
  const collectedActionIds = [];
156
- const isCurrentLayerSatisfied = this.evaluateGroupLogic(group, context);
157
- if (isCurrentLayerSatisfied) {
160
+ const { satisfied, failedRules } = this.evaluateGroupLogicDetailed(
161
+ group,
162
+ context
163
+ );
164
+ if (satisfied) {
158
165
  collectedActionIds.push(...group.actionIds);
159
166
  for (const rule of group.rules) {
160
167
  if (this.isConditionGroup(rule)) {
@@ -164,41 +171,98 @@ var StrategyEngine = class {
164
171
  }
165
172
  }
166
173
  return {
167
- satisfied: isCurrentLayerSatisfied,
168
- actionIds: collectedActionIds
174
+ satisfied,
175
+ actionIds: collectedActionIds,
176
+ failedRules
169
177
  };
170
178
  }
171
179
  /**
172
- * 评估条件组的逻辑运算
180
+ * 评估条件组的逻辑运算(带失败规则收集)
181
+ *
182
+ * 失败规则收集策略:
183
+ * - `and`:返回第一个失败的原子规则(嵌套 group 递归取其首个失败原子规则)
184
+ * - `or`:所有分支失败时,聚合每个分支的失败规则
185
+ * - `not`:被取反规则实际通过时,记录该规则
173
186
  */
174
- evaluateGroupLogic(group, context) {
187
+ evaluateGroupLogicDetailed(group, context) {
175
188
  const { operator, rules } = group;
176
189
  switch (operator) {
177
- case "and":
178
- return rules.every((rule) => this.evaluateRule(rule, context));
179
- case "or":
180
- return rules.some((rule) => this.evaluateRule(rule, context));
181
- case "not":
182
- if (rules.length === 0)
183
- return false;
184
- return !this.evaluateRule(rules[0], context);
190
+ case "and": {
191
+ for (const rule of rules) {
192
+ const ruleResult = this.evaluateRuleDetailed(rule, context);
193
+ if (!ruleResult.satisfied) {
194
+ return {
195
+ satisfied: false,
196
+ failedRules: ruleResult.failedRules
197
+ };
198
+ }
199
+ }
200
+ return { satisfied: true, failedRules: [] };
201
+ }
202
+ case "or": {
203
+ const aggregated = [];
204
+ for (const rule of rules) {
205
+ const ruleResult = this.evaluateRuleDetailed(rule, context);
206
+ if (ruleResult.satisfied) {
207
+ return { satisfied: true, failedRules: [] };
208
+ }
209
+ aggregated.push(...ruleResult.failedRules);
210
+ }
211
+ return { satisfied: false, failedRules: aggregated };
212
+ }
213
+ case "not": {
214
+ if (rules.length === 0) {
215
+ return { satisfied: false, failedRules: [] };
216
+ }
217
+ const ruleResult = this.evaluateRuleDetailed(rules[0], context);
218
+ if (ruleResult.satisfied) {
219
+ const failed = this.isConditionGroup(rules[0]) ? [] : [this.buildFailedRuleInfo(rules[0], context)];
220
+ return { satisfied: false, failedRules: failed };
221
+ }
222
+ return { satisfied: true, failedRules: [] };
223
+ }
185
224
  default:
186
225
  throw new Error(`Unknown operator: ${operator}`);
187
226
  }
188
227
  }
189
228
  /**
190
- * 评估单个规则
229
+ * 评估单个规则(带失败规则收集)
191
230
  */
192
- evaluateRule(rule, context) {
231
+ evaluateRuleDetailed(rule, context) {
193
232
  if (this.isConditionGroup(rule)) {
194
- return this.evaluateGroupLogic(rule, context);
233
+ return this.evaluateGroupLogicDetailed(rule, context);
195
234
  }
196
235
  const conditionRule = rule;
236
+ const satisfied = this.evaluateAtomicRule(conditionRule, context);
237
+ if (satisfied) {
238
+ return { satisfied: true, failedRules: [] };
239
+ }
240
+ return {
241
+ satisfied: false,
242
+ failedRules: [this.buildFailedRuleInfo(conditionRule, context)]
243
+ };
244
+ }
245
+ /**
246
+ * 评估原子规则(不收集失败信息,仅返回布尔结果)
247
+ */
248
+ evaluateAtomicRule(conditionRule, context) {
197
249
  if (conditionRule.type === "code" && conditionRule.code) {
198
250
  return this.evaluateCodeCondition(conditionRule.code, context);
199
251
  }
200
252
  return this.evaluateOperatorCondition(conditionRule, context);
201
253
  }
254
+ /**
255
+ * 构建失败规则信息
256
+ */
257
+ buildFailedRuleInfo(conditionRule, context) {
258
+ const actualValue = conditionRule.field ? this.getFieldValue(conditionRule.field, context) : void 0;
259
+ return {
260
+ field: conditionRule.field,
261
+ operator: conditionRule.operator,
262
+ value: conditionRule.value,
263
+ actualValue
264
+ };
265
+ }
202
266
  /**
203
267
  * 评估代码模式条件
204
268
  */
@@ -165,6 +165,23 @@ export interface MatchedInfo {
165
165
  actionIds: string[];
166
166
  /** 详细匹配信息 */
167
167
  details: Record<string, any>;
168
+ /** 顶层第一个失败的 field(仅在 conditions=false 时存在,便于直接消费) */
169
+ failedField?: string;
170
+ /** 失败的原子规则列表(仅在 conditions=false 时存在;or 全失败时可能有多条) */
171
+ failedRules?: FailedRuleInfo[];
172
+ }
173
+ /**
174
+ * 失败规则信息
175
+ */
176
+ export interface FailedRuleInfo {
177
+ /** 字段名 */
178
+ field?: string;
179
+ /** 运算符 */
180
+ operator?: string;
181
+ /** 配置的比较值(阈值) */
182
+ value?: any;
183
+ /** 实际取到的字段值 */
184
+ actualValue?: any;
168
185
  }
169
186
  /**
170
187
  * 执行轨迹
@@ -75,6 +75,8 @@ export interface CartItem {
75
75
  summaryTotal?: number | string;
76
76
  /** 商品原价总价,排除原始价格为0的场景 */
77
77
  origin_total?: number | string;
78
+ /** 基于 origin_total 乘以 商品数量的价格 */
79
+ summaryOriginTotal?: number | string;
78
80
  /** 商品数量 */
79
81
  num?: number;
80
82
  /** 商品图片 */
@@ -46,6 +46,18 @@ var import_decimal = __toESM(require("decimal.js"));
46
46
  var import_utils = require("../../Product/utils");
47
47
  var import_utils2 = require("../../../solution/ShopDiscount/utils");
48
48
  var import_utils3 = require("../../Summary/utils");
49
+ var toDiscountPayload = (discountItem) => {
50
+ var _a, _b;
51
+ return {
52
+ amount: discountItem.amount,
53
+ tag: discountItem.type,
54
+ par_value: (_a = discountItem.discount) == null ? void 0 : _a.percent,
55
+ config: discountItem.config,
56
+ metadata: {
57
+ discount_card_type: (_b = discountItem == null ? void 0 : discountItem.discount) == null ? void 0 : _b.discount_card_type
58
+ }
59
+ };
60
+ };
49
61
  var handleVariantProduct = (product) => {
50
62
  var _a;
51
63
  if (product == null ? void 0 : product.product_variant_id) {
@@ -90,6 +102,14 @@ var formatProductToCartItem = (params) => {
90
102
  num,
91
103
  discounts
92
104
  });
105
+ const origin_total = getProductTotalPrice({
106
+ product: cartItem._productInit || cartItem._productOrigin,
107
+ bundle,
108
+ options,
109
+ num,
110
+ discounts: []
111
+ });
112
+ cartItem.summaryOriginTotal = (origin_total || 0) * (num || 1);
93
113
  cartItem.image = product == null ? void 0 : product.cover;
94
114
  cartItem.like_status = "common";
95
115
  cartItem.duration = product == null ? void 0 : product.duration;
@@ -184,17 +204,24 @@ var formatProductToCartItemOrigin = (params) => {
184
204
  var getProductTotalPrice = (params) => {
185
205
  const { product, bundle, options, discounts } = params;
186
206
  let price = Number(product.price);
207
+ const optionRows = (options == null ? void 0 : options.map((currentValue) => ({
208
+ unit: Number(currentValue.price ?? currentValue.add_price ?? 0),
209
+ num: Number(currentValue.num ?? currentValue.quantity ?? 1)
210
+ }))) ?? [];
187
211
  if (discounts == null ? void 0 : discounts.length) {
188
212
  discounts.forEach((currentValue) => {
189
213
  var _a;
190
- price = (0, import_utils2.getDiscountAmount)({
191
- amount: currentValue.amount,
192
- tag: currentValue.type,
193
- par_value: currentValue.discount.percent,
194
- metadata: {
195
- discount_card_type: (_a = currentValue == null ? void 0 : currentValue.discount) == null ? void 0 : _a.discount_card_type
214
+ const payload = toDiscountPayload(currentValue);
215
+ price = (0, import_utils2.getDiscountAmount)(payload, price, price);
216
+ if (((_a = currentValue == null ? void 0 : currentValue.config) == null ? void 0 : _a.deductOptionPrice) && optionRows.length) {
217
+ for (let i = 0; i < optionRows.length; i++) {
218
+ const row = optionRows[i];
219
+ optionRows[i] = {
220
+ ...row,
221
+ unit: (0, import_utils2.getDiscountAmount)(payload, row.unit, row.unit)
222
+ };
196
223
  }
197
- }, price, price);
224
+ }
198
225
  });
199
226
  }
200
227
  if (bundle == null ? void 0 : bundle.length) {
@@ -202,10 +229,11 @@ var getProductTotalPrice = (params) => {
202
229
  return accumulator + Number(currentValue.price) * Number(currentValue.num);
203
230
  }, price);
204
231
  }
205
- if (options == null ? void 0 : options.length) {
206
- price = options.reduce((accumulator, currentValue) => {
207
- return accumulator + Number(currentValue.price) * Number(currentValue.num);
208
- }, price);
232
+ if (optionRows.length) {
233
+ price = optionRows.reduce(
234
+ (accumulator, row) => accumulator + row.unit * row.num,
235
+ price
236
+ );
209
237
  }
210
238
  return Math.max(0, price);
211
239
  };
@@ -313,7 +341,6 @@ var formatBundleToOrigin = (bundle) => {
313
341
  option: formatOptionsToOrigin(getBundleValueByKey("option")),
314
342
  discount_list: d.discount_list,
315
343
  "bundle_selling_price": d == null ? void 0 : d.price,
316
- // "custom_price": d?.price,
317
344
  metadata: {
318
345
  custom_product_bundle_map_id: d._id,
319
346
  product_discount_difference
@@ -34,7 +34,7 @@ __export(changePrice_exports, {
34
34
  module.exports = __toCommonJS(changePrice_exports);
35
35
  var import_decimal = __toESM(require("decimal.js"));
36
36
  async function updateAllCartItemPrice(cartItems, priceData, getProduct, updateCart, updateItemInitInfo) {
37
- var _a, _b, _c, _d, _e, _f;
37
+ var _a, _b;
38
38
  for (const item of cartItems) {
39
39
  const targetProduct = priceData.find((n) => n.id === item.id);
40
40
  const cartProduct = await getProduct(
@@ -44,14 +44,10 @@ async function updateAllCartItemPrice(cartItems, priceData, getProduct, updateCa
44
44
  if (!productInfo) {
45
45
  productInfo = item._productOrigin;
46
46
  }
47
- const variantId = ((_a = item == null ? void 0 : item._productOrigin) == null ? void 0 : _a.product_variant_id) ?? ((_c = (_b = item == null ? void 0 : item._origin) == null ? void 0 : _b.product) == null ? void 0 : _c.product_variant_id);
48
- const targetVariant = (_d = targetProduct == null ? void 0 : targetProduct.variant) == null ? void 0 : _d.find(
49
- (variant) => Number(variant.id) === Number(variantId)
50
- );
51
47
  let bundle = item._bundleOrigin;
52
- productInfo.price = (targetVariant == null ? void 0 : targetVariant.price) ?? (targetProduct == null ? void 0 : targetProduct.price) ?? productInfo.price;
53
- productInfo.base_price = (targetVariant == null ? void 0 : targetVariant.base_price) ?? (targetProduct == null ? void 0 : targetProduct.base_price) ?? productInfo.base_price;
54
- productInfo.product_variant_id = (_e = item._productOrigin) == null ? void 0 : _e.product_variant_id;
48
+ productInfo.price = targetProduct == null ? void 0 : targetProduct.price;
49
+ productInfo.base_price = targetProduct == null ? void 0 : targetProduct.base_price;
50
+ productInfo.product_variant_id = (_a = item._productOrigin) == null ? void 0 : _a.product_variant_id;
55
51
  bundle = bundle == null ? void 0 : bundle.map((n) => {
56
52
  var _a2;
57
53
  const targetBundle = (_a2 = targetProduct == null ? void 0 : targetProduct.bundle_group) == null ? void 0 : _a2.find(
@@ -80,14 +76,14 @@ async function updateAllCartItemPrice(cartItems, priceData, getProduct, updateCa
80
76
  return n;
81
77
  });
82
78
  if (targetProduct == null ? void 0 : targetProduct.variant) {
83
- productInfo.variant = (_f = productInfo.variant) == null ? void 0 : _f.map((n) => {
79
+ productInfo.variant = (_b = productInfo.variant) == null ? void 0 : _b.map((n) => {
84
80
  var _a2;
85
- const targetVariant2 = (_a2 = targetProduct.variant) == null ? void 0 : _a2.find((m) => m.id === n.id);
86
- if (targetVariant2) {
81
+ const targetVariant = (_a2 = targetProduct.variant) == null ? void 0 : _a2.find((m) => m.id === n.id);
82
+ if (targetVariant) {
87
83
  return {
88
84
  ...n,
89
- price: targetVariant2.price,
90
- base_price: targetVariant2.base_price
85
+ price: targetVariant.price,
86
+ base_price: targetVariant.base_price
91
87
  };
92
88
  }
93
89
  return n;
@@ -1,6 +1,6 @@
1
1
  import { Module, PisellCore, ModuleOptions } from '../../types';
2
2
  import { BaseModule } from '../BaseModule';
3
- import { Discount, DiscountModuleAPI, DiscountWithReason, DiscountPrepareConfigResult } from './types';
3
+ import { Discount, DiscountModuleAPI } from './types';
4
4
  export declare class DiscountModule extends BaseModule implements Module, DiscountModuleAPI {
5
5
  protected defaultName: string;
6
6
  protected defaultVersion: string;
@@ -17,26 +17,17 @@ export declare class DiscountModule extends BaseModule implements Module, Discou
17
17
  setOriginalDiscountList(originalDiscountList: Discount[]): Promise<void>;
18
18
  getOriginalDiscountList(): Discount[];
19
19
  loadPrepareConfig(params: {
20
- action?: 'create' | 'edit';
20
+ action?: 'create';
21
21
  with_good_pass: 0 | 1;
22
22
  with_discount_card: 0 | 1;
23
23
  customer_id: number;
24
24
  with_wallet_pass_holder: 0 | 1;
25
- with_available_wallet_flag?: 0 | 1;
26
- with_available_wallet_pass_flag?: 0 | 1;
27
25
  request_timezone: string;
28
- order_id?: number;
29
- }): Promise<DiscountPrepareConfigResult>;
30
- private extractAvailableWalletIds;
31
- batchSearch(code: string, options?: {
32
- customerId?: number;
33
- orderId?: number;
34
- }): Promise<DiscountWithReason>;
26
+ }): Promise<Discount[]>;
27
+ batchSearch(code: string, customerId?: number): Promise<Discount[]>;
35
28
  batchSearchByProductIds(productIds: number[]): Promise<any>;
36
29
  filterEnabledDiscountList(discountList: Discount[]): Discount[];
37
30
  private checkUsageCreditsLimit;
38
- filterEnabledDiscountListWithReason(discountList: Discount[]): DiscountWithReason;
39
- private checkUsageCreditsLimitWithFailKey;
40
31
  uniqueByProductId(discountList: Discount[]): Discount[];
41
32
  filterDiscountListByProductIds(discountList: Discount[], productIds: number[]): Discount[];
42
33
  calcDiscountApplicableProductTotalPrice(discount: Discount): number | undefined;
@@ -100,35 +100,22 @@ var DiscountModule = class extends import_BaseModule.BaseModule {
100
100
  const goodPassList = this.filterEnabledDiscountList(
101
101
  [...((_a = prepareConfig == null ? void 0 : prepareConfig.data) == null ? void 0 : _a.good_pass_list) || [], ...((_b = prepareConfig == null ? void 0 : prepareConfig.data) == null ? void 0 : _b.discount_card_list) || []]
102
102
  ) || [];
103
- return {
104
- discountList: goodPassList,
105
- availableWalletIds: this.extractAvailableWalletIds(prepareConfig == null ? void 0 : prepareConfig.data)
106
- };
103
+ return goodPassList;
107
104
  }
108
- extractAvailableWalletIds(data) {
109
- const availableWalletList = Array.isArray(data == null ? void 0 : data.avaiable_wallet_list) ? data.avaiable_wallet_list : Array.isArray(data == null ? void 0 : data.available_wallet_list) ? data.available_wallet_list : [];
110
- const availableWalletPassList = Array.isArray(data == null ? void 0 : data.available_wallet_pass_list) ? data.available_wallet_pass_list : [];
111
- const walletIds = availableWalletList.map((item) => Number(item == null ? void 0 : item.wallet_id)).filter((id) => Number.isFinite(id) && id > 0);
112
- const walletPassProductIds = availableWalletPassList.map((item) => Number(item == null ? void 0 : item.product_id)).filter((id) => Number.isFinite(id) && id > 0);
113
- return Array.from(/* @__PURE__ */ new Set([...walletIds, ...walletPassProductIds]));
114
- }
115
- async batchSearch(code, options) {
116
- const { customerId, orderId } = options || {};
105
+ async batchSearch(code, customerId) {
117
106
  const result = await this.request.get(`/machinecode/batch-search`, {
118
107
  code,
119
108
  translate_flag: 1,
120
109
  tags: ["good_pass", "product_discount_card"],
121
- // available: 1,
110
+ available: 1,
122
111
  relation_product: 1,
123
112
  with: ["extensionData", "customScheduleSnapshot", "holder.detail"],
124
113
  order_behavior_count: 1,
125
114
  order_behavior_count_customer_id: customerId || 1,
126
- ...orderId ? { order_behavior_count_order_id: orderId } : {},
127
- unified_status_info_flag: 1,
128
115
  request_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
129
116
  });
130
- const resultDiscountWithReason = this.filterEnabledDiscountListWithReason((result == null ? void 0 : result.data) || []) || [];
131
- return resultDiscountWithReason;
117
+ const resultDiscountList = this.filterEnabledDiscountList((result == null ? void 0 : result.data) || []) || [];
118
+ return resultDiscountList;
132
119
  }
133
120
  async batchSearchByProductIds(productIds) {
134
121
  const result = await this.request.get(`/machinecode/batch-search`, {
@@ -183,64 +170,6 @@ var DiscountModule = class extends import_BaseModule.BaseModule {
183
170
  }
184
171
  return true;
185
172
  }
186
- // 过滤启用且可用的优惠券,并返回校验失败原因
187
- filterEnabledDiscountListWithReason(discountList) {
188
- let lists = discountList.filter((discount) => discount.limit_status === "enable").filter((discount) => {
189
- const remaining = new import_decimal.default((discount == null ? void 0 : discount.par_value) || 0).minus(new import_decimal.default((discount == null ? void 0 : discount.used_par_value) || 0)).greaterThan(0);
190
- return remaining;
191
- }).map((discount) => {
192
- const limitFailKey = this.checkUsageCreditsLimitWithFailKey(discount);
193
- return {
194
- ...discount,
195
- usageLimitFailKey: limitFailKey
196
- };
197
- });
198
- const availableLists = lists.filter((item) => !item.usageLimitFailKey && item.unified_available_status !== 0);
199
- const currentFailDiscount = lists.find((item) => item.usageLimitFailKey);
200
- return {
201
- discountList: availableLists,
202
- unavailableReasonKey: currentFailDiscount == null ? void 0 : currentFailDiscount.usageLimitFailKey
203
- };
204
- }
205
- // 检查使用次数限制,并返回校验失败原因
206
- checkUsageCreditsLimitWithFailKey(discount) {
207
- if (!discount.extension_data || discount.extension_data.length === 0) {
208
- return null;
209
- }
210
- const usageCreditsData = discount.extension_data.find(
211
- (data) => data.field_key === "usage_credits"
212
- );
213
- if (!usageCreditsData) {
214
- return null;
215
- }
216
- const value = usageCreditsData.value;
217
- if (value.total_credits && value.total_credits > 0) {
218
- if ((discount.total_order_behavior_count || 0) >= value.total_credits) {
219
- return "total_credits";
220
- }
221
- }
222
- if (value.per_user_limit && value.per_user_limit > 0) {
223
- if ((discount.customer_order_behavior_count || 0) >= value.per_user_limit) {
224
- return "per_user_limit";
225
- }
226
- }
227
- if (value.max_per_day && value.max_per_day > 0) {
228
- if ((discount.today_order_behavior_count || 0) >= value.max_per_day) {
229
- return "max_per_day";
230
- }
231
- }
232
- if (value.max_per_week && value.max_per_week > 0) {
233
- if ((discount.week_order_behavior_count || 0) >= value.max_per_week) {
234
- return "max_per_week";
235
- }
236
- }
237
- if (value.max_per_month && value.max_per_month > 0) {
238
- if ((discount.month_order_behavior_count || 0) >= value.max_per_month) {
239
- return "max_per_month";
240
- }
241
- }
242
- return null;
243
- }
244
173
  // 根据productIds去重
245
174
  uniqueByProductId(discountList) {
246
175
  return (0, import_utils.uniqueById)(discountList, "product_id");