UNPKG

@pisell/pisellos

Version:

一个可扩展的前端模块化SDK框架,支持插件系统

1,090 lines (991 loc) 60.9 kB
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); } 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; } 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; } 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; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); } 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); } 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; } } }; } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } 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."); } 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); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } 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; } import Decimal from 'decimal.js'; /** 订单商品数量 */ export var getProductQuantity = function getProductQuantity(product) { return product.quantity || product.product_quantity || 1; }; /** * 订单商品行唯一键,用于 maxPassesPerItem 按行、按件配额(同 SPU 不同规格视为不同行)。 */ export function resolveWalletPassLineKey(product, indexInOrder) { var m = (product === null || product === void 0 ? void 0 : product.metadata) || {}; var u1 = m.product_unique; if (u1 != null && String(u1).length > 0) return String(u1); var u2 = m.unique_identification_number; if (u2 != null && String(u2).length > 0) return String(u2); if ((product === null || product === void 0 ? void 0 : product.id) != null && String(product.id).length > 0) return "order_item:".concat(product.id); if ((product === null || product === void 0 ? void 0 : product.product_unique_string) != null && String(product.product_unique_string).length > 0) { return String(product.product_unique_string); } return "order_line_".concat(indexInOrder); } function getExpandedOrderLineQuantity(p) { if ((p === null || p === void 0 ? void 0 : p._orderLineQuantity) != null && p._orderLineQuantity > 0) return p._orderLineQuantity; return getProductQuantity(p); } /** 该行允许消耗的「券次」上限:maxPassesPerItem × 订单行件数 */ function getMaxPassSlotsForExpandedLine(maxPassesPerItem, p) { if (maxPassesPerItem <= 0) return Infinity; return maxPassesPerItem * getExpandedOrderLineQuantity(p); } /** * 本次抵扣占用多少「券次」配额:有抵扣时至少占 1,并与按金额折算的件数挂钩,不超过剩余额度。 */ function computePassSlotsIncrement(deductAmount, deductQty, maxPassesPerItem, orderLineQuantity, currentUsage) { if (maxPassesPerItem <= 0 || !deductAmount.greaterThan(0)) return 0; var cap = maxPassesPerItem * orderLineQuantity; var room = Math.max(0, cap - currentUsage); if (room <= 0) return 0; var raw = Math.max(1, Math.ceil(Number(deductQty)) || 1); return Math.min(raw, room); } function applyMaxPassUsageIncrements(usageMap, walletPassProductId, maxPassesPerItem, deductionDetails) { deductionDetails.forEach(function (detail) { var _usageMap$get; var lineKey = detail.lineKey; if (!lineKey || maxPassesPerItem <= 0) return; var orderLineQty = detail.orderLineQuantity != null && detail.orderLineQuantity > 0 ? detail.orderLineQuantity : 1; var cur = ((_usageMap$get = usageMap.get(walletPassProductId)) === null || _usageMap$get === void 0 ? void 0 : _usageMap$get.get(lineKey)) || 0; var inc = computePassSlotsIncrement(new Decimal(detail.deductAmount), detail.deductQuantity, maxPassesPerItem, orderLineQty, cur); if (inc <= 0) return; if (!usageMap.has(walletPassProductId)) usageMap.set(walletPassProductId, new Map()); var inner = usageMap.get(walletPassProductId); inner.set(lineKey, cur + inc); }); } // 辅助函数:根据 deductTaxAndFee 配置获取推荐使用金额 var getRecommendedAmount = function getRecommendedAmount(voucher) { var _config$deductTaxAndF; console.log('voucher312', voucher); var config = voucher.config, recommended_usage_amount = voucher.recommended_usage_amount, recommended_pure_product_usage_amount = voucher.recommended_pure_product_usage_amount; var deductTaxAndFee = (_config$deductTaxAndF = config === null || config === void 0 ? void 0 : config.deductTaxAndFee) !== null && _config$deductTaxAndF !== void 0 ? _config$deductTaxAndF : true; // 默认开启抵扣税费 // 如果开启抵扣税费,使用 recommended_usage_amount(包含税费) // 如果关闭抵扣税费,使用 recommended_pure_product_usage_amount(仅商品金额) 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; }; // 辅助函数:获取适用商品ID列表 export var getApplicableProductIds = function getApplicableProductIds(voucher) { var _ref = voucher, available_product_type = _ref.available_product_type, available_product_ids = _ref.available_product_ids; // 如果没有 available_product_type,默认为 product_all var productType = available_product_type || 'product_all'; // product_all 时,返回 null 表示适用所有商品 if (productType === 'product_all') { return null; } // product_collection 或 products 时,返回指定的商品ID列表 if (productType === 'product_collection' || productType === 'products') { return available_product_ids || []; } // 其他情况默认返回空数组(不适用任何商品) return []; }; // 辅助函数:计算适用商品的总金额(基于剩余金额) var getApplicableProductsAmount = function getApplicableProductsAmount(voucher, productsData) { var _config$deductTaxAndF2; var applicableProductIds = getApplicableProductIds(voucher); var config = voucher.config; var deductTaxAndFee = (_config$deductTaxAndF2 = config === null || config === void 0 ? void 0 : config.deductTaxAndFee) !== null && _config$deductTaxAndF2 !== void 0 ? _config$deductTaxAndF2 : true; // 根据券的配置选择使用哪个金额字段 var amountField = deductTaxAndFee ? 'remainingAmountWithTax' : 'remainingAmountPure'; // 如果为 null,适用于所有商品 if (applicableProductIds === null) { return productsData.filter(function (p) { return p[amountField].greaterThan(0); }).reduce(function (sum, p) { return sum.plus(p[amountField]); }, new Decimal(0)); } // 如果为空数组,不适用任何商品 if (applicableProductIds.length === 0) { return new Decimal(0); } // 计算指定商品的总金额 return productsData.filter(function (p) { return applicableProductIds.includes(p.product_id) && p[amountField].greaterThan(0); }).reduce(function (sum, p) { return sum.plus(p[amountField]); }, new Decimal(0)); }; // 辅助函数:获取适用的商品列表 var getApplicableProducts = function getApplicableProducts(voucher, productsData) { var applicableProductIds = getApplicableProductIds(voucher); // 如果为 null,适用于所有商品 if (applicableProductIds === null) { return productsData; } // 如果为空数组,不适用任何商品 if (applicableProductIds.length === 0) { return []; } // 返回指定的商品列表 return productsData.filter(function (p) { return applicableProductIds.includes(p.product_id); }); }; /** * 优惠券处理函数 * @param applicableVouchers 可用的券列表 * @param orderTotalAmount 订单总金额 * @param products 订单商品列表 * @returns 返回推荐券列表和全部列表,每个券包含 _available_max_amount 和 _unified_available_status */ export function processVouchers(applicableVouchers, orderTotalAmount, products) { console.log(products, 'products123'); // 拆分商品数据,同时维护含税和不含税两个金额池 // remainingAmountWithTax: 含税费的剩余可抵扣金额 // remainingAmountPure: 纯商品金额(不含税费)的剩余可抵扣金额 // 在抵扣时,会根据券的 deductTaxAndFee 配置选择从哪个金额池扣除 var productsCopy = expandProductsWithBundleItems(products, true); var remainingOrderAmount = new Decimal(orderTotalAmount); // 订单剩余应付金额 // ========== 辅助工具:maxPassesPerItem(按订单行 + 件数)追踪 ========== var getItemPassUsage = function getItemPassUsage(usageMap, walletPassProductId, lineKey) { var _usageMap$get2; return ((_usageMap$get2 = usageMap.get(walletPassProductId)) === null || _usageMap$get2 === void 0 ? void 0 : _usageMap$get2.get(lineKey)) || 0; }; // 按 maxPassesPerItem 过滤:排除已达到该行「券次」上限的展开行(按 _walletPassLineKey) var filterByMaxPassesPerItem = function filterByMaxPassesPerItem(products, usageMap, walletPassProductId, maxPassesPerItem) { if (maxPassesPerItem <= 0) return products; return products.filter(function (p) { var lineKey = p._walletPassLineKey; if (!lineKey) return true; return getItemPassUsage(usageMap, walletPassProductId, lineKey) < getMaxPassSlotsForExpandedLine(maxPassesPerItem, p); }); }; // ================================================================ // 辅助函数:计算单张券的 _available_max_amount var calculateAvailableMaxAmount = function calculateAvailableMaxAmount(voucher, productsData, itemPassUsage) { var config = voucher.config; var _ref2 = config !== null && config !== void 0 ? config : {}, _ref2$maxDeductionAmo = _ref2.maxDeductionAmount, maxDeductionAmount = _ref2$maxDeductionAmo === void 0 ? 0 : _ref2$maxDeductionAmo, _ref2$allowCrossProdu = _ref2.allowCrossProduct, allowCrossProduct = _ref2$allowCrossProdu === void 0 ? true : _ref2$allowCrossProdu, _ref2$applicableProdu = _ref2.applicableProductLimit, applicableProductLimit = _ref2$applicableProdu === void 0 ? 0 : _ref2$applicableProdu, _ref2$deductTaxAndFee = _ref2.deductTaxAndFee, deductTaxAndFee = _ref2$deductTaxAndFee === void 0 ? true : _ref2$deductTaxAndFee, _ref2$maxPassesPerIte = _ref2.maxPassesPerItem, maxPassesPerItem = _ref2$maxPassesPerIte === void 0 ? 0 : _ref2$maxPassesPerIte; // 根据 deductTaxAndFee 配置获取推荐金额 var recommendedAmount = getRecommendedAmount(voucher); // 基础值 = min(recommendedAmount, maxDeductionAmount) var baseAmount = Decimal.min(new Decimal(recommendedAmount), new Decimal(maxDeductionAmount)); // 根据券的配置选择使用哪个单价字段和金额字段 var unitPriceField = deductTaxAndFee ? 'unitPriceWithTax' : 'unitPricePure'; var amountField = deductTaxAndFee ? 'remainingAmountWithTax' : 'remainingAmountPure'; // 获取适用商品列表(只筛选有剩余金额的商品) var applicableProducts = getApplicableProducts(voucher, productsData).filter(function (p) { return p[amountField].greaterThan(0); }); // 按 maxPassesPerItem 过滤:排除已达到单商品可用卡券上限的商品 if (itemPassUsage) { applicableProducts = filterByMaxPassesPerItem(applicableProducts, itemPassUsage, voucher.product_id, maxPassesPerItem); } if (applicableProducts.length === 0) { return new Decimal(0); } // 根据跨商品配置计算适用商品金额 var finalApplicableAmount = new Decimal(0); if (allowCrossProduct) { // 跨商品券:可以抵扣多个商品 if (applicableProductLimit > 0) { // 有数量限制:按剩余金额从高到低排序,按动态计算的可抵扣数量累计直到达到 limit var sortedProducts = _toConsumableArray(applicableProducts).sort(function (a, b) { return a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1; }); var remainingLimit = applicableProductLimit; var _iterator = _createForOfIteratorHelper(sortedProducts), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var product = _step.value; if (remainingLimit <= 0) break; // 动态计算当前可抵扣数量 = ceil(剩余金额 / 单价) var currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber()); var deductQty = Math.min(currentAvailableQty, remainingLimit); // 实际可抵扣金额 = min(数量 * 单价, 剩余金额) var deductAmount = Decimal.min(product[unitPriceField].times(deductQty), product[amountField]); finalApplicableAmount = finalApplicableAmount.plus(deductAmount); remainingLimit -= deductQty; } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } } else { // 无数量限制:所有适用商品的剩余金额总和 finalApplicableAmount = applicableProducts.reduce(function (sum, p) { return sum.plus(p[amountField]); }, new Decimal(0)); } } else { // 非跨商品券:选择单价最高的商品(优先抵扣高价商品) var maxProduct = applicableProducts.reduce(function (max, p) { return p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max; }); // maxPassesPerItem 限制每张券最多抵扣的单位数 if (maxPassesPerItem > 0) { finalApplicableAmount = Decimal.min(maxProduct[unitPriceField].times(maxPassesPerItem), maxProduct[amountField]); } else { finalApplicableAmount = maxProduct[amountField]; } } // 返回最小值 return Decimal.min(baseAmount, finalApplicableAmount, remainingOrderAmount); }; // 辅助函数:判断券是否可用,返回可用性和原因代码 var isVoucherAvailable = function isVoucherAvailable(voucher, productsData, usedVoucherCounts, itemPassUsage) { var config = voucher.config, id = voucher.id, product_id = voucher.product_id; // 根据 deductTaxAndFee 配置获取推荐金额 var recommendedAmount = getRecommendedAmount(voucher); // 余额为 0 if (recommendedAmount <= 0) { return { isAvailable: false, reasonCode: 'not_meet_the_required_conditions' }; } // 订单金额已抵扣完 if (remainingOrderAmount.lessThanOrEqualTo(0)) { return { isAvailable: false, reasonCode: 'exceeds_the_maximum_deduction_limit' }; } // 适用商品金额已被抵扣完 var applicableAmount = getApplicableProductsAmount(voucher, productsData); if (applicableAmount.lessThanOrEqualTo(0)) { return { isAvailable: false, reasonCode: 'not_meet_the_required_conditions' }; } // 检查 maxUsagePerOrder(同 product_id 的券),0 表示不限制 if (((config === null || config === void 0 ? void 0 : config.maxUsagePerOrder) || 0) > 0) { var usedCount = usedVoucherCounts.get(product_id) || 0; if (usedCount >= ((config === null || config === void 0 ? void 0 : config.maxUsagePerOrder) || 0)) { return { isAvailable: false, reasonCode: 'usage_limit_reached' }; } } // 检查 maxPassesPerItem:如果所有适用商品都已达到单商品可用卡券上限,则不可用 var maxPassesPerItem = (config === null || config === void 0 ? void 0 : config.maxPassesPerItem) || 0; if (maxPassesPerItem > 0 && itemPassUsage) { var _config$deductTaxAndF3; var deductTaxAndFee = (_config$deductTaxAndF3 = config === null || config === void 0 ? void 0 : config.deductTaxAndFee) !== null && _config$deductTaxAndF3 !== void 0 ? _config$deductTaxAndF3 : true; var amountField = deductTaxAndFee ? 'remainingAmountWithTax' : 'remainingAmountPure'; var availableAfterPassLimit = getApplicableProducts(voucher, productsData).filter(function (p) { return p[amountField].greaterThan(0); }).filter(function (p) { var lineKey = p._walletPassLineKey; if (!lineKey) return true; return getItemPassUsage(itemPassUsage, product_id, lineKey) < getMaxPassSlotsForExpandedLine(maxPassesPerItem, p); }); if (availableAfterPassLimit.length === 0) { return { isAvailable: false, reasonCode: 'max_passes_per_item_reached' }; } } return { isAvailable: true }; }; // ========== 第一步:为所有券计算初始的 _available_max_amount 和 _unified_available_status ========== var usedVoucherCountsForAll = new Map(); var allVouchersWithStatus = applicableVouchers.map(function (voucher) { var _available_max_amount = calculateAvailableMaxAmount(voucher, productsCopy); var availabilityResult = isVoucherAvailable(voucher, productsCopy, usedVoucherCountsForAll); var _unified_available_status = availabilityResult.isAvailable ? 1 : 0; return _objectSpread(_objectSpread({}, voucher), {}, { _available_max_amount: _available_max_amount.toNumber(), // 转换为数字 _unified_available_status: _unified_available_status }, availabilityResult.reasonCode && { reasonCode: availabilityResult.reasonCode }); }); // ========== 第二步:计算推荐券列表 ========== var recommendedVouchers = []; var usedVoucherCounts = new Map(); // 跟踪每个券 ID 的使用次数 // 重置商品余额追踪(同时维护含税和不含税两个金额池) var productsForRecommendation = expandProductsWithBundleItems(products, true); remainingOrderAmount = new Decimal(orderTotalAmount); // 追踪推荐阶段每个 Wallet Pass 商品对每个订单商品行的已使用卡券次数(按行唯一键) var itemPassUsageMap = new Map(); /** // 分类券:未跨商品券 vs 跨商品券 const nonCrossProductVouchers = applicableVouchers.filter( (v) => !v.config?.allowCrossProduct, ); const crossProductVouchers = applicableVouchers.filter( (v) => v.config?.allowCrossProduct, ); // 按 tag 分组 const groupByType = (vouchers: any[]) => { const groups = new Map<string, any[]>(); vouchers.forEach((v) => { const tag = v.tag; if (!groups.has(tag)) { groups.set(tag, []); } groups.get(tag)!.push(v); }); return groups; }; // 对每组券按金额(balance)从大到小排序 const sortVouchersByAmount = (vouchers: Voucher[]) => { return [...vouchers].sort((a, b) => getRecommendedAmount(b) - getRecommendedAmount(a)); }; */ // 处理单张券的抵扣 var applyVoucher = function applyVoucher(voucher) { // 检查是否可用 var availabilityCheck = isVoucherAvailable(voucher, productsForRecommendation, usedVoucherCounts, itemPassUsageMap); if (!availabilityCheck.isAvailable) { return false; } var config = voucher.config, id = voucher.id, product_id = voucher.product_id; var _ref3 = config !== null && config !== void 0 ? config : {}, _ref3$maxDeductionAmo = _ref3.maxDeductionAmount, maxDeductionAmount = _ref3$maxDeductionAmo === void 0 ? 0 : _ref3$maxDeductionAmo, _ref3$allowCrossProdu = _ref3.allowCrossProduct, allowCrossProduct = _ref3$allowCrossProdu === void 0 ? true : _ref3$allowCrossProdu, _ref3$applicableProdu = _ref3.applicableProductLimit, applicableProductLimit = _ref3$applicableProdu === void 0 ? 0 : _ref3$applicableProdu, _ref3$deductTaxAndFee = _ref3.deductTaxAndFee, deductTaxAndFee = _ref3$deductTaxAndFee === void 0 ? true : _ref3$deductTaxAndFee, _ref3$maxPassesPerIte = _ref3.maxPassesPerItem, maxPassesPerItem = _ref3$maxPassesPerIte === void 0 ? 0 : _ref3$maxPassesPerIte; // 根据券的配置选择使用哪个单价字段和金额字段 var unitPriceField = deductTaxAndFee ? 'unitPriceWithTax' : 'unitPricePure'; var amountField = deductTaxAndFee ? 'remainingAmountWithTax' : 'remainingAmountPure'; // 获取适用商品(只筛选有剩余金额的商品) var applicableProducts = getApplicableProducts(voucher, productsForRecommendation).filter(function (p) { return p[amountField].greaterThan(0); }); // 按 maxPassesPerItem 过滤:排除已达到单商品可用卡券上限的商品 applicableProducts = filterByMaxPassesPerItem(applicableProducts, itemPassUsageMap, product_id, maxPassesPerItem); if (applicableProducts.length === 0) return false; // ========== 关键修改:在应用券之前,基于当前剩余金额计算 _available_max_amount ========== // 优先使用用户手动编辑的金额,否则根据 deductTaxAndFee 配置获取推荐金额 var usageAmount = typeof voucher.edit_current_amount === 'number' ? voucher.edit_current_amount : getRecommendedAmount(voucher); var baseAmount = Decimal.min(new Decimal(usageAmount), new Decimal(maxDeductionAmount)); var calculatedAvailableMaxAmount = new Decimal(0); if (allowCrossProduct) { // 跨商品券:按 quantity 限制计算可抵扣金额 if (applicableProductLimit > 0) { // 按剩余金额从高到低排序 var sortedProducts = _toConsumableArray(applicableProducts).sort(function (a, b) { return a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1; }); var remainingLimit = applicableProductLimit; var _iterator2 = _createForOfIteratorHelper(sortedProducts), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var product = _step2.value; if (remainingLimit <= 0) break; // 动态计算当前可抵扣数量 = ceil(剩余金额 / 单价) var currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber()); var deductQty = Math.min(currentAvailableQty, remainingLimit); // 实际可抵扣金额 = min(数量 * 单价, 剩余金额) var deductAmount = Decimal.min(product[unitPriceField].times(deductQty), product[amountField]); calculatedAvailableMaxAmount = calculatedAvailableMaxAmount.plus(deductAmount); remainingLimit -= deductQty; } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } } else { // 无数量限制:所有适用商品的剩余金额总和 calculatedAvailableMaxAmount = applicableProducts.reduce(function (sum, p) { return sum.plus(p[amountField]); }, new Decimal(0)); } } else { // 非跨商品券:选择单价最高的商品(优先抵扣高价商品) var maxProduct = applicableProducts.reduce(function (max, p) { return p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max; }); // maxPassesPerItem 限制每张券最多抵扣的单位数 if (maxPassesPerItem > 0) { calculatedAvailableMaxAmount = Decimal.min(maxProduct[unitPriceField].times(maxPassesPerItem), maxProduct[amountField]); } else { calculatedAvailableMaxAmount = maxProduct[amountField]; } } // 取最小值:min(recommended_usage_amount, maxDeductionAmount, 适用商品金额, 订单剩余金额) var availableMaxAmount = Decimal.min(baseAmount, calculatedAvailableMaxAmount, remainingOrderAmount); // ====================================================================================== // 计算本次抵扣金额(使用同样的 usageAmount) var maxDeduction = Decimal.min(new Decimal(usageAmount), new Decimal(maxDeductionAmount)); var deductionLeft = maxDeduction; var deductionDetails = []; if (allowCrossProduct) { // 跨商品券:按剩余金额从高到低抵扣,受 applicableProductLimit 限制 var _sortedProducts = _toConsumableArray(applicableProducts).sort(function (a, b) { return a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1; }); var _remainingLimit = applicableProductLimit > 0 ? applicableProductLimit : Infinity; var _iterator3 = _createForOfIteratorHelper(_sortedProducts), _step3; try { for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { var _product = _step3.value; if (deductionLeft.lessThanOrEqualTo(0) || _remainingLimit <= 0) break; // 动态计算当前可抵扣数量 = ceil(剩余金额 / 单价) var _currentAvailableQty = Math.ceil(_product[amountField].dividedBy(_product[unitPriceField]).toNumber()); var availableQty = Math.min(_currentAvailableQty, _remainingLimit); // 计算本商品最大可抵扣金额 = min(数量 * 单价, 剩余金额) var maxDeductForProduct = Decimal.min(_product[unitPriceField].times(availableQty), _product[amountField]); var actualDeductAmount = Decimal.min(deductionLeft, maxDeductForProduct); // 计算实际抵扣的数量(用于记录和配额计算) var actualDeductQty = Math.ceil(actualDeductAmount.dividedBy(_product[unitPriceField]).toNumber()); // 只更新商品的剩余金额,不更新 remainingQuantity _product[amountField] = _product[amountField].minus(actualDeductAmount); deductionLeft = deductionLeft.minus(actualDeductAmount); _remainingLimit -= actualDeductQty; deductionDetails.push({ product_id: _product.product_id, parent_product_id: _product.parent_product_id || null, is_bundle_item: _product.is_bundle_item || false, lineKey: _product._walletPassLineKey, orderLineQuantity: getExpandedOrderLineQuantity(_product), deductAmount: actualDeductAmount.toNumber(), // 转换为数字 deductQuantity: actualDeductQty // 抵扣涉及的数量(用于记录) }); } } catch (err) { _iterator3.e(err); } finally { _iterator3.f(); } } else { // 非跨商品券:选择单价最高的商品(优先抵扣高价商品) var targetProduct = applicableProducts.reduce(function (max, p) { return p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max; }); // maxPassesPerItem 限制每张券最多抵扣的单位数 var _maxDeductForProduct = targetProduct[amountField]; if (maxPassesPerItem > 0) { _maxDeductForProduct = Decimal.min(targetProduct[unitPriceField].times(maxPassesPerItem), targetProduct[amountField]); } var _actualDeductAmount = Decimal.min(deductionLeft, _maxDeductForProduct); // 计算实际抵扣的数量 var _actualDeductQty = Math.ceil(_actualDeductAmount.dividedBy(targetProduct[unitPriceField]).toNumber()); // 只更新商品的剩余金额,不更新 remainingQuantity targetProduct[amountField] = targetProduct[amountField].minus(_actualDeductAmount); deductionLeft = deductionLeft.minus(_actualDeductAmount); deductionDetails.push({ product_id: targetProduct.product_id, parent_product_id: targetProduct.parent_product_id || null, is_bundle_item: targetProduct.is_bundle_item || false, lineKey: targetProduct._walletPassLineKey, orderLineQuantity: getExpandedOrderLineQuantity(targetProduct), deductAmount: _actualDeductAmount.toNumber(), deductQuantity: _actualDeductQty }); } var totalDeducted = maxDeduction.minus(deductionLeft); if (totalDeducted.greaterThan(0)) { // 更新订单剩余金额 remainingOrderAmount = remainingOrderAmount.minus(totalDeducted); // 更新券使用次数(按 product_id 统计) usedVoucherCounts.set(product_id, (usedVoucherCounts.get(product_id) || 0) + 1); applyMaxPassUsageIncrements(itemPassUsageMap, product_id, maxPassesPerItem, deductionDetails); // 添加到推荐列表(包含基于当前剩余金额计算的 available_max_amount) recommendedVouchers.push(_objectSpread(_objectSpread({}, voucher), {}, { actualDeduction: totalDeducted.toNumber(), // 转换为数字 deductionDetails: deductionDetails, _available_max_amount: availableMaxAmount.toNumber(), // 转换为数字 _unified_available_status: 1 })); return true; } return false; }; /** // 第一轮:处理未跨商品券 const nonCrossGroups = groupByType(nonCrossProductVouchers); nonCrossGroups.forEach((vouchersInGroup) => { const sortedVouchers = sortVouchersByAmount(vouchersInGroup); sortedVouchers.forEach((voucher) => { applyVoucher(voucher); }); }); // 第二轮:处理跨商品券 const crossGroups = groupByType(crossProductVouchers); crossGroups.forEach((vouchersInGroup) => { const sortedVouchers = sortVouchersByAmount(vouchersInGroup); sortedVouchers.forEach((voucher) => { applyVoucher(voucher); }); }); */ // 直接按 applicableVouchers 的顺序处理所有券 applicableVouchers.forEach(function (voucher) { applyVoucher(voucher); }); // recommendedVouchers 已经包含了基于应用时计算的 _available_max_amount 和 _unified_available_status // ========== 第三步:构建 all 数组,以 recommended 为基础 ========== // 创建 recommended 券的 Map,以 id 为 key var recommendedMap = new Map(); recommendedVouchers.forEach(function (v) { recommendedMap.set(v.id, v); }); // 遍历所有券,如果在 recommended 中则使用增强数据,否则使用基础数据 var allWithEnhancedData = allVouchersWithStatus.map(function (voucher) { if (recommendedMap.has(voucher.id)) { // 使用 recommended 中的增强数据 return recommendedMap.get(voucher.id); } else { // 不在 recommended 中的券,补充基础字段 return _objectSpread(_objectSpread({}, voucher), {}, { actualDeduction: 0, deductionDetails: [] // 保留 reasonCode(如果不可用的话) }); } }); return { recommended: recommendedVouchers, transformList: allWithEnhancedData }; } /** * 重新计算优惠券状态(基于已选券的增量计算) * @param allVouchers 所有原始券列表 * @param selectedVouchers 已选中的券列表(按选中顺序) * @param orderTotalAmount 订单总金额 * @param products 订单商品列表 * @returns 返回更新后的所有券列表和已选券的详细抵扣信息 */ export function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, products) { // 深拷贝并拆分商品列表(包含主商品和原价子商品,同时维护含税和不含税两个金额池),用于计算 var productsForCalc = expandProductsWithBundleItems(products, true); var remainingOrderAmount = new Decimal(orderTotalAmount); var selectedWithDetails = []; // 追踪每个 Wallet Pass 商品对每个订单商品行的已使用卡券次数(按行唯一键) var itemPassUsageMap = new Map(); var getItemPassUsageRecalc = function getItemPassUsageRecalc(walletPassProductId, lineKey) { var _itemPassUsageMap$get; return ((_itemPassUsageMap$get = itemPassUsageMap.get(walletPassProductId)) === null || _itemPassUsageMap$get === void 0 ? void 0 : _itemPassUsageMap$get.get(lineKey)) || 0; }; var filterByMaxPassesPerItemRecalc = function filterByMaxPassesPerItemRecalc(products, walletPassProductId, maxPassesPerItem) { if (maxPassesPerItem <= 0) return products; return products.filter(function (p) { var lineKey = p._walletPassLineKey; if (!lineKey) return true; return getItemPassUsageRecalc(walletPassProductId, lineKey) < getMaxPassSlotsForExpandedLine(maxPassesPerItem, p); }); }; // 第一步:按顺序应用已选中的券,计算实际抵扣 selectedVouchers.forEach(function (selectedVoucher) { var config = selectedVoucher.config, id = selectedVoucher.id; var maxDeductionAmount = config.maxDeductionAmount, allowCrossProduct = config.allowCrossProduct, applicableProductLimit = config.applicableProductLimit, _config$deductTaxAndF4 = config.deductTaxAndFee, deductTaxAndFee = _config$deductTaxAndF4 === void 0 ? true : _config$deductTaxAndF4, _config$maxPassesPerI = config.maxPassesPerItem, maxPassesPerItem = _config$maxPassesPerI === void 0 ? 0 : _config$maxPassesPerI; // 根据券的配置选择使用哪个单价字段和金额字段 var unitPriceField = deductTaxAndFee ? 'unitPriceWithTax' : 'unitPricePure'; var amountField = deductTaxAndFee ? 'remainingAmountWithTax' : 'remainingAmountPure'; // 获取适用商品(只筛选有剩余金额的商品) var applicableProducts = getApplicableProducts(selectedVoucher, productsForCalc).filter(function (p) { return p[amountField].greaterThan(0); }); // 按 maxPassesPerItem 过滤:排除已达到该行券次上限的展开行 applicableProducts = filterByMaxPassesPerItemRecalc(applicableProducts, selectedVoucher.product_id, maxPassesPerItem); if (applicableProducts.length === 0) { // 无适用商品,跳过 selectedWithDetails.push(_objectSpread(_objectSpread({}, selectedVoucher), {}, { actualDeduction: 0, deductionDetails: [], _available_max_amount: 0, _unified_available_status: 0, reasonCode: 'not_meet_the_required_conditions' })); return; } // 计算本次抵扣金额 // 优先使用用户手动编辑的金额,否则根据 deductTaxAndFee 配置获取推荐金额 var usageAmount = typeof selectedVoucher.edit_current_amount === 'number' ? selectedVoucher.edit_current_amount : getRecommendedAmount(selectedVoucher); var maxDeduction = Decimal.min(new Decimal(usageAmount), new Decimal(maxDeductionAmount), remainingOrderAmount); var deductionLeft = maxDeduction; var deductionDetails = []; if (allowCrossProduct) { // 跨商品券:按剩余金额从高到低抵扣,受 applicableProductLimit 限制 var sortedProducts = _toConsumableArray(applicableProducts).sort(function (a, b) { return a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1; }); var remainingLimit = applicableProductLimit > 0 ? applicableProductLimit : Infinity; var _iterator4 = _createForOfIteratorHelper(sortedProducts), _step4; try { for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) { var product = _step4.value; if (deductionLeft.lessThanOrEqualTo(0) || remainingLimit <= 0) break; // 动态计算当前可抵扣数量 = ceil(剩余金额 / 单价) var currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber()); var availableQty = Math.min(currentAvailableQty, remainingLimit); // 计算本商品最大可抵扣金额 = min(数量 * 单价, 剩余金额) var maxDeductForProduct = Decimal.min(product[unitPriceField].times(availableQty), product[amountField]); var actualDeductAmount = Decimal.min(deductionLeft, maxDeductForProduct); // 计算实际抵扣的数量(用于记录和配额计算) var actualDeductQty = Math.ceil(actualDeductAmount.dividedBy(product[unitPriceField]).toNumber()); // 只更新商品的剩余金额,不更新 remainingQuantity product[amountField] = product[amountField].minus(actualDeductAmount); deductionLeft = deductionLeft.minus(actualDeductAmount); remainingLimit -= actualDeductQty; deductionDetails.push({ product_id: product.product_id, parent_product_id: product.parent_product_id || null, is_bundle_item: product.is_bundle_item || false, lineKey: product._walletPassLineKey, orderLineQuantity: getExpandedOrderLineQuantity(product), deductAmount: actualDeductAmount.toNumber(), // 转换为数字 deductQuantity: actualDeductQty // 抵扣涉及的数量(用于记录) }); } } catch (err) { _iterator4.e(err); } finally { _iterator4.f(); } } else { // 非跨商品券:选择单价最高的商品(优先抵扣高价商品) var targetProduct = applicableProducts.reduce(function (max, p) { return p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max; }); // maxPassesPerItem 限制每张券最多抵扣的单位数 var _maxDeductForProduct2 = targetProduct[amountField]; if (maxPassesPerItem > 0) { _maxDeductForProduct2 = Decimal.min(targetProduct[unitPriceField].times(maxPassesPerItem), targetProduct[amountField]); } var _actualDeductAmount2 = Decimal.min(deductionLeft, _maxDeductForProduct2); // 计算实际抵扣的数量 var _actualDeductQty2 = Math.ceil(_actualDeductAmount2.dividedBy(targetProduct[unitPriceField]).toNumber()); // 只更新商品的剩余金额,不更新 remainingQuantity targetProduct[amountField] = targetProduct[amountField].minus(_actualDeductAmount2); deductionLeft = deductionLeft.minus(_actualDeductAmount2); deductionDetails.push({ product_id: targetProduct.product_id, parent_product_id: targetProduct.parent_product_id || null, is_bundle_item: targetProduct.is_bundle_item || false, lineKey: targetProduct._walletPassLineKey, orderLineQuantity: getExpandedOrderLineQuantity(targetProduct), deductAmount: _actualDeductAmount2.toNumber(), deductQuantity: _actualDeductQty2 }); } var totalDeducted = maxDeduction.minus(deductionLeft); // 更新订单剩余金额 remainingOrderAmount = remainingOrderAmount.minus(totalDeducted); applyMaxPassUsageIncrements(itemPassUsageMap, selectedVoucher.product_id, maxPassesPerItem, deductionDetails); selectedWithDetails.push(_objectSpread(_objectSpread({}, selectedVoucher), {}, { actualDeduction: totalDeducted.toNumber(), // 转换为数字 deductionDetails: deductionDetails, _available_max_amount: totalDeducted.toNumber(), // 转换为数字 _unified_available_status: totalDeducted.greaterThan(0) ? 1 : 0 })); }); // 第二步:为所有券重新计算 _available_max_amount 和 _unified_available_status var selectedIds = new Set(selectedVouchers.map(function (v) { return v.id; })); var usedVoucherCounts = new Map(); selectedVouchers.forEach(function (v) { usedVoucherCounts.set(v.product_id, (usedVoucherCounts.get(v.product_id) || 0) + 1); }); var allWithUpdatedStatus = allVouchers.map(function (voucher) { // 如果是已选中的券,使用详细计算结果 if (selectedIds.has(voucher.id)) { var selectedDetail = selectedWithDetails.find(function (v) { return v.id === voucher.id; }); return selectedDetail || voucher; } // 未选中的券,重新计算其可用状态 var config = voucher.config, id = voucher.id, product_id = voucher.product_id; var maxDeductionAmount = config.maxDeductionAmount, allowCrossProduct = config.allowCrossProduct, applicableProductLimit = config.applicableProductLimit, _config$deductTaxAndF5 = config.deductTaxAndFee, deductTaxAndFee = _config$deductTaxAndF5 === void 0 ? true : _config$deductTaxAndF5, _config$maxPassesPerI2 = config.maxPassesPerItem, maxPassesPerItem = _config$maxPassesPerI2 === void 0 ? 0 : _config$maxPassesPerI2; // 根据券的配置选择使用哪个单价字段和金额字段 var unitPriceField = deductTaxAndFee ? 'unitPriceWithTax' : 'unitPricePure'; var amountField = deductTaxAndFee ? 'remainingAmountWithTax' : 'remainingAmountPure'; // 根据 deductTaxAndFee 配置获取推荐金额 var recommendedAmount = getRecommendedAmount(voucher); // 检查基本可用性 var isAvailable = true; var calculatedMaxAmount = new Decimal(0); var reasonCode; if (recommendedAmount <= 0) { isAvailable = false; reasonCode = 'not_meet_the_required_conditions'; } else if (remainingOrderAmount.lessThanOrEqualTo(0)) { isAvailable = false; reasonCode = 'exceeds_the_maximum_deduction_limit'; } else { // 检查 maxUsagePerOrder(按 product_id 统计),0 表示不限制 if (config.maxUsagePerOrder > 0) { var usedCount = usedVoucherCounts.get(product_id) || 0; if (usedCount >= config.maxUsagePerOrder) { isAvailable = false; reasonCode = 'usage_limit_reached'; } } if (isAvailable) { // 获取适用商品(只筛选有剩余金额的商品) var applicableProducts = getApplicableProducts(voucher, productsForCalc).filter(function (p) { return p[amountField].greaterThan(0); }); // 按 maxPassesPerItem 过滤:排除已达到单商品可用卡券上限的商品 applicableProducts = filterByMaxPassesPerItemRecalc(applicableProducts, product_id, maxPassesPerItem); if (applicableProducts.length === 0) { isAvailable = false; reasonCode = 'not_meet_the_required_conditions'; } else { // 计算 _available_max_amount var baseAmount = Decimal.min(new Decimal(recommendedAmount), new Decimal(maxDeductionAmount)); if (allowCrossProduct) { if (applicableProductLimit > 0) { // 按剩余金额从高到低排序,按动态计算的可抵扣数量累计直到达到 limit var sortedProducts = _toConsumableArray(applicableProducts).sort(function (a, b) { return a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1; }); var remainingLimit = applicableProductLimit; var _iterator5 = _createForOfIteratorHelper(sortedProducts), _step5; try { for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) { var product = _step5.value; if (remainingLimit <= 0) break; // 动态计算当前可抵扣数量 = ceil(剩余金额 / 单价) var currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber()); var deductQty = Math.min(currentAvailableQty, remainingLimit); // 实际可抵扣金额 = min(数量 * 单价, 剩余金额) var deductAmount = Decimal.min(product[unitPriceField].times(deductQty), product[amountField]); calculatedMaxAmount = calculatedMaxAmount.plus(deductAmount); remainingLimit -= deductQty; } } catch (err) { _iterator5.e(err); } finally { _iterator5.f(); } } else { // 无数量限制:所有适用商品的剩余金额总和 calculatedMaxAmount = applicableProducts.reduce(function (sum, p) { return sum.plus(p[amountField]); }, new Decimal(0)); } } else { // 非跨商品券:选择单价最高的商品(优先抵扣高价商品) var maxProduct = applicableProducts.reduce(function (max, p) { return p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max; }); // maxPassesPerItem 限制每张券最多抵扣的单位数 if (maxPassesPerItem > 0) { calculatedMaxAmount = Decimal.min(maxProduct[unitPriceField].times(maxPassesPerItem), maxProduct[amountField]); } else { calculatedMaxAmount = maxProduct[amountField]; } } calculatedMaxAmount = Decimal.min(baseAmount, calculatedMaxAmount, remainingOrderAmount); if (calculatedMaxAmount.lessThanOrEqualTo(0)) { isAvailable = false; reasonCode = 'exceeds_the_maximum_deduction_limit'; } } } } return _objectSpread(_objectSpread({}, voucher), {}, { _available_max_amount: calculatedMaxAmount.toNumber(), // 转换为数字 _unified_available_status: isAvailable ? 1 : 0 }, reasonCode && { reasonCode: reasonCode }); }); return { allWithUpdatedStatus: allWithUpdatedStatus, selectedWithDetails: selectedWithDetails }; } /** * 获取税费和附加费的舍入余数 * @param product 商品 * @param isDeductTaxAndFee 是否抵扣税费与附加费 * @returns 舍入余数(税费 + 附加费的舍入余数) */ export var getTaxAndFeeRoundingRemainder = function getTaxAndFeeRoundingRemainder(product, isDeductTaxAndFee) { var _product$metadata2; if (!isDeductTaxAndFee) { return 0; } // 税费舍入余数(如果价格包含税则为0) var taxFeeRoundingRemainder = new Decimal(0); if (product.is_price_include_tax !== 1) { var _product$metadata; taxFeeRoundingRemainder = new Decimal((product === null || product === void 0 || (_product$metadata = product.metadata) === null || _product$metadata === void 0 ? void 0 : _product$metadata.tax_fee_rounding_remainder) || 0); } // 附加费舍入余数 var surchargeFeeRoundingRemainder = new Decimal((product === null || product === void 0 || (_product$metadata2 = product.metadata) === null || _product$metadata2 === void 0 ? void 0 : _product$metadata2.surcharge_rounding_remainder) || 0); return taxFeeRoundingRemainder.add(surchargeFeeRoundingRemainder).toNumber(); }; /** * 获取主商品的商品差额 * @param product 商品 * @returns 商品差额(与数量无关,计算总价时需要减去) */ export var getProductDiscountDifference = function getProductDiscountDifference(product) { var _product$metadata3; return new Decimal((product === null || product === void 0 || (_product$metadata3 = product.metadata) === null || _product$metadata3 === void 0 ? void 0 : _product$metadata3.product_discount_difference) || 0).toNumber(); }; /** * 获取主商品价格(单价,不含舍入余数) * @param product 商品 * @param isDeductTaxAndFee 是否抵扣税费与附加费 * @returns 商品单价 */ export var getMainProductPrice = function getMainProductPrice(product, isDeductTaxAndFee) { var _product$metadata4, _product$metadata5, _product$metadata6, _product$metadata7; var mainProductPrice = new Decimal((product === null || product === void 0 ? void 0 : product.main_product_selling_price) || ((_product$metadata4 = product.metadata) === null || _product$metadata4 === void 0 ? void 0 : _product$metadata4.main_product_selling_price) || 0); var _iterator6 = _createForOfIteratorHelper((product === null || product === void 0 ? void 0 : product.product_bundle) || []), _step6; try { for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) { var bundleItem = _step6.value; // 子商品是加价或减价才需要计算 if (getBundleItemIsMarkupOrDiscountPrice(bundleItem)) { var _bundleItem$bundle_se; // 子商品价格 var bundleItemPrice = new Decimal((_bundleItem$bundle_se = bundleItem.bundle_selling_price) !== null && _bundleItem$bundle_se !== void 0 ? _bundleItem$bundle_se : 0); mainProductPrice = mainProductPrice.add(bundleItemPrice.times(bundleItem.num)); } } } catch (err) { _iterator6.e(err); } finally { _iterator6.f(); } var taxFee = new Decimal((product === null || product === void 0 ? void 0 : product.tax_fee) || (product === null || product === void 0 || (_product$metadata5 = product.metadata) === null || _product$metadata5 === void 0 ? void 0 : _product$metadata5.main_product_attached_bundle_tax_fee) || 0).add((product === null || product === void 0 || (_product$metadata6 = product.metadata) === null || _product$metadata6 === void 0 ? void 0 : _product$metadata6.tax_fee_rounding_remainder) || 0); if (product.is_price_include_tax === 1) { taxFee = new Decimal(0); } // 税费 // 附加费 var surchargeFee = new Decimal((product === null || product === void 0 || (_product$metadata7 = product.metadata) === null || _product$metadata7 === void 0 ? void 0 : _product$metadata7.main_product_attached_bundle_surcharge_fee) || 0); // 税费附加费总额 var taxAndFeeTotal = taxFee.add(surchargeFee); // 如果需要抵扣税费与附加费,则加上税费附加费总额 if (isDeductTaxAndFee) { mainProductPrice = mainProductPrice.add(taxAndFeeTotal); } return mainProductPrice.toNumber(); }; /** * 获取套餐子商品税费和附加费的舍入余数 * @param bundleItem 套餐子商品 * @param isDeductTaxAndFee 是否抵扣税费与附加费 * @returns 舍入余数(税费 + 附加费的舍入余数) */ export var getBundleItemTaxAndFeeRoundingRemainder = function getBundleItemTaxAndFeeRoundingRemainder(bundleItem, isDeductTaxAndFee) { var _bundleItem$metadata2; if (!isDeductTaxAndFee) { return 0; } // 税费舍入余数(如果价格包含税则为0) var taxFeeRoundingRemainder = new Decimal(0); if (bundleItem.is_price_include_tax !== 1) { var _bundleItem$metadata; taxFeeRoundingRemainder = new Decimal(((_bundleItem$metadata = bundleItem.metadata) === null || _bundleItem$metadata === void 0 ? void 0 : _bundleItem$metadata.tax_fee_rounding_remainder) || 0); } // 附加费舍入余数 var surchargeFeeRoundingRemainder = new Decimal(((_bundleItem$metadata2 = bundleItem.metadata) === null || _bundleItem$metadata2 === void 0 ? void 0 : _bundleItem$metadata2.surcharge_rounding_remainder) || 0); return taxFeeRoundingRemainder.add(surchargeFeeRoundingRemainder).toNumber(); }; /** * 获取套餐子商品的商品差额 * @param bundleItem 套餐子商品 * @returns 商品差额(与数量无关,计算总价时需要减去) */ export var getBundleItemDiscountDifference = function getBundleItemDiscountDifference(bundleItem) { var _bundleItem$metadata3; return new Decimal(((_bundleItem$metadata3 = bundleItem.metadata) === null || _bundleItem$metadata3 === void 0 ? void 0 : _bundleItem$metadata3.product_discount_difference) || 0).toNumber(); }; /** * 获取套餐子商品价格(不含舍入余数) * @param bundleItem 套餐子商品 * @param parentQuantity 父商品数量 * @param isDeductTaxAndFee 是否抵扣税费与附加费 * @returns 子商品总价格(不含舍入余数) */ export var getBundleItemPrice = function getBundleItemPrice(bundleItem, parentQuantity, isDeductTaxAndFee) { var _bundleItem$bundle_se2; // 子商品基础价格 = bundle_selling_price * num * 主商品数量 var totalQuantity = bundleItem.num * parentQuantity; var bundleItemPrice = new Decimal((_bundleItem$bundle_se2 = bundleItem.bundle_selling_price) !== null && _bundleItem$bundle_se2 !== void 0 ? _bundleItem$bundle_se2 : 0).times(totalQuantity); // 根据 deductTaxAndFee 配置决定是否加上税费和附加费 if (isDeductTaxAndFee) { var _bundleItem$tax_fee, _bundleItem$metadata$, _bundleItem$metadata4; // 税费 var taxFee = new Decimal((_bundleItem$tax_fee = bundleItem.tax_fee) !== null && _bundleItem$tax_fee !== void 0 ? _bundleItem$tax_fee : 0).times(totalQuantity); if (bundleItem.is_price_include_tax === 1) { taxFee = new Decimal(0); } // 附加费 var surchargeFee = new Decimal((_bundleItem$metadata$ = (_bundleItem$metadata4 = bundleItem.metadata) === null || _bundleItem$metadata4 === void 0 ? void 0 : _bundleItem$metadata4.surcharge_fee) !== null && _bundleItem$metadata$ !== void 0 ? _bundleItem$metadata$ : 0).times(totalQuantity); bundleItemPrice = bundleItemPrice.add(taxFee).add(surchargeFee); } return bundleItemPrice.toNumber(); }; /** * 将商品数据拆分,包含主商品和原价子商品 * @param products 原始商品列表 * @param deductTaxAndFee 是否抵扣税费与附加费(已废弃,保留参数以兼容旧代码) * @returns 拆分后的商品数据(包含主商品和子商品,同时维护含税和不含税两个金额池,以及单价和剩余数量) */ var expandProductsWithBundleItems = function expandPr