@pisell/pisellos 2.2.265 → 2.2.266
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/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 +0 -9
- package/dist/model/strategy/adapter/promotion/type.d.ts +90 -2
- package/dist/model/strategy/adapter/promotion/type.js +45 -0
- package/dist/modules/Order/index.js +10 -3
- package/dist/modules/Order/utils.js +2 -1
- package/dist/modules/Rules/index.d.ts +1 -0
- package/dist/modules/Rules/index.js +34 -14
- package/dist/solution/BaseSales/index.d.ts +14 -1
- package/dist/solution/BaseSales/index.js +36 -12
- package/dist/solution/BaseSales/utils/cartPromotion.d.ts +3 -1
- package/dist/solution/BaseSales/utils/cartPromotion.js +90 -31
- package/dist/solution/BookingTicket/index.js +33 -28
- package/dist/solution/ScanOrder/index.js +31 -20
- package/dist/solution/VenueBooking/index.js +30 -19
- 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 +2 -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/Order/index.js +9 -3
- package/lib/modules/Order/utils.js +6 -1
- package/lib/modules/Rules/index.d.ts +1 -0
- package/lib/modules/Rules/index.js +23 -4
- package/lib/solution/BaseSales/index.d.ts +14 -1
- package/lib/solution/BaseSales/index.js +22 -1
- package/lib/solution/BaseSales/utils/cartPromotion.d.ts +3 -1
- package/lib/solution/BaseSales/utils/cartPromotion.js +63 -12
- package/lib/solution/BookingTicket/index.js +4 -2
- package/lib/solution/ScanOrder/index.js +8 -0
- package/lib/solution/VenueBooking/index.js +8 -0
- package/package.json +1 -1
|
@@ -28,6 +28,8 @@ var PROMOTION_ACTION_TYPES = {
|
|
|
28
28
|
X_ITEMS_FOR_Y_PRICE: "X_ITEMS_FOR_Y_PRICE",
|
|
29
29
|
/** 买X送Y(买X件送Y件,可累计) */
|
|
30
30
|
BUY_X_GET_Y_FREE: "BUY_X_GET_Y_FREE",
|
|
31
|
+
/** 商品奖励(满足条件后,订单内指定目标商品享优惠) */
|
|
32
|
+
ITEM_REWARD: "ITEM_REWARD",
|
|
31
33
|
/** 固定折扣 */
|
|
32
34
|
DISCOUNT_RATE: "DISCOUNT_RATE",
|
|
33
35
|
/** 固定减价 */
|
|
@@ -85,6 +85,11 @@ function isPaidPaymentRecord(payment) {
|
|
|
85
85
|
function isCommittedVoucherPaymentRecord(payment) {
|
|
86
86
|
return isVoucherPaymentRecord(payment) && (payment == null ? void 0 : payment.status) !== "voided" && (hasSyncedOrderPaymentRecord(payment) || isPaidPaymentRecord(payment));
|
|
87
87
|
}
|
|
88
|
+
function getVoucherPaymentLifecycleKey(payment) {
|
|
89
|
+
if (!isVoucherPaymentRecord(payment))
|
|
90
|
+
return null;
|
|
91
|
+
return `${String(payment.voucher_id)}::${String(payment.status || "")}`;
|
|
92
|
+
}
|
|
88
93
|
var OrderModule = class extends import_BaseModule.BaseModule {
|
|
89
94
|
constructor(name, version) {
|
|
90
95
|
super(name || "order", version);
|
|
@@ -2746,14 +2751,15 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
2746
2751
|
const committedVoucherPaymentIds = new Set(
|
|
2747
2752
|
committedVoucherPayments.filter((payment) => hasSyncedOrderPaymentRecord(payment)).map((payment) => String(payment.order_payment_id))
|
|
2748
2753
|
);
|
|
2749
|
-
const
|
|
2750
|
-
committedVoucherPayments.map((payment) =>
|
|
2754
|
+
const committedVoucherLifecycleKeys = new Set(
|
|
2755
|
+
committedVoucherPayments.map((payment) => getVoucherPaymentLifecycleKey(payment)).filter((key) => key !== null)
|
|
2751
2756
|
);
|
|
2752
2757
|
const replaceableVouchers = mappedVouchers.filter((payment) => {
|
|
2753
2758
|
if (hasSyncedOrderPaymentRecord(payment) && committedVoucherPaymentIds.has(String(payment.order_payment_id))) {
|
|
2754
2759
|
return false;
|
|
2755
2760
|
}
|
|
2756
|
-
|
|
2761
|
+
const lifecycleKey = getVoucherPaymentLifecycleKey(payment);
|
|
2762
|
+
if (lifecycleKey && committedVoucherLifecycleKeys.has(lifecycleKey)) {
|
|
2757
2763
|
return false;
|
|
2758
2764
|
}
|
|
2759
2765
|
return true;
|
|
@@ -444,7 +444,12 @@ function resolveEffectivePerUnitDiscount(product) {
|
|
|
444
444
|
(sum, discount) => sum + Number((discount == null ? void 0 : discount.amount) || 0),
|
|
445
445
|
0
|
|
446
446
|
);
|
|
447
|
-
const hasPromoDiscountItem = discountList.some(
|
|
447
|
+
const hasPromoDiscountItem = discountList.some(
|
|
448
|
+
(item) => {
|
|
449
|
+
var _a, _b;
|
|
450
|
+
return (item == null ? void 0 : item.type) === "promotion" || (item == null ? void 0 : item.type) === "product" && ((_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a.source) === "promotion" && ((_b = item == null ? void 0 : item.metadata) == null ? void 0 : _b.actionType) === "ITEM_REWARD";
|
|
451
|
+
}
|
|
452
|
+
);
|
|
448
453
|
if (hasPromoDiscountItem)
|
|
449
454
|
return fromList;
|
|
450
455
|
const metadata = (product == null ? void 0 : product.metadata) || {};
|
|
@@ -35,6 +35,7 @@ export declare class RulesModule extends BaseModule implements Module, RulesModu
|
|
|
35
35
|
excludeDiscountListByType(discountList: Discount[], type: string): Discount[];
|
|
36
36
|
/** 手动改价场景:去掉 promotion,保留 type=product 等行内折扣 */
|
|
37
37
|
resolveDiscountListForManualOverride(discountList: Discount[]): Discount[];
|
|
38
|
+
private isItemRewardProductDiscount;
|
|
38
39
|
private getUnavailableReason;
|
|
39
40
|
calcDiscount({ discountList, productList, holders, isFormSubject, orderTotalAmount }: {
|
|
40
41
|
discountList: Discount[];
|
|
@@ -167,6 +167,16 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
167
167
|
resolveDiscountListForManualOverride(discountList) {
|
|
168
168
|
return this.excludeDiscountListByType(discountList, "promotion");
|
|
169
169
|
}
|
|
170
|
+
isItemRewardProductDiscount(product) {
|
|
171
|
+
var _a;
|
|
172
|
+
const discountList = Array.isArray(product == null ? void 0 : product.discount_list) ? product.discount_list : [];
|
|
173
|
+
return ((_a = product == null ? void 0 : product._promotion) == null ? void 0 : _a.actionType) === "ITEM_REWARD" && discountList.some(
|
|
174
|
+
(item) => {
|
|
175
|
+
var _a2, _b;
|
|
176
|
+
return (item == null ? void 0 : item.type) === "product" && ((_a2 = item == null ? void 0 : item.metadata) == null ? void 0 : _a2.source) === "promotion" && ((_b = item == null ? void 0 : item.metadata) == null ? void 0 : _b.actionType) === "ITEM_REWARD";
|
|
177
|
+
}
|
|
178
|
+
);
|
|
179
|
+
}
|
|
170
180
|
// 获取券不可用的原因
|
|
171
181
|
getUnavailableReason(discountList, productList) {
|
|
172
182
|
var _a;
|
|
@@ -500,6 +510,9 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
500
510
|
startDate: (_a2 = flatItem.parentProduct) == null ? void 0 : _a2.startDate
|
|
501
511
|
};
|
|
502
512
|
}
|
|
513
|
+
if (this.isItemRewardProductDiscount(product)) {
|
|
514
|
+
return false;
|
|
515
|
+
}
|
|
503
516
|
const isAvailableProduct = flatItem.type === "main" ? !((product == null ? void 0 : product.booking_id) && ((_b = product == null ? void 0 : product.discount_list) == null ? void 0 : _b.length) && ((_c = product == null ? void 0 : product.discount_list) == null ? void 0 : _c.every((d) => d.id && ["good_pass", "discount_card", "product_discount_card"].includes(d.tag || d.type)))) : !((flatItem == null ? void 0 : flatItem.booking_id) && !!((_e = (_d = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _d.discount_list) == null ? void 0 : _e.length) && ((_g = (_f = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _f.discount_list) == null ? void 0 : _g.every((d) => d.id)));
|
|
504
517
|
if (!isAvailableProduct) {
|
|
505
518
|
return false;
|
|
@@ -625,6 +638,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
625
638
|
};
|
|
626
639
|
originProduct = flatItem.originProduct;
|
|
627
640
|
}
|
|
641
|
+
const isItemRewardProductDiscount = this.isItemRewardProductDiscount(product);
|
|
628
642
|
addModeDiscount.forEach((discount) => {
|
|
629
643
|
var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
630
644
|
const limitedData = discount == null ? void 0 : discount.limited_relation_product_data;
|
|
@@ -648,7 +662,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
648
662
|
].includes(discount2.tag || discount2.type)
|
|
649
663
|
))) : !((flatItem == null ? void 0 : flatItem.booking_id) && !!((_d = (_c = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _c.discount_list) == null ? void 0 : _d.length) && ((_f = (_e = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _e.discount_list) == null ? void 0 : _f.every((discount2) => discount2.id)));
|
|
650
664
|
const isBundleAvailable = this.checkPackageSubItemUsageRules(discount, flatItem);
|
|
651
|
-
if (isAvailableProduct && isLimitedProduct && timeLimit && isBundleAvailable && ((_g = discount.config) == null ? void 0 : _g.isAvailable)) {
|
|
665
|
+
if (isAvailableProduct && !isItemRewardProductDiscount && isLimitedProduct && timeLimit && isBundleAvailable && ((_g = discount.config) == null ? void 0 : _g.isAvailable)) {
|
|
652
666
|
(_h = discountApplicability.get(discount.id)) == null ? void 0 : _h.push(product.id);
|
|
653
667
|
const applicableProducts = discountApplicableProducts.get(discount.id) || [];
|
|
654
668
|
const discountType = discount.tag || discount.type;
|
|
@@ -771,6 +785,8 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
771
785
|
}
|
|
772
786
|
const applicableDiscounts = sortedDiscountList.filter((discount) => {
|
|
773
787
|
var _a3, _b2, _c2, _d2;
|
|
788
|
+
if (this.isItemRewardProductDiscount(product))
|
|
789
|
+
return false;
|
|
774
790
|
const discountType = discount.tag || discount.type;
|
|
775
791
|
const currentOriginUid = getOriginProductUid(originProduct);
|
|
776
792
|
const isReapplyEditModeDiscountForProduct = discount.isEditMode && reapplyBookingDiscountProductUids.size > 0 && currentOriginUid && reapplyBookingDiscountProductUids.has(String(currentOriginUid)) && discount.isSelected === true;
|
|
@@ -845,6 +861,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
845
861
|
);
|
|
846
862
|
const selectedDiscount = selectedDiscountCard || applicableDiscounts[0];
|
|
847
863
|
let isManualDiscount = false;
|
|
864
|
+
let isItemRewardProductDiscount = false;
|
|
848
865
|
if (flatItem.type === "main") {
|
|
849
866
|
isManualDiscount = typeof product.isManualDiscount === "boolean" ? product.isManualDiscount : ((_g = product.discount_list) == null ? void 0 : _g.some((item) => item.type === "product")) || product.total != product.origin_total && (product.bundle || []).every(
|
|
850
867
|
(item) => {
|
|
@@ -855,7 +872,8 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
855
872
|
_i,
|
|
856
873
|
(item) => item.type === "product"
|
|
857
874
|
)));
|
|
858
|
-
|
|
875
|
+
isItemRewardProductDiscount = this.isItemRewardProductDiscount(product);
|
|
876
|
+
if (product.inPromotion && !isItemRewardProductDiscount) {
|
|
859
877
|
isManualDiscount = false;
|
|
860
878
|
}
|
|
861
879
|
} else {
|
|
@@ -969,7 +987,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
969
987
|
} else {
|
|
970
988
|
let total = product.inPromotion ? ((_w = product == null ? void 0 : product._promotion) == null ? void 0 : _w.finalPrice) ?? product.origin_total ?? product.total : product.origin_total ?? product.total;
|
|
971
989
|
let main_product_selling_price = product.price;
|
|
972
|
-
if ((product.discount_list || []).some((item) => item.type === "promotion") || (0, import_lodash_es.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
|
|
990
|
+
if ((product.discount_list || []).some((item) => item.type === "promotion") || isItemRewardProductDiscount || (0, import_lodash_es.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
|
|
973
991
|
total = product.total ?? product.origin_total;
|
|
974
992
|
main_product_selling_price = product.main_product_selling_price ?? main_product_selling_price;
|
|
975
993
|
}
|
|
@@ -977,7 +995,8 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
977
995
|
this.hooks.setProduct(originProduct, {
|
|
978
996
|
...isManualDiscount ? {
|
|
979
997
|
price: product.price,
|
|
980
|
-
main_product_selling_price: product.price
|
|
998
|
+
main_product_selling_price: isItemRewardProductDiscount ? main_product_selling_price : product.price,
|
|
999
|
+
...isItemRewardProductDiscount ? { total } : {}
|
|
981
1000
|
} : {
|
|
982
1001
|
_id: product._id.split("___")[0] + "___" + index,
|
|
983
1002
|
total,
|
|
@@ -48,6 +48,11 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
48
48
|
protected store: BaseSalesState;
|
|
49
49
|
protected otherParams: Record<string, any>;
|
|
50
50
|
protected cacheId: string | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* 由已在初始化阶段解析过设备短号的业务解决方案写入。
|
|
53
|
+
* 未设置时,支付编号仍按原逻辑实时读取设备信息。
|
|
54
|
+
*/
|
|
55
|
+
protected paymentNumberDevicePrefix: string | null;
|
|
51
56
|
/**
|
|
52
57
|
* window / request 暴露为 public:现存外部工具(如 BookingTicket Scan)通过
|
|
53
58
|
* `solution.window` / `solution.request` 直接访问插件,保持原有契约不破坏。
|
|
@@ -141,6 +146,11 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
141
146
|
*/
|
|
142
147
|
protected readSessionCacheData(): Record<string, any>;
|
|
143
148
|
protected getAppData<T>(key: string): T | undefined;
|
|
149
|
+
/**
|
|
150
|
+
* 复用业务解决方案初始化时已解析的支付设备短号。
|
|
151
|
+
* 空值会清除缓存,使后续支付恢复实时读取设备信息的兼容路径。
|
|
152
|
+
*/
|
|
153
|
+
protected setPaymentNumberDevicePrefix(prefix: unknown): void;
|
|
144
154
|
private getPaymentNumberDevicePrefixSync;
|
|
145
155
|
private getPaymentNumberDevicePrefixAsync;
|
|
146
156
|
private syncAppDataToTempOrder;
|
|
@@ -284,7 +294,10 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
284
294
|
* 同步兼容入口。无法等待 IoT 短号时,按调用当下的 device_id 或 LOCAL 生成。
|
|
285
295
|
*/
|
|
286
296
|
addOrderPayment(payment: OrderPaymentSource): OrderPaymentData[];
|
|
287
|
-
/**
|
|
297
|
+
/**
|
|
298
|
+
* 创建新支付项时优先使用业务解决方案初始化阶段缓存的设备短号;
|
|
299
|
+
* 未缓存的通用 BaseSales 保持实时读取设备信息的兼容语义。
|
|
300
|
+
*/
|
|
288
301
|
addOrderPaymentAsync(payment: OrderPaymentSource): Promise<OrderPaymentData[]>;
|
|
289
302
|
private addOrderPaymentWithDevicePrefix;
|
|
290
303
|
/** 更新当前订单中的指定支付项。 */
|
|
@@ -332,6 +332,11 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
332
332
|
order: void 0
|
|
333
333
|
};
|
|
334
334
|
this.otherParams = {};
|
|
335
|
+
/**
|
|
336
|
+
* 由已在初始化阶段解析过设备短号的业务解决方案写入。
|
|
337
|
+
* 未设置时,支付编号仍按原逻辑实时读取设备信息。
|
|
338
|
+
*/
|
|
339
|
+
this.paymentNumberDevicePrefix = null;
|
|
335
340
|
// 当前缓存中已加载的最新 SalesDetail;只读 getter 走它对外暴露详情数据。
|
|
336
341
|
this.currentSalesDetail = null;
|
|
337
342
|
this.discountConfigCacheKey = null;
|
|
@@ -862,6 +867,14 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
862
867
|
const coreData = (_f = (_d = (_c = app == null ? void 0 : app.models) == null ? void 0 : _c.getStore) == null ? void 0 : (_e = _d.call(_c)).getDataByModel) == null ? void 0 : _f.call(_e, "core", "core");
|
|
863
868
|
return coreData == null ? void 0 : coreData[key];
|
|
864
869
|
}
|
|
870
|
+
/**
|
|
871
|
+
* 复用业务解决方案初始化时已解析的支付设备短号。
|
|
872
|
+
* 空值会清除缓存,使后续支付恢复实时读取设备信息的兼容路径。
|
|
873
|
+
*/
|
|
874
|
+
setPaymentNumberDevicePrefix(prefix) {
|
|
875
|
+
const normalized = String(prefix ?? "").trim();
|
|
876
|
+
this.paymentNumberDevicePrefix = normalized || null;
|
|
877
|
+
}
|
|
865
878
|
getPaymentNumberDevicePrefixSync() {
|
|
866
879
|
if (!this.appPlugin)
|
|
867
880
|
return "LOCAL";
|
|
@@ -870,6 +883,9 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
870
883
|
getPaymentNumberDevicePrefixAsync() {
|
|
871
884
|
if (!this.appPlugin)
|
|
872
885
|
return Promise.resolve("LOCAL");
|
|
886
|
+
if (this.paymentNumberDevicePrefix) {
|
|
887
|
+
return Promise.resolve(this.paymentNumberDevicePrefix);
|
|
888
|
+
}
|
|
873
889
|
return (0, import_payment_number.resolvePaymentNumberDevicePrefix)((key) => this.getAppData(key));
|
|
874
890
|
}
|
|
875
891
|
syncAppDataToTempOrder(tempOrder) {
|
|
@@ -912,6 +928,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
912
928
|
var _a, _b;
|
|
913
929
|
this.core = core;
|
|
914
930
|
this.initializeOptions = options || {};
|
|
931
|
+
this.paymentNumberDevicePrefix = null;
|
|
915
932
|
this.otherParams = options.otherParams || {};
|
|
916
933
|
this.cacheId = (_a = this.otherParams) == null ? void 0 : _a.cacheId;
|
|
917
934
|
this.reusedSharedSubModuleNames.clear();
|
|
@@ -973,6 +990,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
973
990
|
}
|
|
974
991
|
});
|
|
975
992
|
this.currentSalesDetail = null;
|
|
993
|
+
this.paymentNumberDevicePrefix = null;
|
|
976
994
|
this.queuedServerOrderChanges = [];
|
|
977
995
|
this.salesDetailLoadSequence += 1;
|
|
978
996
|
await this.core.effects.emit(`${this.name}:onDestroy`, {});
|
|
@@ -2032,7 +2050,10 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2032
2050
|
hasPaymentNumber ? "LOCAL" : this.getPaymentNumberDevicePrefixSync()
|
|
2033
2051
|
);
|
|
2034
2052
|
}
|
|
2035
|
-
/**
|
|
2053
|
+
/**
|
|
2054
|
+
* 创建新支付项时优先使用业务解决方案初始化阶段缓存的设备短号;
|
|
2055
|
+
* 未缓存的通用 BaseSales 保持实时读取设备信息的兼容语义。
|
|
2056
|
+
*/
|
|
2036
2057
|
async addOrderPaymentAsync(payment) {
|
|
2037
2058
|
const paymentRecord = payment;
|
|
2038
2059
|
const hasPaymentNumber = String(paymentRecord.payment_number || "").trim() !== "";
|
|
@@ -78,6 +78,7 @@ export interface CartPromotionEvaluator {
|
|
|
78
78
|
}>;
|
|
79
79
|
hasApplicableStrategy: boolean;
|
|
80
80
|
}>;
|
|
81
|
+
getStrategyConfigs?: () => unknown[];
|
|
81
82
|
}
|
|
82
83
|
/** 单个赠品减量项 */
|
|
83
84
|
export interface GiftReduceItem {
|
|
@@ -267,7 +268,8 @@ export declare function appendPromotionTags<T extends Record<string, any>>(produ
|
|
|
267
268
|
* 处理购物车的促销计算与赠品差异化。
|
|
268
269
|
*
|
|
269
270
|
* 流程:
|
|
270
|
-
* 1. 分离 main / gift / edit-product
|
|
271
|
+
* 1. 分离 main / gift / edit-product 三类(普通促销下带 `booking_id` 的编辑态商品不参与;
|
|
272
|
+
* 配置 ITEM_REWARD 时,编辑态商品也参与商品奖励重算)
|
|
271
273
|
* 2. 转 PromotionProduct 喂评估器 → 拿到 `evaluateCartWithPricing` 与 `getProductsApplicableStrategies`
|
|
272
274
|
* 3. 把 PricedProduct 映射回 OrderProduct 形态:
|
|
273
275
|
* - 参与促销的,写 `metadata._promotion` + 调整 `selling_price` / `main_product_selling_price`
|
|
@@ -77,19 +77,43 @@ function getOrderProductOriginalPriceForPromotion(product) {
|
|
|
77
77
|
}
|
|
78
78
|
return getOrderProductBasePrice(product);
|
|
79
79
|
}
|
|
80
|
-
|
|
80
|
+
var X_ITEMS_FOR_Y_PRICE = "X_ITEMS_FOR_Y_PRICE";
|
|
81
|
+
var ITEM_REWARD = "ITEM_REWARD";
|
|
82
|
+
function isItemRewardPromotionDiscountItem(item) {
|
|
83
|
+
var _a, _b;
|
|
84
|
+
return (item == null ? void 0 : item.type) === "product" && ((_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a.source) === "promotion" && ((_b = item == null ? void 0 : item.metadata) == null ? void 0 : _b.actionType) === ITEM_REWARD;
|
|
85
|
+
}
|
|
86
|
+
function isManagedPromotionDiscountItem(item) {
|
|
87
|
+
if ((item == null ? void 0 : item.type) === "promotion")
|
|
88
|
+
return true;
|
|
89
|
+
return isItemRewardPromotionDiscountItem(item);
|
|
90
|
+
}
|
|
91
|
+
function wasInPromotionBeforeEvaluation(item) {
|
|
92
|
+
var _a, _b;
|
|
93
|
+
if (((_b = (_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a._promotion) == null ? void 0 : _b.inPromotion) === true)
|
|
94
|
+
return true;
|
|
95
|
+
return Array.isArray(item == null ? void 0 : item.discount_list) && item.discount_list.some(isItemRewardPromotionDiscountItem);
|
|
96
|
+
}
|
|
97
|
+
function updatePromotionDiscountList(item, promotionDiscount, options) {
|
|
81
98
|
let discountList = Array.isArray(item.discount_list) ? [...item.discount_list] : [];
|
|
82
|
-
discountList = discountList.filter((d) => (d
|
|
99
|
+
discountList = discountList.filter((d) => !isManagedPromotionDiscountItem(d));
|
|
83
100
|
if (promotionDiscount) {
|
|
101
|
+
const discountType = (options == null ? void 0 : options.discountType) || "promotion";
|
|
84
102
|
discountList.push({
|
|
85
|
-
type:
|
|
103
|
+
type: discountType,
|
|
86
104
|
amount: promotionDiscount.amount,
|
|
87
105
|
discount: {
|
|
88
106
|
original_amount: promotionDiscount.original_amount,
|
|
89
107
|
fixed_amount: promotionDiscount.fixed_amount,
|
|
90
108
|
title: promotionDiscount.title,
|
|
91
109
|
resource_id: ""
|
|
92
|
-
}
|
|
110
|
+
},
|
|
111
|
+
...discountType === "product" ? {
|
|
112
|
+
metadata: {
|
|
113
|
+
source: "promotion",
|
|
114
|
+
actionType: (options == null ? void 0 : options.actionType) || ITEM_REWARD
|
|
115
|
+
}
|
|
116
|
+
} : {}
|
|
93
117
|
});
|
|
94
118
|
}
|
|
95
119
|
if (discountList.length > 0) {
|
|
@@ -98,7 +122,15 @@ function updatePromotionDiscountList(item, promotionDiscount) {
|
|
|
98
122
|
delete item.discount_list;
|
|
99
123
|
}
|
|
100
124
|
}
|
|
101
|
-
|
|
125
|
+
function evaluatorHasActionType(evaluator, actionType) {
|
|
126
|
+
var _a;
|
|
127
|
+
const configs = (_a = evaluator == null ? void 0 : evaluator.getStrategyConfigs) == null ? void 0 : _a.call(evaluator);
|
|
128
|
+
if (!Array.isArray(configs))
|
|
129
|
+
return false;
|
|
130
|
+
return configs.some(
|
|
131
|
+
(config) => ((config == null ? void 0 : config.actions) || []).some((action) => (action == null ? void 0 : action.type) === actionType)
|
|
132
|
+
);
|
|
133
|
+
}
|
|
102
134
|
function applyPromoUnitPriceToLine(item, input) {
|
|
103
135
|
const metadata = item.metadata || (item.metadata = {});
|
|
104
136
|
const optionSum = (0, import_utils.sumOptionUnitPrice)((0, import_utils.getProductSkuOptions)(item)).toNumber();
|
|
@@ -125,6 +157,9 @@ function applyPromoUnitPriceToLine(item, input) {
|
|
|
125
157
|
amount: discountAmount,
|
|
126
158
|
original_amount: catalogSource,
|
|
127
159
|
fixed_amount: discountAmount
|
|
160
|
+
}, {
|
|
161
|
+
actionType: input.actionType,
|
|
162
|
+
discountType: input.actionType === ITEM_REWARD ? "product" : "promotion"
|
|
128
163
|
});
|
|
129
164
|
} else {
|
|
130
165
|
updatePromotionDiscountList(item, null);
|
|
@@ -396,14 +431,13 @@ function buildConsolidateKeyForPromotion(item) {
|
|
|
396
431
|
].join("#");
|
|
397
432
|
}
|
|
398
433
|
function consolidateMainProductsForPromotion(entries) {
|
|
399
|
-
var _a, _b;
|
|
400
434
|
if (!Array.isArray(entries) || entries.length <= 1) {
|
|
401
435
|
return [...entries || []];
|
|
402
436
|
}
|
|
403
437
|
const groups = /* @__PURE__ */ new Map();
|
|
404
438
|
for (const { item, originalListIndex } of entries) {
|
|
405
439
|
const key = buildConsolidateKeyForPromotion(item);
|
|
406
|
-
const wasInPromotion = (
|
|
440
|
+
const wasInPromotion = wasInPromotionBeforeEvaluation(item);
|
|
407
441
|
const existing = groups.get(key);
|
|
408
442
|
if (!existing) {
|
|
409
443
|
const mergedItem = (0, import_lodash_es.cloneDeep)(item);
|
|
@@ -469,6 +503,9 @@ function splitXItemsPromoLinesByGroup(lines, strategyActionMap) {
|
|
|
469
503
|
function generateNumericId() {
|
|
470
504
|
return Math.floor(Math.random() * 1e9) + Date.now();
|
|
471
505
|
}
|
|
506
|
+
function isBookingEditProductLine(product) {
|
|
507
|
+
return (product == null ? void 0 : product.booking_id) !== void 0 && (product == null ? void 0 : product.booking_id) !== null && product.booking_id !== 0 && product.booking_id !== "0";
|
|
508
|
+
}
|
|
472
509
|
function convertToPromotionProduct(product, index) {
|
|
473
510
|
const metadata = (product == null ? void 0 : product.metadata) || {};
|
|
474
511
|
const numericId = generateNumericId();
|
|
@@ -481,6 +518,7 @@ function convertToPromotionProduct(product, index) {
|
|
|
481
518
|
price: getOrderProductOriginalPriceForPromotion(product),
|
|
482
519
|
quantity: Number((product == null ? void 0 : product.num) ?? 1) || 1,
|
|
483
520
|
bundle: getProductBundleForEvaluator(product),
|
|
521
|
+
_promotionOnlyForItemReward: isBookingEditProductLine(product),
|
|
484
522
|
_originalItem: originalItem,
|
|
485
523
|
_originalId: getOrderProductUid(product),
|
|
486
524
|
_originalIndex: index
|
|
@@ -582,6 +620,9 @@ function resolveStrategyRequiredQuantity(matched) {
|
|
|
582
620
|
if (matched.actionType === "BUY_X_GET_Y_FREE") {
|
|
583
621
|
return Number(detail.buyQuantity) || 1;
|
|
584
622
|
}
|
|
623
|
+
if (matched.actionType === "ITEM_REWARD") {
|
|
624
|
+
return Number(detail.triggerQuantity) || 1;
|
|
625
|
+
}
|
|
585
626
|
return 1;
|
|
586
627
|
}
|
|
587
628
|
function resolveStrategyEligibleProducts(matched) {
|
|
@@ -692,6 +733,10 @@ function processCartPromotion(list, evaluator, options) {
|
|
|
692
733
|
};
|
|
693
734
|
if (!list || list.length === 0 || !evaluator)
|
|
694
735
|
return empty;
|
|
736
|
+
const shouldIncludeEditProductsForItemReward = evaluatorHasActionType(
|
|
737
|
+
evaluator,
|
|
738
|
+
ITEM_REWARD
|
|
739
|
+
);
|
|
695
740
|
const mainProductsWithIndex = [];
|
|
696
741
|
const existingGiftsWithIndex = [];
|
|
697
742
|
const editProductsWithIndex = [];
|
|
@@ -702,8 +747,12 @@ function processCartPromotion(list, evaluator, options) {
|
|
|
702
747
|
editProductsWithIndex.push({ item, originalListIndex: i });
|
|
703
748
|
} else if (giftInfo) {
|
|
704
749
|
existingGiftsWithIndex.push({ item, originalListIndex: i });
|
|
705
|
-
} else if ((item
|
|
706
|
-
|
|
750
|
+
} else if (isBookingEditProductLine(item)) {
|
|
751
|
+
if (shouldIncludeEditProductsForItemReward) {
|
|
752
|
+
mainProductsWithIndex.push({ item, originalListIndex: i });
|
|
753
|
+
} else {
|
|
754
|
+
editProductsWithIndex.push({ item, originalListIndex: i });
|
|
755
|
+
}
|
|
707
756
|
} else {
|
|
708
757
|
mainProductsWithIndex.push({ item, originalListIndex: i });
|
|
709
758
|
}
|
|
@@ -746,7 +795,8 @@ function processCartPromotion(list, evaluator, options) {
|
|
|
746
795
|
name: ((_a2 = item == null ? void 0 : item.metadata) == null ? void 0 : _a2.product_name) || (item == null ? void 0 : item.title) || "",
|
|
747
796
|
price: getOrderProductBasePrice(item),
|
|
748
797
|
quantity: Number((item == null ? void 0 : item.num) ?? 1) || 1,
|
|
749
|
-
bundle: getProductBundleForEvaluator(item)
|
|
798
|
+
bundle: getProductBundleForEvaluator(item),
|
|
799
|
+
_promotionOnlyForItemReward: isBookingEditProductLine(item)
|
|
750
800
|
};
|
|
751
801
|
});
|
|
752
802
|
for (let i = 0; i < consolidatedMainProductsWithIndex.length; i++) {
|
|
@@ -815,7 +865,7 @@ function processCartPromotion(list, evaluator, options) {
|
|
|
815
865
|
const metadata = newItem.metadata || {};
|
|
816
866
|
const sourceCartNum = (0, import_utils2.getSafeProductNum)(originalItem.num);
|
|
817
867
|
newItem._sourceCartNum = sourceCartNum;
|
|
818
|
-
const wasInPromotion = (
|
|
868
|
+
const wasInPromotion = wasInPromotionBeforeEvaluation(originalItem) || originalItem._wasInPromotionBeforeConsolidate === true;
|
|
819
869
|
delete metadata._promotion;
|
|
820
870
|
if (Array.isArray(newItem.product_bundle)) {
|
|
821
871
|
for (const b of newItem.product_bundle) {
|
|
@@ -832,7 +882,8 @@ function processCartPromotion(list, evaluator, options) {
|
|
|
832
882
|
applyPromoUnitPriceToLine(newItem, {
|
|
833
883
|
promoUnitPrice,
|
|
834
884
|
originalBasePrice,
|
|
835
|
-
strategyTitle: (
|
|
885
|
+
strategyTitle: (_a = priced.strategyMetadata) == null ? void 0 : _a.name,
|
|
886
|
+
actionType: priced.strategyId ? (_b = strategyActionMap.get(priced.strategyId)) == null ? void 0 : _b.actionType : void 0
|
|
836
887
|
});
|
|
837
888
|
} else {
|
|
838
889
|
const optionSum = (0, import_utils.sumOptionUnitPrice)((0, import_utils.getProductSkuOptions)(newItem)).toNumber();
|
|
@@ -233,6 +233,7 @@ var BookingTicketImpl = class extends import_BaseSales.BaseSalesImpl {
|
|
|
233
233
|
return String(this.getAppData("device_id") || 0).slice(-2);
|
|
234
234
|
}
|
|
235
235
|
async configureIdGeneratorFromOpenData() {
|
|
236
|
+
this.setPaymentNumberDevicePrefix(null);
|
|
236
237
|
let openDataConfig = null;
|
|
237
238
|
try {
|
|
238
239
|
openDataConfig = await this.loadOpenDataConfig();
|
|
@@ -264,6 +265,7 @@ var BookingTicketImpl = class extends import_BaseSales.BaseSalesImpl {
|
|
|
264
265
|
const resetReceiptSequenceDaily = typeof (openDataConfig == null ? void 0 : openDataConfig["sale.short_number_daily_reset"]) === "boolean" ? openDataConfig == null ? void 0 : openDataConfig["sale.short_number_daily_reset"] : false;
|
|
265
266
|
const operatingDayBoundary = this.getAppData("operating_day_boundary");
|
|
266
267
|
const deviceId = await this.getShortNumberOrDeviceId();
|
|
268
|
+
this.setPaymentNumberDevicePrefix(deviceId);
|
|
267
269
|
const businessCode = this.getBookingTicketBusinessCode();
|
|
268
270
|
if (!businessCode) {
|
|
269
271
|
console.warn("[BookingTicket] businessCode 缺失,跳过 idGenerator 配置");
|
|
@@ -1527,8 +1529,8 @@ var BookingTicketImpl = class extends import_BaseSales.BaseSalesImpl {
|
|
|
1527
1529
|
return result;
|
|
1528
1530
|
}
|
|
1529
1531
|
async setOtherParams(params, { cover = false } = {}) {
|
|
1530
|
-
super.setOtherParams(params, { cover });
|
|
1531
|
-
if (params == null ? void 0 : params.businessCode) {
|
|
1532
|
+
await super.setOtherParams(params, { cover });
|
|
1533
|
+
if ((params == null ? void 0 : params.businessCode) !== void 0 || (params == null ? void 0 : params.business_code) !== void 0) {
|
|
1532
1534
|
await this.configureIdGeneratorFromOpenData();
|
|
1533
1535
|
}
|
|
1534
1536
|
}
|
|
@@ -48,6 +48,10 @@ var import_utils2 = require("../../modules/Order/utils");
|
|
|
48
48
|
var import_dayjs = __toESM(require("dayjs"));
|
|
49
49
|
var import_itemRule = require("../../model/strategy/adapter/itemRule");
|
|
50
50
|
__reExport(ScanOrder_exports, require("./types"), module.exports);
|
|
51
|
+
function isItemRewardProductDiscount(discount) {
|
|
52
|
+
var _a, _b;
|
|
53
|
+
return (discount == null ? void 0 : discount.type) === "product" && ((_a = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a.source) === "promotion" && ((_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.actionType) === "ITEM_REWARD";
|
|
54
|
+
}
|
|
51
55
|
var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
52
56
|
constructor(name, version) {
|
|
53
57
|
super(name, version);
|
|
@@ -742,6 +746,10 @@ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
742
746
|
for (const product of tempOrder.products) {
|
|
743
747
|
if ((_c = product._origin) == null ? void 0 : _c.isManualDiscount)
|
|
744
748
|
continue;
|
|
749
|
+
if ((product.discount_list || []).some(isItemRewardProductDiscount)) {
|
|
750
|
+
product.discount_list = (product.discount_list || []).filter(isItemRewardProductDiscount);
|
|
751
|
+
continue;
|
|
752
|
+
}
|
|
745
753
|
product.discount_list = (product.discount_list || []).filter((pd) => {
|
|
746
754
|
var _a2;
|
|
747
755
|
const rid = ((_a2 = pd.discount) == null ? void 0 : _a2.resource_id) ?? pd.id;
|
|
@@ -65,6 +65,10 @@ var OPEN_DATA_SECTION_CODES = [
|
|
|
65
65
|
"workflow",
|
|
66
66
|
"checkout"
|
|
67
67
|
];
|
|
68
|
+
function isItemRewardProductDiscount(discount) {
|
|
69
|
+
var _a, _b;
|
|
70
|
+
return (discount == null ? void 0 : discount.type) === "product" && ((_a = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a.source) === "promotion" && ((_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.actionType) === "ITEM_REWARD";
|
|
71
|
+
}
|
|
68
72
|
function cloneCustomDepositData(customDepositData) {
|
|
69
73
|
if (!customDepositData || typeof customDepositData !== "object")
|
|
70
74
|
return void 0;
|
|
@@ -1339,6 +1343,10 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1339
1343
|
for (const product of tempOrder.products) {
|
|
1340
1344
|
if ((_c = product._origin) == null ? void 0 : _c.isManualDiscount)
|
|
1341
1345
|
continue;
|
|
1346
|
+
if ((product.discount_list || []).some(isItemRewardProductDiscount)) {
|
|
1347
|
+
product.discount_list = (product.discount_list || []).filter(isItemRewardProductDiscount);
|
|
1348
|
+
continue;
|
|
1349
|
+
}
|
|
1342
1350
|
product.discount_list = (product.discount_list || []).filter((pd) => {
|
|
1343
1351
|
var _a2;
|
|
1344
1352
|
const rid = ((_a2 = pd.discount) == null ? void 0 : _a2.resource_id) ?? pd.id;
|