@pisell/pisellos 2.3.39 → 2.3.41
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/core/index.d.ts +2 -0
- package/dist/core/index.js +7 -0
- package/dist/model/strategy/adapter/promotion/adapter.d.ts +4 -0
- package/dist/model/strategy/adapter/promotion/adapter.js +23 -0
- package/dist/model/strategy/adapter/promotion/evaluator.d.ts +17 -0
- package/dist/model/strategy/adapter/promotion/evaluator.js +279 -6
- package/dist/model/strategy/adapter/promotion/examples.d.ts +86 -0
- package/dist/model/strategy/adapter/promotion/examples.js +99 -0
- package/dist/model/strategy/adapter/promotion/index.d.ts +1 -1
- package/dist/model/strategy/adapter/promotion/index.js +9 -0
- package/dist/model/strategy/adapter/promotion/type.d.ts +90 -2
- package/dist/model/strategy/adapter/promotion/type.js +45 -0
- package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +5 -3
- package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +6 -3
- package/dist/modules/Discount/index.d.ts +0 -1
- package/dist/modules/Discount/index.js +11 -40
- package/dist/modules/Discount/types.d.ts +0 -1
- package/dist/modules/OpenData/index.d.ts +2 -0
- package/dist/modules/OpenData/index.js +10 -2
- package/dist/modules/Order/index.d.ts +29 -12
- package/dist/modules/Order/index.js +750 -509
- package/dist/modules/Order/payment-utils.d.ts +26 -0
- package/dist/modules/Order/payment-utils.js +225 -0
- package/dist/modules/Order/types.d.ts +33 -10
- package/dist/modules/Order/utils/orderCollectionIdentity.js +7 -2
- package/dist/modules/Order/utils.d.ts +0 -10
- package/dist/modules/Order/utils.js +13 -41
- package/dist/modules/Payment/index.d.ts +2 -0
- package/dist/modules/Payment/index.js +79 -50
- package/dist/modules/Payment/types.d.ts +99 -28
- package/dist/modules/Payment/types.js +20 -3
- package/dist/modules/Payment/walletpass.d.ts +25 -1
- package/dist/modules/Payment/walletpass.js +707 -157
- package/dist/modules/Product/types.d.ts +0 -1
- package/dist/modules/ProductList/index.js +14 -33
- package/dist/modules/Quotation/index.d.ts +1 -1
- package/dist/modules/Quotation/index.js +2 -2
- package/dist/modules/Rules/index.d.ts +1 -0
- package/dist/modules/Rules/index.js +89 -96
- package/dist/modules/SalesSummary/index.js +13 -12
- package/dist/modules/ScanOrderLogger/index.d.ts +0 -2
- package/dist/modules/ScanOrderLogger/index.js +2 -15
- package/dist/modules/ScanOrderLogger/providers/feishu.js +27 -45
- package/dist/modules/ScanOrderLogger/types.d.ts +0 -1
- package/dist/modules/Schedule/index.d.ts +1 -3
- package/dist/modules/Schedule/index.js +16 -21
- package/dist/modules/Summary/utils.js +13 -38
- package/dist/modules/index.d.ts +0 -2
- package/dist/modules/index.js +1 -3
- package/dist/plugins/window.d.ts +0 -1
- package/dist/server/index.d.ts +16 -14
- package/dist/server/index.js +1925 -1143
- package/dist/server/modules/order/index.d.ts +54 -4
- package/dist/server/modules/order/index.js +1600 -700
- package/dist/server/modules/order/types.d.ts +11 -3
- package/dist/server/modules/order/types.js +1 -1
- package/dist/solution/BaseSales/index.d.ts +109 -20
- package/dist/solution/BaseSales/index.js +1800 -480
- package/dist/solution/BaseSales/types.d.ts +52 -0
- package/dist/solution/BaseSales/types.js +2 -1
- package/dist/solution/BaseSales/utils/cartPromotion.d.ts +3 -1
- package/dist/solution/BaseSales/utils/cartPromotion.js +90 -31
- package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +6 -1
- package/dist/solution/BookingByStep/index.d.ts +2 -17
- package/dist/solution/BookingByStep/index.js +215 -294
- package/dist/solution/BookingByStep/types.d.ts +1 -2
- package/dist/solution/BookingByStep/types.js +1 -3
- package/dist/solution/BookingByStep/utils/capacity.js +1 -17
- package/dist/solution/BookingByStep/utils/timeslots.d.ts +1 -3
- package/dist/solution/BookingByStep/utils/timeslots.js +12 -19
- package/dist/solution/BookingTicket/index.d.ts +7 -3
- package/dist/solution/BookingTicket/index.js +132 -49
- package/dist/solution/BookingTicket/utils/addProductDecision.js +6 -0
- package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +8 -0
- package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.js +172 -82
- package/dist/solution/BookingTicket/utils/weighingProductSku.d.ts +5 -0
- package/dist/solution/BookingTicket/utils/weighingProductSku.js +45 -0
- package/dist/solution/Sales/index.d.ts +1 -0
- package/dist/solution/Sales/index.js +10 -2
- package/dist/solution/ScanOrder/index.d.ts +14 -26
- package/dist/solution/ScanOrder/index.js +756 -1148
- package/dist/solution/ScanOrder/types.d.ts +1 -21
- package/dist/solution/ScanOrder/utils.d.ts +0 -8
- package/dist/solution/ScanOrder/utils.js +25 -66
- package/dist/solution/ShopDiscount/index.d.ts +0 -1
- package/dist/solution/ShopDiscount/index.js +87 -125
- package/dist/solution/VenueBooking/index.d.ts +11 -39
- package/dist/solution/VenueBooking/index.js +860 -1176
- package/dist/solution/VenueBooking/types.d.ts +0 -3
- package/dist/solution/VenueBooking/utils/resource.js +0 -1
- package/dist/solution/VenueBooking/utils/slotMerge.d.ts +4 -4
- package/dist/solution/VenueBooking/utils/slotMerge.js +5 -10
- package/dist/solution/index.d.ts +0 -1
- package/dist/solution/index.js +1 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/utils/payment-number.d.ts +9 -0
- package/dist/utils/payment-number.js +69 -0
- package/lib/core/index.d.ts +2 -0
- package/lib/core/index.js +4 -0
- package/lib/model/strategy/adapter/promotion/adapter.d.ts +4 -0
- package/lib/model/strategy/adapter/promotion/adapter.js +20 -0
- package/lib/model/strategy/adapter/promotion/evaluator.d.ts +17 -0
- package/lib/model/strategy/adapter/promotion/evaluator.js +235 -0
- package/lib/model/strategy/adapter/promotion/examples.d.ts +86 -0
- package/lib/model/strategy/adapter/promotion/examples.js +91 -0
- package/lib/model/strategy/adapter/promotion/index.d.ts +1 -1
- package/lib/model/strategy/adapter/promotion/index.js +51 -0
- package/lib/model/strategy/adapter/promotion/type.d.ts +90 -2
- package/lib/model/strategy/adapter/promotion/type.js +2 -0
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +2 -1
- package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +2 -1
- package/lib/modules/Discount/index.d.ts +0 -1
- package/lib/modules/Discount/index.js +0 -9
- package/lib/modules/Discount/types.d.ts +0 -1
- package/lib/modules/OpenData/index.d.ts +2 -0
- package/lib/modules/OpenData/index.js +6 -1
- package/lib/modules/Order/index.d.ts +29 -12
- package/lib/modules/Order/index.js +196 -86
- package/lib/modules/Order/payment-utils.d.ts +26 -0
- package/lib/modules/Order/payment-utils.js +224 -0
- package/lib/modules/Order/types.d.ts +33 -10
- package/lib/modules/Order/utils/orderCollectionIdentity.js +3 -0
- package/lib/modules/Order/utils.d.ts +0 -10
- package/lib/modules/Order/utils.js +16 -40
- package/lib/modules/Payment/index.d.ts +2 -0
- package/lib/modules/Payment/index.js +34 -13
- package/lib/modules/Payment/types.d.ts +99 -28
- package/lib/modules/Payment/types.js +4 -3
- package/lib/modules/Payment/walletpass.d.ts +25 -1
- package/lib/modules/Payment/walletpass.js +470 -21
- package/lib/modules/Product/types.d.ts +0 -1
- package/lib/modules/ProductList/index.js +31 -40
- package/lib/modules/Quotation/index.d.ts +1 -1
- package/lib/modules/Quotation/index.js +2 -2
- package/lib/modules/Rules/index.d.ts +1 -0
- package/lib/modules/Rules/index.js +47 -40
- package/lib/modules/SalesSummary/index.js +7 -6
- package/lib/modules/ScanOrderLogger/index.d.ts +0 -2
- package/lib/modules/ScanOrderLogger/index.js +1 -13
- package/lib/modules/ScanOrderLogger/providers/feishu.js +6 -15
- package/lib/modules/ScanOrderLogger/types.d.ts +0 -1
- package/lib/modules/Schedule/index.d.ts +1 -3
- package/lib/modules/Schedule/index.js +8 -10
- package/lib/modules/Summary/utils.js +1 -21
- package/lib/modules/index.d.ts +0 -2
- package/lib/modules/index.js +1 -5
- package/lib/plugins/window.d.ts +0 -1
- package/lib/server/index.d.ts +16 -14
- package/lib/server/index.js +675 -83
- package/lib/server/modules/order/index.d.ts +54 -4
- package/lib/server/modules/order/index.js +679 -66
- package/lib/server/modules/order/types.d.ts +11 -3
- package/lib/solution/BaseSales/index.d.ts +109 -20
- package/lib/solution/BaseSales/index.js +883 -70
- package/lib/solution/BaseSales/types.d.ts +52 -0
- package/lib/solution/BaseSales/types.js +2 -1
- package/lib/solution/BaseSales/utils/cartPromotion.d.ts +3 -1
- package/lib/solution/BaseSales/utils/cartPromotion.js +63 -12
- package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +6 -1
- package/lib/solution/BookingByStep/index.d.ts +2 -17
- package/lib/solution/BookingByStep/index.js +18 -60
- package/lib/solution/BookingByStep/types.d.ts +1 -2
- package/lib/solution/BookingByStep/types.js +0 -5
- package/lib/solution/BookingByStep/utils/capacity.js +1 -20
- package/lib/solution/BookingByStep/utils/timeslots.d.ts +1 -3
- package/lib/solution/BookingByStep/utils/timeslots.js +11 -19
- package/lib/solution/BookingTicket/index.d.ts +7 -3
- package/lib/solution/BookingTicket/index.js +62 -9
- package/lib/solution/BookingTicket/utils/addProductDecision.js +4 -0
- package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +8 -0
- package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +36 -4
- package/lib/solution/BookingTicket/utils/weighingProductSku.d.ts +5 -0
- package/lib/solution/BookingTicket/utils/weighingProductSku.js +63 -0
- package/lib/solution/Sales/index.d.ts +1 -0
- package/lib/solution/Sales/index.js +5 -3
- package/lib/solution/ScanOrder/index.d.ts +14 -26
- package/lib/solution/ScanOrder/index.js +190 -449
- package/lib/solution/ScanOrder/types.d.ts +1 -21
- package/lib/solution/ScanOrder/utils.d.ts +0 -8
- package/lib/solution/ScanOrder/utils.js +0 -31
- package/lib/solution/ShopDiscount/index.d.ts +0 -1
- package/lib/solution/ShopDiscount/index.js +0 -14
- package/lib/solution/VenueBooking/index.d.ts +11 -39
- package/lib/solution/VenueBooking/index.js +123 -328
- package/lib/solution/VenueBooking/types.d.ts +0 -3
- package/lib/solution/VenueBooking/utils/resource.js +0 -1
- package/lib/solution/VenueBooking/utils/slotMerge.d.ts +4 -4
- package/lib/solution/VenueBooking/utils/slotMerge.js +4 -6
- package/lib/solution/index.d.ts +0 -1
- package/lib/solution/index.js +1 -3
- package/lib/types/index.d.ts +1 -1
- package/lib/utils/payment-number.d.ts +9 -0
- package/lib/utils/payment-number.js +64 -0
- package/package.json +1 -1
- package/dist/modules/Holder/index.d.ts +0 -48
- package/dist/modules/Holder/index.js +0 -640
- package/dist/modules/Holder/types.d.ts +0 -123
- package/dist/modules/Holder/types.js +0 -1
- package/dist/modules/Holder/utils.d.ts +0 -13
- package/dist/modules/Holder/utils.js +0 -34
- package/dist/modules/ResourcePlanner/index.d.ts +0 -24
- package/dist/modules/ResourcePlanner/index.js +0 -181
- package/dist/modules/ResourcePlanner/planner.d.ts +0 -14
- package/dist/modules/ResourcePlanner/planner.js +0 -1069
- package/dist/modules/ResourcePlanner/types.d.ts +0 -227
- package/dist/modules/ResourcePlanner/types.js +0 -1
- package/dist/solution/UnifiedBookingSales/index.d.ts +0 -183
- package/dist/solution/UnifiedBookingSales/index.js +0 -1871
- package/dist/solution/UnifiedBookingSales/types.d.ts +0 -143
- package/dist/solution/UnifiedBookingSales/types.js +0 -11
- package/lib/modules/Holder/index.d.ts +0 -48
- package/lib/modules/Holder/index.js +0 -402
- package/lib/modules/Holder/types.d.ts +0 -123
- package/lib/modules/Holder/types.js +0 -17
- package/lib/modules/Holder/utils.d.ts +0 -13
- package/lib/modules/Holder/utils.js +0 -71
- package/lib/modules/ResourcePlanner/index.d.ts +0 -24
- package/lib/modules/ResourcePlanner/index.js +0 -148
- package/lib/modules/ResourcePlanner/planner.d.ts +0 -14
- package/lib/modules/ResourcePlanner/planner.js +0 -933
- package/lib/modules/ResourcePlanner/types.d.ts +0 -227
- package/lib/modules/ResourcePlanner/types.js +0 -17
- package/lib/solution/UnifiedBookingSales/index.d.ts +0 -183
- package/lib/solution/UnifiedBookingSales/index.js +0 -1076
- package/lib/solution/UnifiedBookingSales/types.d.ts +0 -143
- package/lib/solution/UnifiedBookingSales/types.js +0 -33
package/dist/core/index.d.ts
CHANGED
|
@@ -28,6 +28,8 @@ declare class PisellOSCore implements PisellCore {
|
|
|
28
28
|
getModule<T extends Module>(name: string): T | null;
|
|
29
29
|
getModuleExports<T = any>(name: string): T | null;
|
|
30
30
|
hasModule(name: string): boolean;
|
|
31
|
+
/** 返回当前已注册模块名,供宿主在切换店铺等生命周期中定向清理运行态。 */
|
|
32
|
+
getModuleNames(): string[];
|
|
31
33
|
destroy(): Promise<void>;
|
|
32
34
|
setContext(ctx: Partial<BusinessContext>): void;
|
|
33
35
|
/**
|
package/dist/core/index.js
CHANGED
|
@@ -300,6 +300,13 @@ var PisellOSCore = /*#__PURE__*/function () {
|
|
|
300
300
|
return this.modules.has(name);
|
|
301
301
|
}
|
|
302
302
|
|
|
303
|
+
/** 返回当前已注册模块名,供宿主在切换店铺等生命周期中定向清理运行态。 */
|
|
304
|
+
}, {
|
|
305
|
+
key: "getModuleNames",
|
|
306
|
+
value: function getModuleNames() {
|
|
307
|
+
return Array.from(this.modules.keys());
|
|
308
|
+
}
|
|
309
|
+
|
|
303
310
|
// 销毁方法
|
|
304
311
|
}, {
|
|
305
312
|
key: "destroy",
|
|
@@ -162,6 +162,8 @@ export var PromotionAdapter = /*#__PURE__*/function () {
|
|
|
162
162
|
return this.parseXItemsForYPriceAction(action);
|
|
163
163
|
case PROMOTION_ACTION_TYPES.BUY_X_GET_Y_FREE:
|
|
164
164
|
return this.parseBuyXGetYFreeAction(action);
|
|
165
|
+
case PROMOTION_ACTION_TYPES.ITEM_REWARD:
|
|
166
|
+
return this.parseItemRewardAction(action);
|
|
165
167
|
default:
|
|
166
168
|
return undefined;
|
|
167
169
|
}
|
|
@@ -204,6 +206,27 @@ export var PromotionAdapter = /*#__PURE__*/function () {
|
|
|
204
206
|
};
|
|
205
207
|
}
|
|
206
208
|
|
|
209
|
+
/**
|
|
210
|
+
* 解析 商品奖励 Action
|
|
211
|
+
*/
|
|
212
|
+
}, {
|
|
213
|
+
key: "parseItemRewardAction",
|
|
214
|
+
value: function parseItemRewardAction(action) {
|
|
215
|
+
var value = action.value || {};
|
|
216
|
+
var config = action.config || {};
|
|
217
|
+
return {
|
|
218
|
+
type: PROMOTION_ACTION_TYPES.ITEM_REWARD,
|
|
219
|
+
rewardMethod: value.rewardMethod || 'free',
|
|
220
|
+
rewardValue: Number(value.rewardValue || 0),
|
|
221
|
+
quantityRule: value.quantityRule || 'per_condition_quantity',
|
|
222
|
+
triggerQuantity: Number(value.triggerQuantity || 1),
|
|
223
|
+
rewardQuantity: Number(value.rewardQuantity || 1),
|
|
224
|
+
maxRewardQuantity: value.maxRewardQuantity === undefined || value.maxRewardQuantity === null ? undefined : Number(value.maxRewardQuantity),
|
|
225
|
+
rewardTargets: Array.isArray(config.rewardTargets) ? config.rewardTargets : [],
|
|
226
|
+
targetSelection: config.targetSelection || 'consumer_best'
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
207
230
|
/**
|
|
208
231
|
* 获取适用的商品列表
|
|
209
232
|
*
|
|
@@ -169,6 +169,21 @@ export declare class PromotionEvaluator {
|
|
|
169
169
|
* 支持 bundle 子商品的数量计算(主商品数量 × 子商品数量)
|
|
170
170
|
*/
|
|
171
171
|
private processBuyXGetYFree;
|
|
172
|
+
/**
|
|
173
|
+
* 处理 商品奖励 促销
|
|
174
|
+
*
|
|
175
|
+
* 1. 使用 group.products 统计触发条件商品数量
|
|
176
|
+
* 2. 按 quantityRule 计算最多奖励的目标商品数量
|
|
177
|
+
* 3. 在全购物车商品中筛选 rewardTargets
|
|
178
|
+
* 4. 按消费者最优(可节省金额从高到低)选择目标单位
|
|
179
|
+
* 5. 对目标商品拆分并写入 finalPrice,触发商品本身不改价
|
|
180
|
+
*/
|
|
181
|
+
private processItemReward;
|
|
182
|
+
private normalizePositiveInteger;
|
|
183
|
+
private getAvailablePromotionQuantity;
|
|
184
|
+
private buildItemRewardTargetUnits;
|
|
185
|
+
private resolveItemRewardFinalPrice;
|
|
186
|
+
private resolveItemRewardLimit;
|
|
172
187
|
/**
|
|
173
188
|
* 获取未参与任何促销的商品
|
|
174
189
|
*/
|
|
@@ -194,6 +209,8 @@ export declare class PromotionEvaluator {
|
|
|
194
209
|
* 检查商品是否在策略的适用范围内
|
|
195
210
|
*/
|
|
196
211
|
private isProductInStrategy;
|
|
212
|
+
private shouldSkipStrategyForProduct;
|
|
213
|
+
private hasActionType;
|
|
197
214
|
/**
|
|
198
215
|
* 查找商品匹配规则
|
|
199
216
|
*/
|
|
@@ -178,6 +178,10 @@ export var PromotionEvaluator = /*#__PURE__*/function () {
|
|
|
178
178
|
try {
|
|
179
179
|
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
180
180
|
var config = _step2.value;
|
|
181
|
+
if (this.shouldSkipStrategyForProduct(product, config)) {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
|
|
181
185
|
// 1. 先用 getProductMatchInfo 检查商品是否在策略的适用范围内(包含 bundle 子商品检查)
|
|
182
186
|
var matchInfo = this.getProductMatchInfo(product, config);
|
|
183
187
|
if (!matchInfo.isMatch) {
|
|
@@ -400,6 +404,12 @@ export var PromotionEvaluator = /*#__PURE__*/function () {
|
|
|
400
404
|
if (_result.giftInfo) {
|
|
401
405
|
gifts.push(_result.giftInfo);
|
|
402
406
|
}
|
|
407
|
+
} else if (actionType === PROMOTION_ACTION_TYPES.ITEM_REWARD) {
|
|
408
|
+
// 商品奖励处理:条件商品触发,目标商品行享优惠,不自动新增商品
|
|
409
|
+
var _result2 = this.processItemReward(group, processedQuantityMap, products, matchedBundleIndexMap);
|
|
410
|
+
pricedProducts.push.apply(pricedProducts, _toConsumableArray(_result2.products));
|
|
411
|
+
totalOriginalAmount = totalOriginalAmount.plus(_result2.originalAmount);
|
|
412
|
+
totalFinalAmount = totalFinalAmount.plus(_result2.finalAmount);
|
|
403
413
|
}
|
|
404
414
|
}
|
|
405
415
|
|
|
@@ -530,6 +540,9 @@ export var PromotionEvaluator = /*#__PURE__*/function () {
|
|
|
530
540
|
try {
|
|
531
541
|
for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
|
|
532
542
|
var config = _step8.value;
|
|
543
|
+
if (_this3.shouldSkipStrategyForProduct(product, config)) {
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
533
546
|
var contextProduct = product;
|
|
534
547
|
if (!matchVariant) {
|
|
535
548
|
// 只匹配 product_id,忽略 product_variant_id
|
|
@@ -627,6 +640,9 @@ export var PromotionEvaluator = /*#__PURE__*/function () {
|
|
|
627
640
|
} else if (actionType === 'X_ITEMS_FOR_Y_PRICE') {
|
|
628
641
|
var _detail = actionDetail;
|
|
629
642
|
requiredQuantity = _detail.x || 0;
|
|
643
|
+
} else if (actionType === 'ITEM_REWARD') {
|
|
644
|
+
var _detail2 = actionDetail;
|
|
645
|
+
requiredQuantity = _detail2.triggerQuantity || 1;
|
|
630
646
|
}
|
|
631
647
|
|
|
632
648
|
// 获取可参与商品列表
|
|
@@ -1104,6 +1120,248 @@ export var PromotionEvaluator = /*#__PURE__*/function () {
|
|
|
1104
1120
|
};
|
|
1105
1121
|
}
|
|
1106
1122
|
|
|
1123
|
+
/**
|
|
1124
|
+
* 处理 商品奖励 促销
|
|
1125
|
+
*
|
|
1126
|
+
* 1. 使用 group.products 统计触发条件商品数量
|
|
1127
|
+
* 2. 按 quantityRule 计算最多奖励的目标商品数量
|
|
1128
|
+
* 3. 在全购物车商品中筛选 rewardTargets
|
|
1129
|
+
* 4. 按消费者最优(可节省金额从高到低)选择目标单位
|
|
1130
|
+
* 5. 对目标商品拆分并写入 finalPrice,触发商品本身不改价
|
|
1131
|
+
*/
|
|
1132
|
+
}, {
|
|
1133
|
+
key: "processItemReward",
|
|
1134
|
+
value: function processItemReward(group, processedQuantityMap, allProducts, matchedBundleIndexMap) {
|
|
1135
|
+
var _this4 = this;
|
|
1136
|
+
var strategyId = group.strategyId,
|
|
1137
|
+
strategyMetadata = group.strategyMetadata,
|
|
1138
|
+
actionDetail = group.actionDetail,
|
|
1139
|
+
triggerProducts = group.products;
|
|
1140
|
+
var detail = actionDetail;
|
|
1141
|
+
var triggerQuantity = this.normalizePositiveInteger(detail.triggerQuantity, 1);
|
|
1142
|
+
var rewardQuantity = this.normalizePositiveInteger(detail.rewardQuantity, 1);
|
|
1143
|
+
var conditionQuantity = this.getAvailablePromotionQuantity(triggerProducts, processedQuantityMap, matchedBundleIndexMap);
|
|
1144
|
+
if (conditionQuantity < triggerQuantity) {
|
|
1145
|
+
return {
|
|
1146
|
+
products: [],
|
|
1147
|
+
originalAmount: 0,
|
|
1148
|
+
finalAmount: 0
|
|
1149
|
+
};
|
|
1150
|
+
}
|
|
1151
|
+
var targetProducts = allProducts.filter(function (product) {
|
|
1152
|
+
return _this4.isProductMatch(product, detail.rewardTargets || []);
|
|
1153
|
+
});
|
|
1154
|
+
var targetUnitCandidates = this.buildItemRewardTargetUnits(targetProducts, processedQuantityMap, detail);
|
|
1155
|
+
if (targetUnitCandidates.length === 0) {
|
|
1156
|
+
return {
|
|
1157
|
+
products: [],
|
|
1158
|
+
originalAmount: 0,
|
|
1159
|
+
finalAmount: 0
|
|
1160
|
+
};
|
|
1161
|
+
}
|
|
1162
|
+
var rewardLimit = this.resolveItemRewardLimit(detail, conditionQuantity, triggerQuantity, rewardQuantity, targetUnitCandidates.length);
|
|
1163
|
+
if (rewardLimit <= 0) {
|
|
1164
|
+
return {
|
|
1165
|
+
products: [],
|
|
1166
|
+
originalAmount: 0,
|
|
1167
|
+
finalAmount: 0
|
|
1168
|
+
};
|
|
1169
|
+
}
|
|
1170
|
+
var selectedUnits = _toConsumableArray(targetUnitCandidates).sort(function (a, b) {
|
|
1171
|
+
var discountDiff = b.discountAmount.minus(a.discountAmount).toNumber();
|
|
1172
|
+
if (discountDiff !== 0) return discountDiff;
|
|
1173
|
+
return b.originalPrice.minus(a.originalPrice).toNumber();
|
|
1174
|
+
}).slice(0, rewardLimit);
|
|
1175
|
+
var selectedByProductId = new Map();
|
|
1176
|
+
var _iterator18 = _createForOfIteratorHelper(selectedUnits),
|
|
1177
|
+
_step18;
|
|
1178
|
+
try {
|
|
1179
|
+
for (_iterator18.s(); !(_step18 = _iterator18.n()).done;) {
|
|
1180
|
+
var unit = _step18.value;
|
|
1181
|
+
var existing = selectedByProductId.get(unit.product.id);
|
|
1182
|
+
if (existing) {
|
|
1183
|
+
existing.quantity += 1;
|
|
1184
|
+
} else {
|
|
1185
|
+
selectedByProductId.set(unit.product.id, {
|
|
1186
|
+
quantity: 1,
|
|
1187
|
+
finalPrice: unit.finalPrice,
|
|
1188
|
+
originalPrice: unit.originalPrice
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
} catch (err) {
|
|
1193
|
+
_iterator18.e(err);
|
|
1194
|
+
} finally {
|
|
1195
|
+
_iterator18.f();
|
|
1196
|
+
}
|
|
1197
|
+
var result = [];
|
|
1198
|
+
var originalAmount = new Decimal(0);
|
|
1199
|
+
var finalAmount = new Decimal(0);
|
|
1200
|
+
var _iterator19 = _createForOfIteratorHelper(targetProducts),
|
|
1201
|
+
_step19;
|
|
1202
|
+
try {
|
|
1203
|
+
for (_iterator19.s(); !(_step19 = _iterator19.n()).done;) {
|
|
1204
|
+
var product = _step19.value;
|
|
1205
|
+
var key = this.getProductKey(product);
|
|
1206
|
+
var processedQty = processedQuantityMap.get(key) || 0;
|
|
1207
|
+
var availableQty = product.quantity - processedQty;
|
|
1208
|
+
if (availableQty <= 0) continue;
|
|
1209
|
+
var selected = selectedByProductId.get(product.id);
|
|
1210
|
+
var selectedQty = (selected === null || selected === void 0 ? void 0 : selected.quantity) || 0;
|
|
1211
|
+
var remainingQty = availableQty - selectedQty;
|
|
1212
|
+
if (selectedQty <= 0) continue;
|
|
1213
|
+
if (selectedQty > 0) {
|
|
1214
|
+
result.push(_objectSpread(_objectSpread({}, product), {}, {
|
|
1215
|
+
id: selectedQty === availableQty ? product.id : this.generateRandomId(),
|
|
1216
|
+
originalId: product.id,
|
|
1217
|
+
quantity: selectedQty,
|
|
1218
|
+
finalPrice: this.formatPrice(selected.finalPrice),
|
|
1219
|
+
strategyId: strategyId,
|
|
1220
|
+
strategyMetadata: strategyMetadata,
|
|
1221
|
+
inPromotion: true,
|
|
1222
|
+
isSplit: selectedQty !== product.quantity
|
|
1223
|
+
}));
|
|
1224
|
+
originalAmount = originalAmount.plus(selected.originalPrice.mul(selectedQty));
|
|
1225
|
+
finalAmount = finalAmount.plus(selected.finalPrice.mul(selectedQty));
|
|
1226
|
+
}
|
|
1227
|
+
if (remainingQty > 0) {
|
|
1228
|
+
result.push(_objectSpread(_objectSpread({}, product), {}, {
|
|
1229
|
+
quantity: remainingQty,
|
|
1230
|
+
finalPrice: this.formatPrice(product.price),
|
|
1231
|
+
strategyId: undefined,
|
|
1232
|
+
strategyMetadata: undefined,
|
|
1233
|
+
inPromotion: false,
|
|
1234
|
+
isSplit: selectedQty > 0
|
|
1235
|
+
}));
|
|
1236
|
+
var remainingAmount = new Decimal(product.price).mul(remainingQty);
|
|
1237
|
+
originalAmount = originalAmount.plus(remainingAmount);
|
|
1238
|
+
finalAmount = finalAmount.plus(remainingAmount);
|
|
1239
|
+
}
|
|
1240
|
+
processedQuantityMap.set(key, processedQty + availableQty);
|
|
1241
|
+
}
|
|
1242
|
+
} catch (err) {
|
|
1243
|
+
_iterator19.e(err);
|
|
1244
|
+
} finally {
|
|
1245
|
+
_iterator19.f();
|
|
1246
|
+
}
|
|
1247
|
+
return {
|
|
1248
|
+
products: result,
|
|
1249
|
+
originalAmount: originalAmount.toNumber(),
|
|
1250
|
+
finalAmount: finalAmount.toNumber()
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
}, {
|
|
1254
|
+
key: "normalizePositiveInteger",
|
|
1255
|
+
value: function normalizePositiveInteger(value, fallback) {
|
|
1256
|
+
var n = Math.floor(Number(value));
|
|
1257
|
+
return Number.isFinite(n) && n > 0 ? n : fallback;
|
|
1258
|
+
}
|
|
1259
|
+
}, {
|
|
1260
|
+
key: "getAvailablePromotionQuantity",
|
|
1261
|
+
value: function getAvailablePromotionQuantity(products, processedQuantityMap, matchedBundleIndexMap) {
|
|
1262
|
+
var total = 0;
|
|
1263
|
+
var _iterator20 = _createForOfIteratorHelper(products),
|
|
1264
|
+
_step20;
|
|
1265
|
+
try {
|
|
1266
|
+
for (_iterator20.s(); !(_step20 = _iterator20.n()).done;) {
|
|
1267
|
+
var product = _step20.value;
|
|
1268
|
+
var key = this.getProductKey(product);
|
|
1269
|
+
var processedQty = processedQuantityMap.get(key) || 0;
|
|
1270
|
+
var availableQty = product.quantity - processedQty;
|
|
1271
|
+
if (availableQty <= 0) continue;
|
|
1272
|
+
var matchedBundleIndex = matchedBundleIndexMap === null || matchedBundleIndexMap === void 0 ? void 0 : matchedBundleIndexMap.get(product.id);
|
|
1273
|
+
if (matchedBundleIndex !== undefined && product.bundle) {
|
|
1274
|
+
var bundleItem = product.bundle[matchedBundleIndex];
|
|
1275
|
+
total += availableQty * ((bundleItem === null || bundleItem === void 0 ? void 0 : bundleItem.quantity) || 1);
|
|
1276
|
+
} else {
|
|
1277
|
+
total += availableQty;
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
} catch (err) {
|
|
1281
|
+
_iterator20.e(err);
|
|
1282
|
+
} finally {
|
|
1283
|
+
_iterator20.f();
|
|
1284
|
+
}
|
|
1285
|
+
return total;
|
|
1286
|
+
}
|
|
1287
|
+
}, {
|
|
1288
|
+
key: "buildItemRewardTargetUnits",
|
|
1289
|
+
value: function buildItemRewardTargetUnits(products, processedQuantityMap, detail) {
|
|
1290
|
+
var units = [];
|
|
1291
|
+
var _iterator21 = _createForOfIteratorHelper(products),
|
|
1292
|
+
_step21;
|
|
1293
|
+
try {
|
|
1294
|
+
for (_iterator21.s(); !(_step21 = _iterator21.n()).done;) {
|
|
1295
|
+
var product = _step21.value;
|
|
1296
|
+
var key = this.getProductKey(product);
|
|
1297
|
+
var processedQty = processedQuantityMap.get(key) || 0;
|
|
1298
|
+
var availableQty = product.quantity - processedQty;
|
|
1299
|
+
if (availableQty <= 0) continue;
|
|
1300
|
+
var originalPrice = new Decimal(product.price || 0);
|
|
1301
|
+
var finalPrice = this.resolveItemRewardFinalPrice(originalPrice, detail);
|
|
1302
|
+
var discountAmount = originalPrice.minus(finalPrice);
|
|
1303
|
+
if (discountAmount.lte(0)) continue;
|
|
1304
|
+
for (var i = 0; i < availableQty; i++) {
|
|
1305
|
+
units.push({
|
|
1306
|
+
product: product,
|
|
1307
|
+
originalPrice: originalPrice,
|
|
1308
|
+
finalPrice: finalPrice,
|
|
1309
|
+
discountAmount: discountAmount
|
|
1310
|
+
});
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
} catch (err) {
|
|
1314
|
+
_iterator21.e(err);
|
|
1315
|
+
} finally {
|
|
1316
|
+
_iterator21.f();
|
|
1317
|
+
}
|
|
1318
|
+
return units;
|
|
1319
|
+
}
|
|
1320
|
+
}, {
|
|
1321
|
+
key: "resolveItemRewardFinalPrice",
|
|
1322
|
+
value: function resolveItemRewardFinalPrice(originalPrice, detail) {
|
|
1323
|
+
var rewardValue = new Decimal(Number(detail.rewardValue) || 0);
|
|
1324
|
+
var finalPrice;
|
|
1325
|
+
switch (detail.rewardMethod) {
|
|
1326
|
+
case 'percent_off':
|
|
1327
|
+
{
|
|
1328
|
+
var percent = Decimal.min(100, Decimal.max(0, rewardValue));
|
|
1329
|
+
finalPrice = originalPrice.mul(new Decimal(100).minus(percent)).div(100);
|
|
1330
|
+
break;
|
|
1331
|
+
}
|
|
1332
|
+
case 'amount_off':
|
|
1333
|
+
finalPrice = originalPrice.minus(Decimal.max(0, rewardValue));
|
|
1334
|
+
break;
|
|
1335
|
+
case 'fixed_price':
|
|
1336
|
+
finalPrice = Decimal.max(0, rewardValue);
|
|
1337
|
+
break;
|
|
1338
|
+
case 'free':
|
|
1339
|
+
default:
|
|
1340
|
+
finalPrice = new Decimal(0);
|
|
1341
|
+
break;
|
|
1342
|
+
}
|
|
1343
|
+
return Decimal.max(0, Decimal.min(originalPrice, finalPrice)).toDecimalPlaces(2, Decimal.ROUND_HALF_UP);
|
|
1344
|
+
}
|
|
1345
|
+
}, {
|
|
1346
|
+
key: "resolveItemRewardLimit",
|
|
1347
|
+
value: function resolveItemRewardLimit(detail, conditionQuantity, triggerQuantity, rewardQuantity, targetUnitCount) {
|
|
1348
|
+
var _detail$maxRewardQuan;
|
|
1349
|
+
var limit = 0;
|
|
1350
|
+
switch (detail.quantityRule) {
|
|
1351
|
+
case 'all_targets':
|
|
1352
|
+
limit = targetUnitCount;
|
|
1353
|
+
break;
|
|
1354
|
+
case 'max_per_order':
|
|
1355
|
+
limit = this.normalizePositiveInteger((_detail$maxRewardQuan = detail.maxRewardQuantity) !== null && _detail$maxRewardQuan !== void 0 ? _detail$maxRewardQuan : detail.rewardQuantity, rewardQuantity);
|
|
1356
|
+
break;
|
|
1357
|
+
case 'per_condition_quantity':
|
|
1358
|
+
default:
|
|
1359
|
+
limit = Math.floor(conditionQuantity / triggerQuantity) * rewardQuantity;
|
|
1360
|
+
break;
|
|
1361
|
+
}
|
|
1362
|
+
return Math.min(Math.max(0, limit), targetUnitCount);
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1107
1365
|
/**
|
|
1108
1366
|
* 获取未参与任何促销的商品
|
|
1109
1367
|
*/
|
|
@@ -1111,11 +1369,11 @@ export var PromotionEvaluator = /*#__PURE__*/function () {
|
|
|
1111
1369
|
key: "getRemainingProducts",
|
|
1112
1370
|
value: function getRemainingProducts(allProducts, processedQuantityMap) {
|
|
1113
1371
|
var result = [];
|
|
1114
|
-
var
|
|
1115
|
-
|
|
1372
|
+
var _iterator22 = _createForOfIteratorHelper(allProducts),
|
|
1373
|
+
_step22;
|
|
1116
1374
|
try {
|
|
1117
|
-
for (
|
|
1118
|
-
var product =
|
|
1375
|
+
for (_iterator22.s(); !(_step22 = _iterator22.n()).done;) {
|
|
1376
|
+
var product = _step22.value;
|
|
1119
1377
|
var key = this.getProductKey(product);
|
|
1120
1378
|
var processedQty = processedQuantityMap.get(key) || 0;
|
|
1121
1379
|
var remainingQty = product.quantity - processedQty;
|
|
@@ -1130,9 +1388,9 @@ export var PromotionEvaluator = /*#__PURE__*/function () {
|
|
|
1130
1388
|
}
|
|
1131
1389
|
}
|
|
1132
1390
|
} catch (err) {
|
|
1133
|
-
|
|
1391
|
+
_iterator22.e(err);
|
|
1134
1392
|
} finally {
|
|
1135
|
-
|
|
1393
|
+
_iterator22.f();
|
|
1136
1394
|
}
|
|
1137
1395
|
return result;
|
|
1138
1396
|
}
|
|
@@ -1210,8 +1468,23 @@ export var PromotionEvaluator = /*#__PURE__*/function () {
|
|
|
1210
1468
|
}, {
|
|
1211
1469
|
key: "isProductInStrategy",
|
|
1212
1470
|
value: function isProductInStrategy(product, config) {
|
|
1471
|
+
if (this.shouldSkipStrategyForProduct(product, config)) {
|
|
1472
|
+
return false;
|
|
1473
|
+
}
|
|
1213
1474
|
return this.getProductMatchInfo(product, config).isMatch;
|
|
1214
1475
|
}
|
|
1476
|
+
}, {
|
|
1477
|
+
key: "shouldSkipStrategyForProduct",
|
|
1478
|
+
value: function shouldSkipStrategyForProduct(product, config) {
|
|
1479
|
+
return Boolean(product._promotionOnlyForItemReward) && !this.hasActionType(config, PROMOTION_ACTION_TYPES.ITEM_REWARD);
|
|
1480
|
+
}
|
|
1481
|
+
}, {
|
|
1482
|
+
key: "hasActionType",
|
|
1483
|
+
value: function hasActionType(config, actionType) {
|
|
1484
|
+
return (config.actions || []).some(function (action) {
|
|
1485
|
+
return (action === null || action === void 0 ? void 0 : action.type) === actionType;
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1215
1488
|
|
|
1216
1489
|
/**
|
|
1217
1490
|
* 查找商品匹配规则
|
|
@@ -136,3 +136,89 @@ export declare const BUY_X_GET_Y_FREE_STRATEGY: {
|
|
|
136
136
|
};
|
|
137
137
|
}[];
|
|
138
138
|
};
|
|
139
|
+
/**
|
|
140
|
+
* ITEM_REWARD 策略配置示例:儿童票触发婴儿票免费
|
|
141
|
+
*
|
|
142
|
+
* 业务规则:
|
|
143
|
+
* - 条件商品:儿童票(conditions.rules.productIdAndVariantId)
|
|
144
|
+
* - 奖励商品:购物车/订单内已经存在的婴儿票(actions[0].config.rewardTargets)
|
|
145
|
+
* - 本 action 不自动新增婴儿票;每次购物车变更后由统一促销链路重算
|
|
146
|
+
*
|
|
147
|
+
* 字段说明:
|
|
148
|
+
* - type: "ITEM_REWARD" 表示商品奖励 action
|
|
149
|
+
* - target: "product" 表示本期只奖励商品行
|
|
150
|
+
* - config.rewardTargets: 奖励对象数组,支持 { product_id, product_variant_id }
|
|
151
|
+
* - config.targetSelection: "consumer_best" 表示目标商品超额时选择节省金额最高的商品
|
|
152
|
+
* - value.rewardMethod:
|
|
153
|
+
* - "free": 目标商品最终价为 0
|
|
154
|
+
* - "percent_off": 百分比折扣,rewardValue 为 0-100
|
|
155
|
+
* - "amount_off": 每个目标商品固定减免 rewardValue
|
|
156
|
+
* - "fixed_price": 目标商品最终单价为 rewardValue
|
|
157
|
+
* - value.quantityRule:
|
|
158
|
+
* - "per_condition_quantity": 每满足 triggerQuantity 个条件商品,奖励 rewardQuantity 个目标商品
|
|
159
|
+
* - "all_targets": 满足条件后奖励全部目标商品
|
|
160
|
+
* - "max_per_order": 满足条件后每单最多奖励 maxRewardQuantity 个目标商品
|
|
161
|
+
*/
|
|
162
|
+
export declare const ITEM_REWARD_STRATEGY: {
|
|
163
|
+
metadata: {
|
|
164
|
+
id: string;
|
|
165
|
+
name: {
|
|
166
|
+
en: string;
|
|
167
|
+
'zh-CN': string;
|
|
168
|
+
'zh-HK': string;
|
|
169
|
+
};
|
|
170
|
+
type: string;
|
|
171
|
+
custom: {
|
|
172
|
+
display: {
|
|
173
|
+
product_card: {
|
|
174
|
+
text: {
|
|
175
|
+
en: string;
|
|
176
|
+
'zh-CN': string;
|
|
177
|
+
'zh-HK': string;
|
|
178
|
+
};
|
|
179
|
+
type: string;
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
conditions: {
|
|
185
|
+
operator: string;
|
|
186
|
+
rules: ({
|
|
187
|
+
type: string;
|
|
188
|
+
field: string;
|
|
189
|
+
value: string;
|
|
190
|
+
operator: string;
|
|
191
|
+
} | {
|
|
192
|
+
type: string;
|
|
193
|
+
field: string;
|
|
194
|
+
value: {
|
|
195
|
+
product_id: number;
|
|
196
|
+
product_variant_id: number;
|
|
197
|
+
}[];
|
|
198
|
+
operator: string;
|
|
199
|
+
})[];
|
|
200
|
+
actionIds: string[];
|
|
201
|
+
};
|
|
202
|
+
actions: {
|
|
203
|
+
id: string;
|
|
204
|
+
type: string;
|
|
205
|
+
value: {
|
|
206
|
+
rewardMethod: string;
|
|
207
|
+
rewardValue: number;
|
|
208
|
+
quantityRule: string;
|
|
209
|
+
triggerQuantity: number;
|
|
210
|
+
rewardQuantity: number;
|
|
211
|
+
maxRewardQuantity: number;
|
|
212
|
+
};
|
|
213
|
+
valueType: string;
|
|
214
|
+
target: string;
|
|
215
|
+
priority: number;
|
|
216
|
+
config: {
|
|
217
|
+
rewardTargets: {
|
|
218
|
+
product_id: number;
|
|
219
|
+
product_variant_id: number;
|
|
220
|
+
}[];
|
|
221
|
+
targetSelection: string;
|
|
222
|
+
};
|
|
223
|
+
}[];
|
|
224
|
+
};
|
|
@@ -163,4 +163,103 @@ export var BUY_X_GET_Y_FREE_STRATEGY = {
|
|
|
163
163
|
}]
|
|
164
164
|
}
|
|
165
165
|
}]
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* ITEM_REWARD 策略配置示例:儿童票触发婴儿票免费
|
|
170
|
+
*
|
|
171
|
+
* 业务规则:
|
|
172
|
+
* - 条件商品:儿童票(conditions.rules.productIdAndVariantId)
|
|
173
|
+
* - 奖励商品:购物车/订单内已经存在的婴儿票(actions[0].config.rewardTargets)
|
|
174
|
+
* - 本 action 不自动新增婴儿票;每次购物车变更后由统一促销链路重算
|
|
175
|
+
*
|
|
176
|
+
* 字段说明:
|
|
177
|
+
* - type: "ITEM_REWARD" 表示商品奖励 action
|
|
178
|
+
* - target: "product" 表示本期只奖励商品行
|
|
179
|
+
* - config.rewardTargets: 奖励对象数组,支持 { product_id, product_variant_id }
|
|
180
|
+
* - config.targetSelection: "consumer_best" 表示目标商品超额时选择节省金额最高的商品
|
|
181
|
+
* - value.rewardMethod:
|
|
182
|
+
* - "free": 目标商品最终价为 0
|
|
183
|
+
* - "percent_off": 百分比折扣,rewardValue 为 0-100
|
|
184
|
+
* - "amount_off": 每个目标商品固定减免 rewardValue
|
|
185
|
+
* - "fixed_price": 目标商品最终单价为 rewardValue
|
|
186
|
+
* - value.quantityRule:
|
|
187
|
+
* - "per_condition_quantity": 每满足 triggerQuantity 个条件商品,奖励 rewardQuantity 个目标商品
|
|
188
|
+
* - "all_targets": 满足条件后奖励全部目标商品
|
|
189
|
+
* - "max_per_order": 满足条件后每单最多奖励 maxRewardQuantity 个目标商品
|
|
190
|
+
*/
|
|
191
|
+
export var ITEM_REWARD_STRATEGY = {
|
|
192
|
+
metadata: {
|
|
193
|
+
id: 'STRATEGY_003',
|
|
194
|
+
name: {
|
|
195
|
+
en: 'Infant ticket free with child ticket',
|
|
196
|
+
'zh-CN': '儿童票触发婴儿票免费',
|
|
197
|
+
'zh-HK': '兒童票觸發嬰兒票免費'
|
|
198
|
+
},
|
|
199
|
+
type: 'promotion',
|
|
200
|
+
custom: {
|
|
201
|
+
display: {
|
|
202
|
+
product_card: {
|
|
203
|
+
text: {
|
|
204
|
+
en: 'Infant ticket free',
|
|
205
|
+
'zh-CN': '婴儿票免费',
|
|
206
|
+
'zh-HK': '嬰兒票免費'
|
|
207
|
+
},
|
|
208
|
+
type: 'tag'
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
conditions: {
|
|
214
|
+
operator: 'and',
|
|
215
|
+
rules: [{
|
|
216
|
+
type: 'operator',
|
|
217
|
+
field: 'currentDateTime',
|
|
218
|
+
value: '2023-01-01 00:00:00',
|
|
219
|
+
operator: '>='
|
|
220
|
+
}, {
|
|
221
|
+
type: 'operator',
|
|
222
|
+
field: 'currentDateTime',
|
|
223
|
+
value: '2030-01-01 00:00:00',
|
|
224
|
+
operator: '<='
|
|
225
|
+
}, {
|
|
226
|
+
type: 'operator',
|
|
227
|
+
field: 'productIdAndVariantId',
|
|
228
|
+
value: [{
|
|
229
|
+
product_id: 1001,
|
|
230
|
+
// 条件商品:儿童票
|
|
231
|
+
product_variant_id: 0 // 0 = 匹配任意变体
|
|
232
|
+
}],
|
|
233
|
+
operator: 'product_match'
|
|
234
|
+
}],
|
|
235
|
+
actionIds: ['1']
|
|
236
|
+
},
|
|
237
|
+
actions: [{
|
|
238
|
+
id: '1',
|
|
239
|
+
type: 'ITEM_REWARD',
|
|
240
|
+
value: {
|
|
241
|
+
rewardMethod: 'free',
|
|
242
|
+
// free | percent_off | amount_off | fixed_price
|
|
243
|
+
rewardValue: 0,
|
|
244
|
+
// free 可省略;其他 rewardMethod 使用
|
|
245
|
+
quantityRule: 'per_condition_quantity',
|
|
246
|
+
// per_condition_quantity | all_targets | max_per_order
|
|
247
|
+
triggerQuantity: 1,
|
|
248
|
+
// N:每满足 N 个条件商品
|
|
249
|
+
rewardQuantity: 1,
|
|
250
|
+
// Y:奖励 Y 个目标商品
|
|
251
|
+
maxRewardQuantity: 1 // max_per_order 使用;本例保留为配置示意
|
|
252
|
+
},
|
|
253
|
+
valueType: 'object',
|
|
254
|
+
target: 'product',
|
|
255
|
+
priority: 1,
|
|
256
|
+
config: {
|
|
257
|
+
rewardTargets: [{
|
|
258
|
+
product_id: 2001,
|
|
259
|
+
// 奖励对象:婴儿票
|
|
260
|
+
product_variant_id: 0 // 0 = 匹配任意变体
|
|
261
|
+
}],
|
|
262
|
+
targetSelection: 'consumer_best' // consumer_best = 按可节省金额从高到低选择
|
|
263
|
+
}
|
|
264
|
+
}]
|
|
166
265
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { PromotionEvaluator } from './evaluator';
|
|
2
2
|
export { PromotionAdapter } from './adapter';
|
|
3
3
|
export { default } from './adapter';
|
|
4
|
-
export { X_ITEMS_FOR_Y_PRICE_STRATEGY, BUY_X_GET_Y_FREE_STRATEGY, } from './examples';
|
|
4
|
+
export { X_ITEMS_FOR_Y_PRICE_STRATEGY, BUY_X_GET_Y_FREE_STRATEGY, ITEM_REWARD_STRATEGY, } from './examples';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// 导出评估器
|
|
2
|
+
export { PromotionEvaluator } from "./evaluator";
|
|
3
|
+
|
|
4
|
+
// 导出适配器
|
|
5
|
+
export { PromotionAdapter } from "./adapter";
|
|
6
|
+
export { default } from "./adapter";
|
|
7
|
+
|
|
8
|
+
// 导出策略配置示例常量
|
|
9
|
+
export { X_ITEMS_FOR_Y_PRICE_STRATEGY, BUY_X_GET_Y_FREE_STRATEGY, ITEM_REWARD_STRATEGY } from "./examples";
|