@pisell/pisellos 2.2.71 → 2.2.72
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.
- package/dist/model/strategy/adapter/index.d.ts +2 -0
- package/dist/model/strategy/adapter/index.js +2 -1
- package/dist/model/strategy/adapter/promotion/adapter.d.ts +66 -0
- package/dist/model/strategy/adapter/promotion/adapter.js +271 -0
- package/dist/model/strategy/adapter/promotion/evaluator.d.ts +213 -0
- package/dist/model/strategy/adapter/promotion/evaluator.js +1206 -0
- package/dist/model/strategy/adapter/promotion/examples.d.ts +138 -0
- package/dist/model/strategy/adapter/promotion/examples.js +166 -0
- package/dist/model/strategy/adapter/promotion/index.d.ts +4 -0
- package/dist/model/strategy/adapter/promotion/index.js +0 -0
- package/dist/model/strategy/adapter/promotion/type.d.ts +447 -0
- package/dist/model/strategy/adapter/promotion/type.js +209 -0
- package/dist/model/strategy/adapter/walletPass/evaluator.js +4 -1
- package/dist/model/strategy/engine.d.ts +106 -0
- package/dist/model/strategy/engine.js +611 -0
- package/dist/model/strategy/index.d.ts +2 -93
- package/dist/model/strategy/index.js +6 -549
- package/dist/modules/BaseModule.d.ts +4 -0
- package/dist/modules/BaseModule.js +5 -0
- package/dist/modules/Rules/index.d.ts +1 -0
- package/dist/modules/Rules/index.js +28 -16
- package/lib/model/strategy/adapter/index.d.ts +2 -0
- package/lib/model/strategy/adapter/index.js +6 -0
- package/lib/model/strategy/adapter/promotion/adapter.d.ts +66 -0
- package/lib/model/strategy/adapter/promotion/adapter.js +217 -0
- package/lib/model/strategy/adapter/promotion/evaluator.d.ts +213 -0
- package/lib/model/strategy/adapter/promotion/evaluator.js +844 -0
- package/lib/model/strategy/adapter/promotion/examples.d.ts +138 -0
- package/lib/model/strategy/adapter/promotion/examples.js +192 -0
- package/lib/model/strategy/adapter/promotion/index.d.ts +4 -0
- package/lib/model/strategy/adapter/promotion/index.js +0 -0
- package/lib/model/strategy/adapter/promotion/type.d.ts +447 -0
- package/lib/model/strategy/adapter/promotion/type.js +51 -0
- package/lib/model/strategy/adapter/walletPass/evaluator.js +2 -1
- package/lib/model/strategy/engine.d.ts +106 -0
- package/lib/model/strategy/engine.js +450 -0
- package/lib/model/strategy/index.d.ts +2 -93
- package/lib/model/strategy/index.js +6 -381
- package/lib/modules/BaseModule.d.ts +4 -0
- package/lib/modules/BaseModule.js +3 -0
- package/lib/modules/Rules/index.d.ts +1 -0
- package/lib/modules/Rules/index.js +23 -17
- package/package.json +1 -1
|
@@ -0,0 +1,1206 @@
|
|
|
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
|
+
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
3
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
4
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
5
|
+
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
6
|
+
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; } } }; }
|
|
7
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
8
|
+
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; }
|
|
9
|
+
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; }
|
|
10
|
+
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; }
|
|
11
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
12
|
+
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
|
|
13
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
14
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
15
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
16
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
17
|
+
import Decimal from 'decimal.js';
|
|
18
|
+
import { StrategyEngine } from "../../engine";
|
|
19
|
+
import { PromotionAdapter } from "./adapter";
|
|
20
|
+
import { PROMOTION_ACTION_TYPES } from "./type";
|
|
21
|
+
|
|
22
|
+
// ============================================
|
|
23
|
+
// 类型定义
|
|
24
|
+
// ============================================
|
|
25
|
+
|
|
26
|
+
// ============================================
|
|
27
|
+
// 多语言定义
|
|
28
|
+
// ============================================
|
|
29
|
+
|
|
30
|
+
var defaultLocales = {
|
|
31
|
+
en: {
|
|
32
|
+
no_applicable_promotion: 'No applicable promotion',
|
|
33
|
+
promotion_not_in_time_range: 'Promotion not in valid time range',
|
|
34
|
+
product_not_in_promotion: 'Product not in promotion scope'
|
|
35
|
+
},
|
|
36
|
+
'zh-CN': {
|
|
37
|
+
no_applicable_promotion: '无适用的促销活动',
|
|
38
|
+
promotion_not_in_time_range: '促销活动不在有效时间范围内',
|
|
39
|
+
product_not_in_promotion: '商品不在促销范围内'
|
|
40
|
+
},
|
|
41
|
+
'zh-HK': {
|
|
42
|
+
no_applicable_promotion: '無適用的促銷活動',
|
|
43
|
+
promotion_not_in_time_range: '促銷活動不在有效時間範圍內',
|
|
44
|
+
product_not_in_promotion: '商品不在促銷範圍內'
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// ============================================
|
|
49
|
+
// PromotionEvaluator 实现
|
|
50
|
+
// ============================================
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Promotion 评估器
|
|
54
|
+
*
|
|
55
|
+
* 用于评估商品适用的促销活动
|
|
56
|
+
* 封装了 StrategyEngine 和 PromotionAdapter 的调用逻辑
|
|
57
|
+
*/
|
|
58
|
+
export var PromotionEvaluator = /*#__PURE__*/function () {
|
|
59
|
+
function PromotionEvaluator() {
|
|
60
|
+
_classCallCheck(this, PromotionEvaluator);
|
|
61
|
+
_defineProperty(this, "engine", void 0);
|
|
62
|
+
_defineProperty(this, "adapter", void 0);
|
|
63
|
+
_defineProperty(this, "strategyConfigs", []);
|
|
64
|
+
_defineProperty(this, "locale", 'en');
|
|
65
|
+
_defineProperty(this, "locales", defaultLocales);
|
|
66
|
+
this.engine = new StrategyEngine({
|
|
67
|
+
debug: false,
|
|
68
|
+
enableTrace: false
|
|
69
|
+
});
|
|
70
|
+
this.adapter = new PromotionAdapter();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ============================================
|
|
74
|
+
// 配置管理
|
|
75
|
+
// ============================================
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* 设置策略配置列表
|
|
79
|
+
*/
|
|
80
|
+
_createClass(PromotionEvaluator, [{
|
|
81
|
+
key: "setStrategyConfigs",
|
|
82
|
+
value: function setStrategyConfigs(strategyConfigs) {
|
|
83
|
+
var newStrategyConfigs = strategyConfigs.filter(function (item) {
|
|
84
|
+
return item.metadata.type === 'promotion';
|
|
85
|
+
});
|
|
86
|
+
this.strategyConfigs = newStrategyConfigs;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* 获取策略配置列表
|
|
91
|
+
*/
|
|
92
|
+
}, {
|
|
93
|
+
key: "getStrategyConfigs",
|
|
94
|
+
value: function getStrategyConfigs() {
|
|
95
|
+
return this.strategyConfigs;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 添加策略配置
|
|
100
|
+
*/
|
|
101
|
+
}, {
|
|
102
|
+
key: "addStrategyConfig",
|
|
103
|
+
value: function addStrategyConfig(strategyConfig) {
|
|
104
|
+
this.strategyConfigs.push(strategyConfig);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* 设置语言
|
|
109
|
+
*/
|
|
110
|
+
}, {
|
|
111
|
+
key: "setLocale",
|
|
112
|
+
value: function setLocale(locale) {
|
|
113
|
+
this.locale = locale;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 设置自定义多语言文案
|
|
118
|
+
*/
|
|
119
|
+
}, {
|
|
120
|
+
key: "setLocales",
|
|
121
|
+
value: function setLocales(locales) {
|
|
122
|
+
this.locales = _objectSpread(_objectSpread({}, defaultLocales), locales);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* 获取多语言文案
|
|
127
|
+
*/
|
|
128
|
+
}, {
|
|
129
|
+
key: "getText",
|
|
130
|
+
value: function getText(key) {
|
|
131
|
+
var _this$locales;
|
|
132
|
+
return ((_this$locales = this.locales) === null || _this$locales === void 0 || (_this$locales = _this$locales[this.locale]) === null || _this$locales === void 0 ? void 0 : _this$locales[key]) || key;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* 获取多语言名称
|
|
137
|
+
*/
|
|
138
|
+
}, {
|
|
139
|
+
key: "getLocalizedName",
|
|
140
|
+
value: function getLocalizedName(name) {
|
|
141
|
+
if (typeof name === 'string') {
|
|
142
|
+
return name;
|
|
143
|
+
}
|
|
144
|
+
return name[this.locale] || name['en'] || Object.values(name)[0] || '';
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// ============================================
|
|
148
|
+
// 核心评估方法
|
|
149
|
+
// ============================================
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* 评估商品列表
|
|
153
|
+
*
|
|
154
|
+
* 判断每个商品适用哪些促销活动
|
|
155
|
+
* 支持主商品和 bundle 子商品的匹配
|
|
156
|
+
*
|
|
157
|
+
* @param input 评估输入
|
|
158
|
+
* @returns 每个商品的促销评估结果
|
|
159
|
+
*/
|
|
160
|
+
}, {
|
|
161
|
+
key: "evaluateProducts",
|
|
162
|
+
value: function evaluateProducts(input) {
|
|
163
|
+
var products = input.products,
|
|
164
|
+
strategyConfigs = input.strategyConfigs,
|
|
165
|
+
channel = input.channel;
|
|
166
|
+
var configs = strategyConfigs || this.strategyConfigs;
|
|
167
|
+
var results = [];
|
|
168
|
+
var _iterator = _createForOfIteratorHelper(products),
|
|
169
|
+
_step;
|
|
170
|
+
try {
|
|
171
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
172
|
+
var product = _step.value;
|
|
173
|
+
var applicablePromotions = [];
|
|
174
|
+
|
|
175
|
+
// 遍历所有策略,检查此商品是否适用
|
|
176
|
+
var _iterator2 = _createForOfIteratorHelper(configs),
|
|
177
|
+
_step2;
|
|
178
|
+
try {
|
|
179
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
180
|
+
var config = _step2.value;
|
|
181
|
+
// 1. 先用 getProductMatchInfo 检查商品是否在策略的适用范围内(包含 bundle 子商品检查)
|
|
182
|
+
var matchInfo = this.getProductMatchInfo(product, config);
|
|
183
|
+
if (!matchInfo.isMatch) {
|
|
184
|
+
// 商品不在策略适用范围内,跳过
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// 2. 准备上下文(如果是 bundle 子商品匹配,需要用 bundle 子商品的 ID)
|
|
189
|
+
var contextProduct = product;
|
|
190
|
+
if (matchInfo.matchedBundleIndex !== undefined && product.bundle) {
|
|
191
|
+
var bundleItem = product.bundle[matchInfo.matchedBundleIndex];
|
|
192
|
+
// 创建一个临时的"虚拟商品"用于策略引擎评估
|
|
193
|
+
// 这样策略引擎的 product_match 条件能正确通过
|
|
194
|
+
contextProduct = _objectSpread(_objectSpread({}, product), {}, {
|
|
195
|
+
product_id: bundleItem._bundle_product_id,
|
|
196
|
+
product_variant_id: bundleItem.product_variant_id
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
var context = this.adapter.prepareContext({
|
|
200
|
+
products: [contextProduct],
|
|
201
|
+
currentProduct: contextProduct,
|
|
202
|
+
channel: channel
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// 3. 评估策略(检查其他条件如时间范围等)
|
|
206
|
+
var result = this.engine.evaluate(config, context);
|
|
207
|
+
if (result.applicable && result.matchedActions.length > 0) {
|
|
208
|
+
var action = result.matchedActions[0];
|
|
209
|
+
var transformedResult = this.adapter.transformResult(result, {
|
|
210
|
+
products: [product],
|
|
211
|
+
currentProduct: product,
|
|
212
|
+
channel: channel
|
|
213
|
+
});
|
|
214
|
+
if (transformedResult.actionDetail) {
|
|
215
|
+
applicablePromotions.push({
|
|
216
|
+
strategyId: config.metadata.id,
|
|
217
|
+
strategyName: config.metadata.name,
|
|
218
|
+
actionType: action.type,
|
|
219
|
+
actionDetail: transformedResult.actionDetail,
|
|
220
|
+
display: this.getDisplayConfig(config),
|
|
221
|
+
strategyConfig: config,
|
|
222
|
+
// 记录匹配的是哪个 bundle 子商品
|
|
223
|
+
matchedBundleIndex: matchInfo.matchedBundleIndex
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
} catch (err) {
|
|
229
|
+
_iterator2.e(err);
|
|
230
|
+
} finally {
|
|
231
|
+
_iterator2.f();
|
|
232
|
+
}
|
|
233
|
+
results.push({
|
|
234
|
+
product: product,
|
|
235
|
+
applicablePromotions: applicablePromotions,
|
|
236
|
+
hasPromotion: applicablePromotions.length > 0
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
} catch (err) {
|
|
240
|
+
_iterator.e(err);
|
|
241
|
+
} finally {
|
|
242
|
+
_iterator.f();
|
|
243
|
+
}
|
|
244
|
+
return results;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* 评估购物车
|
|
249
|
+
*
|
|
250
|
+
* 返回所有适用的促销及按促销分组的商品
|
|
251
|
+
* 支持 bundle 子商品的数量计算(主商品数量 × 子商品数量)
|
|
252
|
+
*
|
|
253
|
+
* @param input 评估输入
|
|
254
|
+
* @returns 购物车评估结果
|
|
255
|
+
*/
|
|
256
|
+
}, {
|
|
257
|
+
key: "evaluateCart",
|
|
258
|
+
value: function evaluateCart(input) {
|
|
259
|
+
var products = input.products,
|
|
260
|
+
strategyConfigs = input.strategyConfigs,
|
|
261
|
+
channel = input.channel;
|
|
262
|
+
var configs = strategyConfigs || this.strategyConfigs;
|
|
263
|
+
|
|
264
|
+
// 1. 先获取每个商品的促销结果
|
|
265
|
+
var productResults = this.evaluateProducts(input);
|
|
266
|
+
|
|
267
|
+
// 2. 收集所有适用的促销(去重)
|
|
268
|
+
var promotionMap = new Map();
|
|
269
|
+
var _iterator3 = _createForOfIteratorHelper(productResults),
|
|
270
|
+
_step3;
|
|
271
|
+
try {
|
|
272
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
273
|
+
var productResult = _step3.value;
|
|
274
|
+
var _iterator4 = _createForOfIteratorHelper(productResult.applicablePromotions),
|
|
275
|
+
_step4;
|
|
276
|
+
try {
|
|
277
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
278
|
+
var promo = _step4.value;
|
|
279
|
+
var existing = promotionMap.get(promo.strategyId);
|
|
280
|
+
var product = productResult.product;
|
|
281
|
+
|
|
282
|
+
// 计算促销数量:如果是 bundle 子商品匹配,数量 = 主商品数量 × 子商品数量
|
|
283
|
+
var promoQuantity = product.quantity;
|
|
284
|
+
if (promo.matchedBundleIndex !== undefined && product.bundle) {
|
|
285
|
+
var bundleItem = product.bundle[promo.matchedBundleIndex];
|
|
286
|
+
promoQuantity = product.quantity * (bundleItem.quantity || 1);
|
|
287
|
+
}
|
|
288
|
+
if (existing) {
|
|
289
|
+
// 已存在,添加商品到列表
|
|
290
|
+
existing.applicableProducts.push(product);
|
|
291
|
+
existing.totalQuantity += promoQuantity;
|
|
292
|
+
existing.totalAmount += product.price * product.quantity;
|
|
293
|
+
// 记录每个商品的 matchedBundleIndex
|
|
294
|
+
if (!existing.productMatchedBundleIndexMap) {
|
|
295
|
+
existing.productMatchedBundleIndexMap = new Map();
|
|
296
|
+
}
|
|
297
|
+
existing.productMatchedBundleIndexMap.set(product.id, promo.matchedBundleIndex);
|
|
298
|
+
} else {
|
|
299
|
+
// 新促销
|
|
300
|
+
var productMatchedBundleIndexMap = new Map();
|
|
301
|
+
productMatchedBundleIndexMap.set(product.id, promo.matchedBundleIndex);
|
|
302
|
+
promotionMap.set(promo.strategyId, _objectSpread(_objectSpread({}, promo), {}, {
|
|
303
|
+
applicableProducts: [product],
|
|
304
|
+
totalQuantity: promoQuantity,
|
|
305
|
+
totalAmount: product.price * product.quantity,
|
|
306
|
+
productMatchedBundleIndexMap: productMatchedBundleIndexMap
|
|
307
|
+
}));
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
} catch (err) {
|
|
311
|
+
_iterator4.e(err);
|
|
312
|
+
} finally {
|
|
313
|
+
_iterator4.f();
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
} catch (err) {
|
|
317
|
+
_iterator3.e(err);
|
|
318
|
+
} finally {
|
|
319
|
+
_iterator3.f();
|
|
320
|
+
}
|
|
321
|
+
var applicablePromotions = Array.from(promotionMap.values());
|
|
322
|
+
|
|
323
|
+
// 3. 按促销分组
|
|
324
|
+
var promotionGroups = applicablePromotions.map(function (promo) {
|
|
325
|
+
var _promo$strategyConfig;
|
|
326
|
+
return {
|
|
327
|
+
strategyId: promo.strategyId,
|
|
328
|
+
strategyName: promo.strategyName,
|
|
329
|
+
strategyMetadata: (_promo$strategyConfig = promo.strategyConfig) === null || _promo$strategyConfig === void 0 ? void 0 : _promo$strategyConfig.metadata,
|
|
330
|
+
strategyConfig: promo.strategyConfig,
|
|
331
|
+
actionType: promo.actionType,
|
|
332
|
+
actionDetail: promo.actionDetail,
|
|
333
|
+
products: promo.applicableProducts,
|
|
334
|
+
totalQuantity: promo.totalQuantity,
|
|
335
|
+
totalAmount: promo.totalAmount,
|
|
336
|
+
// 传递 productMatchedBundleIndexMap 到 group
|
|
337
|
+
productMatchedBundleIndexMap: promo.productMatchedBundleIndexMap
|
|
338
|
+
};
|
|
339
|
+
});
|
|
340
|
+
return {
|
|
341
|
+
productResults: productResults,
|
|
342
|
+
applicablePromotions: applicablePromotions,
|
|
343
|
+
promotionGroups: promotionGroups
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* 评估购物车并计算定价
|
|
349
|
+
*
|
|
350
|
+
* 返回处理后的商品数组(包含拆分、finalPrice)和赠品信息
|
|
351
|
+
* - 对于 X_ITEMS_FOR_Y_PRICE:按原价比例均摊价格,优先使用高价商品
|
|
352
|
+
* - 对于 BUY_X_GET_Y_FREE:计算赠品数量和可选赠品列表
|
|
353
|
+
*
|
|
354
|
+
* @param input 评估输入
|
|
355
|
+
* @returns 带定价的购物车评估结果
|
|
356
|
+
*/
|
|
357
|
+
}, {
|
|
358
|
+
key: "evaluateCartWithPricing",
|
|
359
|
+
value: function evaluateCartWithPricing(input) {
|
|
360
|
+
var products = input.products;
|
|
361
|
+
|
|
362
|
+
// 1. 先调用 evaluateCart 获取分组结果
|
|
363
|
+
var cartResult = this.evaluateCart(input);
|
|
364
|
+
|
|
365
|
+
// 2. 按 action priority 排序促销组(从 strategyConfig 获取 priority)
|
|
366
|
+
var sortedGroups = this.sortPromotionGroupsByPriority(cartResult.promotionGroups, cartResult.applicablePromotions);
|
|
367
|
+
|
|
368
|
+
// 3. 追踪已处理的商品(避免重复处理)
|
|
369
|
+
// key: `${product_id}_${product_variant_id}`
|
|
370
|
+
var processedQuantityMap = new Map();
|
|
371
|
+
|
|
372
|
+
// 4. 处理每个促销组,收集结果
|
|
373
|
+
var pricedProducts = [];
|
|
374
|
+
var gifts = [];
|
|
375
|
+
var totalOriginalAmount = new Decimal(0);
|
|
376
|
+
var totalFinalAmount = new Decimal(0);
|
|
377
|
+
var _iterator5 = _createForOfIteratorHelper(sortedGroups),
|
|
378
|
+
_step5;
|
|
379
|
+
try {
|
|
380
|
+
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
381
|
+
var group = _step5.value;
|
|
382
|
+
var actionType = group.actionType;
|
|
383
|
+
|
|
384
|
+
// 直接使用 evaluateCart 阶段计算好的 matchedBundleIndexMap
|
|
385
|
+
var matchedBundleIndexMap = group.productMatchedBundleIndexMap || new Map();
|
|
386
|
+
if (actionType === PROMOTION_ACTION_TYPES.X_ITEMS_FOR_Y_PRICE) {
|
|
387
|
+
// X件Y元处理
|
|
388
|
+
var result = this.processXItemsForYPrice(group, processedQuantityMap, matchedBundleIndexMap);
|
|
389
|
+
pricedProducts.push.apply(pricedProducts, _toConsumableArray(result.products));
|
|
390
|
+
totalOriginalAmount = totalOriginalAmount.plus(result.originalAmount);
|
|
391
|
+
totalFinalAmount = totalFinalAmount.plus(result.finalAmount);
|
|
392
|
+
} else if (actionType === PROMOTION_ACTION_TYPES.BUY_X_GET_Y_FREE) {
|
|
393
|
+
// 买X送Y处理
|
|
394
|
+
var _result = this.processBuyXGetYFree(group, processedQuantityMap, matchedBundleIndexMap);
|
|
395
|
+
pricedProducts.push.apply(pricedProducts, _toConsumableArray(_result.products));
|
|
396
|
+
totalOriginalAmount = totalOriginalAmount.plus(_result.originalAmount);
|
|
397
|
+
totalFinalAmount = totalFinalAmount.plus(_result.finalAmount);
|
|
398
|
+
|
|
399
|
+
// 添加赠品信息
|
|
400
|
+
if (_result.giftInfo) {
|
|
401
|
+
gifts.push(_result.giftInfo);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// 5. 处理未参与任何促销的商品
|
|
407
|
+
} catch (err) {
|
|
408
|
+
_iterator5.e(err);
|
|
409
|
+
} finally {
|
|
410
|
+
_iterator5.f();
|
|
411
|
+
}
|
|
412
|
+
var remainingProducts = this.getRemainingProducts(products, processedQuantityMap);
|
|
413
|
+
var _iterator6 = _createForOfIteratorHelper(remainingProducts),
|
|
414
|
+
_step6;
|
|
415
|
+
try {
|
|
416
|
+
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
417
|
+
var product = _step6.value;
|
|
418
|
+
var amount = new Decimal(product.price).mul(product.quantity);
|
|
419
|
+
totalOriginalAmount = totalOriginalAmount.plus(amount);
|
|
420
|
+
totalFinalAmount = totalFinalAmount.plus(amount);
|
|
421
|
+
}
|
|
422
|
+
} catch (err) {
|
|
423
|
+
_iterator6.e(err);
|
|
424
|
+
} finally {
|
|
425
|
+
_iterator6.f();
|
|
426
|
+
}
|
|
427
|
+
pricedProducts.push.apply(pricedProducts, _toConsumableArray(remainingProducts));
|
|
428
|
+
|
|
429
|
+
// 6. 计算总优惠金额
|
|
430
|
+
var totalDiscount = totalOriginalAmount.minus(totalFinalAmount);
|
|
431
|
+
return {
|
|
432
|
+
products: pricedProducts,
|
|
433
|
+
gifts: gifts,
|
|
434
|
+
totalDiscount: Decimal.max(0, totalDiscount).toNumber()
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* 获取商品适用的促销列表
|
|
440
|
+
*
|
|
441
|
+
* 简化方法,用于商品卡片展示
|
|
442
|
+
*
|
|
443
|
+
* @param product 商品
|
|
444
|
+
* @param strategyConfigs 策略配置(可选)
|
|
445
|
+
* @returns 适用的促销列表
|
|
446
|
+
*/
|
|
447
|
+
}, {
|
|
448
|
+
key: "getProductPromotions",
|
|
449
|
+
value: function getProductPromotions(product, strategyConfigs) {
|
|
450
|
+
var _results$;
|
|
451
|
+
var results = this.evaluateProducts({
|
|
452
|
+
products: [product],
|
|
453
|
+
strategyConfigs: strategyConfigs
|
|
454
|
+
});
|
|
455
|
+
return ((_results$ = results[0]) === null || _results$ === void 0 ? void 0 : _results$.applicablePromotions) || [];
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* 获取商品的促销标签
|
|
460
|
+
*
|
|
461
|
+
* 用于商品卡片展示
|
|
462
|
+
*
|
|
463
|
+
* @param product 商品
|
|
464
|
+
* @param strategyConfigs 策略配置(可选)
|
|
465
|
+
* @returns 促销标签列表
|
|
466
|
+
*/
|
|
467
|
+
}, {
|
|
468
|
+
key: "getProductPromotionTags",
|
|
469
|
+
value: function getProductPromotionTags(product, strategyConfigs) {
|
|
470
|
+
var _this = this;
|
|
471
|
+
var promotions = this.getProductPromotions(product, strategyConfigs);
|
|
472
|
+
return promotions.filter(function (promo) {
|
|
473
|
+
return promo.display;
|
|
474
|
+
}).map(function (promo) {
|
|
475
|
+
return {
|
|
476
|
+
text: _this.getLocalizedName(promo.display.text),
|
|
477
|
+
type: promo.display.type,
|
|
478
|
+
strategyId: promo.strategyId
|
|
479
|
+
};
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* 查找商品适用的策略配置
|
|
485
|
+
*
|
|
486
|
+
* @param product 商品
|
|
487
|
+
* @param strategyConfigs 策略配置列表(可选)
|
|
488
|
+
* @returns 适用的策略配置列表
|
|
489
|
+
*/
|
|
490
|
+
}, {
|
|
491
|
+
key: "findApplicableStrategies",
|
|
492
|
+
value: function findApplicableStrategies(product, strategyConfigs) {
|
|
493
|
+
var _this2 = this;
|
|
494
|
+
var configs = strategyConfigs || this.strategyConfigs;
|
|
495
|
+
return configs.filter(function (config) {
|
|
496
|
+
return _this2.isProductInStrategy(product, config);
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* 批量获取商品列表的适用策略信息
|
|
502
|
+
*
|
|
503
|
+
* 用于给商品列表追加策略标签信息
|
|
504
|
+
* 只检查商品 ID 匹配和策略时间范围
|
|
505
|
+
*
|
|
506
|
+
* @param input 评估输入(商品列表)
|
|
507
|
+
* @param matchVariant 是否需要匹配 product_variant_id,默认 true(严格匹配),false 时只匹配 product_id
|
|
508
|
+
* @returns 每个商品的适用策略完整数据
|
|
509
|
+
*/
|
|
510
|
+
}, {
|
|
511
|
+
key: "getProductsApplicableStrategies",
|
|
512
|
+
value: function getProductsApplicableStrategies(input) {
|
|
513
|
+
var _this3 = this;
|
|
514
|
+
var matchVariant = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
515
|
+
var products = input.products,
|
|
516
|
+
strategyConfigs = input.strategyConfigs,
|
|
517
|
+
channel = input.channel;
|
|
518
|
+
var configs = strategyConfigs || this.strategyConfigs;
|
|
519
|
+
var results = [];
|
|
520
|
+
var _iterator7 = _createForOfIteratorHelper(products),
|
|
521
|
+
_step7;
|
|
522
|
+
try {
|
|
523
|
+
var _loop = function _loop() {
|
|
524
|
+
var product = _step7.value;
|
|
525
|
+
var applicableStrategies = [];
|
|
526
|
+
|
|
527
|
+
// 遍历所有策略,检查此商品是否适用
|
|
528
|
+
var _iterator8 = _createForOfIteratorHelper(configs),
|
|
529
|
+
_step8;
|
|
530
|
+
try {
|
|
531
|
+
for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
|
|
532
|
+
var config = _step8.value;
|
|
533
|
+
var contextProduct = product;
|
|
534
|
+
if (!matchVariant) {
|
|
535
|
+
// 只匹配 product_id,忽略 product_variant_id
|
|
536
|
+
var productMatchRule = _this3.findProductMatchRule(config);
|
|
537
|
+
if (productMatchRule) {
|
|
538
|
+
var configProducts = productMatchRule.value;
|
|
539
|
+
var matchedConfig = configProducts.find(function (item) {
|
|
540
|
+
return item.product_id === product.product_id;
|
|
541
|
+
});
|
|
542
|
+
if (!matchedConfig) {
|
|
543
|
+
// product_id 不在策略适用范围内,跳过
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
546
|
+
// 用配置中的 variant_id 构造上下文,确保引擎 product_match 通过
|
|
547
|
+
if (matchedConfig.product_variant_id !== 0 && matchedConfig.product_variant_id !== product.product_variant_id) {
|
|
548
|
+
contextProduct = _objectSpread(_objectSpread({}, product), {}, {
|
|
549
|
+
product_variant_id: matchedConfig.product_variant_id
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
var context = _this3.adapter.prepareContext({
|
|
555
|
+
products: [contextProduct],
|
|
556
|
+
currentProduct: contextProduct,
|
|
557
|
+
channel: channel
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
// 评估策略
|
|
561
|
+
var result = _this3.engine.evaluate(config, context);
|
|
562
|
+
if (result.applicable && result.matchedActions.length > 0) {
|
|
563
|
+
var action = result.matchedActions[0];
|
|
564
|
+
var transformedResult = _this3.adapter.transformResult(result, {
|
|
565
|
+
products: [product],
|
|
566
|
+
currentProduct: product,
|
|
567
|
+
channel: channel
|
|
568
|
+
});
|
|
569
|
+
if (transformedResult.actionDetail) {
|
|
570
|
+
// 计算所需数量和可参与商品列表
|
|
571
|
+
var _this3$getPromotionRe = _this3.getPromotionRequirements(action.type, transformedResult.actionDetail, config),
|
|
572
|
+
requiredQuantity = _this3$getPromotionRe.requiredQuantity,
|
|
573
|
+
eligibleProducts = _this3$getPromotionRe.eligibleProducts;
|
|
574
|
+
applicableStrategies.push({
|
|
575
|
+
strategyId: config.metadata.id,
|
|
576
|
+
strategyName: config.metadata.name,
|
|
577
|
+
strategyMetadata: config.metadata,
|
|
578
|
+
actionType: action.type,
|
|
579
|
+
actionDetail: transformedResult.actionDetail,
|
|
580
|
+
display: _this3.getDisplayConfig(config),
|
|
581
|
+
strategyConfig: config,
|
|
582
|
+
requiredQuantity: requiredQuantity,
|
|
583
|
+
eligibleProducts: eligibleProducts
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
} catch (err) {
|
|
589
|
+
_iterator8.e(err);
|
|
590
|
+
} finally {
|
|
591
|
+
_iterator8.f();
|
|
592
|
+
}
|
|
593
|
+
results.push({
|
|
594
|
+
product: product,
|
|
595
|
+
applicableStrategies: applicableStrategies,
|
|
596
|
+
hasApplicableStrategy: applicableStrategies.length > 0
|
|
597
|
+
});
|
|
598
|
+
};
|
|
599
|
+
for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
|
|
600
|
+
_loop();
|
|
601
|
+
}
|
|
602
|
+
} catch (err) {
|
|
603
|
+
_iterator7.e(err);
|
|
604
|
+
} finally {
|
|
605
|
+
_iterator7.f();
|
|
606
|
+
}
|
|
607
|
+
return results;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* 获取促销所需数量和可参与商品列表
|
|
612
|
+
*
|
|
613
|
+
* @param actionType 促销类型
|
|
614
|
+
* @param actionDetail 促销详情
|
|
615
|
+
* @param config 策略配置
|
|
616
|
+
* @returns { requiredQuantity, eligibleProducts }
|
|
617
|
+
*/
|
|
618
|
+
}, {
|
|
619
|
+
key: "getPromotionRequirements",
|
|
620
|
+
value: function getPromotionRequirements(actionType, actionDetail, config) {
|
|
621
|
+
var requiredQuantity = 0;
|
|
622
|
+
|
|
623
|
+
// 根据促销类型获取所需数量
|
|
624
|
+
if (actionType === 'BUY_X_GET_Y_FREE') {
|
|
625
|
+
var detail = actionDetail;
|
|
626
|
+
requiredQuantity = detail.buyQuantity || 0;
|
|
627
|
+
} else if (actionType === 'X_ITEMS_FOR_Y_PRICE') {
|
|
628
|
+
var _detail = actionDetail;
|
|
629
|
+
requiredQuantity = _detail.x || 0;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// 获取可参与商品列表
|
|
633
|
+
var productMatchRule = this.findProductMatchRule(config);
|
|
634
|
+
var eligibleProducts = (productMatchRule === null || productMatchRule === void 0 ? void 0 : productMatchRule.value) || [];
|
|
635
|
+
return {
|
|
636
|
+
requiredQuantity: requiredQuantity,
|
|
637
|
+
eligibleProducts: eligibleProducts
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// ============================================
|
|
642
|
+
// 私有辅助方法
|
|
643
|
+
// ============================================
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* 按优先级排序促销组
|
|
647
|
+
* 优先级从 strategyConfig.actions[0].priority 获取,数值越小优先级越高
|
|
648
|
+
*/
|
|
649
|
+
}, {
|
|
650
|
+
key: "sortPromotionGroupsByPriority",
|
|
651
|
+
value: function sortPromotionGroupsByPriority(groups, promotions) {
|
|
652
|
+
// 创建策略ID到优先级的映射
|
|
653
|
+
var priorityMap = new Map();
|
|
654
|
+
var _iterator9 = _createForOfIteratorHelper(promotions),
|
|
655
|
+
_step9;
|
|
656
|
+
try {
|
|
657
|
+
for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
|
|
658
|
+
var _promo$strategyConfig2, _actions$0$priority, _actions$;
|
|
659
|
+
var promo = _step9.value;
|
|
660
|
+
var actions = ((_promo$strategyConfig2 = promo.strategyConfig) === null || _promo$strategyConfig2 === void 0 ? void 0 : _promo$strategyConfig2.actions) || [];
|
|
661
|
+
var priority = (_actions$0$priority = (_actions$ = actions[0]) === null || _actions$ === void 0 ? void 0 : _actions$.priority) !== null && _actions$0$priority !== void 0 ? _actions$0$priority : 999;
|
|
662
|
+
priorityMap.set(promo.strategyId, priority);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// 按优先级排序(数值越小优先级越高)
|
|
666
|
+
} catch (err) {
|
|
667
|
+
_iterator9.e(err);
|
|
668
|
+
} finally {
|
|
669
|
+
_iterator9.f();
|
|
670
|
+
}
|
|
671
|
+
return _toConsumableArray(groups).sort(function (a, b) {
|
|
672
|
+
var _priorityMap$get, _priorityMap$get2;
|
|
673
|
+
var priorityA = (_priorityMap$get = priorityMap.get(a.strategyId)) !== null && _priorityMap$get !== void 0 ? _priorityMap$get : 999;
|
|
674
|
+
var priorityB = (_priorityMap$get2 = priorityMap.get(b.strategyId)) !== null && _priorityMap$get2 !== void 0 ? _priorityMap$get2 : 999;
|
|
675
|
+
return priorityA - priorityB;
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* 处理 X件Y元 促销
|
|
681
|
+
*
|
|
682
|
+
* 1. 展开商品为单件列表,按价格从高到低排序
|
|
683
|
+
* 2. 计算可凑成的组数
|
|
684
|
+
* 3. 按原价比例均摊价格
|
|
685
|
+
* 4. 拆分商品(部分参与促销、部分原价)
|
|
686
|
+
*
|
|
687
|
+
* 注意:每个商品按 id 独立处理,不会合并不同 id 的商品
|
|
688
|
+
*/
|
|
689
|
+
}, {
|
|
690
|
+
key: "processXItemsForYPrice",
|
|
691
|
+
value: function processXItemsForYPrice(group, processedQuantityMap, matchedBundleIndexMap) {
|
|
692
|
+
var strategyId = group.strategyId,
|
|
693
|
+
strategyMetadata = group.strategyMetadata,
|
|
694
|
+
actionDetail = group.actionDetail,
|
|
695
|
+
groupProducts = group.products;
|
|
696
|
+
var detail = actionDetail;
|
|
697
|
+
var x = detail.x,
|
|
698
|
+
groupPrice = detail.price,
|
|
699
|
+
cumulative = detail.cumulative;
|
|
700
|
+
var result = [];
|
|
701
|
+
var originalAmount = new Decimal(0);
|
|
702
|
+
var finalAmount = new Decimal(0);
|
|
703
|
+
|
|
704
|
+
// 1. 展开所有商品为单件列表(排除已处理的数量)
|
|
705
|
+
// 每个单件记录来自哪个原商品(通过 product.id)
|
|
706
|
+
var unitProducts = [];
|
|
707
|
+
var _iterator10 = _createForOfIteratorHelper(groupProducts),
|
|
708
|
+
_step10;
|
|
709
|
+
try {
|
|
710
|
+
for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) {
|
|
711
|
+
var product = _step10.value;
|
|
712
|
+
var key = this.getProductKey(product);
|
|
713
|
+
var processedQty = processedQuantityMap.get(key) || 0;
|
|
714
|
+
var availableQty = product.quantity - processedQty;
|
|
715
|
+
if (availableQty <= 0) continue;
|
|
716
|
+
|
|
717
|
+
// 展开为单件,每个单件都记录来源商品
|
|
718
|
+
for (var _i = 0; _i < availableQty; _i++) {
|
|
719
|
+
unitProducts.push({
|
|
720
|
+
product: product,
|
|
721
|
+
price: product.price,
|
|
722
|
+
productId: product.id
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
} catch (err) {
|
|
727
|
+
_iterator10.e(err);
|
|
728
|
+
} finally {
|
|
729
|
+
_iterator10.f();
|
|
730
|
+
}
|
|
731
|
+
if (unitProducts.length === 0) {
|
|
732
|
+
return {
|
|
733
|
+
products: [],
|
|
734
|
+
originalAmount: 0,
|
|
735
|
+
finalAmount: 0
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
// 2. 按价格从高到低排序(优先使用高价商品)
|
|
740
|
+
unitProducts.sort(function (a, b) {
|
|
741
|
+
return b.price - a.price;
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
// 3. 计算可以凑成多少组
|
|
745
|
+
var totalUnits = unitProducts.length;
|
|
746
|
+
var groupCount = cumulative ? Math.floor(totalUnits / x) : totalUnits >= x ? 1 : 0;
|
|
747
|
+
var promotionUnits = groupCount * x;
|
|
748
|
+
|
|
749
|
+
// 4. 分离参与促销的和不参与的商品
|
|
750
|
+
var inPromotionUnits = unitProducts.slice(0, promotionUnits);
|
|
751
|
+
var notInPromotionUnits = unitProducts.slice(promotionUnits);
|
|
752
|
+
|
|
753
|
+
// 5. 按原商品 id 统计参与促销和不参与的数量
|
|
754
|
+
var promotionQtyByProductId = new Map();
|
|
755
|
+
var _iterator11 = _createForOfIteratorHelper(inPromotionUnits),
|
|
756
|
+
_step11;
|
|
757
|
+
try {
|
|
758
|
+
for (_iterator11.s(); !(_step11 = _iterator11.n()).done;) {
|
|
759
|
+
var _unit = _step11.value;
|
|
760
|
+
var id = _unit.productId;
|
|
761
|
+
promotionQtyByProductId.set(id, (promotionQtyByProductId.get(id) || 0) + 1);
|
|
762
|
+
}
|
|
763
|
+
} catch (err) {
|
|
764
|
+
_iterator11.e(err);
|
|
765
|
+
} finally {
|
|
766
|
+
_iterator11.f();
|
|
767
|
+
}
|
|
768
|
+
var remainingQtyByProductId = new Map();
|
|
769
|
+
var _iterator12 = _createForOfIteratorHelper(notInPromotionUnits),
|
|
770
|
+
_step12;
|
|
771
|
+
try {
|
|
772
|
+
for (_iterator12.s(); !(_step12 = _iterator12.n()).done;) {
|
|
773
|
+
var _unit2 = _step12.value;
|
|
774
|
+
var _id = _unit2.productId;
|
|
775
|
+
remainingQtyByProductId.set(_id, (remainingQtyByProductId.get(_id) || 0) + 1);
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
// 6. 为每个参与促销的单件计算均摊价格
|
|
779
|
+
// 按组内原价比例均摊
|
|
780
|
+
// 记录每个原商品的均摊价格累加(用于后续聚合)
|
|
781
|
+
} catch (err) {
|
|
782
|
+
_iterator12.e(err);
|
|
783
|
+
} finally {
|
|
784
|
+
_iterator12.f();
|
|
785
|
+
}
|
|
786
|
+
var allocatedPricesByProductId = new Map();
|
|
787
|
+
for (var g = 0; g < groupCount; g++) {
|
|
788
|
+
var startIdx = g * x;
|
|
789
|
+
var endIdx = startIdx + x;
|
|
790
|
+
var groupUnits = inPromotionUnits.slice(startIdx, endIdx);
|
|
791
|
+
|
|
792
|
+
// 计算组内原价总和
|
|
793
|
+
var groupOriginalTotal = groupUnits.reduce(function (sum, u) {
|
|
794
|
+
return sum.plus(u.price);
|
|
795
|
+
}, new Decimal(0));
|
|
796
|
+
|
|
797
|
+
// 按原价比例均摊
|
|
798
|
+
var groupPriceDecimal = new Decimal(groupPrice);
|
|
799
|
+
var allocatedSum = new Decimal(0);
|
|
800
|
+
for (var i = 0; i < groupUnits.length; i++) {
|
|
801
|
+
var unit = groupUnits[i];
|
|
802
|
+
var isLastUnit = i === groupUnits.length - 1;
|
|
803
|
+
var ratio = groupOriginalTotal.eq(0) ? new Decimal(0) : new Decimal(unit.price).div(groupOriginalTotal);
|
|
804
|
+
var allocatedDecimal = isLastUnit ? groupPriceDecimal.minus(allocatedSum) : groupPriceDecimal.mul(ratio);
|
|
805
|
+
|
|
806
|
+
// 记录这个单件的均摊价格
|
|
807
|
+
var productId = unit.productId;
|
|
808
|
+
var prices = allocatedPricesByProductId.get(productId) || [];
|
|
809
|
+
prices.push(allocatedDecimal);
|
|
810
|
+
allocatedPricesByProductId.set(productId, prices);
|
|
811
|
+
allocatedSum = allocatedSum.plus(allocatedDecimal);
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
// 7. 为每个原商品生成结果
|
|
816
|
+
var _iterator13 = _createForOfIteratorHelper(groupProducts),
|
|
817
|
+
_step13;
|
|
818
|
+
try {
|
|
819
|
+
for (_iterator13.s(); !(_step13 = _iterator13.n()).done;) {
|
|
820
|
+
var _product = _step13.value;
|
|
821
|
+
var _key = this.getProductKey(_product);
|
|
822
|
+
var _processedQty = processedQuantityMap.get(_key) || 0;
|
|
823
|
+
var _availableQty = _product.quantity - _processedQty;
|
|
824
|
+
if (_availableQty <= 0) continue;
|
|
825
|
+
var promoQty = promotionQtyByProductId.get(_product.id) || 0;
|
|
826
|
+
var remainingQty = remainingQtyByProductId.get(_product.id) || 0;
|
|
827
|
+
var allocatedPrices = allocatedPricesByProductId.get(_product.id) || [];
|
|
828
|
+
|
|
829
|
+
// 获取当前商品的 matchedBundleIndex
|
|
830
|
+
var matchedBundleIndex = matchedBundleIndexMap === null || matchedBundleIndexMap === void 0 ? void 0 : matchedBundleIndexMap.get(_product.id);
|
|
831
|
+
if (promoQty > 0 && remainingQty === 0) {
|
|
832
|
+
// 全部参与促销:保留原 id,计算总 finalPrice
|
|
833
|
+
var totalAllocated = allocatedPrices.reduce(function (sum, p) {
|
|
834
|
+
return sum.plus(p);
|
|
835
|
+
}, new Decimal(0));
|
|
836
|
+
var finalPricePerUnit = this.formatPrice(totalAllocated.div(promoQty));
|
|
837
|
+
result.push(_objectSpread(_objectSpread({}, _product), {}, {
|
|
838
|
+
quantity: promoQty,
|
|
839
|
+
finalPrice: finalPricePerUnit,
|
|
840
|
+
strategyId: strategyId,
|
|
841
|
+
strategyMetadata: strategyMetadata,
|
|
842
|
+
inPromotion: true,
|
|
843
|
+
isSplit: false,
|
|
844
|
+
matchedBundleIndex: matchedBundleIndex
|
|
845
|
+
}));
|
|
846
|
+
var productOriginalAmount = new Decimal(_product.price).mul(promoQty);
|
|
847
|
+
originalAmount = originalAmount.plus(productOriginalAmount);
|
|
848
|
+
finalAmount = finalAmount.plus(totalAllocated);
|
|
849
|
+
} else if (promoQty === 0 && remainingQty > 0) {
|
|
850
|
+
// 全部不参与促销:保留原 id,finalPrice = 原价
|
|
851
|
+
result.push(_objectSpread(_objectSpread({}, _product), {}, {
|
|
852
|
+
quantity: remainingQty,
|
|
853
|
+
finalPrice: this.formatPrice(_product.price),
|
|
854
|
+
strategyId: undefined,
|
|
855
|
+
strategyMetadata: undefined,
|
|
856
|
+
inPromotion: false,
|
|
857
|
+
isSplit: false
|
|
858
|
+
}));
|
|
859
|
+
var amount = new Decimal(_product.price).mul(remainingQty);
|
|
860
|
+
originalAmount = originalAmount.plus(amount);
|
|
861
|
+
finalAmount = finalAmount.plus(amount);
|
|
862
|
+
} else if (promoQty > 0 && remainingQty > 0) {
|
|
863
|
+
// 部分参与促销,部分不参与:需要拆分
|
|
864
|
+
// 参与促销的部分:新 id
|
|
865
|
+
var _totalAllocated = allocatedPrices.reduce(function (sum, p) {
|
|
866
|
+
return sum.plus(p);
|
|
867
|
+
}, new Decimal(0));
|
|
868
|
+
var _finalPricePerUnit = this.formatPrice(_totalAllocated.div(promoQty));
|
|
869
|
+
result.push(_objectSpread(_objectSpread({}, _product), {}, {
|
|
870
|
+
id: this.generateRandomId(),
|
|
871
|
+
originalId: _product.id,
|
|
872
|
+
quantity: promoQty,
|
|
873
|
+
finalPrice: _finalPricePerUnit,
|
|
874
|
+
strategyId: strategyId,
|
|
875
|
+
strategyMetadata: strategyMetadata,
|
|
876
|
+
inPromotion: true,
|
|
877
|
+
matchedBundleIndex: matchedBundleIndex,
|
|
878
|
+
isSplit: true
|
|
879
|
+
}));
|
|
880
|
+
var promoOriginalAmount = new Decimal(_product.price).mul(promoQty);
|
|
881
|
+
originalAmount = originalAmount.plus(promoOriginalAmount);
|
|
882
|
+
finalAmount = finalAmount.plus(_totalAllocated);
|
|
883
|
+
|
|
884
|
+
// 不参与促销的部分:保留原 id
|
|
885
|
+
result.push(_objectSpread(_objectSpread({}, _product), {}, {
|
|
886
|
+
quantity: remainingQty,
|
|
887
|
+
finalPrice: this.formatPrice(_product.price),
|
|
888
|
+
strategyId: undefined,
|
|
889
|
+
strategyMetadata: undefined,
|
|
890
|
+
inPromotion: false,
|
|
891
|
+
isSplit: true
|
|
892
|
+
}));
|
|
893
|
+
var remainingAmount = new Decimal(_product.price).mul(remainingQty);
|
|
894
|
+
originalAmount = originalAmount.plus(remainingAmount);
|
|
895
|
+
finalAmount = finalAmount.plus(remainingAmount);
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
// 更新已处理数量
|
|
899
|
+
processedQuantityMap.set(_key, _processedQty + _availableQty);
|
|
900
|
+
}
|
|
901
|
+
} catch (err) {
|
|
902
|
+
_iterator13.e(err);
|
|
903
|
+
} finally {
|
|
904
|
+
_iterator13.f();
|
|
905
|
+
}
|
|
906
|
+
return {
|
|
907
|
+
products: result,
|
|
908
|
+
originalAmount: originalAmount.toNumber(),
|
|
909
|
+
finalAmount: finalAmount.toNumber()
|
|
910
|
+
};
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
/**
|
|
914
|
+
* 处理 买X送Y 促销
|
|
915
|
+
*
|
|
916
|
+
* 计算赠品数量,商品本身价格不变
|
|
917
|
+
* 支持 bundle 子商品的数量计算(主商品数量 × 子商品数量)
|
|
918
|
+
*/
|
|
919
|
+
}, {
|
|
920
|
+
key: "processBuyXGetYFree",
|
|
921
|
+
value: function processBuyXGetYFree(group, processedQuantityMap, matchedBundleIndexMap) {
|
|
922
|
+
var strategyId = group.strategyId,
|
|
923
|
+
strategyName = group.strategyName,
|
|
924
|
+
strategyMetadata = group.strategyMetadata,
|
|
925
|
+
actionDetail = group.actionDetail,
|
|
926
|
+
groupProducts = group.products;
|
|
927
|
+
var detail = actionDetail;
|
|
928
|
+
var buyQuantity = detail.buyQuantity,
|
|
929
|
+
freeQuantity = detail.freeQuantity,
|
|
930
|
+
cumulative = detail.cumulative,
|
|
931
|
+
giftProducts = detail.giftProducts;
|
|
932
|
+
var result = [];
|
|
933
|
+
var originalAmount = new Decimal(0);
|
|
934
|
+
var finalAmount = new Decimal(0);
|
|
935
|
+
|
|
936
|
+
// 1. 先计算可用商品总数量(第一次遍历)
|
|
937
|
+
// 对于 bundle 子商品匹配,促销数量 = 主商品数量 × bundle子商品数量
|
|
938
|
+
var totalPromoQty = 0;
|
|
939
|
+
var productInfoMap = new Map();
|
|
940
|
+
var _iterator14 = _createForOfIteratorHelper(groupProducts),
|
|
941
|
+
_step14;
|
|
942
|
+
try {
|
|
943
|
+
for (_iterator14.s(); !(_step14 = _iterator14.n()).done;) {
|
|
944
|
+
var product = _step14.value;
|
|
945
|
+
var key = this.getProductKey(product);
|
|
946
|
+
var processedQty = processedQuantityMap.get(key) || 0;
|
|
947
|
+
var availableQty = product.quantity - processedQty;
|
|
948
|
+
if (availableQty <= 0) continue;
|
|
949
|
+
|
|
950
|
+
// 获取 matchedBundleIndex
|
|
951
|
+
var matchedBundleIndex = matchedBundleIndexMap === null || matchedBundleIndexMap === void 0 ? void 0 : matchedBundleIndexMap.get(product.id);
|
|
952
|
+
|
|
953
|
+
// 计算用于促销的数量
|
|
954
|
+
var promoQty = availableQty;
|
|
955
|
+
if (matchedBundleIndex !== undefined && product.bundle) {
|
|
956
|
+
var bundleItem = product.bundle[matchedBundleIndex];
|
|
957
|
+
// 促销数量 = 主商品数量 × bundle子商品数量
|
|
958
|
+
promoQty = availableQty * (bundleItem.quantity || 1);
|
|
959
|
+
}
|
|
960
|
+
totalPromoQty += promoQty;
|
|
961
|
+
productInfoMap.set(key, {
|
|
962
|
+
availableQty: availableQty,
|
|
963
|
+
promoQty: promoQty,
|
|
964
|
+
matchedBundleIndex: matchedBundleIndex
|
|
965
|
+
});
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
// 2. 判断是否满足促销条件
|
|
969
|
+
} catch (err) {
|
|
970
|
+
_iterator14.e(err);
|
|
971
|
+
} finally {
|
|
972
|
+
_iterator14.f();
|
|
973
|
+
}
|
|
974
|
+
var isFulfilled = totalPromoQty >= buyQuantity;
|
|
975
|
+
|
|
976
|
+
// 3. 生成商品结果(第二次遍历)
|
|
977
|
+
var _iterator15 = _createForOfIteratorHelper(groupProducts),
|
|
978
|
+
_step15;
|
|
979
|
+
try {
|
|
980
|
+
for (_iterator15.s(); !(_step15 = _iterator15.n()).done;) {
|
|
981
|
+
var _product2 = _step15.value;
|
|
982
|
+
var _key2 = this.getProductKey(_product2);
|
|
983
|
+
var info = productInfoMap.get(_key2);
|
|
984
|
+
if (!info || info.availableQty <= 0) continue;
|
|
985
|
+
var _processedQty2 = processedQuantityMap.get(_key2) || 0;
|
|
986
|
+
|
|
987
|
+
// 商品本身价格不变,只是触发赠品
|
|
988
|
+
// inPromotion 只有在满足条件时才为 true
|
|
989
|
+
result.push(_objectSpread(_objectSpread({}, _product2), {}, {
|
|
990
|
+
quantity: info.availableQty,
|
|
991
|
+
// 返回主商品数量
|
|
992
|
+
finalPrice: this.formatPrice(_product2.price),
|
|
993
|
+
strategyId: strategyId,
|
|
994
|
+
strategyMetadata: strategyMetadata,
|
|
995
|
+
inPromotion: isFulfilled,
|
|
996
|
+
isSplit: info.availableQty < _product2.quantity,
|
|
997
|
+
matchedBundleIndex: info.matchedBundleIndex
|
|
998
|
+
}));
|
|
999
|
+
var amount = new Decimal(_product2.price).mul(info.availableQty);
|
|
1000
|
+
originalAmount = originalAmount.plus(amount);
|
|
1001
|
+
finalAmount = finalAmount.plus(amount);
|
|
1002
|
+
|
|
1003
|
+
// 更新已处理数量(使用主商品数量)
|
|
1004
|
+
processedQuantityMap.set(_key2, _processedQty2 + info.availableQty);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
// 4. 计算赠品数量(使用促销数量)
|
|
1008
|
+
} catch (err) {
|
|
1009
|
+
_iterator15.e(err);
|
|
1010
|
+
} finally {
|
|
1011
|
+
_iterator15.f();
|
|
1012
|
+
}
|
|
1013
|
+
var giftCount = 0;
|
|
1014
|
+
if (isFulfilled) {
|
|
1015
|
+
giftCount = cumulative ? Math.floor(totalPromoQty / buyQuantity) * freeQuantity : freeQuantity;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
// 5. 构建赠品信息
|
|
1019
|
+
var giftInfo = giftCount > 0 ? {
|
|
1020
|
+
strategyId: strategyId,
|
|
1021
|
+
strategyName: strategyName,
|
|
1022
|
+
giftCount: giftCount,
|
|
1023
|
+
giftOptions: giftProducts || []
|
|
1024
|
+
} : null;
|
|
1025
|
+
return {
|
|
1026
|
+
products: result,
|
|
1027
|
+
originalAmount: originalAmount.toNumber(),
|
|
1028
|
+
finalAmount: finalAmount.toNumber(),
|
|
1029
|
+
giftInfo: giftInfo
|
|
1030
|
+
};
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
/**
|
|
1034
|
+
* 获取未参与任何促销的商品
|
|
1035
|
+
*/
|
|
1036
|
+
}, {
|
|
1037
|
+
key: "getRemainingProducts",
|
|
1038
|
+
value: function getRemainingProducts(allProducts, processedQuantityMap) {
|
|
1039
|
+
var result = [];
|
|
1040
|
+
var _iterator16 = _createForOfIteratorHelper(allProducts),
|
|
1041
|
+
_step16;
|
|
1042
|
+
try {
|
|
1043
|
+
for (_iterator16.s(); !(_step16 = _iterator16.n()).done;) {
|
|
1044
|
+
var product = _step16.value;
|
|
1045
|
+
var key = this.getProductKey(product);
|
|
1046
|
+
var processedQty = processedQuantityMap.get(key) || 0;
|
|
1047
|
+
var remainingQty = product.quantity - processedQty;
|
|
1048
|
+
if (remainingQty > 0) {
|
|
1049
|
+
result.push(_objectSpread(_objectSpread({}, product), {}, {
|
|
1050
|
+
quantity: remainingQty,
|
|
1051
|
+
finalPrice: this.formatPrice(product.price),
|
|
1052
|
+
strategyId: undefined,
|
|
1053
|
+
inPromotion: false,
|
|
1054
|
+
isSplit: remainingQty < product.quantity
|
|
1055
|
+
}));
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
} catch (err) {
|
|
1059
|
+
_iterator16.e(err);
|
|
1060
|
+
} finally {
|
|
1061
|
+
_iterator16.f();
|
|
1062
|
+
}
|
|
1063
|
+
return result;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
/**
|
|
1067
|
+
* 价格统一保留两位小数
|
|
1068
|
+
*/
|
|
1069
|
+
}, {
|
|
1070
|
+
key: "formatPrice",
|
|
1071
|
+
value: function formatPrice(value) {
|
|
1072
|
+
return new Decimal(value).toDecimalPlaces(2, Decimal.ROUND_HALF_UP).toNumber();
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
/**
|
|
1076
|
+
* 获取商品唯一标识 key
|
|
1077
|
+
* 使用商品的 id 作为唯一标识,不同 id 的商品不会被合并
|
|
1078
|
+
*/
|
|
1079
|
+
}, {
|
|
1080
|
+
key: "getProductKey",
|
|
1081
|
+
value: function getProductKey(product) {
|
|
1082
|
+
return String(product.id);
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
/**
|
|
1086
|
+
* 生成随机ID
|
|
1087
|
+
*/
|
|
1088
|
+
}, {
|
|
1089
|
+
key: "generateRandomId",
|
|
1090
|
+
value: function generateRandomId() {
|
|
1091
|
+
return Math.floor(Math.random() * 1000000000) + Date.now();
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
/**
|
|
1095
|
+
* 商品匹配结果信息
|
|
1096
|
+
*/
|
|
1097
|
+
}, {
|
|
1098
|
+
key: "getProductMatchInfo",
|
|
1099
|
+
value: function getProductMatchInfo(product, config) {
|
|
1100
|
+
var productMatchRule = this.findProductMatchRule(config);
|
|
1101
|
+
if (!productMatchRule) {
|
|
1102
|
+
// 没有商品范围条件,默认适用所有商品(匹配主商品)
|
|
1103
|
+
return {
|
|
1104
|
+
isMatch: true
|
|
1105
|
+
};
|
|
1106
|
+
}
|
|
1107
|
+
var configProducts = productMatchRule.value;
|
|
1108
|
+
|
|
1109
|
+
// 1. 先检查主商品是否匹配
|
|
1110
|
+
if (this.isProductIdMatch(product.product_id, product.product_variant_id, configProducts)) {
|
|
1111
|
+
return {
|
|
1112
|
+
isMatch: true
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
// 2. 主商品不匹配,检查 bundle 子商品
|
|
1117
|
+
if (product.bundle && product.bundle.length > 0) {
|
|
1118
|
+
for (var i = 0; i < product.bundle.length; i++) {
|
|
1119
|
+
var bundleItem = product.bundle[i];
|
|
1120
|
+
if (this.isProductIdMatch(bundleItem._bundle_product_id, bundleItem.product_variant_id, configProducts)) {
|
|
1121
|
+
return {
|
|
1122
|
+
isMatch: true,
|
|
1123
|
+
matchedBundleIndex: i
|
|
1124
|
+
};
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
return {
|
|
1129
|
+
isMatch: false
|
|
1130
|
+
};
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
/**
|
|
1134
|
+
* 检查商品是否在策略的适用范围内
|
|
1135
|
+
*/
|
|
1136
|
+
}, {
|
|
1137
|
+
key: "isProductInStrategy",
|
|
1138
|
+
value: function isProductInStrategy(product, config) {
|
|
1139
|
+
return this.getProductMatchInfo(product, config).isMatch;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
/**
|
|
1143
|
+
* 查找商品匹配规则
|
|
1144
|
+
*/
|
|
1145
|
+
}, {
|
|
1146
|
+
key: "findProductMatchRule",
|
|
1147
|
+
value: function findProductMatchRule(config) {
|
|
1148
|
+
var _config$conditions;
|
|
1149
|
+
if (!(config !== null && config !== void 0 && (_config$conditions = config.conditions) !== null && _config$conditions !== void 0 && _config$conditions.rules)) {
|
|
1150
|
+
return null;
|
|
1151
|
+
}
|
|
1152
|
+
return config.conditions.rules.find(function (rule) {
|
|
1153
|
+
return rule.field === 'productIdAndVariantId' && (rule.operator === 'product_match' || rule.operator === 'object_in');
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
/**
|
|
1158
|
+
* 检查商品ID是否匹配配置列表
|
|
1159
|
+
*/
|
|
1160
|
+
}, {
|
|
1161
|
+
key: "isProductIdMatch",
|
|
1162
|
+
value: function isProductIdMatch(productId, productVariantId, configProducts) {
|
|
1163
|
+
return configProducts.some(function (config) {
|
|
1164
|
+
// 首先检查 product_id
|
|
1165
|
+
if (config.product_id !== productId) {
|
|
1166
|
+
return false;
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
// 如果配置的 product_variant_id = 0,只需要 product_id 匹配
|
|
1170
|
+
if (config.product_variant_id === 0) {
|
|
1171
|
+
return true;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
// 否则需要 product_variant_id 精确匹配
|
|
1175
|
+
return config.product_variant_id === productVariantId;
|
|
1176
|
+
});
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
/**
|
|
1180
|
+
* 检查商品是否匹配配置(兼容旧方法)
|
|
1181
|
+
*/
|
|
1182
|
+
}, {
|
|
1183
|
+
key: "isProductMatch",
|
|
1184
|
+
value: function isProductMatch(product, configProducts) {
|
|
1185
|
+
return this.isProductIdMatch(product.product_id, product.product_variant_id, configProducts);
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
/**
|
|
1189
|
+
* 获取展示配置
|
|
1190
|
+
*/
|
|
1191
|
+
}, {
|
|
1192
|
+
key: "getDisplayConfig",
|
|
1193
|
+
value: function getDisplayConfig(config) {
|
|
1194
|
+
var _custom$display;
|
|
1195
|
+
var custom = config.metadata.custom;
|
|
1196
|
+
if (custom !== null && custom !== void 0 && (_custom$display = custom.display) !== null && _custom$display !== void 0 && _custom$display.product_card) {
|
|
1197
|
+
return {
|
|
1198
|
+
text: custom.display.product_card.text,
|
|
1199
|
+
type: custom.display.product_card.type
|
|
1200
|
+
};
|
|
1201
|
+
}
|
|
1202
|
+
return undefined;
|
|
1203
|
+
}
|
|
1204
|
+
}]);
|
|
1205
|
+
return PromotionEvaluator;
|
|
1206
|
+
}();
|