@pisell/pisellos 2.1.54 → 2.1.59
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/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/modules/Cart/types.d.ts +0 -2
- package/dist/modules/Cart/utils/cartProduct.js +0 -11
- package/dist/modules/Discount/types.d.ts +2 -15
- package/dist/modules/Payment/index.d.ts +1 -2
- package/dist/modules/Payment/index.js +7 -10
- package/dist/modules/Payment/utils.js +0 -3
- package/dist/modules/Payment/walletpass.d.ts +0 -23
- package/dist/modules/Payment/walletpass.js +95 -191
- package/dist/modules/Rules/index.d.ts +5 -8
- package/dist/modules/Rules/index.js +31 -154
- package/dist/modules/Rules/types.d.ts +1 -1
- package/dist/modules/Summary/types.d.ts +0 -2
- package/dist/modules/Summary/utils.d.ts +0 -6
- package/dist/modules/Summary/utils.js +0 -21
- package/dist/plugins/window.d.ts +0 -2
- package/dist/solution/BookingByStep/index.d.ts +1 -2
- package/dist/solution/Checkout/index.js +0 -2
- package/dist/solution/ShopDiscount/index.d.ts +4 -1
- package/dist/solution/ShopDiscount/index.js +11 -12
- package/dist/solution/ShopDiscount/types.d.ts +4 -1
- package/dist/solution/ShopDiscount/utils.js +28 -29
- package/lib/index.d.ts +0 -1
- package/lib/index.js +1 -3
- package/lib/modules/Cart/types.d.ts +0 -2
- package/lib/modules/Cart/utils/cartProduct.js +0 -9
- package/lib/modules/Discount/types.d.ts +2 -15
- package/lib/modules/Payment/index.d.ts +1 -2
- package/lib/modules/Payment/index.js +0 -1
- package/lib/modules/Payment/utils.js +0 -3
- package/lib/modules/Payment/walletpass.d.ts +0 -23
- package/lib/modules/Payment/walletpass.js +17 -94
- package/lib/modules/Rules/index.d.ts +5 -8
- package/lib/modules/Rules/index.js +197 -372
- package/lib/modules/Rules/types.d.ts +1 -1
- package/lib/modules/Summary/types.d.ts +0 -2
- package/lib/modules/Summary/utils.d.ts +0 -6
- package/lib/modules/Summary/utils.js +0 -15
- package/lib/plugins/window.d.ts +0 -2
- package/lib/solution/BookingByStep/index.d.ts +1 -2
- package/lib/solution/Checkout/index.js +0 -2
- package/lib/solution/ShopDiscount/index.d.ts +4 -1
- package/lib/solution/ShopDiscount/index.js +9 -8
- package/lib/solution/ShopDiscount/types.d.ts +4 -1
- package/lib/solution/ShopDiscount/utils.js +18 -13
- package/package.json +1 -1
- package/dist/model/index.d.ts +0 -1
- package/dist/model/index.js +0 -1
- package/dist/model/strategy/adapter/index.d.ts +0 -3
- package/dist/model/strategy/adapter/index.js +0 -4
- package/dist/model/strategy/adapter/type.d.ts +0 -28
- package/dist/model/strategy/adapter/type.js +0 -1
- package/dist/model/strategy/adapter/walletPass/evaluator.d.ts +0 -84
- package/dist/model/strategy/adapter/walletPass/evaluator.js +0 -496
- package/dist/model/strategy/adapter/walletPass/example.d.ts +0 -4
- package/dist/model/strategy/adapter/walletPass/example.js +0 -258
- package/dist/model/strategy/adapter/walletPass/index.d.ts +0 -32
- package/dist/model/strategy/adapter/walletPass/index.js +0 -182
- package/dist/model/strategy/adapter/walletPass/locales.d.ts +0 -1
- package/dist/model/strategy/adapter/walletPass/locales.js +0 -23
- package/dist/model/strategy/adapter/walletPass/type.d.ts +0 -163
- package/dist/model/strategy/adapter/walletPass/type.js +0 -1
- package/dist/model/strategy/adapter/walletPass/utils.d.ts +0 -50
- package/dist/model/strategy/adapter/walletPass/utils.js +0 -965
- package/dist/model/strategy/index.d.ts +0 -94
- package/dist/model/strategy/index.js +0 -551
- package/dist/model/strategy/strategy-example.d.ts +0 -5
- package/dist/model/strategy/strategy-example.js +0 -331
- package/dist/model/strategy/type.d.ts +0 -228
- package/dist/model/strategy/type.js +0 -94
- package/lib/model/index.d.ts +0 -1
- package/lib/model/index.js +0 -23
- package/lib/model/strategy/adapter/index.d.ts +0 -3
- package/lib/model/strategy/adapter/index.js +0 -45
- package/lib/model/strategy/adapter/type.d.ts +0 -28
- package/lib/model/strategy/adapter/type.js +0 -17
- package/lib/model/strategy/adapter/walletPass/evaluator.d.ts +0 -84
- package/lib/model/strategy/adapter/walletPass/evaluator.js +0 -420
- package/lib/model/strategy/adapter/walletPass/example.d.ts +0 -4
- package/lib/model/strategy/adapter/walletPass/example.js +0 -207
- package/lib/model/strategy/adapter/walletPass/index.d.ts +0 -32
- package/lib/model/strategy/adapter/walletPass/index.js +0 -142
- package/lib/model/strategy/adapter/walletPass/locales.d.ts +0 -1
- package/lib/model/strategy/adapter/walletPass/locales.js +0 -51
- package/lib/model/strategy/adapter/walletPass/type.d.ts +0 -163
- package/lib/model/strategy/adapter/walletPass/type.js +0 -17
- package/lib/model/strategy/adapter/walletPass/utils.d.ts +0 -50
- package/lib/model/strategy/adapter/walletPass/utils.js +0 -660
- package/lib/model/strategy/index.d.ts +0 -94
- package/lib/model/strategy/index.js +0 -413
- package/lib/model/strategy/strategy-example.d.ts +0 -5
- package/lib/model/strategy/strategy-example.js +0 -318
- package/lib/model/strategy/type.d.ts +0 -228
- package/lib/model/strategy/type.js +0 -44
|
@@ -1,965 +0,0 @@
|
|
|
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); }
|
|
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; } } }; }
|
|
8
|
-
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
9
|
-
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
10
|
-
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); }
|
|
11
|
-
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
12
|
-
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
13
|
-
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; }
|
|
14
|
-
import Decimal from 'decimal.js';
|
|
15
|
-
// 辅助函数:根据 deductTaxAndFee 配置获取推荐使用金额
|
|
16
|
-
var getRecommendedAmount = function getRecommendedAmount(voucher) {
|
|
17
|
-
var _config$deductTaxAndF;
|
|
18
|
-
console.log('voucher312', voucher);
|
|
19
|
-
var config = voucher.config,
|
|
20
|
-
recommended_usage_amount = voucher.recommended_usage_amount,
|
|
21
|
-
recommended_pure_product_usage_amount = voucher.recommended_pure_product_usage_amount;
|
|
22
|
-
var deductTaxAndFee = (_config$deductTaxAndF = config === null || config === void 0 ? void 0 : config.deductTaxAndFee) !== null && _config$deductTaxAndF !== void 0 ? _config$deductTaxAndF : true; // 默认开启抵扣税费
|
|
23
|
-
|
|
24
|
-
// 如果开启抵扣税费,使用 recommended_usage_amount(包含税费)
|
|
25
|
-
// 如果关闭抵扣税费,使用 recommended_pure_product_usage_amount(仅商品金额)
|
|
26
|
-
return deductTaxAndFee ? recommended_usage_amount : recommended_pure_product_usage_amount !== null && recommended_pure_product_usage_amount !== void 0 ? recommended_pure_product_usage_amount : recommended_usage_amount;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
// 辅助函数:获取适用商品ID列表
|
|
30
|
-
export var getApplicableProductIds = function getApplicableProductIds(voucher) {
|
|
31
|
-
var _ref = voucher,
|
|
32
|
-
available_product_type = _ref.available_product_type,
|
|
33
|
-
available_product_ids = _ref.available_product_ids;
|
|
34
|
-
|
|
35
|
-
// 如果没有 available_product_type,默认为 product_all
|
|
36
|
-
var productType = available_product_type || 'product_all';
|
|
37
|
-
|
|
38
|
-
// product_all 时,返回 null 表示适用所有商品
|
|
39
|
-
if (productType === 'product_all') {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// product_collection 或 products 时,返回指定的商品ID列表
|
|
44
|
-
if (productType === 'product_collection' || productType === 'products') {
|
|
45
|
-
return available_product_ids || [];
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// 其他情况默认返回空数组(不适用任何商品)
|
|
49
|
-
return [];
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
// 辅助函数:计算适用商品的总金额(基于剩余金额)
|
|
53
|
-
var getApplicableProductsAmount = function getApplicableProductsAmount(voucher, productsData) {
|
|
54
|
-
var _config$deductTaxAndF2;
|
|
55
|
-
var applicableProductIds = getApplicableProductIds(voucher);
|
|
56
|
-
var config = voucher.config;
|
|
57
|
-
var deductTaxAndFee = (_config$deductTaxAndF2 = config === null || config === void 0 ? void 0 : config.deductTaxAndFee) !== null && _config$deductTaxAndF2 !== void 0 ? _config$deductTaxAndF2 : true;
|
|
58
|
-
|
|
59
|
-
// 根据券的配置选择使用哪个金额字段
|
|
60
|
-
var amountField = deductTaxAndFee ? 'remainingAmountWithTax' : 'remainingAmountPure';
|
|
61
|
-
|
|
62
|
-
// 如果为 null,适用于所有商品
|
|
63
|
-
if (applicableProductIds === null) {
|
|
64
|
-
return productsData.filter(function (p) {
|
|
65
|
-
return p[amountField].greaterThan(0);
|
|
66
|
-
}).reduce(function (sum, p) {
|
|
67
|
-
return sum.plus(p[amountField]);
|
|
68
|
-
}, new Decimal(0));
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// 如果为空数组,不适用任何商品
|
|
72
|
-
if (applicableProductIds.length === 0) {
|
|
73
|
-
return new Decimal(0);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// 计算指定商品的总金额
|
|
77
|
-
return productsData.filter(function (p) {
|
|
78
|
-
return applicableProductIds.includes(p.product_id) && p[amountField].greaterThan(0);
|
|
79
|
-
}).reduce(function (sum, p) {
|
|
80
|
-
return sum.plus(p[amountField]);
|
|
81
|
-
}, new Decimal(0));
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
// 辅助函数:获取适用的商品列表
|
|
85
|
-
var getApplicableProducts = function getApplicableProducts(voucher, productsData) {
|
|
86
|
-
var applicableProductIds = getApplicableProductIds(voucher);
|
|
87
|
-
|
|
88
|
-
// 如果为 null,适用于所有商品
|
|
89
|
-
if (applicableProductIds === null) {
|
|
90
|
-
return productsData;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// 如果为空数组,不适用任何商品
|
|
94
|
-
if (applicableProductIds.length === 0) {
|
|
95
|
-
return [];
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// 返回指定的商品列表
|
|
99
|
-
return productsData.filter(function (p) {
|
|
100
|
-
return applicableProductIds.includes(p.product_id);
|
|
101
|
-
});
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* 优惠券处理函数
|
|
106
|
-
* @param applicableVouchers 可用的券列表
|
|
107
|
-
* @param orderTotalAmount 订单总金额
|
|
108
|
-
* @param products 订单商品列表
|
|
109
|
-
* @returns 返回推荐券列表和全部列表,每个券包含 _available_max_amount 和 _unified_available_status
|
|
110
|
-
*/
|
|
111
|
-
export function processVouchers(applicableVouchers, orderTotalAmount, products) {
|
|
112
|
-
console.log(products, 'products123');
|
|
113
|
-
|
|
114
|
-
// 拆分商品数据,同时维护含税和不含税两个金额池
|
|
115
|
-
// remainingAmountWithTax: 含税费的剩余可抵扣金额
|
|
116
|
-
// remainingAmountPure: 纯商品金额(不含税费)的剩余可抵扣金额
|
|
117
|
-
// 在抵扣时,会根据券的 deductTaxAndFee 配置选择从哪个金额池扣除
|
|
118
|
-
var productsCopy = expandProductsWithBundleItems(products, true);
|
|
119
|
-
var remainingOrderAmount = new Decimal(orderTotalAmount); // 订单剩余应付金额
|
|
120
|
-
|
|
121
|
-
// 辅助函数:计算单张券的 _available_max_amount
|
|
122
|
-
var calculateAvailableMaxAmount = function calculateAvailableMaxAmount(voucher, productsData) {
|
|
123
|
-
var config = voucher.config;
|
|
124
|
-
var _ref2 = config !== null && config !== void 0 ? config : {},
|
|
125
|
-
_ref2$maxDeductionAmo = _ref2.maxDeductionAmount,
|
|
126
|
-
maxDeductionAmount = _ref2$maxDeductionAmo === void 0 ? 0 : _ref2$maxDeductionAmo,
|
|
127
|
-
_ref2$allowCrossProdu = _ref2.allowCrossProduct,
|
|
128
|
-
allowCrossProduct = _ref2$allowCrossProdu === void 0 ? true : _ref2$allowCrossProdu,
|
|
129
|
-
_ref2$applicableProdu = _ref2.applicableProductLimit,
|
|
130
|
-
applicableProductLimit = _ref2$applicableProdu === void 0 ? 0 : _ref2$applicableProdu,
|
|
131
|
-
_ref2$deductTaxAndFee = _ref2.deductTaxAndFee,
|
|
132
|
-
deductTaxAndFee = _ref2$deductTaxAndFee === void 0 ? true : _ref2$deductTaxAndFee;
|
|
133
|
-
|
|
134
|
-
// 根据 deductTaxAndFee 配置获取推荐金额
|
|
135
|
-
var recommendedAmount = getRecommendedAmount(voucher);
|
|
136
|
-
|
|
137
|
-
// 基础值 = min(recommendedAmount, maxDeductionAmount)
|
|
138
|
-
var baseAmount = Decimal.min(new Decimal(recommendedAmount), new Decimal(maxDeductionAmount));
|
|
139
|
-
|
|
140
|
-
// 根据券的配置选择使用哪个单价字段和金额字段
|
|
141
|
-
var unitPriceField = deductTaxAndFee ? 'unitPriceWithTax' : 'unitPricePure';
|
|
142
|
-
var amountField = deductTaxAndFee ? 'remainingAmountWithTax' : 'remainingAmountPure';
|
|
143
|
-
|
|
144
|
-
// 获取适用商品列表(只筛选有剩余金额的商品)
|
|
145
|
-
var applicableProducts = getApplicableProducts(voucher, productsData).filter(function (p) {
|
|
146
|
-
return p[amountField].greaterThan(0);
|
|
147
|
-
});
|
|
148
|
-
if (applicableProducts.length === 0) {
|
|
149
|
-
return new Decimal(0);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// 根据跨商品配置计算适用商品金额
|
|
153
|
-
var finalApplicableAmount = new Decimal(0);
|
|
154
|
-
if (allowCrossProduct) {
|
|
155
|
-
// 跨商品券:可以抵扣多个商品
|
|
156
|
-
if (applicableProductLimit > 0) {
|
|
157
|
-
// 有数量限制:按剩余金额从高到低排序,按动态计算的可抵扣数量累计直到达到 limit
|
|
158
|
-
var sortedProducts = _toConsumableArray(applicableProducts).sort(function (a, b) {
|
|
159
|
-
return a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1;
|
|
160
|
-
});
|
|
161
|
-
var remainingLimit = applicableProductLimit;
|
|
162
|
-
var _iterator = _createForOfIteratorHelper(sortedProducts),
|
|
163
|
-
_step;
|
|
164
|
-
try {
|
|
165
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
166
|
-
var product = _step.value;
|
|
167
|
-
if (remainingLimit <= 0) break;
|
|
168
|
-
// 动态计算当前可抵扣数量 = ceil(剩余金额 / 单价)
|
|
169
|
-
var currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
|
|
170
|
-
var deductQty = Math.min(currentAvailableQty, remainingLimit);
|
|
171
|
-
// 实际可抵扣金额 = min(数量 * 单价, 剩余金额)
|
|
172
|
-
var deductAmount = Decimal.min(product[unitPriceField].times(deductQty), product[amountField]);
|
|
173
|
-
finalApplicableAmount = finalApplicableAmount.plus(deductAmount);
|
|
174
|
-
remainingLimit -= deductQty;
|
|
175
|
-
}
|
|
176
|
-
} catch (err) {
|
|
177
|
-
_iterator.e(err);
|
|
178
|
-
} finally {
|
|
179
|
-
_iterator.f();
|
|
180
|
-
}
|
|
181
|
-
} else {
|
|
182
|
-
// 无数量限制:所有适用商品的剩余金额总和
|
|
183
|
-
finalApplicableAmount = applicableProducts.reduce(function (sum, p) {
|
|
184
|
-
return sum.plus(p[amountField]);
|
|
185
|
-
}, new Decimal(0));
|
|
186
|
-
}
|
|
187
|
-
} else {
|
|
188
|
-
// 非跨商品券:只能抵扣单个商品(剩余金额最高的)
|
|
189
|
-
var maxProduct = applicableProducts.reduce(function (max, p) {
|
|
190
|
-
return p[amountField].greaterThan(max[amountField]) ? p : max;
|
|
191
|
-
});
|
|
192
|
-
// 动态计算当前可抵扣数量
|
|
193
|
-
var _currentAvailableQty = Math.ceil(maxProduct[amountField].dividedBy(maxProduct[unitPriceField]).toNumber());
|
|
194
|
-
// 非跨商品券也受 applicableProductLimit 限制
|
|
195
|
-
var _deductQty = applicableProductLimit > 0 ? Math.min(_currentAvailableQty, applicableProductLimit) : _currentAvailableQty;
|
|
196
|
-
// 实际可抵扣金额 = min(数量 * 单价, 剩余金额)
|
|
197
|
-
finalApplicableAmount = Decimal.min(maxProduct[unitPriceField].times(_deductQty), maxProduct[amountField]);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// 返回最小值
|
|
201
|
-
return Decimal.min(baseAmount, finalApplicableAmount, remainingOrderAmount);
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
// 辅助函数:判断券是否可用,返回可用性和原因代码
|
|
205
|
-
var isVoucherAvailable = function isVoucherAvailable(voucher, productsData, usedVoucherCounts) {
|
|
206
|
-
var config = voucher.config,
|
|
207
|
-
id = voucher.id,
|
|
208
|
-
product_id = voucher.product_id;
|
|
209
|
-
|
|
210
|
-
// 根据 deductTaxAndFee 配置获取推荐金额
|
|
211
|
-
var recommendedAmount = getRecommendedAmount(voucher);
|
|
212
|
-
|
|
213
|
-
// 余额为 0
|
|
214
|
-
if (recommendedAmount <= 0) {
|
|
215
|
-
return {
|
|
216
|
-
isAvailable: false,
|
|
217
|
-
reasonCode: 'not_meet_the_required_conditions'
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// 订单金额已抵扣完
|
|
222
|
-
if (remainingOrderAmount.lessThanOrEqualTo(0)) {
|
|
223
|
-
return {
|
|
224
|
-
isAvailable: false,
|
|
225
|
-
reasonCode: 'exceeds_the_maximum_deduction_limit'
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// 适用商品金额已被抵扣完
|
|
230
|
-
var applicableAmount = getApplicableProductsAmount(voucher, productsData);
|
|
231
|
-
if (applicableAmount.lessThanOrEqualTo(0)) {
|
|
232
|
-
return {
|
|
233
|
-
isAvailable: false,
|
|
234
|
-
reasonCode: 'not_meet_the_required_conditions'
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// 检查 maxUsagePerOrder(同 product_id 的券),0 表示不限制
|
|
239
|
-
if (((config === null || config === void 0 ? void 0 : config.maxUsagePerOrder) || 0) > 0) {
|
|
240
|
-
var usedCount = usedVoucherCounts.get(product_id) || 0;
|
|
241
|
-
if (usedCount >= ((config === null || config === void 0 ? void 0 : config.maxUsagePerOrder) || 0)) {
|
|
242
|
-
return {
|
|
243
|
-
isAvailable: false,
|
|
244
|
-
reasonCode: 'usage_limit_reached'
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
return {
|
|
249
|
-
isAvailable: true
|
|
250
|
-
};
|
|
251
|
-
};
|
|
252
|
-
|
|
253
|
-
// ========== 第一步:为所有券计算初始的 _available_max_amount 和 _unified_available_status ==========
|
|
254
|
-
var usedVoucherCountsForAll = new Map();
|
|
255
|
-
var allVouchersWithStatus = applicableVouchers.map(function (voucher) {
|
|
256
|
-
var _available_max_amount = calculateAvailableMaxAmount(voucher, productsCopy);
|
|
257
|
-
var availabilityResult = isVoucherAvailable(voucher, productsCopy, usedVoucherCountsForAll);
|
|
258
|
-
var _unified_available_status = availabilityResult.isAvailable ? 1 : 0;
|
|
259
|
-
return _objectSpread(_objectSpread({}, voucher), {}, {
|
|
260
|
-
_available_max_amount: _available_max_amount.toNumber(),
|
|
261
|
-
// 转换为数字
|
|
262
|
-
_unified_available_status: _unified_available_status
|
|
263
|
-
}, availabilityResult.reasonCode && {
|
|
264
|
-
reasonCode: availabilityResult.reasonCode
|
|
265
|
-
});
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
// ========== 第二步:计算推荐券列表 ==========
|
|
269
|
-
var recommendedVouchers = [];
|
|
270
|
-
var usedVoucherCounts = new Map(); // 跟踪每个券 ID 的使用次数
|
|
271
|
-
|
|
272
|
-
// 重置商品余额追踪(同时维护含税和不含税两个金额池)
|
|
273
|
-
var productsForRecommendation = expandProductsWithBundleItems(products, true);
|
|
274
|
-
remainingOrderAmount = new Decimal(orderTotalAmount);
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
// 分类券:未跨商品券 vs 跨商品券
|
|
278
|
-
const nonCrossProductVouchers = applicableVouchers.filter(
|
|
279
|
-
(v) => !v.config?.allowCrossProduct,
|
|
280
|
-
);
|
|
281
|
-
const crossProductVouchers = applicableVouchers.filter(
|
|
282
|
-
(v) => v.config?.allowCrossProduct,
|
|
283
|
-
);
|
|
284
|
-
// 按 tag 分组
|
|
285
|
-
const groupByType = (vouchers: any[]) => {
|
|
286
|
-
const groups = new Map<string, any[]>();
|
|
287
|
-
vouchers.forEach((v) => {
|
|
288
|
-
const tag = v.tag;
|
|
289
|
-
if (!groups.has(tag)) {
|
|
290
|
-
groups.set(tag, []);
|
|
291
|
-
}
|
|
292
|
-
groups.get(tag)!.push(v);
|
|
293
|
-
});
|
|
294
|
-
return groups;
|
|
295
|
-
};
|
|
296
|
-
// 对每组券按金额(balance)从大到小排序
|
|
297
|
-
const sortVouchersByAmount = (vouchers: Voucher[]) => {
|
|
298
|
-
return [...vouchers].sort((a, b) => getRecommendedAmount(b) - getRecommendedAmount(a));
|
|
299
|
-
};
|
|
300
|
-
*/
|
|
301
|
-
|
|
302
|
-
// 处理单张券的抵扣
|
|
303
|
-
var applyVoucher = function applyVoucher(voucher) {
|
|
304
|
-
// 检查是否可用
|
|
305
|
-
var availabilityCheck = isVoucherAvailable(voucher, productsForRecommendation, usedVoucherCounts);
|
|
306
|
-
if (!availabilityCheck.isAvailable) {
|
|
307
|
-
return false;
|
|
308
|
-
}
|
|
309
|
-
var config = voucher.config,
|
|
310
|
-
id = voucher.id,
|
|
311
|
-
product_id = voucher.product_id;
|
|
312
|
-
var _ref3 = config !== null && config !== void 0 ? config : {},
|
|
313
|
-
_ref3$maxDeductionAmo = _ref3.maxDeductionAmount,
|
|
314
|
-
maxDeductionAmount = _ref3$maxDeductionAmo === void 0 ? 0 : _ref3$maxDeductionAmo,
|
|
315
|
-
_ref3$allowCrossProdu = _ref3.allowCrossProduct,
|
|
316
|
-
allowCrossProduct = _ref3$allowCrossProdu === void 0 ? true : _ref3$allowCrossProdu,
|
|
317
|
-
_ref3$applicableProdu = _ref3.applicableProductLimit,
|
|
318
|
-
applicableProductLimit = _ref3$applicableProdu === void 0 ? 0 : _ref3$applicableProdu,
|
|
319
|
-
_ref3$deductTaxAndFee = _ref3.deductTaxAndFee,
|
|
320
|
-
deductTaxAndFee = _ref3$deductTaxAndFee === void 0 ? true : _ref3$deductTaxAndFee;
|
|
321
|
-
|
|
322
|
-
// 根据券的配置选择使用哪个单价字段和金额字段
|
|
323
|
-
var unitPriceField = deductTaxAndFee ? 'unitPriceWithTax' : 'unitPricePure';
|
|
324
|
-
var amountField = deductTaxAndFee ? 'remainingAmountWithTax' : 'remainingAmountPure';
|
|
325
|
-
|
|
326
|
-
// 获取适用商品(只筛选有剩余金额的商品)
|
|
327
|
-
var applicableProducts = getApplicableProducts(voucher, productsForRecommendation).filter(function (p) {
|
|
328
|
-
return p[amountField].greaterThan(0);
|
|
329
|
-
});
|
|
330
|
-
if (applicableProducts.length === 0) return false;
|
|
331
|
-
|
|
332
|
-
// ========== 关键修改:在应用券之前,基于当前剩余金额计算 _available_max_amount ==========
|
|
333
|
-
// 优先使用用户手动编辑的金额,否则根据 deductTaxAndFee 配置获取推荐金额
|
|
334
|
-
var usageAmount = typeof voucher.edit_current_amount === 'number' ? voucher.edit_current_amount : getRecommendedAmount(voucher);
|
|
335
|
-
var baseAmount = Decimal.min(new Decimal(usageAmount), new Decimal(maxDeductionAmount));
|
|
336
|
-
var calculatedAvailableMaxAmount = new Decimal(0);
|
|
337
|
-
if (allowCrossProduct) {
|
|
338
|
-
// 跨商品券:按 quantity 限制计算可抵扣金额
|
|
339
|
-
if (applicableProductLimit > 0) {
|
|
340
|
-
// 按剩余金额从高到低排序
|
|
341
|
-
var sortedProducts = _toConsumableArray(applicableProducts).sort(function (a, b) {
|
|
342
|
-
return a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1;
|
|
343
|
-
});
|
|
344
|
-
var remainingLimit = applicableProductLimit;
|
|
345
|
-
var _iterator2 = _createForOfIteratorHelper(sortedProducts),
|
|
346
|
-
_step2;
|
|
347
|
-
try {
|
|
348
|
-
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
349
|
-
var product = _step2.value;
|
|
350
|
-
if (remainingLimit <= 0) break;
|
|
351
|
-
// 动态计算当前可抵扣数量 = ceil(剩余金额 / 单价)
|
|
352
|
-
var currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
|
|
353
|
-
var deductQty = Math.min(currentAvailableQty, remainingLimit);
|
|
354
|
-
// 实际可抵扣金额 = min(数量 * 单价, 剩余金额)
|
|
355
|
-
var deductAmount = Decimal.min(product[unitPriceField].times(deductQty), product[amountField]);
|
|
356
|
-
calculatedAvailableMaxAmount = calculatedAvailableMaxAmount.plus(deductAmount);
|
|
357
|
-
remainingLimit -= deductQty;
|
|
358
|
-
}
|
|
359
|
-
} catch (err) {
|
|
360
|
-
_iterator2.e(err);
|
|
361
|
-
} finally {
|
|
362
|
-
_iterator2.f();
|
|
363
|
-
}
|
|
364
|
-
} else {
|
|
365
|
-
// 无数量限制:所有适用商品的剩余金额总和
|
|
366
|
-
calculatedAvailableMaxAmount = applicableProducts.reduce(function (sum, p) {
|
|
367
|
-
return sum.plus(p[amountField]);
|
|
368
|
-
}, new Decimal(0));
|
|
369
|
-
}
|
|
370
|
-
} else {
|
|
371
|
-
// 非跨商品券:单个剩余金额最高的商品,也受 applicableProductLimit 限制
|
|
372
|
-
var maxProduct = applicableProducts.reduce(function (max, p) {
|
|
373
|
-
return p[amountField].greaterThan(max[amountField]) ? p : max;
|
|
374
|
-
});
|
|
375
|
-
// 动态计算当前可抵扣数量
|
|
376
|
-
var _currentAvailableQty2 = Math.ceil(maxProduct[amountField].dividedBy(maxProduct[unitPriceField]).toNumber());
|
|
377
|
-
var _deductQty2 = applicableProductLimit > 0 ? Math.min(_currentAvailableQty2, applicableProductLimit) : _currentAvailableQty2;
|
|
378
|
-
// 实际可抵扣金额 = min(数量 * 单价, 剩余金额)
|
|
379
|
-
calculatedAvailableMaxAmount = Decimal.min(maxProduct[unitPriceField].times(_deductQty2), maxProduct[amountField]);
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// 取最小值:min(recommended_usage_amount, maxDeductionAmount, 适用商品金额, 订单剩余金额)
|
|
383
|
-
var availableMaxAmount = Decimal.min(baseAmount, calculatedAvailableMaxAmount, remainingOrderAmount);
|
|
384
|
-
// ======================================================================================
|
|
385
|
-
|
|
386
|
-
// 计算本次抵扣金额(使用同样的 usageAmount)
|
|
387
|
-
var maxDeduction = Decimal.min(new Decimal(usageAmount), new Decimal(maxDeductionAmount));
|
|
388
|
-
var deductionLeft = maxDeduction;
|
|
389
|
-
var deductionDetails = [];
|
|
390
|
-
if (allowCrossProduct) {
|
|
391
|
-
// 跨商品券:按剩余金额从高到低抵扣,受 applicableProductLimit 限制
|
|
392
|
-
var _sortedProducts = _toConsumableArray(applicableProducts).sort(function (a, b) {
|
|
393
|
-
return a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1;
|
|
394
|
-
});
|
|
395
|
-
var _remainingLimit = applicableProductLimit > 0 ? applicableProductLimit : Infinity;
|
|
396
|
-
var _iterator3 = _createForOfIteratorHelper(_sortedProducts),
|
|
397
|
-
_step3;
|
|
398
|
-
try {
|
|
399
|
-
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
400
|
-
var _product = _step3.value;
|
|
401
|
-
if (deductionLeft.lessThanOrEqualTo(0) || _remainingLimit <= 0) break;
|
|
402
|
-
|
|
403
|
-
// 动态计算当前可抵扣数量 = ceil(剩余金额 / 单价)
|
|
404
|
-
var _currentAvailableQty3 = Math.ceil(_product[amountField].dividedBy(_product[unitPriceField]).toNumber());
|
|
405
|
-
var availableQty = Math.min(_currentAvailableQty3, _remainingLimit);
|
|
406
|
-
|
|
407
|
-
// 计算本商品最大可抵扣金额 = min(数量 * 单价, 剩余金额)
|
|
408
|
-
var maxDeductForProduct = Decimal.min(_product[unitPriceField].times(availableQty), _product[amountField]);
|
|
409
|
-
var actualDeductAmount = Decimal.min(deductionLeft, maxDeductForProduct);
|
|
410
|
-
|
|
411
|
-
// 计算实际抵扣的数量(用于记录和配额计算)
|
|
412
|
-
var actualDeductQty = Math.ceil(actualDeductAmount.dividedBy(_product[unitPriceField]).toNumber());
|
|
413
|
-
|
|
414
|
-
// 只更新商品的剩余金额,不更新 remainingQuantity
|
|
415
|
-
_product[amountField] = _product[amountField].minus(actualDeductAmount);
|
|
416
|
-
deductionLeft = deductionLeft.minus(actualDeductAmount);
|
|
417
|
-
_remainingLimit -= actualDeductQty;
|
|
418
|
-
deductionDetails.push({
|
|
419
|
-
product_id: _product.product_id,
|
|
420
|
-
parent_product_id: _product.parent_product_id || null,
|
|
421
|
-
is_bundle_item: _product.is_bundle_item || false,
|
|
422
|
-
deductAmount: actualDeductAmount.toNumber(),
|
|
423
|
-
// 转换为数字
|
|
424
|
-
deductQuantity: actualDeductQty // 抵扣涉及的数量(用于记录)
|
|
425
|
-
});
|
|
426
|
-
}
|
|
427
|
-
} catch (err) {
|
|
428
|
-
_iterator3.e(err);
|
|
429
|
-
} finally {
|
|
430
|
-
_iterator3.f();
|
|
431
|
-
}
|
|
432
|
-
} else {
|
|
433
|
-
// 非跨商品券:只抵扣一个商品(剩余金额最高的),也受 applicableProductLimit 限制
|
|
434
|
-
var targetProduct = applicableProducts.reduce(function (max, p) {
|
|
435
|
-
return p[amountField].greaterThan(max[amountField]) ? p : max;
|
|
436
|
-
});
|
|
437
|
-
|
|
438
|
-
// 动态计算当前可抵扣数量
|
|
439
|
-
var _currentAvailableQty4 = Math.ceil(targetProduct[amountField].dividedBy(targetProduct[unitPriceField]).toNumber());
|
|
440
|
-
var _availableQty = applicableProductLimit > 0 ? Math.min(_currentAvailableQty4, applicableProductLimit) : _currentAvailableQty4;
|
|
441
|
-
|
|
442
|
-
// 计算本商品最大可抵扣金额 = min(数量 * 单价, 剩余金额)
|
|
443
|
-
var _maxDeductForProduct = Decimal.min(targetProduct[unitPriceField].times(_availableQty), targetProduct[amountField]);
|
|
444
|
-
var _actualDeductAmount = Decimal.min(deductionLeft, _maxDeductForProduct);
|
|
445
|
-
|
|
446
|
-
// 计算实际抵扣的数量
|
|
447
|
-
var _actualDeductQty = Math.ceil(_actualDeductAmount.dividedBy(targetProduct[unitPriceField]).toNumber());
|
|
448
|
-
|
|
449
|
-
// 只更新商品的剩余金额,不更新 remainingQuantity
|
|
450
|
-
targetProduct[amountField] = targetProduct[amountField].minus(_actualDeductAmount);
|
|
451
|
-
deductionLeft = deductionLeft.minus(_actualDeductAmount);
|
|
452
|
-
deductionDetails.push({
|
|
453
|
-
product_id: targetProduct.product_id,
|
|
454
|
-
parent_product_id: targetProduct.parent_product_id || null,
|
|
455
|
-
is_bundle_item: targetProduct.is_bundle_item || false,
|
|
456
|
-
deductAmount: _actualDeductAmount.toNumber(),
|
|
457
|
-
// 转换为数字
|
|
458
|
-
deductQuantity: _actualDeductQty // 抵扣涉及的数量(用于记录)
|
|
459
|
-
});
|
|
460
|
-
}
|
|
461
|
-
var totalDeducted = maxDeduction.minus(deductionLeft);
|
|
462
|
-
if (totalDeducted.greaterThan(0)) {
|
|
463
|
-
// 更新订单剩余金额
|
|
464
|
-
remainingOrderAmount = remainingOrderAmount.minus(totalDeducted);
|
|
465
|
-
|
|
466
|
-
// 更新券使用次数(按 product_id 统计)
|
|
467
|
-
usedVoucherCounts.set(product_id, (usedVoucherCounts.get(product_id) || 0) + 1);
|
|
468
|
-
|
|
469
|
-
// 添加到推荐列表(包含基于当前剩余金额计算的 available_max_amount)
|
|
470
|
-
recommendedVouchers.push(_objectSpread(_objectSpread({}, voucher), {}, {
|
|
471
|
-
actualDeduction: totalDeducted.toNumber(),
|
|
472
|
-
// 转换为数字
|
|
473
|
-
deductionDetails: deductionDetails,
|
|
474
|
-
_available_max_amount: availableMaxAmount.toNumber(),
|
|
475
|
-
// 转换为数字
|
|
476
|
-
_unified_available_status: 1
|
|
477
|
-
}));
|
|
478
|
-
return true;
|
|
479
|
-
}
|
|
480
|
-
return false;
|
|
481
|
-
};
|
|
482
|
-
|
|
483
|
-
/**
|
|
484
|
-
// 第一轮:处理未跨商品券
|
|
485
|
-
const nonCrossGroups = groupByType(nonCrossProductVouchers);
|
|
486
|
-
nonCrossGroups.forEach((vouchersInGroup) => {
|
|
487
|
-
const sortedVouchers = sortVouchersByAmount(vouchersInGroup);
|
|
488
|
-
sortedVouchers.forEach((voucher) => {
|
|
489
|
-
applyVoucher(voucher);
|
|
490
|
-
});
|
|
491
|
-
});
|
|
492
|
-
// 第二轮:处理跨商品券
|
|
493
|
-
const crossGroups = groupByType(crossProductVouchers);
|
|
494
|
-
crossGroups.forEach((vouchersInGroup) => {
|
|
495
|
-
const sortedVouchers = sortVouchersByAmount(vouchersInGroup);
|
|
496
|
-
sortedVouchers.forEach((voucher) => {
|
|
497
|
-
applyVoucher(voucher);
|
|
498
|
-
});
|
|
499
|
-
});
|
|
500
|
-
*/
|
|
501
|
-
|
|
502
|
-
// 直接按 applicableVouchers 的顺序处理所有券
|
|
503
|
-
applicableVouchers.forEach(function (voucher) {
|
|
504
|
-
applyVoucher(voucher);
|
|
505
|
-
});
|
|
506
|
-
|
|
507
|
-
// recommendedVouchers 已经包含了基于应用时计算的 _available_max_amount 和 _unified_available_status
|
|
508
|
-
|
|
509
|
-
// ========== 第三步:构建 all 数组,以 recommended 为基础 ==========
|
|
510
|
-
// 创建 recommended 券的 Map,以 id 为 key
|
|
511
|
-
var recommendedMap = new Map();
|
|
512
|
-
recommendedVouchers.forEach(function (v) {
|
|
513
|
-
recommendedMap.set(v.id, v);
|
|
514
|
-
});
|
|
515
|
-
|
|
516
|
-
// 遍历所有券,如果在 recommended 中则使用增强数据,否则使用基础数据
|
|
517
|
-
var allWithEnhancedData = allVouchersWithStatus.map(function (voucher) {
|
|
518
|
-
if (recommendedMap.has(voucher.id)) {
|
|
519
|
-
// 使用 recommended 中的增强数据
|
|
520
|
-
return recommendedMap.get(voucher.id);
|
|
521
|
-
} else {
|
|
522
|
-
// 不在 recommended 中的券,补充基础字段
|
|
523
|
-
return _objectSpread(_objectSpread({}, voucher), {}, {
|
|
524
|
-
actualDeduction: 0,
|
|
525
|
-
deductionDetails: []
|
|
526
|
-
// 保留 reasonCode(如果不可用的话)
|
|
527
|
-
});
|
|
528
|
-
}
|
|
529
|
-
});
|
|
530
|
-
return {
|
|
531
|
-
recommended: recommendedVouchers,
|
|
532
|
-
transformList: allWithEnhancedData
|
|
533
|
-
};
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
/**
|
|
537
|
-
* 重新计算优惠券状态(基于已选券的增量计算)
|
|
538
|
-
* @param allVouchers 所有原始券列表
|
|
539
|
-
* @param selectedVouchers 已选中的券列表(按选中顺序)
|
|
540
|
-
* @param orderTotalAmount 订单总金额
|
|
541
|
-
* @param products 订单商品列表
|
|
542
|
-
* @returns 返回更新后的所有券列表和已选券的详细抵扣信息
|
|
543
|
-
*/
|
|
544
|
-
export function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, products) {
|
|
545
|
-
// 深拷贝并拆分商品列表(包含主商品和原价子商品,同时维护含税和不含税两个金额池),用于计算
|
|
546
|
-
var productsForCalc = expandProductsWithBundleItems(products, true);
|
|
547
|
-
var remainingOrderAmount = new Decimal(orderTotalAmount);
|
|
548
|
-
var selectedWithDetails = [];
|
|
549
|
-
|
|
550
|
-
// 第一步:按顺序应用已选中的券,计算实际抵扣
|
|
551
|
-
selectedVouchers.forEach(function (selectedVoucher) {
|
|
552
|
-
var config = selectedVoucher.config,
|
|
553
|
-
id = selectedVoucher.id;
|
|
554
|
-
var maxDeductionAmount = config.maxDeductionAmount,
|
|
555
|
-
allowCrossProduct = config.allowCrossProduct,
|
|
556
|
-
applicableProductLimit = config.applicableProductLimit,
|
|
557
|
-
_config$deductTaxAndF3 = config.deductTaxAndFee,
|
|
558
|
-
deductTaxAndFee = _config$deductTaxAndF3 === void 0 ? true : _config$deductTaxAndF3;
|
|
559
|
-
|
|
560
|
-
// 根据券的配置选择使用哪个单价字段和金额字段
|
|
561
|
-
var unitPriceField = deductTaxAndFee ? 'unitPriceWithTax' : 'unitPricePure';
|
|
562
|
-
var amountField = deductTaxAndFee ? 'remainingAmountWithTax' : 'remainingAmountPure';
|
|
563
|
-
|
|
564
|
-
// 获取适用商品(只筛选有剩余金额的商品)
|
|
565
|
-
var applicableProducts = getApplicableProducts(selectedVoucher, productsForCalc).filter(function (p) {
|
|
566
|
-
return p[amountField].greaterThan(0);
|
|
567
|
-
});
|
|
568
|
-
if (applicableProducts.length === 0) {
|
|
569
|
-
// 无适用商品,跳过
|
|
570
|
-
selectedWithDetails.push(_objectSpread(_objectSpread({}, selectedVoucher), {}, {
|
|
571
|
-
actualDeduction: 0,
|
|
572
|
-
deductionDetails: [],
|
|
573
|
-
_available_max_amount: 0,
|
|
574
|
-
_unified_available_status: 0,
|
|
575
|
-
reasonCode: 'not_meet_the_required_conditions'
|
|
576
|
-
}));
|
|
577
|
-
return;
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
// 计算本次抵扣金额
|
|
581
|
-
// 优先使用用户手动编辑的金额,否则根据 deductTaxAndFee 配置获取推荐金额
|
|
582
|
-
var usageAmount = typeof selectedVoucher.edit_current_amount === 'number' ? selectedVoucher.edit_current_amount : getRecommendedAmount(selectedVoucher);
|
|
583
|
-
var maxDeduction = Decimal.min(new Decimal(usageAmount), new Decimal(maxDeductionAmount), remainingOrderAmount);
|
|
584
|
-
var deductionLeft = maxDeduction;
|
|
585
|
-
var deductionDetails = [];
|
|
586
|
-
if (allowCrossProduct) {
|
|
587
|
-
// 跨商品券:按剩余金额从高到低抵扣,受 applicableProductLimit 限制
|
|
588
|
-
var sortedProducts = _toConsumableArray(applicableProducts).sort(function (a, b) {
|
|
589
|
-
return a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1;
|
|
590
|
-
});
|
|
591
|
-
var remainingLimit = applicableProductLimit > 0 ? applicableProductLimit : Infinity;
|
|
592
|
-
var _iterator4 = _createForOfIteratorHelper(sortedProducts),
|
|
593
|
-
_step4;
|
|
594
|
-
try {
|
|
595
|
-
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
596
|
-
var product = _step4.value;
|
|
597
|
-
if (deductionLeft.lessThanOrEqualTo(0) || remainingLimit <= 0) break;
|
|
598
|
-
|
|
599
|
-
// 动态计算当前可抵扣数量 = ceil(剩余金额 / 单价)
|
|
600
|
-
var currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
|
|
601
|
-
var availableQty = Math.min(currentAvailableQty, remainingLimit);
|
|
602
|
-
|
|
603
|
-
// 计算本商品最大可抵扣金额 = min(数量 * 单价, 剩余金额)
|
|
604
|
-
var maxDeductForProduct = Decimal.min(product[unitPriceField].times(availableQty), product[amountField]);
|
|
605
|
-
var actualDeductAmount = Decimal.min(deductionLeft, maxDeductForProduct);
|
|
606
|
-
|
|
607
|
-
// 计算实际抵扣的数量(用于记录和配额计算)
|
|
608
|
-
var actualDeductQty = Math.ceil(actualDeductAmount.dividedBy(product[unitPriceField]).toNumber());
|
|
609
|
-
|
|
610
|
-
// 只更新商品的剩余金额,不更新 remainingQuantity
|
|
611
|
-
product[amountField] = product[amountField].minus(actualDeductAmount);
|
|
612
|
-
deductionLeft = deductionLeft.minus(actualDeductAmount);
|
|
613
|
-
remainingLimit -= actualDeductQty;
|
|
614
|
-
deductionDetails.push({
|
|
615
|
-
product_id: product.product_id,
|
|
616
|
-
parent_product_id: product.parent_product_id || null,
|
|
617
|
-
is_bundle_item: product.is_bundle_item || false,
|
|
618
|
-
deductAmount: actualDeductAmount.toNumber(),
|
|
619
|
-
// 转换为数字
|
|
620
|
-
deductQuantity: actualDeductQty // 抵扣涉及的数量(用于记录)
|
|
621
|
-
});
|
|
622
|
-
}
|
|
623
|
-
} catch (err) {
|
|
624
|
-
_iterator4.e(err);
|
|
625
|
-
} finally {
|
|
626
|
-
_iterator4.f();
|
|
627
|
-
}
|
|
628
|
-
} else {
|
|
629
|
-
// 非跨商品券:只抵扣一个商品(剩余金额最高的),也受 applicableProductLimit 限制
|
|
630
|
-
var targetProduct = applicableProducts.reduce(function (max, p) {
|
|
631
|
-
return p[amountField].greaterThan(max[amountField]) ? p : max;
|
|
632
|
-
});
|
|
633
|
-
|
|
634
|
-
// 动态计算当前可抵扣数量
|
|
635
|
-
var _currentAvailableQty5 = Math.ceil(targetProduct[amountField].dividedBy(targetProduct[unitPriceField]).toNumber());
|
|
636
|
-
var _availableQty2 = applicableProductLimit > 0 ? Math.min(_currentAvailableQty5, applicableProductLimit) : _currentAvailableQty5;
|
|
637
|
-
|
|
638
|
-
// 计算本商品最大可抵扣金额 = min(数量 * 单价, 剩余金额)
|
|
639
|
-
var _maxDeductForProduct2 = Decimal.min(targetProduct[unitPriceField].times(_availableQty2), targetProduct[amountField]);
|
|
640
|
-
var _actualDeductAmount2 = Decimal.min(deductionLeft, _maxDeductForProduct2);
|
|
641
|
-
|
|
642
|
-
// 计算实际抵扣的数量
|
|
643
|
-
var _actualDeductQty2 = Math.ceil(_actualDeductAmount2.dividedBy(targetProduct[unitPriceField]).toNumber());
|
|
644
|
-
|
|
645
|
-
// 只更新商品的剩余金额,不更新 remainingQuantity
|
|
646
|
-
targetProduct[amountField] = targetProduct[amountField].minus(_actualDeductAmount2);
|
|
647
|
-
deductionLeft = deductionLeft.minus(_actualDeductAmount2);
|
|
648
|
-
deductionDetails.push({
|
|
649
|
-
product_id: targetProduct.product_id,
|
|
650
|
-
parent_product_id: targetProduct.parent_product_id || null,
|
|
651
|
-
is_bundle_item: targetProduct.is_bundle_item || false,
|
|
652
|
-
deductAmount: _actualDeductAmount2.toNumber(),
|
|
653
|
-
// 转换为数字
|
|
654
|
-
deductQuantity: _actualDeductQty2 // 抵扣涉及的数量(用于记录)
|
|
655
|
-
});
|
|
656
|
-
}
|
|
657
|
-
var totalDeducted = maxDeduction.minus(deductionLeft);
|
|
658
|
-
|
|
659
|
-
// 更新订单剩余金额
|
|
660
|
-
remainingOrderAmount = remainingOrderAmount.minus(totalDeducted);
|
|
661
|
-
selectedWithDetails.push(_objectSpread(_objectSpread({}, selectedVoucher), {}, {
|
|
662
|
-
actualDeduction: totalDeducted.toNumber(),
|
|
663
|
-
// 转换为数字
|
|
664
|
-
deductionDetails: deductionDetails,
|
|
665
|
-
_available_max_amount: totalDeducted.toNumber(),
|
|
666
|
-
// 转换为数字
|
|
667
|
-
_unified_available_status: totalDeducted.greaterThan(0) ? 1 : 0
|
|
668
|
-
}));
|
|
669
|
-
});
|
|
670
|
-
|
|
671
|
-
// 第二步:为所有券重新计算 _available_max_amount 和 _unified_available_status
|
|
672
|
-
var selectedIds = new Set(selectedVouchers.map(function (v) {
|
|
673
|
-
return v.id;
|
|
674
|
-
}));
|
|
675
|
-
var usedVoucherCounts = new Map();
|
|
676
|
-
selectedVouchers.forEach(function (v) {
|
|
677
|
-
usedVoucherCounts.set(v.product_id, (usedVoucherCounts.get(v.product_id) || 0) + 1);
|
|
678
|
-
});
|
|
679
|
-
var allWithUpdatedStatus = allVouchers.map(function (voucher) {
|
|
680
|
-
// 如果是已选中的券,使用详细计算结果
|
|
681
|
-
if (selectedIds.has(voucher.id)) {
|
|
682
|
-
var selectedDetail = selectedWithDetails.find(function (v) {
|
|
683
|
-
return v.id === voucher.id;
|
|
684
|
-
});
|
|
685
|
-
return selectedDetail || voucher;
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
// 未选中的券,重新计算其可用状态
|
|
689
|
-
var config = voucher.config,
|
|
690
|
-
id = voucher.id,
|
|
691
|
-
product_id = voucher.product_id;
|
|
692
|
-
var maxDeductionAmount = config.maxDeductionAmount,
|
|
693
|
-
allowCrossProduct = config.allowCrossProduct,
|
|
694
|
-
applicableProductLimit = config.applicableProductLimit,
|
|
695
|
-
_config$deductTaxAndF4 = config.deductTaxAndFee,
|
|
696
|
-
deductTaxAndFee = _config$deductTaxAndF4 === void 0 ? true : _config$deductTaxAndF4;
|
|
697
|
-
|
|
698
|
-
// 根据券的配置选择使用哪个单价字段和金额字段
|
|
699
|
-
var unitPriceField = deductTaxAndFee ? 'unitPriceWithTax' : 'unitPricePure';
|
|
700
|
-
var amountField = deductTaxAndFee ? 'remainingAmountWithTax' : 'remainingAmountPure';
|
|
701
|
-
|
|
702
|
-
// 根据 deductTaxAndFee 配置获取推荐金额
|
|
703
|
-
var recommendedAmount = getRecommendedAmount(voucher);
|
|
704
|
-
|
|
705
|
-
// 检查基本可用性
|
|
706
|
-
var isAvailable = true;
|
|
707
|
-
var calculatedMaxAmount = new Decimal(0);
|
|
708
|
-
var reasonCode;
|
|
709
|
-
if (recommendedAmount <= 0) {
|
|
710
|
-
isAvailable = false;
|
|
711
|
-
reasonCode = 'not_meet_the_required_conditions';
|
|
712
|
-
} else if (remainingOrderAmount.lessThanOrEqualTo(0)) {
|
|
713
|
-
isAvailable = false;
|
|
714
|
-
reasonCode = 'exceeds_the_maximum_deduction_limit';
|
|
715
|
-
} else {
|
|
716
|
-
// 检查 maxUsagePerOrder(按 product_id 统计),0 表示不限制
|
|
717
|
-
if (config.maxUsagePerOrder > 0) {
|
|
718
|
-
var usedCount = usedVoucherCounts.get(product_id) || 0;
|
|
719
|
-
if (usedCount >= config.maxUsagePerOrder) {
|
|
720
|
-
isAvailable = false;
|
|
721
|
-
reasonCode = 'usage_limit_reached';
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
if (isAvailable) {
|
|
725
|
-
// 获取适用商品(只筛选有剩余金额的商品)
|
|
726
|
-
var applicableProducts = getApplicableProducts(voucher, productsForCalc).filter(function (p) {
|
|
727
|
-
return p[amountField].greaterThan(0);
|
|
728
|
-
});
|
|
729
|
-
if (applicableProducts.length === 0) {
|
|
730
|
-
isAvailable = false;
|
|
731
|
-
reasonCode = 'not_meet_the_required_conditions';
|
|
732
|
-
} else {
|
|
733
|
-
// 计算 _available_max_amount
|
|
734
|
-
var baseAmount = Decimal.min(new Decimal(recommendedAmount), new Decimal(maxDeductionAmount));
|
|
735
|
-
if (allowCrossProduct) {
|
|
736
|
-
if (applicableProductLimit > 0) {
|
|
737
|
-
// 按剩余金额从高到低排序,按动态计算的可抵扣数量累计直到达到 limit
|
|
738
|
-
var sortedProducts = _toConsumableArray(applicableProducts).sort(function (a, b) {
|
|
739
|
-
return a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1;
|
|
740
|
-
});
|
|
741
|
-
var remainingLimit = applicableProductLimit;
|
|
742
|
-
var _iterator5 = _createForOfIteratorHelper(sortedProducts),
|
|
743
|
-
_step5;
|
|
744
|
-
try {
|
|
745
|
-
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
746
|
-
var product = _step5.value;
|
|
747
|
-
if (remainingLimit <= 0) break;
|
|
748
|
-
// 动态计算当前可抵扣数量 = ceil(剩余金额 / 单价)
|
|
749
|
-
var currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
|
|
750
|
-
var deductQty = Math.min(currentAvailableQty, remainingLimit);
|
|
751
|
-
// 实际可抵扣金额 = min(数量 * 单价, 剩余金额)
|
|
752
|
-
var deductAmount = Decimal.min(product[unitPriceField].times(deductQty), product[amountField]);
|
|
753
|
-
calculatedMaxAmount = calculatedMaxAmount.plus(deductAmount);
|
|
754
|
-
remainingLimit -= deductQty;
|
|
755
|
-
}
|
|
756
|
-
} catch (err) {
|
|
757
|
-
_iterator5.e(err);
|
|
758
|
-
} finally {
|
|
759
|
-
_iterator5.f();
|
|
760
|
-
}
|
|
761
|
-
} else {
|
|
762
|
-
// 无数量限制:所有适用商品的剩余金额总和
|
|
763
|
-
calculatedMaxAmount = applicableProducts.reduce(function (sum, p) {
|
|
764
|
-
return sum.plus(p[amountField]);
|
|
765
|
-
}, new Decimal(0));
|
|
766
|
-
}
|
|
767
|
-
} else {
|
|
768
|
-
// 非跨商品券:单个剩余金额最高的商品,也受 applicableProductLimit 限制
|
|
769
|
-
var maxProduct = applicableProducts.reduce(function (max, p) {
|
|
770
|
-
return p[amountField].greaterThan(max[amountField]) ? p : max;
|
|
771
|
-
});
|
|
772
|
-
// 动态计算当前可抵扣数量
|
|
773
|
-
var _currentAvailableQty6 = Math.ceil(maxProduct[amountField].dividedBy(maxProduct[unitPriceField]).toNumber());
|
|
774
|
-
var _deductQty3 = applicableProductLimit > 0 ? Math.min(_currentAvailableQty6, applicableProductLimit) : _currentAvailableQty6;
|
|
775
|
-
// 实际可抵扣金额 = min(数量 * 单价, 剩余金额)
|
|
776
|
-
calculatedMaxAmount = Decimal.min(maxProduct[unitPriceField].times(_deductQty3), maxProduct[amountField]);
|
|
777
|
-
}
|
|
778
|
-
calculatedMaxAmount = Decimal.min(baseAmount, calculatedMaxAmount, remainingOrderAmount);
|
|
779
|
-
if (calculatedMaxAmount.lessThanOrEqualTo(0)) {
|
|
780
|
-
isAvailable = false;
|
|
781
|
-
reasonCode = 'exceeds_the_maximum_deduction_limit';
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
return _objectSpread(_objectSpread({}, voucher), {}, {
|
|
787
|
-
_available_max_amount: calculatedMaxAmount.toNumber(),
|
|
788
|
-
// 转换为数字
|
|
789
|
-
_unified_available_status: isAvailable ? 1 : 0
|
|
790
|
-
}, reasonCode && {
|
|
791
|
-
reasonCode: reasonCode
|
|
792
|
-
});
|
|
793
|
-
});
|
|
794
|
-
return {
|
|
795
|
-
allWithUpdatedStatus: allWithUpdatedStatus,
|
|
796
|
-
selectedWithDetails: selectedWithDetails
|
|
797
|
-
};
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
/**
|
|
801
|
-
* 获取主商品价格
|
|
802
|
-
* @param product 商品
|
|
803
|
-
* @param isDeductTaxAndFee 是否抵扣税费与附加费
|
|
804
|
-
* @returns 商品价格
|
|
805
|
-
*/
|
|
806
|
-
export var getMainProductPrice = function getMainProductPrice(product, isDeductTaxAndFee) {
|
|
807
|
-
var _product$metadata, _product$metadata2, _product$metadata3, _product$metadata4;
|
|
808
|
-
var mainProductPrice = new Decimal((product === null || product === void 0 ? void 0 : product.main_product_selling_price) || ((_product$metadata = product.metadata) === null || _product$metadata === void 0 ? void 0 : _product$metadata.main_product_selling_price) || 0);
|
|
809
|
-
var _iterator6 = _createForOfIteratorHelper((product === null || product === void 0 ? void 0 : product.product_bundle) || []),
|
|
810
|
-
_step6;
|
|
811
|
-
try {
|
|
812
|
-
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
813
|
-
var bundleItem = _step6.value;
|
|
814
|
-
// 子商品是加价或减价才需要计算
|
|
815
|
-
if (getBundleItemIsMarkupOrDiscountPrice(bundleItem)) {
|
|
816
|
-
var _bundleItem$bundle_se;
|
|
817
|
-
// 子商品价格
|
|
818
|
-
var bundleItemPrice = new Decimal((_bundleItem$bundle_se = bundleItem.bundle_selling_price) !== null && _bundleItem$bundle_se !== void 0 ? _bundleItem$bundle_se : 0);
|
|
819
|
-
mainProductPrice = mainProductPrice.add(bundleItemPrice.times(bundleItem.num));
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
} catch (err) {
|
|
823
|
-
_iterator6.e(err);
|
|
824
|
-
} finally {
|
|
825
|
-
_iterator6.f();
|
|
826
|
-
}
|
|
827
|
-
var taxFee = new Decimal((product === null || product === void 0 ? void 0 : product.tax_fee) || (product === null || product === void 0 || (_product$metadata2 = product.metadata) === null || _product$metadata2 === void 0 ? void 0 : _product$metadata2.main_product_attached_bundle_tax_fee) || 0);
|
|
828
|
-
if (product.is_price_include_tax === 1) {
|
|
829
|
-
taxFee = new Decimal(0);
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
// 税费
|
|
833
|
-
// 附加费
|
|
834
|
-
var surchargeFee = new Decimal((product === null || product === void 0 || (_product$metadata3 = product.metadata) === null || _product$metadata3 === void 0 ? void 0 : _product$metadata3.main_product_attached_bundle_surcharge_fee) || 0).add((product === null || product === void 0 || (_product$metadata4 = product.metadata) === null || _product$metadata4 === void 0 ? void 0 : _product$metadata4.surcharge_rounding_remainder) || 0);
|
|
835
|
-
|
|
836
|
-
// 税费附加费总额
|
|
837
|
-
var taxAndFeeTotal = taxFee.add(surchargeFee);
|
|
838
|
-
|
|
839
|
-
// 如果需要抵扣税费与附加费,则加上税费附加费总额
|
|
840
|
-
if (isDeductTaxAndFee) {
|
|
841
|
-
mainProductPrice = mainProductPrice.add(taxAndFeeTotal);
|
|
842
|
-
}
|
|
843
|
-
return mainProductPrice.toNumber();
|
|
844
|
-
};
|
|
845
|
-
|
|
846
|
-
/**
|
|
847
|
-
* 获取套餐子商品价格
|
|
848
|
-
* @param bundleItem 套餐子商品
|
|
849
|
-
* @param parentQuantity 父商品数量
|
|
850
|
-
* @param isDeductTaxAndFee 是否抵扣税费与附加费
|
|
851
|
-
* @returns 子商品总价格
|
|
852
|
-
*/
|
|
853
|
-
export var getBundleItemPrice = function getBundleItemPrice(bundleItem, parentQuantity, isDeductTaxAndFee) {
|
|
854
|
-
var _bundleItem$bundle_se2;
|
|
855
|
-
// 子商品基础价格 = bundle_selling_price * num * 主商品数量
|
|
856
|
-
var totalQuantity = bundleItem.num * parentQuantity;
|
|
857
|
-
var bundleItemPrice = new Decimal((_bundleItem$bundle_se2 = bundleItem.bundle_selling_price) !== null && _bundleItem$bundle_se2 !== void 0 ? _bundleItem$bundle_se2 : 0).times(totalQuantity);
|
|
858
|
-
|
|
859
|
-
// 根据 deductTaxAndFee 配置决定是否加上税费和附加费
|
|
860
|
-
if (isDeductTaxAndFee) {
|
|
861
|
-
var _bundleItem$tax_fee, _bundleItem$metadata$, _bundleItem$metadata;
|
|
862
|
-
// 税费
|
|
863
|
-
var taxFee = new Decimal((_bundleItem$tax_fee = bundleItem.tax_fee) !== null && _bundleItem$tax_fee !== void 0 ? _bundleItem$tax_fee : 0).times(totalQuantity);
|
|
864
|
-
if (bundleItem.is_price_include_tax === 1) {
|
|
865
|
-
taxFee = new Decimal(0);
|
|
866
|
-
}
|
|
867
|
-
// 附加费
|
|
868
|
-
var surchargeFee = new Decimal((_bundleItem$metadata$ = (_bundleItem$metadata = bundleItem.metadata) === null || _bundleItem$metadata === void 0 ? void 0 : _bundleItem$metadata.surcharge_fee) !== null && _bundleItem$metadata$ !== void 0 ? _bundleItem$metadata$ : 0).times(totalQuantity);
|
|
869
|
-
bundleItemPrice = bundleItemPrice.add(taxFee).add(surchargeFee);
|
|
870
|
-
}
|
|
871
|
-
return bundleItemPrice.toNumber();
|
|
872
|
-
};
|
|
873
|
-
|
|
874
|
-
/**
|
|
875
|
-
* 将商品数据拆分,包含主商品和原价子商品
|
|
876
|
-
* @param products 原始商品列表
|
|
877
|
-
* @param deductTaxAndFee 是否抵扣税费与附加费(已废弃,保留参数以兼容旧代码)
|
|
878
|
-
* @returns 拆分后的商品数据(包含主商品和子商品,同时维护含税和不含税两个金额池,以及单价和剩余数量)
|
|
879
|
-
*/
|
|
880
|
-
var expandProductsWithBundleItems = function expandProductsWithBundleItems(products, deductTaxAndFee) {
|
|
881
|
-
var expandedProducts = [];
|
|
882
|
-
products.forEach(function (product) {
|
|
883
|
-
var productQuantity = getProductQuantity(product);
|
|
884
|
-
|
|
885
|
-
// 计算主商品单价(含税和不含税)
|
|
886
|
-
var unitPriceWithTax = getMainProductPrice(product, true);
|
|
887
|
-
var unitPricePure = getMainProductPrice(product, false);
|
|
888
|
-
|
|
889
|
-
// 1. 添加主商品(同时计算含税和不含税两个金额,以及单价和剩余数量)
|
|
890
|
-
expandedProducts.push(_objectSpread(_objectSpread({}, product), {}, {
|
|
891
|
-
is_bundle_item: false,
|
|
892
|
-
parent_product_id: null,
|
|
893
|
-
// 单价(用于按 quantity 计算抵扣)
|
|
894
|
-
unitPriceWithTax: new Decimal(unitPriceWithTax),
|
|
895
|
-
unitPricePure: new Decimal(unitPricePure),
|
|
896
|
-
// 剩余可抵扣数量
|
|
897
|
-
remainingQuantity: productQuantity,
|
|
898
|
-
// 含税费的剩余金额
|
|
899
|
-
remainingAmountWithTax: new Decimal(unitPriceWithTax).times(productQuantity),
|
|
900
|
-
// 纯商品金额(不含税费)
|
|
901
|
-
remainingAmountPure: new Decimal(unitPricePure).times(productQuantity)
|
|
902
|
-
}));
|
|
903
|
-
|
|
904
|
-
// 2. 添加原价子商品(作为独立商品项)
|
|
905
|
-
if (product.product_bundle && product.product_bundle.length > 0) {
|
|
906
|
-
product.product_bundle.forEach(function (bundleItem) {
|
|
907
|
-
if (getBundleItemIsOriginalPrice(bundleItem)) {
|
|
908
|
-
var bundleQuantity = bundleItem.num * productQuantity;
|
|
909
|
-
// 计算子商品单价(注意:getBundleItemPrice 返回的是总价,需要除以数量得到单价)
|
|
910
|
-
var bundleUnitPriceWithTax = new Decimal(getBundleItemPrice(bundleItem, 1, true)).dividedBy(bundleItem.num);
|
|
911
|
-
var bundleUnitPricePure = new Decimal(getBundleItemPrice(bundleItem, 1, false)).dividedBy(bundleItem.num);
|
|
912
|
-
|
|
913
|
-
// 原价子商品作为独立商品
|
|
914
|
-
expandedProducts.push(_objectSpread(_objectSpread({}, bundleItem), {}, {
|
|
915
|
-
product_id: bundleItem.bundle_product_id,
|
|
916
|
-
// 使用 bundle_product_id 作为 product_id
|
|
917
|
-
is_bundle_item: true,
|
|
918
|
-
parent_product_id: product.product_id,
|
|
919
|
-
quantity: bundleQuantity,
|
|
920
|
-
// 子商品数量 * 主商品数量
|
|
921
|
-
// 单价(用于按 quantity 计算抵扣)
|
|
922
|
-
unitPriceWithTax: bundleUnitPriceWithTax,
|
|
923
|
-
unitPricePure: bundleUnitPricePure,
|
|
924
|
-
// 剩余可抵扣数量
|
|
925
|
-
remainingQuantity: bundleQuantity,
|
|
926
|
-
// 含税费的剩余金额
|
|
927
|
-
remainingAmountWithTax: new Decimal(getBundleItemPrice(bundleItem, productQuantity, true)),
|
|
928
|
-
// 纯商品金额(不含税费)
|
|
929
|
-
remainingAmountPure: new Decimal(getBundleItemPrice(bundleItem, productQuantity, false))
|
|
930
|
-
}));
|
|
931
|
-
}
|
|
932
|
-
});
|
|
933
|
-
}
|
|
934
|
-
});
|
|
935
|
-
return expandedProducts;
|
|
936
|
-
};
|
|
937
|
-
|
|
938
|
-
/**
|
|
939
|
-
* 获取商品数量
|
|
940
|
-
* @param product 商品
|
|
941
|
-
* @returns 商品数量
|
|
942
|
-
*/
|
|
943
|
-
export var getProductQuantity = function getProductQuantity(product) {
|
|
944
|
-
return product.quantity || product.product_quantity || 1;
|
|
945
|
-
};
|
|
946
|
-
|
|
947
|
-
// bundle商品是否是原价
|
|
948
|
-
export var getBundleItemIsOriginalPrice = function getBundleItemIsOriginalPrice(item) {
|
|
949
|
-
return (item === null || item === void 0 ? void 0 : item.price_type) === 'markup' && (item === null || item === void 0 ? void 0 : item.price_type_ext) === 'product_price';
|
|
950
|
-
};
|
|
951
|
-
|
|
952
|
-
// bundle商品是否是加价
|
|
953
|
-
export var getBundleItemIsMarkupPrice = function getBundleItemIsMarkupPrice(item) {
|
|
954
|
-
return (item === null || item === void 0 ? void 0 : item.price_type) === 'markup' && ((item === null || item === void 0 ? void 0 : item.price_type_ext) === '' || !(item !== null && item !== void 0 && item.price_type_ext));
|
|
955
|
-
};
|
|
956
|
-
|
|
957
|
-
// bundle商品是否是减价
|
|
958
|
-
export var getBundleItemIsDiscountPrice = function getBundleItemIsDiscountPrice(item) {
|
|
959
|
-
return (item === null || item === void 0 ? void 0 : item.price_type) === 'markdown' && ((item === null || item === void 0 ? void 0 : item.price_type_ext) === '' || !(item !== null && item !== void 0 && item.price_type_ext));
|
|
960
|
-
};
|
|
961
|
-
|
|
962
|
-
// bundle商品是否是加价或减价
|
|
963
|
-
export var getBundleItemIsMarkupOrDiscountPrice = function getBundleItemIsMarkupOrDiscountPrice(item) {
|
|
964
|
-
return getBundleItemIsMarkupPrice(item) || getBundleItemIsDiscountPrice(item);
|
|
965
|
-
};
|