import { BigNumber } from "bignumber.js"; import _ from "lodash"; /** * 返回可以抵扣优惠券的商品列表,过滤掉赠品、临时商品,价格从高到低排序 * @param arr 商品列表 * @param user 用户信息 */ export function returnCanDikouGoods(arr, user) { return arr .filter((v) => { return v.is_temporary != 1 && v.is_gift != 1; }) .filter((v) => { return v.num > 0; }) .sort((a, b) => { return returnGoodsPrice(b, user) - returnGoodsPrice(a, user); }); } /** * 返回商品单价 * @param goods 商品 * @param user 用户信息 */ export function returnGoodsPrice(goods, user) { if (goods.discount_sale_amount * 1 > 0) { return goods.discount_sale_amount; } if (user.isVip && goods.memberPrice * 1 <= goods.salePrice * 1 && goods.memberPrice * 1 > 0) { return goods.memberPrice; } return goods.salePrice; } /** * 返回商品分组 * @param arr 商品列表 */ export function returnGoodsGroupMap(arr) { let map = {}; arr.forEach((v) => { const key = v.productId + "_" + v.skuId; if (!map[key]) { map[key] = []; } map[key].push(v); }); return map; } /** * 优惠券类型:1-满减券,2-商品兑换券,3-折扣券,4-第二件半价券,5-消费送券,6-买一送一券,7-固定价格券,8-免配送费券 * @param coupon */ export function returnCoupType(coupon) { const couponTypes = { 1: "满减券", 2: "商品券", 3: "折扣券", 4: "第二件半价券", 5: "消费送券", 6: "买一送一券", 7: "固定价格券", 8: "免配送费券", }; return couponTypes[coupon.type] || "未知类型"; } /** * 返回商品券抵扣后的商品列表 * @param canDikouGoodsArr 可抵扣商品列表 * @param selCoupon 已选择的优惠券列表 * @param user 用户信息 */ export function returnCanDikouGoodsArr(canDikouGoodsArr, selCoupon, user) { const goodsCouponGoods = selCoupon .filter((v) => v.type == 2) .reduce((prve, cur) => { prve.push(...cur.discount.hasDiscountGoodsArr); return prve; }, []); const arr = _.cloneDeep(canDikouGoodsArr) .map((v) => { const findCart = goodsCouponGoods.find((carts) => carts.id == v.id); if (findCart) { v.num -= findCart.num; } return v; }) .filter((v) => v.num > 0); return arr; } /** * 判断优惠券是否可使用 * * @param {Object} args - 函数参数集合 * @param {Array} args.canDikouGoodsArr - 可参与抵扣的商品列表,每个元素包含商品信息(productId、num等) * @param {Object} args.coupon - 优惠券信息对象 * @param {boolean} args.coupon.use - 优惠券是否启用(true为启用,false为禁用) * @param {Array} args.coupon.useFoods - 优惠券适用的商品ID列表(空数组表示适用全部商品) * @param {number} args.coupon.fullAmount - 优惠券使用门槛金额 * @param {number} args.coupon.type - 优惠券类型(1:满减券, 2:商品券, 3:折扣券, 4:第二件半价券, 6:买一送一券) * @param {number} args.goodsOrderPrice - 订单中所有商品的总金额(未筛选时的初始金额) * @param {Object} args.user - 用户信息对象(用于计算商品价格,如会员价等) * @param {Object} args.user - 用户信息对象(用于计算商品价格,如会员价等) * @param {Object} args.selCoupon - 已经选择的优惠券信息对象 * @returns {boolean} - 优惠券是否可用(true可用,false不可用) */ export function returnCouponCanUse(args) { let { canDikouGoodsArr, coupon, goodsOrderPrice, user, selCoupon } = args; if (!coupon.use) { return false; } canDikouGoodsArr = returnCanDikouGoodsArr(canDikouGoodsArr, selCoupon, user); // 计算门槛金额 let fullAmount = goodsOrderPrice; //是否抵扣全部商品 const isDikouAll = coupon.useFoods.length === 0; let canCalcGoodsArr = []; // 订单里参与门槛计算的商品 if (!isDikouAll) { canCalcGoodsArr = canDikouGoodsArr.filter((v) => { return coupon.useFoods.find((food) => food.id == v.productId); }); fullAmount = canCalcGoodsArr.reduce((pre, cur) => { return pre + returnGoodsPrice(cur, user) * cur.num; }, 0); } //没有符合商品 if (!isDikouAll && canCalcGoodsArr.length == 0) { return false; } //不满足门槛金额 if (fullAmount < coupon.fullAmount) { console.log("不满足门槛金额"); return false; } if (coupon.type == 2) { //商品券 return isDikouAll || canCalcGoodsArr.length > 0; } if (coupon.type == 1) { //满减券 return fullAmount >= coupon.fullAmount; } if (coupon.type == 6) { //买一送一券 let canUse = false; if (isDikouAll) { canUse = canDikouGoodsArr.some((v) => v.num >= 2); } if (canCalcGoodsArr.length > 0) { canUse = canDikouGoodsArr .filter((v) => { return coupon.useFoods.find((food) => food.id == v.productId); }) .some((v) => v.num >= 2); } return canUse; } if (coupon.type == 4) { //第二件半价券 let canUse = false; if (isDikouAll) { canUse = canDikouGoodsArr.some((v) => v.num >= 2); } if (canCalcGoodsArr.length > 0) { canUse = canDikouGoodsArr .filter((v) => { return coupon.useFoods.find((food) => food.id == v.productId); }) .some((v) => v.num >= 2); } return canUse; } if (coupon.type == 3) { //折扣券 return true; } } /** * 计算抵扣商品金额 * @param discountGoodsArr 可抵扣商品列表 * @param discountNum 抵扣数量 * @param user 用户信息 */ export function calcDiscountGoodsArrPrice(discountGoodsArr, discountNum, user) { let hasCountNum = 0; let discountPrice = 0; let hasDiscountGoodsArr = []; for (let i = 0; i < discountGoodsArr.length; i++) { if (hasCountNum >= discountNum) { break; } const goods = discountGoodsArr[i]; const shengyuNum = discountNum - hasCountNum; const num = Math.min(goods.num, shengyuNum); discountPrice += returnGoodsPrice(goods, user) * num; hasCountNum += num; hasDiscountGoodsArr.push({ ...goods, num }); } return { discountPrice, hasDiscountGoodsArr }; } /** * 计算优惠券抵扣金额 * @param canDikouGoodsArr 可抵扣商品列表 * @param coupon 优惠券 * @param user 用户信息 * @param goodsOrderPrice 商品订单金额 * @param selCoupon 已选择的优惠券列表 */ export function returnCouponDiscount(canDikouGoodsArr, coupon, user, goodsOrderPrice, selCoupon) { canDikouGoodsArr = returnCanDikouGoodsArr(canDikouGoodsArr, selCoupon, user); if (coupon.type == 2) { return returnCouponProductDiscount(canDikouGoodsArr, coupon, user, goodsOrderPrice); } if (coupon.type == 6) { return returnCouponBuyOneGiveOneDiscount(canDikouGoodsArr, coupon, user, goodsOrderPrice); } if (coupon.type == 4) { return returnSecoendDiscount(canDikouGoodsArr, coupon, user, goodsOrderPrice); } if (coupon.type == 3) { return returnCouponZhekouDiscount(canDikouGoodsArr, coupon, user, goodsOrderPrice, selCoupon); } } /** * 折扣券抵扣金额 * @param canDikouGoodsArr 可抵扣商品列表 * @param coupon 优惠券 * @param user 用户信息 * @param goodsOrderPrice 商品订单金额 * @param selCoupon 已选择的优惠券列表 * */ export function returnCouponZhekouDiscount( canDikouGoodsArr, coupon, user, goodsOrderPrice, selCoupon ) { const { discountRate, maxDiscountAmount } = coupon; const goodsCouponDiscount = selCoupon .filter((v) => v.type == 2) .reduce((prve, cur) => { return prve + cur.discount.discountPrice; }, 0); goodsOrderPrice -= goodsCouponDiscount; // 使用bignumber处理高精度计算 // 1. 计算折扣率(百分比转小数):discountRate / 100 const discountRatio = new BigNumber(discountRate).dividedBy(100); // 2. 计算优惠比例:1 - 折扣率(例如:8折的优惠比例是 1 - 0.8 = 0.2) const discountAmountRatio = new BigNumber(1).minus(discountRatio); // 3. 计算折扣金额:商品订单金额 × 优惠比例 let discountPrice = new BigNumber(goodsOrderPrice).times(discountAmountRatio).toNumber(); if (maxDiscountAmount != 0) { discountPrice = discountPrice >= maxDiscountAmount ? maxDiscountAmount : discountPrice; } return { discountPrice, // 折扣抵扣金额(即优惠的金额) hasDiscountGoodsArr: [], }; } /** * 商品券抵扣金额 * @param canDikouGoodsArr 可抵扣商品列表 * @param coupon 优惠券 * @param user 用户信息 */ export function returnCouponProductDiscount(canDikouGoodsArr, coupon, user) { const { useFoods, discountNum, useRule } = coupon; //抵扣商品数组 let discountGoodsArr = []; //抵扣全部商品 if (useFoods.length === 0) { if (useRule == "price_asc") { discountGoodsArr = canDikouGoodsArr .slice(canDikouGoodsArr.length - discountNum, canDikouGoodsArr.length) .reverse(); } else { discountGoodsArr = canDikouGoodsArr.slice(0, discountNum); } } else { //抵扣选中商品 const discountSelGoodsArr = canDikouGoodsArr.filter((v) => useFoods.find((food) => food.id == v.productId) ); if (useRule == "price_asc") { discountGoodsArr = discountSelGoodsArr .slice(discountSelGoodsArr.length - discountNum, discountSelGoodsArr.length) .reverse(); } else { discountGoodsArr = discountSelGoodsArr.slice(0, discountNum); } } const result = calcDiscountGoodsArrPrice(discountGoodsArr, discountNum, user); console.log(result); return result; } // 返回买一送一券抵扣详情 /** * @param canDikouGoodsArr 可抵扣商品列表 * @param coupon 优惠券 * @param user 用户信息 */ function returnCouponBuyOneGiveOneDiscount(canDikouGoodsArr, coupon, user) { const { useFoods, useRule } = coupon; //抵扣商品 let discountGoods = undefined; //符合买一送一条件的商品 const canUseGoods = canDikouGoodsArr.filter((v) => v.num >= 2); //抵扣全部商品 if (useFoods.length === 0) { if (useRule == "price_asc") { discountGoods = canUseGoods[canUseGoods.length - 1]; } else { discountGoods = canUseGoods.slice(0, 1); } } else { //符合抵扣条件的商品 const canUseGoods1 = canUseGoods.filter((v) => useFoods.find((food) => food.id == v.productId)); console.log(canUseGoods1); if (useRule == "price_asc") { discountGoods = canUseGoods1[canUseGoods1.length - 1]; } else { discountGoods = canUseGoods1.slice(0, 1); } } console.log("discountGoods"); console.log(discountGoods); const discountPrice = returnGoodsPrice(discountGoods, user); const hasDiscountGoodsArr = [discountGoods]; return { discountPrice, hasDiscountGoodsArr }; } /** * 返回第二件半价券抵扣详情 * @param canDikouGoodsArr 可抵扣商品列表 * @param coupon 优惠券 * @param user 用户信息 */ function returnSecoendDiscount(canDikouGoodsArr, coupon, user) { const { useFoods, useRule } = coupon; //抵扣商品 let discountGoods = undefined; //符合买一送一条件的商品 const canUseGoods = canDikouGoodsArr.filter((v) => v.num >= 2); //抵扣全部商品 if (useFoods.length === 0) { if (useRule == "price_asc") { discountGoods = canUseGoods[canUseGoods.length - 1]; } else { discountGoods = canUseGoods.slice(0, 1); } } else { //符合抵扣条件的商品 const canUseGoods1 = canUseGoods.filter((v) => useFoods.find((food) => food.id == v.productId)); console.log(canUseGoods1); if (useRule == "price_asc") { discountGoods = canUseGoods1[canUseGoods1.length - 1]; } else { discountGoods = canUseGoods1.slice(0, 1); } } const discountPrice = returnGoodsPrice(discountGoods, user); const hasDiscountGoodsArr = [discountGoods]; //返回半价价格 return { discountPrice: new BigNumber(discountPrice).dividedBy(2).toNumber(), hasDiscountGoodsArr, }; }