@pisell/pisellos 2.2.183 → 2.2.184
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/evaluator.js +3 -2
- package/dist/model/strategy/adapter/promotion/index.js +9 -0
- package/dist/modules/Order/index.d.ts +2 -0
- package/dist/modules/Order/index.js +100 -38
- package/dist/modules/Order/types.d.ts +1 -0
- package/dist/modules/Product/index.d.ts +1 -1
- package/dist/solution/BaseSales/index.js +38 -39
- package/dist/solution/BaseSales/utils/cartPromotion.d.ts +12 -0
- package/dist/solution/BaseSales/utils/cartPromotion.js +271 -130
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.js +9 -0
- package/lib/model/strategy/adapter/promotion/evaluator.js +2 -1
- package/lib/model/strategy/adapter/promotion/index.js +49 -0
- package/lib/modules/Order/index.d.ts +2 -0
- package/lib/modules/Order/index.js +63 -13
- package/lib/modules/Order/types.d.ts +1 -0
- package/lib/modules/Product/index.d.ts +1 -1
- package/lib/solution/BaseSales/index.js +0 -1
- package/lib/solution/BaseSales/utils/cartPromotion.d.ts +12 -0
- package/lib/solution/BaseSales/utils/cartPromotion.js +118 -12
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.js +7 -0
- package/package.json +1 -1
|
@@ -311,7 +311,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
311
311
|
date: string;
|
|
312
312
|
status: string;
|
|
313
313
|
week: string;
|
|
314
|
-
weekNum: 0 |
|
|
314
|
+
weekNum: 0 | 5 | 1 | 4 | 2 | 3 | 6;
|
|
315
315
|
}[]>;
|
|
316
316
|
submitTimeSlot(timeSlots: TimeSliceItem): void;
|
|
317
317
|
private getScheduleDataByIds;
|
|
@@ -929,6 +929,7 @@ export var BookingTicketImpl = /*#__PURE__*/function (_BaseSalesImpl) {
|
|
|
929
929
|
return;
|
|
930
930
|
}
|
|
931
931
|
var previousCustomerId = (_this$store$order$get3 = this.store.order.getOrderCustomer()) === null || _this$store$order$get3 === void 0 ? void 0 : _this$store$order$get3.customer_id;
|
|
932
|
+
var snapshotBeforeSet = this.store.order.getOrderCustomerSnapshot();
|
|
932
933
|
var patch = formatOrderCustomerPatch(customer);
|
|
933
934
|
var customerUnchanged = Number(previousCustomerId || 0) === Number(patch.customer_id || 0);
|
|
934
935
|
if (!customerUnchanged) {
|
|
@@ -936,7 +937,15 @@ export var BookingTicketImpl = /*#__PURE__*/function (_BaseSalesImpl) {
|
|
|
936
937
|
this.hasManualDiscountSelection = false;
|
|
937
938
|
}
|
|
938
939
|
this.store.order.setOrderCustomer(patch, customer);
|
|
940
|
+
var snapshotAfterOrderSet = this.store.order.getOrderCustomerSnapshot();
|
|
939
941
|
if (customerUnchanged) {
|
|
942
|
+
// hydrate 后 customer_id 已存在但 _extend.customerSnapshot 仍为空时,
|
|
943
|
+
// 须通知 SalesSdk 刷新 selected(否则会一直停在 onSalesOrderLoaded 时的 null)。
|
|
944
|
+
var snapshotReplenished = !snapshotBeforeSet && Boolean(snapshotAfterOrderSet);
|
|
945
|
+
if (snapshotReplenished) {
|
|
946
|
+
var _next2 = this.buildOrderCustomerPayload();
|
|
947
|
+
this.core.effects.emit("".concat(this.name, ":onOrderCustomerChange"), _next2);
|
|
948
|
+
}
|
|
940
949
|
return;
|
|
941
950
|
}
|
|
942
951
|
var next = this.buildOrderCustomerPayload();
|
|
@@ -528,7 +528,8 @@ var PromotionEvaluator = class {
|
|
|
528
528
|
return b.price - a.price;
|
|
529
529
|
});
|
|
530
530
|
const totalUnits = unitProducts.length;
|
|
531
|
-
const
|
|
531
|
+
const isCumulative = cumulative !== false;
|
|
532
|
+
const groupCount = isCumulative ? Math.floor(totalUnits / x) : totalUnits >= x ? 1 : 0;
|
|
532
533
|
const promotionUnits = groupCount * x;
|
|
533
534
|
const inPromotionUnits = unitProducts.slice(0, promotionUnits);
|
|
534
535
|
const notInPromotionUnits = unitProducts.slice(promotionUnits);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
|
|
29
|
+
// src/model/strategy/adapter/promotion/index.ts
|
|
30
|
+
var promotion_exports = {};
|
|
31
|
+
__export(promotion_exports, {
|
|
32
|
+
BUY_X_GET_Y_FREE_STRATEGY: () => import_examples.BUY_X_GET_Y_FREE_STRATEGY,
|
|
33
|
+
PromotionAdapter: () => import_adapter.PromotionAdapter,
|
|
34
|
+
PromotionEvaluator: () => import_evaluator.PromotionEvaluator,
|
|
35
|
+
X_ITEMS_FOR_Y_PRICE_STRATEGY: () => import_examples.X_ITEMS_FOR_Y_PRICE_STRATEGY,
|
|
36
|
+
default: () => import_adapter2.default
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(promotion_exports);
|
|
39
|
+
var import_evaluator = require("./evaluator");
|
|
40
|
+
var import_adapter = require("./adapter");
|
|
41
|
+
var import_adapter2 = __toESM(require("./adapter"));
|
|
42
|
+
var import_examples = require("./examples");
|
|
43
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
44
|
+
0 && (module.exports = {
|
|
45
|
+
BUY_X_GET_Y_FREE_STRATEGY,
|
|
46
|
+
PromotionAdapter,
|
|
47
|
+
PromotionEvaluator,
|
|
48
|
+
X_ITEMS_FOR_Y_PRICE_STRATEGY
|
|
49
|
+
});
|
|
@@ -312,6 +312,8 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
|
|
|
312
312
|
recalcOnHydrate?: boolean;
|
|
313
313
|
}): Promise<OrderTempOrder>;
|
|
314
314
|
private normalizeTempOrderForRuntime;
|
|
315
|
+
private normalizeHydratedProductOptionItem;
|
|
316
|
+
private resolveHydratedProductOptions;
|
|
315
317
|
private normalizeHydratedOrderProduct;
|
|
316
318
|
getLastOrderInfo(): Record<string, any> | undefined;
|
|
317
319
|
getOrderInfo(order_id: number): Promise<any>;
|
|
@@ -1443,7 +1443,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1443
1443
|
productToAdd.product_option_item,
|
|
1444
1444
|
productToAdd.product_bundle
|
|
1445
1445
|
);
|
|
1446
|
-
const normalizedIncoming = (0,
|
|
1446
|
+
const normalizedIncoming = (0, import_utils.mergeOrderProductDisplayFields)(
|
|
1447
|
+
productToAdd,
|
|
1448
|
+
(0, import_utils3.normalizeOrderProduct)(productToAdd)
|
|
1449
|
+
);
|
|
1447
1450
|
normalizedIncoming.discount_list = (0, import_utils.normalizeOrderProductDiscountList)(
|
|
1448
1451
|
normalizedIncoming.discount_list
|
|
1449
1452
|
);
|
|
@@ -1496,13 +1499,16 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1496
1499
|
} else {
|
|
1497
1500
|
const targetProduct = matchedProduct;
|
|
1498
1501
|
const targetUid = (_a = targetProduct.metadata) == null ? void 0 : _a.unique_identification_number;
|
|
1499
|
-
const normalizedProduct = (0,
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
...productToAdd
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1502
|
+
const normalizedProduct = (0, import_utils.mergeOrderProductDisplayFields)(
|
|
1503
|
+
targetProduct,
|
|
1504
|
+
(0, import_utils3.normalizeOrderProduct)({
|
|
1505
|
+
...productToAdd,
|
|
1506
|
+
metadata: {
|
|
1507
|
+
...productToAdd.metadata || {},
|
|
1508
|
+
unique_identification_number: targetUid
|
|
1509
|
+
}
|
|
1510
|
+
})
|
|
1511
|
+
);
|
|
1506
1512
|
normalizedProduct.discount_list = (0, import_utils.normalizeOrderProductDiscountList)(
|
|
1507
1513
|
normalizedProduct.discount_list
|
|
1508
1514
|
);
|
|
@@ -1621,7 +1627,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1621
1627
|
delete nextProduct.metadata.main_product_original_price;
|
|
1622
1628
|
delete nextProduct.metadata.price_schema_version;
|
|
1623
1629
|
}
|
|
1624
|
-
let normalizedProduct = (0,
|
|
1630
|
+
let normalizedProduct = (0, import_utils.mergeOrderProductDisplayFields)(
|
|
1631
|
+
nextProduct,
|
|
1632
|
+
(0, import_utils3.normalizeOrderProduct)(nextProduct)
|
|
1633
|
+
);
|
|
1625
1634
|
normalizedProduct.discount_list = (0, import_utils.normalizeOrderProductDiscountList)(
|
|
1626
1635
|
normalizedProduct.discount_list
|
|
1627
1636
|
);
|
|
@@ -2240,7 +2249,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
2240
2249
|
async getOrderInfoByRemote(order_id) {
|
|
2241
2250
|
const res = await this.request.get(`/order/sales/${order_id}`, {
|
|
2242
2251
|
with: ["products", "bookings", "payments", "customer", "summary", "contacts_info"]
|
|
2243
|
-
});
|
|
2252
|
+
}, { osServer: true });
|
|
2244
2253
|
if (res.code === 200) {
|
|
2245
2254
|
this.store.lastOrderInfo = res.data;
|
|
2246
2255
|
}
|
|
@@ -2265,6 +2274,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
2265
2274
|
return nextTempOrder;
|
|
2266
2275
|
}
|
|
2267
2276
|
normalizeTempOrderForRuntime(raw, options) {
|
|
2277
|
+
var _a, _b;
|
|
2268
2278
|
const nextTempOrder = {
|
|
2269
2279
|
...this.createDefaultTempOrderInstance(),
|
|
2270
2280
|
...raw || {}
|
|
@@ -2284,7 +2294,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
2284
2294
|
delete nextTempOrder.holder_id;
|
|
2285
2295
|
nextTempOrder.metadata = raw.metadata && typeof raw.metadata === "object" ? { ...raw.metadata } : {};
|
|
2286
2296
|
nextTempOrder.holder = raw.holder && typeof raw.holder === "object" ? { ...raw.holder } : null;
|
|
2287
|
-
|
|
2297
|
+
const rawProducts = Array.isArray(raw.products) ? raw.products : [];
|
|
2298
|
+
nextTempOrder.products = rawProducts.length > 0 ? rawProducts.map((p) => this.normalizeHydratedOrderProduct(p)) : [];
|
|
2288
2299
|
nextTempOrder.bookings = Array.isArray(raw.bookings) ? raw.bookings.map((b) => ({
|
|
2289
2300
|
...b || {},
|
|
2290
2301
|
is_all: (0, import_utils.normalizeBookingIsAll)(b || {}),
|
|
@@ -2299,19 +2310,57 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
2299
2310
|
...raw._extend,
|
|
2300
2311
|
productsByUid: raw._extend.productsByUid || {}
|
|
2301
2312
|
} : { productsByUid: {} };
|
|
2313
|
+
const tempOrderExtend = nextTempOrder._extend;
|
|
2314
|
+
const productsByUid = tempOrderExtend.productsByUid || {};
|
|
2315
|
+
for (const [index, product] of nextTempOrder.products.entries()) {
|
|
2316
|
+
const uid = (_a = product.metadata) == null ? void 0 : _a.unique_identification_number;
|
|
2317
|
+
if (!uid)
|
|
2318
|
+
continue;
|
|
2319
|
+
const existed = productsByUid[uid] && typeof productsByUid[uid] === "object" ? productsByUid[uid] : {};
|
|
2320
|
+
const rawProduct = rawProducts[index] && typeof rawProducts[index] === "object" ? rawProducts[index] : product;
|
|
2321
|
+
const origin = existed.origin ?? rawProduct._origin ?? ((_b = rawProduct.metadata) == null ? void 0 : _b.origin) ?? rawProduct;
|
|
2322
|
+
productsByUid[uid] = {
|
|
2323
|
+
...existed,
|
|
2324
|
+
origin: (0, import_lodash_es.cloneDeep)(origin)
|
|
2325
|
+
};
|
|
2326
|
+
}
|
|
2327
|
+
tempOrderExtend.productsByUid = productsByUid;
|
|
2302
2328
|
if ((options == null ? void 0 : options.ensureIdentity) !== false) {
|
|
2303
2329
|
this.ensureExternalSaleNumber(nextTempOrder);
|
|
2304
2330
|
}
|
|
2305
2331
|
nextTempOrder.vouchers = raw.vouchers || [];
|
|
2306
2332
|
return nextTempOrder;
|
|
2307
2333
|
}
|
|
2334
|
+
normalizeHydratedProductOptionItem(optionItem) {
|
|
2335
|
+
const rawNum = (optionItem == null ? void 0 : optionItem.num) ?? (optionItem == null ? void 0 : optionItem.quantity) ?? 1;
|
|
2336
|
+
const parsedNum = Number(rawNum);
|
|
2337
|
+
const rawPrice = (optionItem == null ? void 0 : optionItem.price) ?? (optionItem == null ? void 0 : optionItem.add_price) ?? 0;
|
|
2338
|
+
const parsedPrice = Number(rawPrice);
|
|
2339
|
+
return {
|
|
2340
|
+
option_group_item_id: optionItem == null ? void 0 : optionItem.option_group_item_id,
|
|
2341
|
+
option_group_id: optionItem == null ? void 0 : optionItem.option_group_id,
|
|
2342
|
+
num: Number.isFinite(parsedNum) && parsedNum > 0 ? parsedNum : 1,
|
|
2343
|
+
price: Number.isFinite(parsedPrice) ? parsedPrice : 0
|
|
2344
|
+
};
|
|
2345
|
+
}
|
|
2346
|
+
resolveHydratedProductOptions(row) {
|
|
2347
|
+
var _a;
|
|
2348
|
+
if (Array.isArray(row.product_option_item) && row.product_option_item.length > 0) {
|
|
2349
|
+
return row.product_option_item;
|
|
2350
|
+
}
|
|
2351
|
+
const skuOptions = (_a = row.product_sku) == null ? void 0 : _a.option;
|
|
2352
|
+
if (!Array.isArray(skuOptions))
|
|
2353
|
+
return [];
|
|
2354
|
+
return skuOptions.map(
|
|
2355
|
+
(optionItem) => this.normalizeHydratedProductOptionItem(optionItem || {})
|
|
2356
|
+
);
|
|
2357
|
+
}
|
|
2308
2358
|
normalizeHydratedOrderProduct(product) {
|
|
2309
2359
|
const row = { ...product || {} };
|
|
2310
2360
|
if (row.num === void 0 && row.product_quantity !== void 0) {
|
|
2311
2361
|
row.num = row.product_quantity;
|
|
2312
2362
|
}
|
|
2313
|
-
|
|
2314
|
-
row.product_option_item = [];
|
|
2363
|
+
row.product_option_item = this.resolveHydratedProductOptions(row);
|
|
2315
2364
|
if (!Array.isArray(row.product_bundle))
|
|
2316
2365
|
row.product_bundle = [];
|
|
2317
2366
|
if (!row.metadata || typeof row.metadata !== "object")
|
|
@@ -2327,6 +2376,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
2327
2376
|
const result = {
|
|
2328
2377
|
...row,
|
|
2329
2378
|
...normalized,
|
|
2379
|
+
product_sku: row.product_sku,
|
|
2330
2380
|
metadata: {
|
|
2331
2381
|
...row.metadata,
|
|
2332
2382
|
...normalized.metadata
|
|
@@ -49,5 +49,5 @@ export declare class Product extends BaseModule implements Module {
|
|
|
49
49
|
getCategories(): ProductCategory[];
|
|
50
50
|
setOtherParams(key: string, value: any): void;
|
|
51
51
|
getOtherParams(): any;
|
|
52
|
-
getProductType(): "
|
|
52
|
+
getProductType(): "normal" | "duration" | "session";
|
|
53
53
|
}
|
|
@@ -430,7 +430,6 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
430
430
|
throw new Error("order 模块未初始化");
|
|
431
431
|
const params = typeof orderIdOrParams === "object" ? orderIdOrParams : { orderId: orderIdOrParams };
|
|
432
432
|
const externalSaleNumber = params.externalSaleNumber || params.external_sale_number;
|
|
433
|
-
debugger;
|
|
434
433
|
if (!params.forceRemote) {
|
|
435
434
|
const localRecord = params.orderId !== void 0 ? await this.store.order.getLocalOrderByOrderId(params.orderId) : externalSaleNumber ? await this.store.order.getLocalOrderByExternalSaleNumber(externalSaleNumber) : params.orderNumber ? await this.store.order.getLocalOrderByOrderNumber(params.orderNumber) : null;
|
|
436
435
|
if (localRecord) {
|
|
@@ -176,6 +176,18 @@ export declare function getOrderProductOriginalPriceForPromotion(product: any):
|
|
|
176
176
|
export declare function mergeIdenticalPromotionCartLines(products: any[]): any[];
|
|
177
177
|
/** 获取行 uid(统一以 `metadata.unique_identification_number` 为唯一键) */
|
|
178
178
|
export declare function getOrderProductUid(product: any): string;
|
|
179
|
+
/**
|
|
180
|
+
* 促销评估前合并同 SKU 拆分行(含促销/原价行),避免加购后仅前 2 件享受优惠。
|
|
181
|
+
* 带 `booking_uid` 的预约行不参与合并(每次加车独立 booking + 商品行)。
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* consolidateMainProductsForPromotion([
|
|
185
|
+
* { item: promoLineNum2, originalListIndex: 0 },
|
|
186
|
+
* { item: regularLineNum2, originalListIndex: 1 },
|
|
187
|
+
* ]);
|
|
188
|
+
* // => 单行 num=4,清除 _promotion 后重新评估
|
|
189
|
+
*/
|
|
190
|
+
export declare function buildConsolidateKeyForPromotion(item: any): string;
|
|
179
191
|
/**
|
|
180
192
|
* 从策略配置的 product_match 规则提取可参与商品列表。
|
|
181
193
|
*
|
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
var cartPromotion_exports = {};
|
|
31
31
|
__export(cartPromotion_exports, {
|
|
32
32
|
appendPromotionTags: () => appendPromotionTags,
|
|
33
|
+
buildConsolidateKeyForPromotion: () => buildConsolidateKeyForPromotion,
|
|
33
34
|
calculateUnfulfilledPromotions: () => calculateUnfulfilledPromotions,
|
|
34
35
|
extractProductMatchIdentifiersFromStrategyConfig: () => extractProductMatchIdentifiersFromStrategyConfig,
|
|
35
36
|
getOrderProductBasePrice: () => getOrderProductBasePrice,
|
|
@@ -151,7 +152,7 @@ function resolveXItemsExpectedUnitPrice(promotion, sourceCartNum) {
|
|
|
151
152
|
return Number(new import_decimal.default(y).div(x).toDecimalPlaces(2).toFixed(2));
|
|
152
153
|
}
|
|
153
154
|
function mergeIdenticalPromotionCartLines(products) {
|
|
154
|
-
var _a, _b, _c;
|
|
155
|
+
var _a, _b, _c, _d;
|
|
155
156
|
if (!Array.isArray(products) || products.length <= 1) {
|
|
156
157
|
return [...products || []];
|
|
157
158
|
}
|
|
@@ -177,10 +178,12 @@ function mergeIdenticalPromotionCartLines(products) {
|
|
|
177
178
|
const promoUnitPrice = String(
|
|
178
179
|
promotion.finalPrice ?? ((_c = line.metadata) == null ? void 0 : _c.main_product_selling_price) ?? ""
|
|
179
180
|
);
|
|
181
|
+
const bookingUid = (line == null ? void 0 : line.booking_uid) ?? ((_d = line == null ? void 0 : line.metadata) == null ? void 0 : _d.booking_uid);
|
|
180
182
|
const mergeKey = [
|
|
181
183
|
line.product_id,
|
|
182
184
|
line.product_variant_id ?? 0,
|
|
183
185
|
fingerprint,
|
|
186
|
+
bookingUid ? String(bookingUid) : "",
|
|
184
187
|
promotion.strategyId,
|
|
185
188
|
unitPrice,
|
|
186
189
|
promoUnitPrice
|
|
@@ -197,7 +200,7 @@ function mergeIdenticalPromotionCartLines(products) {
|
|
|
197
200
|
return merged;
|
|
198
201
|
}
|
|
199
202
|
function dedupePromotionProcessedLines(lines) {
|
|
200
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
203
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
201
204
|
if (!Array.isArray(lines) || lines.length <= 1)
|
|
202
205
|
return [...lines || []];
|
|
203
206
|
const passthrough = [];
|
|
@@ -263,9 +266,24 @@ function dedupePromotionProcessedLines(lines) {
|
|
|
263
266
|
return promotionDelta(line) > promotionDelta(best) ? line : best;
|
|
264
267
|
}, pool[0]);
|
|
265
268
|
}
|
|
266
|
-
|
|
269
|
+
const winnerIsXItems = getPromotionActionType((_c = winner.metadata) == null ? void 0 : _c._promotion) === X_ITEMS_FOR_Y_PRICE;
|
|
270
|
+
if (winnerIsXItems) {
|
|
271
|
+
const xItemsGroupLines = group.filter(
|
|
272
|
+
(line) => {
|
|
273
|
+
var _a2;
|
|
274
|
+
return getPromotionActionType((_a2 = line.metadata) == null ? void 0 : _a2._promotion) === X_ITEMS_FOR_Y_PRICE;
|
|
275
|
+
}
|
|
276
|
+
);
|
|
277
|
+
const evaluatedPromoQty = xItemsGroupLines.reduce(
|
|
278
|
+
(sum, line) => sum + Number(line.num || 0),
|
|
279
|
+
0
|
|
280
|
+
);
|
|
281
|
+
winner.num = (0, import_utils2.getSafeProductNum)(evaluatedPromoQty || winner.num || 1);
|
|
282
|
+
} else {
|
|
283
|
+
winner.num = (0, import_utils2.getSafeProductNum)(sourceCartNum || winner.num || 1);
|
|
284
|
+
}
|
|
267
285
|
const recomputeUnit = resolveXItemsExpectedUnitPrice(
|
|
268
|
-
(
|
|
286
|
+
(_d = winner.metadata) == null ? void 0 : _d._promotion,
|
|
269
287
|
sourceCartNum
|
|
270
288
|
);
|
|
271
289
|
if (recomputeUnit != null) {
|
|
@@ -273,13 +291,13 @@ function dedupePromotionProcessedLines(lines) {
|
|
|
273
291
|
applyPromoUnitPriceToLine(winner, {
|
|
274
292
|
promoUnitPrice: recomputeUnit,
|
|
275
293
|
originalBasePrice: Number(promo.originalPrice),
|
|
276
|
-
strategyTitle: (
|
|
294
|
+
strategyTitle: (_e = promo.strategyMetadata) == null ? void 0 : _e.name
|
|
277
295
|
});
|
|
278
296
|
promo.finalPrice = recomputeUnit;
|
|
279
297
|
}
|
|
280
298
|
for (const line of group) {
|
|
281
|
-
const giftInfo = (
|
|
282
|
-
if (giftInfo && ((
|
|
299
|
+
const giftInfo = (_g = (_f = line.metadata) == null ? void 0 : _f._promotion) == null ? void 0 : _g.giftInfo;
|
|
300
|
+
if (giftInfo && ((_h = winner.metadata) == null ? void 0 : _h._promotion) && !winner.metadata._promotion.giftInfo) {
|
|
283
301
|
winner.metadata._promotion.giftInfo = giftInfo;
|
|
284
302
|
}
|
|
285
303
|
}
|
|
@@ -309,12 +327,93 @@ function getProductBundleForEvaluator(product) {
|
|
|
309
327
|
_bundle_product_id: (b == null ? void 0 : b._bundle_product_id) ?? (b == null ? void 0 : b.bundle_product_id) ?? (b == null ? void 0 : b.product_id)
|
|
310
328
|
}));
|
|
311
329
|
}
|
|
330
|
+
function buildConsolidateKeyForPromotion(item) {
|
|
331
|
+
var _a;
|
|
332
|
+
const fingerprint = (0, import_utils2.buildProductLineFingerprint)(
|
|
333
|
+
item.product_option_item,
|
|
334
|
+
item.product_bundle
|
|
335
|
+
);
|
|
336
|
+
const bookingUid = (item == null ? void 0 : item.booking_uid) ?? ((_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a.booking_uid);
|
|
337
|
+
if (bookingUid !== void 0 && bookingUid !== null && String(bookingUid) !== "") {
|
|
338
|
+
return [
|
|
339
|
+
item.product_id,
|
|
340
|
+
item.product_variant_id ?? 0,
|
|
341
|
+
fingerprint,
|
|
342
|
+
String(bookingUid)
|
|
343
|
+
].join("#");
|
|
344
|
+
}
|
|
345
|
+
return [item.product_id, item.product_variant_id ?? 0, fingerprint].join("#");
|
|
346
|
+
}
|
|
347
|
+
function consolidateMainProductsForPromotion(entries) {
|
|
348
|
+
if (!Array.isArray(entries) || entries.length <= 1) {
|
|
349
|
+
return [...entries || []];
|
|
350
|
+
}
|
|
351
|
+
const groups = /* @__PURE__ */ new Map();
|
|
352
|
+
for (const { item, originalListIndex } of entries) {
|
|
353
|
+
const key = buildConsolidateKeyForPromotion(item);
|
|
354
|
+
const existing = groups.get(key);
|
|
355
|
+
if (!existing) {
|
|
356
|
+
const mergedItem = (0, import_lodash_es.cloneDeep)(item);
|
|
357
|
+
const metadata = mergedItem.metadata || {};
|
|
358
|
+
delete metadata._promotion;
|
|
359
|
+
mergedItem.metadata = metadata;
|
|
360
|
+
if (Array.isArray(mergedItem.product_bundle)) {
|
|
361
|
+
for (const bundle of mergedItem.product_bundle) {
|
|
362
|
+
if (bundle && typeof bundle === "object")
|
|
363
|
+
delete bundle._promotion;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
groups.set(key, { item: mergedItem, originalListIndex });
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
existing.item.num = (0, import_utils2.getSafeProductNum)(
|
|
370
|
+
Number(existing.item.num || 0) + Number(item.num || 0)
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
return Array.from(groups.values());
|
|
374
|
+
}
|
|
375
|
+
function splitXItemsPromoLinesByGroup(lines, strategyActionMap) {
|
|
376
|
+
var _a;
|
|
377
|
+
const result = [];
|
|
378
|
+
for (const line of lines) {
|
|
379
|
+
const promo = (_a = line == null ? void 0 : line.metadata) == null ? void 0 : _a._promotion;
|
|
380
|
+
if (!(promo == null ? void 0 : promo.inPromotion) || !promo.strategyId) {
|
|
381
|
+
result.push(line);
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
if (getPromotionActionType(promo) !== X_ITEMS_FOR_Y_PRICE) {
|
|
385
|
+
result.push(line);
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
const actionMeta = strategyActionMap.get(promo.strategyId);
|
|
389
|
+
const detail = (actionMeta == null ? void 0 : actionMeta.actionDetail) ?? promo.actionDetail;
|
|
390
|
+
const x = Number(detail == null ? void 0 : detail.x);
|
|
391
|
+
const num = Number(line.num || 0);
|
|
392
|
+
const isCumulative = (detail == null ? void 0 : detail.cumulative) !== false;
|
|
393
|
+
if (!isCumulative || !Number.isFinite(x) || x <= 0 || num <= x || num % x !== 0) {
|
|
394
|
+
result.push(line);
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
const groupCount = num / x;
|
|
398
|
+
for (let i = 0; i < groupCount; i++) {
|
|
399
|
+
const splitLine = (0, import_lodash_es.cloneDeep)(line);
|
|
400
|
+
splitLine.num = (0, import_utils2.getSafeProductNum)(x);
|
|
401
|
+
splitLine.metadata = {
|
|
402
|
+
...splitLine.metadata || {},
|
|
403
|
+
unique_identification_number: (0, import_utils.createUuidV4)()
|
|
404
|
+
};
|
|
405
|
+
result.push(splitLine);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return result;
|
|
409
|
+
}
|
|
312
410
|
function generateNumericId() {
|
|
313
411
|
return Math.floor(Math.random() * 1e9) + Date.now();
|
|
314
412
|
}
|
|
315
413
|
function convertToPromotionProduct(product, index) {
|
|
316
414
|
const metadata = (product == null ? void 0 : product.metadata) || {};
|
|
317
415
|
const numericId = generateNumericId();
|
|
416
|
+
const originalItem = product;
|
|
318
417
|
return {
|
|
319
418
|
id: numericId,
|
|
320
419
|
product_id: Number((product == null ? void 0 : product.product_id) ?? 0) || 0,
|
|
@@ -323,7 +422,7 @@ function convertToPromotionProduct(product, index) {
|
|
|
323
422
|
price: getOrderProductOriginalPriceForPromotion(product),
|
|
324
423
|
quantity: Number((product == null ? void 0 : product.num) ?? 1) || 1,
|
|
325
424
|
bundle: getProductBundleForEvaluator(product),
|
|
326
|
-
_originalItem:
|
|
425
|
+
_originalItem: originalItem,
|
|
327
426
|
_originalId: getOrderProductUid(product),
|
|
328
427
|
_originalIndex: index
|
|
329
428
|
};
|
|
@@ -548,7 +647,10 @@ function processCartPromotion(list, evaluator, options) {
|
|
|
548
647
|
mainProductsWithIndex.push({ item, originalListIndex: i });
|
|
549
648
|
}
|
|
550
649
|
}
|
|
551
|
-
const
|
|
650
|
+
const consolidatedMainProductsWithIndex = consolidateMainProductsForPromotion(
|
|
651
|
+
mainProductsWithIndex
|
|
652
|
+
);
|
|
653
|
+
const mainProducts = consolidatedMainProductsWithIndex.map((x) => x.item);
|
|
552
654
|
const existingGifts = existingGiftsWithIndex.map((x) => x.item);
|
|
553
655
|
if (mainProducts.length === 0) {
|
|
554
656
|
const editProducts = editProductsWithIndex.map((x) => x.item);
|
|
@@ -574,7 +676,7 @@ function processCartPromotion(list, evaluator, options) {
|
|
|
574
676
|
}
|
|
575
677
|
const promotionProducts = [];
|
|
576
678
|
const originalItemMap = /* @__PURE__ */ new Map();
|
|
577
|
-
const productsForStrategies =
|
|
679
|
+
const productsForStrategies = consolidatedMainProductsWithIndex.map(({ item }, i) => {
|
|
578
680
|
var _a2;
|
|
579
681
|
return {
|
|
580
682
|
id: i,
|
|
@@ -586,8 +688,8 @@ function processCartPromotion(list, evaluator, options) {
|
|
|
586
688
|
bundle: getProductBundleForEvaluator(item)
|
|
587
689
|
};
|
|
588
690
|
});
|
|
589
|
-
for (let i = 0; i <
|
|
590
|
-
const { item, originalListIndex } =
|
|
691
|
+
for (let i = 0; i < consolidatedMainProductsWithIndex.length; i++) {
|
|
692
|
+
const { item, originalListIndex } = consolidatedMainProductsWithIndex[i];
|
|
591
693
|
const promotionProduct = convertToPromotionProduct(item, originalListIndex);
|
|
592
694
|
promotionProducts.push(promotionProduct);
|
|
593
695
|
originalItemMap.set(promotionProduct.id, { item, index: originalListIndex });
|
|
@@ -765,6 +867,8 @@ function processCartPromotion(list, evaluator, options) {
|
|
|
765
867
|
processedProducts.splice(0, processedProducts.length, ...dedupedPromotionLines);
|
|
766
868
|
const mergedPromotionLines = mergeIdenticalPromotionCartLines(processedProducts);
|
|
767
869
|
processedProducts.splice(0, processedProducts.length, ...mergedPromotionLines);
|
|
870
|
+
const splitPromoLines = splitXItemsPromoLinesByGroup(processedProducts, strategyActionMap);
|
|
871
|
+
processedProducts.splice(0, processedProducts.length, ...splitPromoLines);
|
|
768
872
|
for (const product of processedProducts) {
|
|
769
873
|
const metadata = product.metadata || {};
|
|
770
874
|
if (metadata._promotion)
|
|
@@ -812,6 +916,7 @@ function processCartPromotion(list, evaluator, options) {
|
|
|
812
916
|
delete product._sortIndex;
|
|
813
917
|
delete product._sortSubIndex;
|
|
814
918
|
delete product._originalProductUid;
|
|
919
|
+
delete product._sourceCartNum;
|
|
815
920
|
}
|
|
816
921
|
return {
|
|
817
922
|
products: processedProducts,
|
|
@@ -824,6 +929,7 @@ function processCartPromotion(list, evaluator, options) {
|
|
|
824
929
|
// Annotate the CommonJS export names for ESM import in node:
|
|
825
930
|
0 && (module.exports = {
|
|
826
931
|
appendPromotionTags,
|
|
932
|
+
buildConsolidateKeyForPromotion,
|
|
827
933
|
calculateUnfulfilledPromotions,
|
|
828
934
|
extractProductMatchIdentifiersFromStrategyConfig,
|
|
829
935
|
getOrderProductBasePrice,
|
|
@@ -311,7 +311,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
311
311
|
date: string;
|
|
312
312
|
status: string;
|
|
313
313
|
week: string;
|
|
314
|
-
weekNum: 0 |
|
|
314
|
+
weekNum: 0 | 5 | 1 | 4 | 2 | 3 | 6;
|
|
315
315
|
}[]>;
|
|
316
316
|
submitTimeSlot(timeSlots: TimeSliceItem): void;
|
|
317
317
|
private getScheduleDataByIds;
|
|
@@ -520,6 +520,7 @@ var BookingTicketImpl = class extends import_BaseSales.BaseSalesImpl {
|
|
|
520
520
|
return;
|
|
521
521
|
}
|
|
522
522
|
const previousCustomerId = (_a = this.store.order.getOrderCustomer()) == null ? void 0 : _a.customer_id;
|
|
523
|
+
const snapshotBeforeSet = this.store.order.getOrderCustomerSnapshot();
|
|
523
524
|
const patch = (0, import_orderCustomer.formatOrderCustomerPatch)(customer);
|
|
524
525
|
const customerUnchanged = Number(previousCustomerId || 0) === Number(patch.customer_id || 0);
|
|
525
526
|
if (!customerUnchanged) {
|
|
@@ -527,7 +528,13 @@ var BookingTicketImpl = class extends import_BaseSales.BaseSalesImpl {
|
|
|
527
528
|
this.hasManualDiscountSelection = false;
|
|
528
529
|
}
|
|
529
530
|
this.store.order.setOrderCustomer(patch, customer);
|
|
531
|
+
const snapshotAfterOrderSet = this.store.order.getOrderCustomerSnapshot();
|
|
530
532
|
if (customerUnchanged) {
|
|
533
|
+
const snapshotReplenished = !snapshotBeforeSet && Boolean(snapshotAfterOrderSet);
|
|
534
|
+
if (snapshotReplenished) {
|
|
535
|
+
const next2 = this.buildOrderCustomerPayload();
|
|
536
|
+
this.core.effects.emit(`${this.name}:onOrderCustomerChange`, next2);
|
|
537
|
+
}
|
|
531
538
|
return;
|
|
532
539
|
}
|
|
533
540
|
const next = this.buildOrderCustomerPayload();
|