@pisell/pisellos 2.2.23 → 2.2.24
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/modules/Cart/utils/cartProduct.js +21 -4
- package/dist/modules/Customer/index.js +1 -1
- package/dist/modules/Discount/index.js +3 -3
- package/dist/modules/Discount/types.d.ts +9 -0
- package/dist/modules/Order/utils.js +1 -1
- package/dist/modules/Rules/index.js +401 -102
- package/dist/modules/Summary/utils.d.ts +5 -0
- package/dist/modules/Summary/utils.js +36 -1
- package/dist/solution/BookingByStep/index.d.ts +1 -0
- package/dist/solution/BookingByStep/index.js +12 -1
- package/dist/solution/Checkout/index.js +181 -108
- package/dist/solution/ShopDiscount/index.js +4 -3
- package/dist/solution/ShopDiscount/utils.d.ts +24 -0
- package/dist/solution/ShopDiscount/utils.js +135 -1
- package/lib/modules/Cart/utils/cartProduct.js +22 -6
- package/lib/modules/Customer/index.js +1 -1
- package/lib/modules/Discount/index.js +3 -3
- package/lib/modules/Discount/types.d.ts +9 -0
- package/lib/modules/Order/utils.js +1 -1
- package/lib/modules/Rules/index.js +290 -63
- package/lib/modules/Summary/utils.d.ts +5 -0
- package/lib/modules/Summary/utils.js +27 -3
- package/lib/solution/BookingByStep/index.d.ts +1 -0
- package/lib/solution/BookingByStep/index.js +12 -1
- package/lib/solution/Checkout/index.js +45 -6
- package/lib/solution/ShopDiscount/index.js +6 -6
- package/lib/solution/ShopDiscount/utils.d.ts +24 -0
- package/lib/solution/ShopDiscount/utils.js +88 -1
- package/package.json +1 -1
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
6
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
1
7
|
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
2
8
|
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
3
9
|
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
@@ -45,7 +51,8 @@ export var getDiscountAmount = function getDiscountAmount(discount, total, price
|
|
|
45
51
|
|
|
46
52
|
// 固定金额 小于0时返回0
|
|
47
53
|
if (isFixedAmount) {
|
|
48
|
-
|
|
54
|
+
var _discount$amount;
|
|
55
|
+
return Math.max(new Decimal(price).minus(new Decimal(((_discount$amount = discount.amount) !== null && _discount$amount !== void 0 ? _discount$amount : discount.par_value) || 0)).toNumber(), 0);
|
|
49
56
|
}
|
|
50
57
|
|
|
51
58
|
// 百分比:根据折扣卡金额计算
|
|
@@ -462,4 +469,131 @@ export var filterDiscountListByBookingTime = function filterDiscountListByBookin
|
|
|
462
469
|
return true;
|
|
463
470
|
}
|
|
464
471
|
});
|
|
472
|
+
};
|
|
473
|
+
/**
|
|
474
|
+
* 判断是否是订单级别的固定金额折扣卡
|
|
475
|
+
* @param discount 折扣
|
|
476
|
+
* @returns 是否是订单级别的固定金额折扣卡
|
|
477
|
+
*/
|
|
478
|
+
export var isOrderLevelFixedAmountDiscount = function isOrderLevelFixedAmountDiscount(discount) {
|
|
479
|
+
var _discount$metadata3, _discount$metadata4;
|
|
480
|
+
return discount.tag === 'product_discount_card' && (discount === null || discount === void 0 || (_discount$metadata3 = discount.metadata) === null || _discount$metadata3 === void 0 ? void 0 : _discount$metadata3.discount_card_type) === 'fixed_amount' && (discount === null || discount === void 0 || (_discount$metadata4 = discount.metadata) === null || _discount$metadata4 === void 0 ? void 0 : _discount$metadata4.discount_calculation_mode) === 'order_level';
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* 计算订单级别固定金额折扣卡的分摊结果
|
|
485
|
+
* @param discount 折扣卡
|
|
486
|
+
* @param applicableProducts 适用商品列表 { productId, amount, quantity, parentQuantity }
|
|
487
|
+
* @returns 分摊结果 Map<productId, { discountAmount, difference }>
|
|
488
|
+
* 注意:
|
|
489
|
+
* - discountAmount 是单价折扣金额(不是总折扣金额)
|
|
490
|
+
* - difference(总差值)优先直接加到数量为1的单商品折扣上,如果没有则存储在metadata中
|
|
491
|
+
*/
|
|
492
|
+
export var calculateOrderLevelDiscountAllocation = function calculateOrderLevelDiscountAllocation(discount, applicableProducts) {
|
|
493
|
+
var result = new Map();
|
|
494
|
+
if (applicableProducts.length === 0) {
|
|
495
|
+
return result;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// 计算适用商品的总金额(数量 × 单价)
|
|
499
|
+
var totalAmount = applicableProducts.reduce(function (acc, product) {
|
|
500
|
+
return new Decimal(acc).plus(new Decimal(product.amount).mul(product.quantity)).toNumber();
|
|
501
|
+
}, 0);
|
|
502
|
+
if (totalAmount <= 0) {
|
|
503
|
+
return result;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// 固定减免金额
|
|
507
|
+
var fixedAmount = new Decimal(discount.par_value || 0).toNumber();
|
|
508
|
+
|
|
509
|
+
// 如果固定金额 >= 商品总金额,折扣最高为商品金额(免费)
|
|
510
|
+
var actualDiscountTotal = Math.min(fixedAmount, totalAmount);
|
|
511
|
+
|
|
512
|
+
// 计算每个商品的单价折扣金额
|
|
513
|
+
var allocatedTotal = new Decimal(0);
|
|
514
|
+
applicableProducts.forEach(function (product) {
|
|
515
|
+
// 🔥 分摊公式改为:(单价 / 适用商品总金额) × 固定金额
|
|
516
|
+
// 这样只有一次取整,避免精度损失
|
|
517
|
+
var rawDiscountPerItem = new Decimal(product.amount).div(totalAmount).mul(actualDiscountTotal);
|
|
518
|
+
|
|
519
|
+
// 保留两位小数,向下取整(单价折扣)
|
|
520
|
+
var discountAmountPerItem = rawDiscountPerItem.toDecimalPlaces(2, Decimal.ROUND_DOWN).toNumber();
|
|
521
|
+
result.set(product.productId, {
|
|
522
|
+
discountAmount: discountAmountPerItem,
|
|
523
|
+
// 单价折扣金额
|
|
524
|
+
difference: 0 // 默认差值为0
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
// 累加实际分配的总折扣金额(单价折扣 × 数量)
|
|
528
|
+
allocatedTotal = allocatedTotal.plus(new Decimal(discountAmountPerItem).mul(product.quantity));
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
// 🔥 计算总差值
|
|
532
|
+
// 总差值 = 固定金额 - 所有商品的 (单价折扣 × 数量) 之和
|
|
533
|
+
var totalDifference = new Decimal(actualDiscountTotal).minus(allocatedTotal).toDecimalPlaces(2, Decimal.ROUND_HALF_UP).toNumber();
|
|
534
|
+
if (totalDifference > 0) {
|
|
535
|
+
// 🔥 判断商品是否是真正的"数量为1"
|
|
536
|
+
// 主商品:quantity === 1
|
|
537
|
+
// 子商品:quantity === 1 且 parentQuantity === 1
|
|
538
|
+
var isSingleQuantity = function isSingleQuantity(product) {
|
|
539
|
+
if (product.parentQuantity !== undefined) {
|
|
540
|
+
// 子商品:需要同时满足自身数量为1且主商品数量为1
|
|
541
|
+
return product.quantity === 1 && product.parentQuantity === 1;
|
|
542
|
+
}
|
|
543
|
+
// 主商品:只需要自身数量为1
|
|
544
|
+
return product.quantity === 1;
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
// 🔥 筛选出数量为1的商品
|
|
548
|
+
var singleQuantityProducts = applicableProducts.filter(isSingleQuantity);
|
|
549
|
+
if (singleQuantityProducts.length > 0) {
|
|
550
|
+
// 🔥 优先级1:找到有足够剩余空间且金额最大的商品
|
|
551
|
+
// 剩余空间 = 商品价格 - 当前折扣金额 >= 差值
|
|
552
|
+
var productsWithEnoughSpace = singleQuantityProducts.filter(function (product) {
|
|
553
|
+
var allocation = result.get(product.productId);
|
|
554
|
+
if (!allocation) return false;
|
|
555
|
+
var remainingSpace = new Decimal(product.amount).minus(allocation.discountAmount).toNumber();
|
|
556
|
+
return remainingSpace >= totalDifference;
|
|
557
|
+
});
|
|
558
|
+
if (productsWithEnoughSpace.length > 0) {
|
|
559
|
+
// 按金额降序排序,选择金额最大的
|
|
560
|
+
productsWithEnoughSpace.sort(function (a, b) {
|
|
561
|
+
return b.amount - a.amount;
|
|
562
|
+
});
|
|
563
|
+
var targetProduct = productsWithEnoughSpace[0];
|
|
564
|
+
var targetAllocation = result.get(targetProduct.productId);
|
|
565
|
+
if (targetAllocation) {
|
|
566
|
+
// 差值直接加到折扣金额上
|
|
567
|
+
result.set(targetProduct.productId, {
|
|
568
|
+
discountAmount: new Decimal(targetAllocation.discountAmount).plus(totalDifference).toNumber(),
|
|
569
|
+
difference: 0 // 不需要存储差值
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
} else {
|
|
573
|
+
// 🔥 优先级2:所有数量为1的商品都没有足够剩余空间
|
|
574
|
+
// 选择金额最大的商品,差值存储在metadata中
|
|
575
|
+
singleQuantityProducts.sort(function (a, b) {
|
|
576
|
+
return b.amount - a.amount;
|
|
577
|
+
});
|
|
578
|
+
var _targetProduct = singleQuantityProducts[0];
|
|
579
|
+
var _targetAllocation = result.get(_targetProduct.productId);
|
|
580
|
+
if (_targetAllocation) {
|
|
581
|
+
result.set(_targetProduct.productId, _objectSpread(_objectSpread({}, _targetAllocation), {}, {
|
|
582
|
+
difference: totalDifference
|
|
583
|
+
}));
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
} else {
|
|
587
|
+
// 🔥 优先级3:没有数量为1的商品,走原有逻辑
|
|
588
|
+
// 差值存储在最后一个商品的metadata中
|
|
589
|
+
var lastProduct = applicableProducts[applicableProducts.length - 1];
|
|
590
|
+
var lastProductAllocation = result.get(lastProduct.productId);
|
|
591
|
+
if (lastProductAllocation) {
|
|
592
|
+
result.set(lastProduct.productId, _objectSpread(_objectSpread({}, lastProductAllocation), {}, {
|
|
593
|
+
difference: totalDifference
|
|
594
|
+
}));
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
return result;
|
|
465
599
|
};
|
|
@@ -139,7 +139,7 @@ var formatProductToCartItem = (params) => {
|
|
|
139
139
|
return cartItem;
|
|
140
140
|
};
|
|
141
141
|
var formatProductToCartItemOrigin = (params) => {
|
|
142
|
-
var _a, _b, _c, _d;
|
|
142
|
+
var _a, _b, _c, _d, _e;
|
|
143
143
|
const {
|
|
144
144
|
cartItem,
|
|
145
145
|
product,
|
|
@@ -149,17 +149,27 @@ var formatProductToCartItemOrigin = (params) => {
|
|
|
149
149
|
quantity = 1
|
|
150
150
|
} = params;
|
|
151
151
|
let origin = cartItem._origin;
|
|
152
|
+
const product_discount_difference = (((_a = origin.product) == null ? void 0 : _a.discount_list) || []).filter((item) => {
|
|
153
|
+
var _a2;
|
|
154
|
+
return !((_a2 = item == null ? void 0 : item.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id);
|
|
155
|
+
}).reduce((pre, cur) => {
|
|
156
|
+
var _a2;
|
|
157
|
+
return pre + (((_a2 = cur == null ? void 0 : cur.metadata) == null ? void 0 : _a2.product_discount_difference) || 0);
|
|
158
|
+
}, 0);
|
|
152
159
|
if (product) {
|
|
153
160
|
origin.product = {
|
|
154
161
|
...origin.product || {},
|
|
155
162
|
num: quantity,
|
|
156
163
|
product_id: product.id,
|
|
157
164
|
product_variant_id: product_variant_id || 0,
|
|
158
|
-
product_bundle: ((
|
|
159
|
-
product_option_item: ((
|
|
165
|
+
product_bundle: ((_b = origin.product) == null ? void 0 : _b.product_bundle) || [],
|
|
166
|
+
product_option_item: ((_c = origin.product) == null ? void 0 : _c.product_option_item) || [],
|
|
167
|
+
metadata: {
|
|
168
|
+
product_discount_difference
|
|
169
|
+
}
|
|
160
170
|
};
|
|
161
|
-
origin.sub_type = (
|
|
162
|
-
origin.duration = (
|
|
171
|
+
origin.sub_type = (_d = product == null ? void 0 : product.duration) == null ? void 0 : _d.type;
|
|
172
|
+
origin.duration = (_e = product == null ? void 0 : product.duration) == null ? void 0 : _e.value;
|
|
163
173
|
if (bundle == null ? void 0 : bundle.length) {
|
|
164
174
|
origin.product.product_bundle = formatBundleToOrigin(bundle);
|
|
165
175
|
}
|
|
@@ -176,6 +186,7 @@ var getProductTotalPrice = (params) => {
|
|
|
176
186
|
discounts.forEach((currentValue) => {
|
|
177
187
|
var _a;
|
|
178
188
|
price = (0, import_utils2.getDiscountAmount)({
|
|
189
|
+
amount: currentValue.amount,
|
|
179
190
|
tag: currentValue.type,
|
|
180
191
|
par_value: currentValue.discount.percent,
|
|
181
192
|
metadata: {
|
|
@@ -272,6 +283,10 @@ var formatBundleToOrigin = (bundle) => {
|
|
|
272
283
|
var _a;
|
|
273
284
|
return (d == null ? void 0 : d[key]) || ((_a = d == null ? void 0 : d.originBundleItem) == null ? void 0 : _a[key]);
|
|
274
285
|
};
|
|
286
|
+
const product_discount_difference = ((d == null ? void 0 : d.discount_list) || []).reduce((pre, cur) => {
|
|
287
|
+
var _a;
|
|
288
|
+
return pre + (((_a = cur == null ? void 0 : cur.metadata) == null ? void 0 : _a.product_discount_difference) || 0);
|
|
289
|
+
}, 0);
|
|
275
290
|
return {
|
|
276
291
|
bundle_group_id: getBundleValueByKey("group_id"),
|
|
277
292
|
bundle_id: d.id,
|
|
@@ -284,7 +299,8 @@ var formatBundleToOrigin = (bundle) => {
|
|
|
284
299
|
discount_list: d.discount_list,
|
|
285
300
|
"bundle_selling_price": d == null ? void 0 : d.price,
|
|
286
301
|
metadata: {
|
|
287
|
-
custom_product_bundle_map_id: d._id
|
|
302
|
+
custom_product_bundle_map_id: d._id,
|
|
303
|
+
product_discount_difference
|
|
288
304
|
}
|
|
289
305
|
};
|
|
290
306
|
});
|
|
@@ -102,7 +102,7 @@ var CustomerModule = class extends import_BaseModule.BaseModule {
|
|
|
102
102
|
skip,
|
|
103
103
|
num,
|
|
104
104
|
sort_by: import_constants.SORT_BY,
|
|
105
|
-
with: ["latestWalletDetail.wallet", "contactsInfo"],
|
|
105
|
+
with: ["latestWalletDetail.wallet", "contactsInfo", "formRecord"],
|
|
106
106
|
search_wallet_flag: 1,
|
|
107
107
|
search_wallet_pass_flag: 1,
|
|
108
108
|
...search && { search },
|
|
@@ -109,7 +109,7 @@ var DiscountModule = class extends import_BaseModule.BaseModule {
|
|
|
109
109
|
tags: ["good_pass", "product_discount_card"],
|
|
110
110
|
available: 1,
|
|
111
111
|
relation_product: 1,
|
|
112
|
-
with: ["extensionData", "holder.detail"],
|
|
112
|
+
with: ["extensionData", "customScheduleSnapshot", "holder.detail"],
|
|
113
113
|
order_behavior_count: 1,
|
|
114
114
|
order_behavior_count_customer_id: customerId || 1
|
|
115
115
|
});
|
|
@@ -176,9 +176,9 @@ var DiscountModule = class extends import_BaseModule.BaseModule {
|
|
|
176
176
|
}
|
|
177
177
|
if (discount.appliedProductDetails) {
|
|
178
178
|
return discount.appliedProductDetails.reduce((total, product) => {
|
|
179
|
-
var _a;
|
|
179
|
+
var _a, _b;
|
|
180
180
|
const price = new import_decimal.default(((_a = product == null ? void 0 : product.discount) == null ? void 0 : _a.fixed_amount) || 0).mul((product == null ? void 0 : product._num) || 1);
|
|
181
|
-
return new import_decimal.default(total).plus(price).toNumber();
|
|
181
|
+
return new import_decimal.default(total).plus(price).add(((_b = product == null ? void 0 : product.metadata) == null ? void 0 : _b.product_discount_difference) || 0).toNumber();
|
|
182
182
|
}, 0);
|
|
183
183
|
}
|
|
184
184
|
}
|
|
@@ -33,6 +33,9 @@ interface ApplicableProductDetails {
|
|
|
33
33
|
title: string;
|
|
34
34
|
original_amount: string;
|
|
35
35
|
num: number;
|
|
36
|
+
metadata?: {
|
|
37
|
+
product_discount_difference?: number;
|
|
38
|
+
};
|
|
36
39
|
discount?: {
|
|
37
40
|
fixed_amount?: number;
|
|
38
41
|
product_id?: number;
|
|
@@ -81,6 +84,10 @@ export interface Discount {
|
|
|
81
84
|
discount_card_type?: 'fixed_amount' | 'percent';
|
|
82
85
|
custom_product_bundle_map_id?: string;
|
|
83
86
|
validity_type?: "custom_schedule_validity" | "fixed_validity";
|
|
87
|
+
discount_calculation_mode: 'item_level' | 'order_level';
|
|
88
|
+
holder: {
|
|
89
|
+
type: "customer" | "custom";
|
|
90
|
+
};
|
|
84
91
|
};
|
|
85
92
|
product: Product;
|
|
86
93
|
type: "product" | 'good_pass';
|
|
@@ -89,7 +96,9 @@ export interface Discount {
|
|
|
89
96
|
isEditMode?: boolean;
|
|
90
97
|
isScan?: boolean;
|
|
91
98
|
discount?: {
|
|
99
|
+
discount_product_id: number;
|
|
92
100
|
resource_id: number;
|
|
101
|
+
discount_calculation_mode: 'item_level' | 'order_level';
|
|
93
102
|
};
|
|
94
103
|
isManualSelect?: boolean;
|
|
95
104
|
isDisabled?: boolean;
|
|
@@ -60,7 +60,7 @@ var getAllDiscountList = (cartItem) => {
|
|
|
60
60
|
var _a, _b, _c, _d;
|
|
61
61
|
let discountList = ((_b = (_a = cartItem == null ? void 0 : cartItem._origin) == null ? void 0 : _a.product) == null ? void 0 : _b.discount_list) || [];
|
|
62
62
|
(((_d = (_c = cartItem == null ? void 0 : cartItem._origin) == null ? void 0 : _c.product) == null ? void 0 : _d.product_bundle) || []).forEach((item) => {
|
|
63
|
-
discountList = [...discountList, ...item.discount_list || []];
|
|
63
|
+
discountList = [...discountList, ...(item == null ? void 0 : item.discount_list) || []];
|
|
64
64
|
item.discount_list = void 0;
|
|
65
65
|
});
|
|
66
66
|
return discountList;
|