问题修复,下单优化,订单结算问题修复

This commit is contained in:
2025-10-31 16:30:47 +08:00
parent 09fc28de06
commit 31d91f7de5
10 changed files with 379 additions and 148 deletions

View File

@@ -69,7 +69,7 @@
<text class="color-666" v-if="item.status == 'success'" <text class="color-666" v-if="item.status == 'success'"
>已入账</text >已入账</text
> >
<text class="color-666" v-if="item.status == 'REFUND'" <text class="color-666" v-if="item.status == 'refund'"
>已退款</text >已退款</text
> >
</view> </view>
@@ -80,12 +80,12 @@
<text class="color-333 font-700">{{ item.orderNo }}</text> <text class="color-333 font-700">{{ item.orderNo }}</text>
</view> </view>
<view class="money"> <view class="money">
<text class="money reduce" v-if="item.status == 'REFUND'" <text class="money reduce" v-if="item.status == 'refund'"
>-{{ item.rewardAmount }}</text >-{{ item.rewardAmount }}</text
> >
<text class="money" v-else>+{{ item.rewardAmount }}</text> <text class="money" v-else>+{{ item.rewardAmount }}</text>
<text class="tag" v-if="item.status == 'REFUND'">订单退款</text> <text class="tag" v-if="item.status == 'refund'">订单退款</text>
<text class="tag" v-else-if="item.level == 1" <text class="tag" v-else-if="item.level == 1"
>(订单一级分成)</text >(订单一级分成)</text
> >
@@ -205,7 +205,7 @@ const statusList = ref([
fontSize: "16", fontSize: "16",
}, },
{ {
value: "REFUND", value: "refund",
name: "已退款", name: "已退款",
color: "#333", color: "#333",
fontSize: "16", fontSize: "16",

View File

@@ -54,7 +54,14 @@
@click="questionClick('等级升级条件')" @click="questionClick('等级升级条件')"
/> />
</view> </view>
<view class="u-m-t-28 u-flex align-center" v-if="juNextLvMoney&&state.distributionUser&&!state.distributionUser.IsAssignLevel"> <view
class="u-m-t-28 u-flex align-center"
v-if="
juNextLvMoney &&
state.distributionUser &&
state.distributionUser.isAssignLevel == 0
"
>
<text class="color-666">距离下一级还差:</text> <text class="color-666">距离下一级还差:</text>
<text class="color-333 font-700 u-m-r-18" <text class="color-333 font-700 u-m-r-18"
>{{ juNextLvMoney }} >{{ juNextLvMoney }}
@@ -72,7 +79,11 @@
<view class="u-flex u-m-t-28"> <view class="u-flex u-m-t-28">
<view class="u-flex-1"> <view class="u-flex-1">
<view class="u-flex align-center"> <view class="u-flex align-center">
<text class="u-m-r-10 font-12 color-666" @click="toShouyiDetail('')">总收益</text> <text
class="u-m-r-10 font-12 color-666"
@click="toShouyiDetail('')"
>总收益</text
>
<up-icon <up-icon
name="question-circle" name="question-circle"
size="24rpx" size="24rpx"
@@ -80,13 +91,20 @@
@click="questionClick('总收益')" @click="questionClick('总收益')"
/> />
</view> </view>
<view class="u-m-t-16 price" @click="toShouyiDetail('')" v-if="state.distributionUser">{{ <view
state.distributionUser.totalIncome class="u-m-t-16 price"
}}</view> @click="toShouyiDetail('')"
v-if="state.distributionUser"
>{{ state.distributionUser.totalIncome }}</view
>
</view> </view>
<view class="u-flex-1"> <view class="u-flex-1">
<view class="u-flex align-center"> <view class="u-flex align-center">
<text class="u-m-r-10 font-12 color-666" @click="toShouyiDetail('待入账')">待入账</text> <text
class="u-m-r-10 font-12 color-666"
@click="toShouyiDetail('待入账')"
>待入账</text
>
<up-icon <up-icon
name="question-circle" name="question-circle"
size="24rpx" size="24rpx"
@@ -94,9 +112,12 @@
@click="questionClick('待入账')" @click="questionClick('待入账')"
/> />
</view> </view>
<view class="u-m-t-16 price" @click="toShouyiDetail('待入账')" v-if="state.distributionUser">{{ <view
state.distributionUser.pendingIncome class="u-m-t-16 price"
}}</view> @click="toShouyiDetail('待入账')"
v-if="state.distributionUser"
>{{ state.distributionUser.pendingIncome }}</view
>
</view> </view>
</view> </view>
</view> </view>
@@ -219,9 +240,7 @@
<text v-if="item.inviteTime">{{ <text v-if="item.inviteTime">{{
item.inviteTime.split(" ")[0] item.inviteTime.split(" ")[0]
}}</text> }}</text>
<text style="color: #fff" v-else>{{ <text style="color: #fff" v-else>{{ "yyyy-MM-dd" }}</text>
"yyyy-MM-dd"
}}</text>
</view> </view>
</view> </view>
</view> </view>
@@ -358,7 +377,11 @@ const commissionTipsType = ref("");
function toShouyiDetail(name) { function toShouyiDetail(name) {
uni.navigateTo({ uni.navigateTo({
url: "/distribution/income-details/index?name="+name+'&shopId='+options.shopId, url:
"/distribution/income-details/index?name=" +
name +
"&shopId=" +
options.shopId,
}); });
} }
function questionClick(title) { function questionClick(title) {

View File

@@ -891,7 +891,7 @@ async function getDiscountActivity() {
} }
onMounted(async () => { onMounted(async () => {
await getConsumeDiscount(); await getConsumeDiscount();
// getDiscountActivity(); getDiscountActivity();
}); });
</script> </script>

View File

@@ -83,7 +83,7 @@
></goodsPrice> ></goodsPrice>
<text <text
class="originalprice" class="originalprice" v-if="showLimitDiscount(item)"
>{{ item.salePrice }}</text >{{ item.salePrice }}</text
> >

View File

@@ -58,7 +58,10 @@
v-for="(item, index) in shopProductList.hots" v-for="(item, index) in shopProductList.hots"
:key="index" :key="index"
> >
<view class="limitDiscount" v-if="showLimitDiscount(item)" <!-- <view class="limitDiscount" v-if="showLimitDiscount(item)"
>限时折扣</view
> -->
<view class="limitDiscount" v-if="item.is_time_discount"
>限时折扣</view >限时折扣</view
> >
<image <image
@@ -441,7 +444,12 @@
<text class="money_num" v-if="item1.unitName" <text class="money_num" v-if="item1.unitName"
>/{{ item1.unitName }}</text >/{{ item1.unitName }}</text
> >
<text class="old-price">¥{{ item1.salePrice }}</text> <!-- <text class="old-price" v-if=" showLimitDiscount(item1)"
>¥{{ item1.salePrice }}</text
> -->
<text class="old-price" v-if="item1.is_time_discount"
>¥{{ item1.salePrice }}</text
>
<!-- <text v-if="item1.suitNum>1 && item1.type!= 'sku'" <!-- <text v-if="item1.suitNum>1 && item1.type!= 'sku'"
style="font-size: 14rpx;"> style="font-size: 14rpx;">
@@ -706,7 +714,6 @@
</view> </view>
<text class="num" v-if="false"> <text class="num" v-if="false">
{{ {{
shopInfo.isVip == 1 && shopInfo.isMemberPrice == 1 shopInfo.isVip == 1 && shopInfo.isMemberPrice == 1
? specifications.item.result.memberPrice || ? specifications.item.result.memberPrice ||
@@ -1440,6 +1447,8 @@ const submitSelection = async () => {
memberPrice: specifications.item.memberPrice, memberPrice: specifications.item.memberPrice,
is_print: 1, is_print: 1,
product_type: specifications.item.type, product_type: specifications.item.type,
is_time_discount:specifications.item.is_time_discount
}); });
// 清空套餐选中 // 清空套餐选中
selectedGroupSnap.value = []; selectedGroupSnap.value = [];
@@ -1587,6 +1596,7 @@ const singleclick = async (item, i) => {
number: await calculateValue(item.cartNumber, i, suitNum), number: await calculateValue(item.cartNumber, i, suitNum),
is_print: 1, is_print: 1,
product_type: item.type, product_type: item.type,
is_time_discount:item.is_time_discount
}); });
}; };
@@ -1663,23 +1673,9 @@ const updateProductQuantities = () => {
//websocket产值 //websocket产值
const websocketsendMessage = (data) => { const websocketsendMessage = (data) => {
console.log("websocketsendMessage", data); console.log("websocketsendMessage", data);
const sendData = { ...data, is_time_discount: 0 }; delete data.memberPrice;
if (cartStore.limitTimeDiscount && cartStore.limitTimeDiscount.id) {
const canUse = orderUtils.canUseLimitTimeDiscount(
data,
cartStore.limitTimeDiscount,
shopInfo,
shopUserInfo.value,
"product_id"
);
console.log("canUse", canUse);
if (canUse) {
sendData.is_time_discount = 1;
}
}
delete sendData.memberPrice;
uni.$u.debounce(() => { uni.$u.debounce(() => {
useSocket.sendMessage(sendData); useSocket.sendMessage(data);
}, 500); }, 500);
}; };
@@ -1792,7 +1788,11 @@ async function onMessage(Message) {
} }
// 提示 // 提示
if (Message.status == 0 && Message.type != "no_suit_num") { if (
Message.status == 0 &&
Message.type != "no_suit_num" &&
Message.type != "time_discount"
) {
uni.showToast({ uni.showToast({
title: Message.msg, title: Message.msg,
icon: "none", icon: "none",
@@ -2038,29 +2038,6 @@ function ifcartNumber(item) {
// 如果类型不匹配,返回原始值 // 如果类型不匹配,返回原始值
return item.cartNumber; return item.cartNumber;
} }
// const ifcartNumber = computed(() => {
// return (item) => {
// // 如果 item 为空或者 cartNumber 不是字符串类型,返回 0
// if (!item || typeof item.cartNumber !== 'string') {
// return 0;
// }
// let numValue = parseFloat(item.cartNumber);
// if (isNaN(numValue)) {
// // 如果转换结果是 NaN说明 cartNumber 不是有效的数字字符串,返回 0
// return 0;
// }
// // type string 商品类型 single-单规格商品 sku-多规格商品 package-套餐商品 weight-称重商品 coupon-团购券
// if (item.type === 'weight') {
// // 如果类型是称重重量,将值保留两位小数
// return parseFloat(numValue.toFixed(2));
// } else {
// // 如果类型是整数,将值转换为整数
// return Math.round(numValue);
// }
// // 如果类型不匹配,返回原始值
// return item.cartNumber;
// };
// })
// 计算处理后的购物车列表 // 用于筛选后的购物车数组 // 计算处理后的购物车列表 // 用于筛选后的购物车数组
const cartListFilter = computed(() => { const cartListFilter = computed(() => {
@@ -2146,6 +2123,9 @@ const productqueryProduct = async () => {
product.startTime, product.startTime,
product.endTime product.endTime
); );
product.is_time_discount = showLimitDiscount(product)?1:0;
product.limitSalePrice = returnLimitPrice(product);
cartStore.setGoodsMap(product.id, product); cartStore.setGoodsMap(product.id, product);
}); });
}); });
@@ -2156,6 +2136,8 @@ const productqueryProduct = async () => {
i.startTime, i.startTime,
i.endTime i.endTime
); );
i.is_time_discount = showLimitDiscount(i)?1:0;
i.limitSalePrice = returnLimitPrice(i);
cartStore.setGoodsMap(i.id, i); cartStore.setGoodsMap(i.id, i);
}); });
@@ -2204,6 +2186,16 @@ function showLimitDiscount(item) {
); );
} }
function returnLimitPrice(item) {
return orderUtils.returnPrice({
goods: item,
limitTimeDiscountRes: cartStore.limitTimeDiscount,
shopInfo: shopInfo,
shopUserInfo: shopUserInfo.value,
idKey: "id",
});
}
onShow(async () => { onShow(async () => {
// 监听页面显示和隐藏 // 监听页面显示和隐藏
useSocket.setOnMessage(onMessage); useSocket.setOnMessage(onMessage);
@@ -2242,6 +2234,7 @@ onMounted(async () => {
}); });
if (limitRes && typeof limitRes == "object") { if (limitRes && typeof limitRes == "object") {
limitTimeDiscountRes.value = limitRes; limitTimeDiscountRes.value = limitRes;
cartStore.limitTimeDiscount = limitRes;
websocketsendMessage({ websocketsendMessage({
type: "shopping", type: "shopping",
operate_type: "time_discount_save", operate_type: "time_discount_save",
@@ -2251,6 +2244,7 @@ onMounted(async () => {
data: limitRes, data: limitRes,
}); });
} else { } else {
cartStore.limitTimeDiscount = null;
websocketsendMessage({ websocketsendMessage({
type: "shopping", type: "shopping",
operate_type: "time_discount_save", operate_type: "time_discount_save",
@@ -2259,6 +2253,7 @@ onMounted(async () => {
operate_type: "time_discount_save", operate_type: "time_discount_save",
data: null, data: null,
}); });
} }
await productqueryProduct(); await productqueryProduct();

View File

@@ -47,6 +47,7 @@ export const useCartsStore = defineStore("cart", () => {
product_id: item.product_id || item.productId, product_id: item.product_id || item.productId,
sku_id: item.skuId || item.sku_id, sku_id: item.skuId || item.sku_id,
}); });
console.log('convertToBaseCartItem',item)
const discountSaleAmount=item.discount_sale_amount?(item.discount_sale_amount*1) : (item.discountSaleAmount?item.discountSaleAmount*1:0) const discountSaleAmount=item.discount_sale_amount?(item.discount_sale_amount*1) : (item.discountSaleAmount?item.discountSaleAmount*1:0)
return { return {
...item, ...item,

View File

@@ -268,6 +268,12 @@ export interface TimeLimitDiscountConfig {
[property: string]: any; [property: string]: any;
} }
//用户信息
interface ShopUserInfo {
isVip: number | null; //是否会员
discount: number | null; //用户折扣
isMemberPrice: number | null; //会员折扣与会员价是否同时使用
}
/** 订单额外费用配置 */ /** 订单额外费用配置 */
export interface OrderExtraConfig { export interface OrderExtraConfig {
// merchantReduction: number; // 商家减免金额默认0 // merchantReduction: number; // 商家减免金额默认0
@@ -286,6 +292,7 @@ export interface OrderExtraConfig {
isFreeDine?: boolean; //是否霸王餐 isFreeDine?: boolean; //是否霸王餐
freeDineConfig?: FreeDineConfig; freeDineConfig?: FreeDineConfig;
limitTimeDiscount?: TimeLimitDiscountConfig; //限时折扣 limitTimeDiscount?: TimeLimitDiscountConfig; //限时折扣
shopUserInfo: ShopUserInfo; // 用户信息
} }
/** 订单费用汇总(修改:补充商家减免类型和明细) */ /** 订单费用汇总(修改:补充商家减免类型和明细) */
@@ -318,10 +325,12 @@ export interface OrderCostSummary {
config: OrderExtraConfig; // 订单额外费用配置 config: OrderExtraConfig; // 订单额外费用配置
//满减活动 //满减活动
fullReduction: { fullReduction: {
usedFullReductionActivityFullAmount: number; // 计算出的满减活动的门槛金额
usedActivity?: FullReductionActivity; // 实际使用的满减活动 usedActivity?: FullReductionActivity; // 实际使用的满减活动
usedThreshold?: FullReductionThreshold; // 实际使用的满减阈值(多门槛中选最优) usedThreshold?: FullReductionThreshold; // 实际使用的满减阈值(多门槛中选最优)
actualAmount: number; // 满减实际减免金额(元) actualAmount: number; // 满减实际减免金额(元)
}; };
vipDiscountAmount: number; //会员折扣减免金额
// 订单原支付金额 // 订单原支付金额
orderOriginFinalPayAmount: number; //订单原金额(包含打包费+餐位费) orderOriginFinalPayAmount: number; //订单原金额(包含打包费+餐位费)
} }
@@ -437,58 +446,190 @@ function isDinnerTypeMatch(
//判断商品是否可以使用限时折扣 //判断商品是否可以使用限时折扣
export function returnCanUseLimitTimeDiscount( export function returnCanUseLimitTimeDiscount(
goods:BaseCartItem, goods: BaseCartItem,
limitTimeDiscountRes:TimeLimitDiscountConfig|null|undefined, limitTimeDiscount: TimeLimitDiscountConfig | null | undefined,
useVipPrice:boolean, useVipPrice: boolean,
idKey = "product_id" idKey = "product_id"
) { ) {
if (!limitTimeDiscountRes || !limitTimeDiscountRes.id) { if (!limitTimeDiscount || !limitTimeDiscount.id) {
return false; return false;
} }
const canUseFoods = (limitTimeDiscountRes.foods || "").split(","); const canUseFoods = (limitTimeDiscount.foods || "").split(",");
if (limitTimeDiscountRes.discountPriority == "limit-time") { const goodsCanUse =
if ( limitTimeDiscount.foodType == 1 || canUseFoods.includes("" + goods[idKey]);
limitTimeDiscountRes.foodType == 1 || if (!goodsCanUse) {
canUseFoods.includes("" + goods[idKey]) return false;
) { }
if (limitTimeDiscount.discountPriority == "limit-time") {
return true; return true;
} }
} if (limitTimeDiscount.discountPriority == "vip-price") {
if ( if (!useVipPrice) {
limitTimeDiscountRes.discountPriority == "vip-price"
) {
if(!useVipPrice){
return true; return true;
} }
if (useVipPrice && goods.hasOwnProperty("memberPrice")) {
if (goods.memberPrice && goods.memberPrice * 1 <= 0) {
return true;
}
}
} }
return false; return false;
} }
function returnMemberPrice(useVipPrice: boolean, goods: BaseCartItem) {
if (useVipPrice) {
return goods.memberPrice || goods.salePrice;
} else {
return goods.salePrice;
}
}
/**
* 返回商品限时折扣价格
*/
function returnLimitPrice(
goods: BaseCartItem,
limitTimeDiscount: TimeLimitDiscountConfig | null | undefined,
useVipPrice
) {
if (!limitTimeDiscount) {
return 0;
}
const discountRate = new BigNumber(limitTimeDiscount.discountRate).dividedBy(
100
);
const canuseLimit = returnCanUseLimitTimeDiscount(
goods,
limitTimeDiscount,
useVipPrice
);
if (canuseLimit) {
//可以使用限时折扣
if (limitTimeDiscount.discountPriority == "limit-time") {
//限时价优先
const result = BigNumber(goods.salePrice)
.times(discountRate)
.decimalPlaces(2, BigNumber.ROUND_UP)
.toNumber();
return result;
}
if (limitTimeDiscount.discountPriority == "vip-price") {
//会员价优先
if (useVipPrice && goods.memberPrice && goods.memberPrice * 1 > 0) {
//使用会员价
return returnMemberPrice(useVipPrice, goods);
} else {
//不使用会员价
const result = BigNumber(goods.salePrice)
.times(discountRate)
.decimalPlaces(2, BigNumber.ROUND_UP)
.toNumber();
return result;
}
}
} else {
//不可以使用限时折扣
//会员价优先
if (useVipPrice) {
//使用会员价
return returnMemberPrice(useVipPrice, goods);
} else {
return goods.salePrice;
}
}
}
/**
* 计算商品计算门槛时的金额
*/
export function returnCalcPrice(
goods: BaseCartItem,
fullReductionActivitie: FullReductionActivity | undefined,
limitTimeDiscount: TimeLimitDiscountConfig | null | undefined,
useVipPrice: boolean,
idKey = "product_id"
) {
if (goods.discountSaleAmount && goods.discountSaleAmount * 1 > 0) {
return goods.salePrice;
}
//限时折扣和满减活动都有
if (fullReductionActivitie && limitTimeDiscount) {
if (
fullReductionActivitie.discountShare == 1 &&
fullReductionActivitie.vipPriceShare == 1
) {
//与限时折扣同享,与会员价不同享
return returnLimitPrice(goods, limitTimeDiscount, useVipPrice);
}
if (
fullReductionActivitie.discountShare != 1 &&
fullReductionActivitie.vipPriceShare == 1
) {
//与限时折扣不同享,与会员价同享
return returnMemberPrice(useVipPrice, goods);
}
if (fullReductionActivitie.vipPriceShare != 1) {
//与会员价不同享
return goods.salePrice;
}
return goods.salePrice;
}
//只有满减活动
if (fullReductionActivitie) {
if (fullReductionActivitie.vipPriceShare == 1) {
return returnMemberPrice(useVipPrice, goods);
} else {
return goods.salePrice;
}
}
//只有限时折扣
if (limitTimeDiscount) {
return returnLimitPrice(goods, limitTimeDiscount, useVipPrice);
}
if (useVipPrice) {
return returnMemberPrice(useVipPrice, goods);
}
return goods.salePrice;
}
/** /**
* 计算满减活动门槛 * 计算满减活动门槛
*/ */
export function calcFullReductionActivityFullAmount(goodsList: BaseCartItem[],fullReductionActivitie:FullReductionActivity|undefined,limitTimeDiscount:TimeLimitDiscountConfig|null|undefined export function calcFullReductionActivityFullAmount(
,useVipPrice:boolean goodsList: BaseCartItem[],
fullReductionActivitie: FullReductionActivity | undefined,
) { limitTimeDiscount: TimeLimitDiscountConfig | null | undefined,
if(!fullReductionActivitie){ useVipPrice: boolean,
return 0 seatFee: number,
packFee: number
): number {
if (!fullReductionActivitie) {
return 0;
} }
let amount=0; let amount = 0;
console.log('calcFullReductionActivityFullAmount') for (let goods of goodsList) {
console.log('fullReductionActivitie',fullReductionActivitie)
console.log('limitTimeDiscount',limitTimeDiscount)
for(let goods of goodsList){
const canuseLimit=returnCanUseLimitTimeDiscount(goods,limitTimeDiscount,useVipPrice,"product_id")
console.log('canuseLimit',canuseLimit)
if(!fullReductionActivitie.discountShare){
const availableNum = Math.max(0, goods.number - (goods.returnNum || 0)); const availableNum = Math.max(0, goods.number - (goods.returnNum || 0));
amount+=goods.salePrice*availableNum if (goods.is_temporary || goods.is_gift || availableNum <= 0) {
//临时菜,赠菜,数量<=0的商品不计算
continue;
}
const calcPrice = returnCalcPrice(
goods,
fullReductionActivitie,
limitTimeDiscount,
useVipPrice,
"product_id"
);
if (calcPrice !== undefined) {
amount += calcPrice * availableNum;
} }
} }
return amount + seatFee + packFee;
console.log("amount", amount);
} }
/** /**
@@ -516,6 +657,8 @@ export function filterOptimalFullReductionActivity(
activity.thresholds?.length // 至少有一个满减阈值 activity.thresholds?.length // 至少有一个满减阈值
); );
}); });
console.log("baseEligible", baseEligible);
if (!baseEligible.length) return undefined; if (!baseEligible.length) return undefined;
// 第二步:时间筛选(有效期内+周期内+时段内) // 第二步:时间筛选(有效期内+周期内+时段内)
@@ -766,6 +909,7 @@ export function calcSingleGoodsRealPrice(
> >
): number { ): number {
const { isMember, memberDiscountRate, limitTimeDiscount: activity } = config; const { isMember, memberDiscountRate, limitTimeDiscount: activity } = config;
console.log("activity", activity);
//如果是增菜价格为0 //如果是增菜价格为0
if (goods.is_gift) { if (goods.is_gift) {
@@ -776,7 +920,6 @@ export function calcSingleGoodsRealPrice(
if (goods.discountSaleAmount && goods.discountSaleAmount > 0) { if (goods.discountSaleAmount && goods.discountSaleAmount > 0) {
return truncateToTwoDecimals(goods.discountSaleAmount); return truncateToTwoDecimals(goods.discountSaleAmount);
} }
console.log("calcSingleGoodsRealPrice:goods", goods);
// 2. 优先级2会员价含会员折扣率SKU会员价优先 // 2. 优先级2会员价含会员折扣率SKU会员价优先
const memberPrice = new BigNumber( const memberPrice = new BigNumber(
@@ -798,15 +941,18 @@ export function calcSingleGoodsRealPrice(
if (!activity || !isActivityApplicable) { if (!activity || !isActivityApplicable) {
return memberPrice.toNumber(); return memberPrice.toNumber();
} }
console.log("isMember", isMember);
//限时折扣优先或者会员价优先但是不是会员或者未开启会员价格时限时折扣优先 //限时折扣优先或者会员价优先但是不是会员或者未开启会员价格时限时折扣优先
if ( if (
activity.discountPriority == "limit-time" || activity.discountPriority == "limit-time" ||
(activity.discountPriority == "vip-price" && !isMember) (activity.discountPriority == "vip-price" && !isMember) ||
(activity.discountPriority == "vip-price" && isMember && !goods.memberPrice)
) { ) {
//限时折扣优先 //限时折扣优先
return truncateToTwoDecimals( return truncateToTwoDecimals(
new BigNumber(goods.salePrice) new BigNumber(goods.salePrice)
.multipliedBy(activity.discountRate / 100) .times(activity.discountRate / 100)
.decimalPlaces(2, BigNumber.ROUND_UP)
.toNumber() .toNumber()
); );
} }
@@ -881,6 +1027,7 @@ export function calcGoodsRealAmount(
for (const goods of goodsList) { for (const goods of goodsList) {
const availableNum = Math.max(0, goods.number - (goods.returnNum || 0)); const availableNum = Math.max(0, goods.number - (goods.returnNum || 0));
if (availableNum <= 0) continue; if (availableNum <= 0) continue;
console.log("goods", goods);
const realPrice = new BigNumber(calcSingleGoodsRealPrice(goods, config)); const realPrice = new BigNumber(calcSingleGoodsRealPrice(goods, config));
total = total.plus(realPrice.multipliedBy(availableNum)); total = total.plus(realPrice.multipliedBy(availableNum));
} }
@@ -929,11 +1076,15 @@ export function selectOptimalThreshold(
const validThresholds = thresholds.filter((threshold) => { const validThresholds = thresholds.filter((threshold) => {
const fullAmount = new BigNumber(threshold.fullAmount || 0); const fullAmount = new BigNumber(threshold.fullAmount || 0);
const discountAmount = new BigNumber(threshold.discountAmount || 0); const discountAmount = new BigNumber(threshold.discountAmount || 0);
console.log("fullAmount", fullAmount);
console.log("discountAmount", discountAmount);
return ( return (
fullAmount.isLessThanOrEqualTo(thresholdBase) && fullAmount.isLessThanOrEqualTo(thresholdBase) &&
discountAmount.isGreaterThan(0) discountAmount.isGreaterThan(0)
); );
}); });
console.log("validThresholds", validThresholds);
if (!validThresholds.length) return undefined; if (!validThresholds.length) return undefined;
@@ -1154,6 +1305,24 @@ export function calcPointDeduction(
}; };
} }
function calcVipDiscountAmount(
goodsRealAmount: number,
shopUserInfo: ShopUserInfo
): number {
if (!shopUserInfo.isVip || shopUserInfo.discount === 0) return 0;
if (shopUserInfo.isVip == 1 && shopUserInfo.isMemberPrice != 1) {
return 0;
}
console.log("goodsRealAmount", goodsRealAmount);
console.log("discount", (100 - (shopUserInfo.discount || 0)) / 100);
return truncateToTwoDecimals(
new BigNumber(goodsRealAmount)
.times((100 - (shopUserInfo.discount || 0)) / 100)
.decimalPlaces(2, BigNumber.ROUND_UP)
.toNumber()
);
}
// ============================ 6. 订单总费用汇总与实付金额计算(核心入口,补充细分字段) ============================ // ============================ 6. 订单总费用汇总与实付金额计算(核心入口,补充细分字段) ============================
/** /**
* 计算订单所有费用子项并汇总(核心入口函数) * 计算订单所有费用子项并汇总(核心入口函数)
@@ -1175,14 +1344,15 @@ export function calculateOrderCostSummary(
cartOrder: Record<string, number> = {}, cartOrder: Record<string, number> = {},
currentTime: Date = new Date() currentTime: Date = new Date()
): OrderCostSummary { ): OrderCostSummary {
//是否使用霸王餐,霸王餐配置 //是否使用霸王餐,霸王餐配置
const { const {
isFreeDine, isFreeDine,
freeDineConfig, freeDineConfig,
limitTimeDiscount, limitTimeDiscount,
fullReductionActivities, fullReductionActivities,
shopUserInfo,
} = config; } = config;
console.log("shopUserInfo", shopUserInfo);
// ------------------------------ 1. 基础费用计算 ------------------------------ // ------------------------------ 1. 基础费用计算 ------------------------------
const goodsOriginalAmount = calcGoodsOriginalAmount(goodsList); // 商品原价总和 const goodsOriginalAmount = calcGoodsOriginalAmount(goodsList); // 商品原价总和
@@ -1199,12 +1369,28 @@ export function calculateOrderCostSummary(
goodsOriginalAmount, goodsOriginalAmount,
goodsRealAmount goodsRealAmount
); // 商品折扣金额 ); // 商品折扣金额
const newUserDiscount = config.newUserDiscount || 0; // 新客立减 const newUserDiscount = config.newUserDiscount || 0; // 新客立减
// 其他费用计算(原有逻辑不变) ------------------------------
const packFee = calcTotalPackFee(goodsList, dinnerType); // 打包费
let seatFee = calcSeatFee(config.seatFeeConfig); // 餐位费
seatFee = dinnerType === "dine-in" ? seatFee : 0; // 外卖不收餐位费
const additionalFee = Math.max(0, config.additionalFee); // 附加费
// ------------------------------ 2. 满减活动计算(核心步骤) ------------------------------ // ------------------------------ 2. 满减活动计算(核心步骤) ------------------------------
let usedFullReductionActivity: FullReductionActivity | undefined; let usedFullReductionActivity: FullReductionActivity | undefined;
let usedFullReductionThreshold: FullReductionThreshold | undefined; let usedFullReductionThreshold: FullReductionThreshold | undefined;
let fullReductionAmount = 0; let fullReductionAmount = 0;
let usedFullReductionActivityFullAmount = calcFullReductionActivityFullAmount(
goodsList,
usedFullReductionActivity,
config.limitTimeDiscount,
config.isMember,
seatFee,
packFee
);
// 2.1 筛选最优满减活动(后端活动列表、当前店铺、就餐类型、时间) // 2.1 筛选最优满减活动(后端活动列表、当前店铺、就餐类型、时间)
usedFullReductionActivity = filterOptimalFullReductionActivity( usedFullReductionActivity = filterOptimalFullReductionActivity(
config.fullReductionActivities, config.fullReductionActivities,
@@ -1213,17 +1399,6 @@ export function calculateOrderCostSummary(
currentTime currentTime
); );
calcFullReductionActivityFullAmount(goodsList,usedFullReductionActivity,config.limitTimeDiscount,config.isMember);
console.log("usedFullReductionActivity", usedFullReductionActivity);
// 其他费用计算(原有逻辑不变) ------------------------------
const packFee = calcTotalPackFee(goodsList, dinnerType); // 打包费
let seatFee = calcSeatFee(config.seatFeeConfig); // 餐位费
seatFee = dinnerType === "dine-in" ? seatFee : 0; // 外卖不收餐位费
const additionalFee = Math.max(0, config.additionalFee); // 附加费
// 2.2 计算满减基数(先扣新客立减) // 2.2 计算满减基数(先扣新客立减)
let baseAfterNewUserDiscount = new BigNumber( let baseAfterNewUserDiscount = new BigNumber(
limitTimeDiscount && limitTimeDiscount &&
@@ -1243,9 +1418,19 @@ export function calculateOrderCostSummary(
// 2.3 选择最优满减阈值(多门槛场景) // 2.3 选择最优满减阈值(多门槛场景)
if (usedFullReductionActivity) { if (usedFullReductionActivity) {
//计算当前满减活动的门槛金额
usedFullReductionActivityFullAmount = calcFullReductionActivityFullAmount(
goodsList,
usedFullReductionActivity,
config.limitTimeDiscount,
config.isMember,
seatFee,
packFee
);
usedFullReductionThreshold = selectOptimalThreshold( usedFullReductionThreshold = selectOptimalThreshold(
usedFullReductionActivity.thresholds, usedFullReductionActivity.thresholds,
baseAfterNewUserDiscount, usedFullReductionActivityFullAmount,
goodsOriginalAmount, goodsOriginalAmount,
goodsRealAmount, goodsRealAmount,
usedFullReductionActivity.discountShare || 0 // 与限时折扣同享规则 usedFullReductionActivity.discountShare || 0 // 与限时折扣同享规则
@@ -1258,6 +1443,7 @@ export function calculateOrderCostSummary(
usedFullReductionThreshold usedFullReductionThreshold
); );
} }
// ------------------------------ 3. 优惠券抵扣(适配满减同享规则) ------------------------------ // ------------------------------ 3. 优惠券抵扣(适配满减同享规则) ------------------------------
let couponDeductionAmount = 0; let couponDeductionAmount = 0;
let productCouponDeduction = 0; let productCouponDeduction = 0;
@@ -1279,6 +1465,7 @@ export function calculateOrderCostSummary(
currentTime, currentTime,
} }
); );
console.log("couponResult", couponResult);
couponDeductionAmount = couponResult.deductionAmount; couponDeductionAmount = couponResult.deductionAmount;
productCouponDeduction = couponResult.productCouponDeduction; productCouponDeduction = couponResult.productCouponDeduction;
fullCouponDeduction = couponResult.fullCouponDeduction; fullCouponDeduction = couponResult.fullCouponDeduction;
@@ -1286,7 +1473,10 @@ export function calculateOrderCostSummary(
excludedProductIds = couponResult.excludedProductIds; excludedProductIds = couponResult.excludedProductIds;
// 若满减与优惠券同享couponShare=1才计算优惠券否则优惠券抵扣为0 // 若满减与优惠券同享couponShare=1才计算优惠券否则优惠券抵扣为0
if (usedFullReductionActivity && !usedFullReductionActivity.couponShare) { if (
usedFullReductionThreshold &&
(!usedFullReductionActivity || !usedFullReductionActivity.couponShare)
) {
couponDeductionAmount = 0; couponDeductionAmount = 0;
productCouponDeduction = 0; productCouponDeduction = 0;
fullCouponDeduction = 0; fullCouponDeduction = 0;
@@ -1315,20 +1505,20 @@ export function calculateOrderCostSummary(
config.pointDeductionRule, config.pointDeductionRule,
maxPointDeductionLimit maxPointDeductionLimit
); );
console.log("积分抵扣结果:", pointResult);
pointDeductionAmount = pointResult.deductionAmount; pointDeductionAmount = pointResult.deductionAmount;
usedPoints = pointResult.usedPoints; usedPoints = pointResult.usedPoints;
// 若满减与积分不同享pointsShare=1积分抵扣为0 // 若满减与积分不同享pointsShare=1积分抵扣为0
if (usedFullReductionActivity && !usedFullReductionActivity.pointsShare) { if (
console.log("满减与积分不同享:积分抵扣为0"); usedFullReductionThreshold &&
(!usedFullReductionActivity || !usedFullReductionActivity.pointsShare)
) {
pointDeductionAmount = 0; pointDeductionAmount = 0;
usedPoints = 0; usedPoints = 0;
} }
//使用霸王餐 //使用霸王餐
if (isFreeDine && freeDineConfig && freeDineConfig.enable) { if (isFreeDine && freeDineConfig && freeDineConfig.enable) {
console.log("使用霸王餐");
fullReductionAmount = 0; fullReductionAmount = 0;
//不与优惠券同享 //不与优惠券同享
if (!freeDineConfig.withCoupon) { if (!freeDineConfig.withCoupon) {
@@ -1386,9 +1576,21 @@ export function calculateOrderCostSummary(
truncateToTwoDecimals(merchantReductionActualAmount) truncateToTwoDecimals(merchantReductionActualAmount)
); );
// 会员折扣减免
const vipDiscountAmount = calcVipDiscountAmount(
new BigNumber(goodsRealAmount)
.minus(couponDeductionAmount)
.plus(packFee)
.plus(seatFee)
.minus(newUserDiscount)
.minus(fullReductionAmount)
.toNumber(),
shopUserInfo
); // 会员折扣减免金额
// ------------------------------ 6. 最终实付金额计算 ------------------------------ // ------------------------------ 6. 最终实付金额计算 ------------------------------
const finalPayAmountBn = new BigNumber(goodsRealAmount) const finalPayAmountBn = new BigNumber(goodsRealAmount)
.minus(newUserDiscount) .minus(newUserDiscount)
.minus(vipDiscountAmount)
.minus(fullReductionAmount) .minus(fullReductionAmount)
.minus(couponDeductionAmount) .minus(couponDeductionAmount)
.minus(pointDeductionAmount) .minus(pointDeductionAmount)
@@ -1416,6 +1618,7 @@ export function calculateOrderCostSummary(
.plus(couponDeductionAmount) .plus(couponDeductionAmount)
.plus(pointDeductionAmount) .plus(pointDeductionAmount)
.plus(merchantReductionActualAmount) .plus(merchantReductionActualAmount)
.plus(vipDiscountAmount)
.toNumber() .toNumber()
); );
//积分可抵扣最大金额 最终支付金额+积分抵扣-商家减免 //积分可抵扣最大金额 最终支付金额+积分抵扣-商家减免
@@ -1424,8 +1627,6 @@ export function calculateOrderCostSummary(
.minus(merchantReductionActualAmount) .minus(merchantReductionActualAmount)
.toNumber(); .toNumber();
console.log("限时折扣:", config.limitTimeDiscount);
// ------------------------------ 8. 返回完整结果 ------------------------------ // ------------------------------ 8. 返回完整结果 ------------------------------
return { return {
goodsTotal: goodsList.reduce( goodsTotal: goodsList.reduce(
@@ -1448,10 +1649,12 @@ export function calculateOrderCostSummary(
scoreMaxMoney, scoreMaxMoney,
// 满减活动明细(后端字段) // 满减活动明细(后端字段)
fullReduction: { fullReduction: {
usedFullReductionActivityFullAmount: usedFullReductionActivityFullAmount,
usedActivity: usedFullReductionActivity, usedActivity: usedFullReductionActivity,
usedThreshold: usedFullReductionThreshold, usedThreshold: usedFullReductionThreshold,
actualAmount: truncateToTwoDecimals(fullReductionAmount), actualAmount: truncateToTwoDecimals(fullReductionAmount),
}, },
vipDiscountAmount: vipDiscountAmount, //会员折扣减免金额
merchantReduction: { merchantReduction: {
type: merchantReductionConfig.type, type: merchantReductionConfig.type,
originalConfig: merchantReductionConfig, originalConfig: merchantReductionConfig,

View File

@@ -31,11 +31,8 @@ export function returnGoodsPrice(goods, user, shopInfo, limitTimeDiscount) {
.decimalPlaces(2, BigNumber.ROUND_UP) .decimalPlaces(2, BigNumber.ROUND_UP)
.toNumber(); .toNumber();
} }
if (
canUseLimit && if (canUseLimit && limitTimeDiscount.discountPriority == "vip-price") {
limitTimeDiscount.discountPriority == "vip-price" &&
!canUseVipPrice
) {
if (canUseVipPrice) { if (canUseVipPrice) {
return goods.memberPrice; return goods.memberPrice;
} else { } else {
@@ -161,7 +158,10 @@ function returnCanCalcGoodsList(canCalcGoodsArr, coupon, shopInfo, user) {
return canCalcGoodsArr.filter((goods) => { return canCalcGoodsArr.filter((goods) => {
console.log("goods"); console.log("goods");
console.log(goods); console.log(goods);
if (!coupon.discountShare && (goods.is_time_discount||goods.isTimeDiscount)) { if (
!coupon.discountShare &&
(goods.is_time_discount || goods.isTimeDiscount)
) {
return false; return false;
} }
if ( if (
@@ -391,6 +391,7 @@ export function calcDiscountGoodsArrPrice(
let hasCountNum = 0; let hasCountNum = 0;
let discountPrice = 0; let discountPrice = 0;
let hasDiscountGoodsArr = []; let hasDiscountGoodsArr = [];
for (let i = 0; i < discountGoodsArr.length; i++) { for (let i = 0; i < discountGoodsArr.length; i++) {
if (hasCountNum >= discountNum) { if (hasCountNum >= discountNum) {
break; break;
@@ -398,8 +399,14 @@ export function calcDiscountGoodsArrPrice(
const goods = discountGoodsArr[i]; const goods = discountGoodsArr[i];
const shengyuNum = discountNum - hasCountNum; const shengyuNum = discountNum - hasCountNum;
const num = Math.min(goods.num, shengyuNum); const num = Math.min(goods.num, shengyuNum);
discountPrice += const realPrice = returnGoodsPrice(
returnGoodsPrice(goods, user, shopInfo, limitTimeDiscount) * num; goods,
user,
shopInfo,
limitTimeDiscount
);
discountPrice += realPrice * num;
hasCountNum += num; hasCountNum += num;
hasDiscountGoodsArr.push({ hasDiscountGoodsArr.push({
@@ -433,7 +440,7 @@ export function returnCouponDiscount(
shopInfo, shopInfo,
limitTimeDiscount limitTimeDiscount
) { ) {
arr = returnCanDikouGoods(arr, user, shopInfo); arr = returnCanDikouGoods(arr, user, shopInfo,limitTimeDiscount);
const canDikouGoodsArr = returnCanDikouGoodsArr({ const canDikouGoodsArr = returnCanDikouGoodsArr({
canDikouGoodsArr: arr, canDikouGoodsArr: arr,
selCoupon, selCoupon,
@@ -554,8 +561,10 @@ export function returnCouponProductDiscount(
limitTimeDiscount limitTimeDiscount
) { ) {
const { useFoods, discountNum, useRule } = coupon; const { useFoods, discountNum, useRule } = coupon;
//抵扣商品数组 //抵扣商品数组
let discountGoodsArr = []; let discountGoodsArr = [];
//抵扣全部商品 //抵扣全部商品
if (useFoods.length === 0) { if (useFoods.length === 0) {
if (useRule == "price_asc") { if (useRule == "price_asc") {
@@ -574,6 +583,8 @@ export function returnCouponProductDiscount(
discountGoodsArr = discountSelGoodsArr.slice(0, discountNum); discountGoodsArr = discountSelGoodsArr.slice(0, discountNum);
} }
} }
const result = calcDiscountGoodsArrPrice( const result = calcDiscountGoodsArrPrice(
discountGoodsArr, discountGoodsArr,
discountNum, discountNum,

View File

@@ -758,9 +758,7 @@ export function calcMemberPrice(
if (!isMember) return truncateToTwoDecimals(goods.salePrice); if (!isMember) return truncateToTwoDecimals(goods.salePrice);
// 优先级SKU会员价 > 商品会员价 > 商品原价(无会员价时用会员折扣) // 优先级SKU会员价 > 商品会员价 > 商品原价(无会员价时用会员折扣)
const basePrice = const basePrice = goods.memberPrice || goods.salePrice;
goods.skuData?.memberPrice ?? goods.memberPrice ?? goods.salePrice;
// 仅当无SKU会员价、无商品会员价时才应用会员折扣率 // 仅当无SKU会员价、无商品会员价时才应用会员折扣率
if (memberDiscountRate && !goods.skuData?.memberPrice && !goods.memberPrice) { if (memberDiscountRate && !goods.skuData?.memberPrice && !goods.memberPrice) {
return truncateToTwoDecimals( return truncateToTwoDecimals(

View File

@@ -15,9 +15,10 @@ export function canUseLimitTimeDiscount(
} }
const canUseFoods = (limitTimeDiscountRes.foods || "").split(","); const canUseFoods = (limitTimeDiscountRes.foods || "").split(",");
const goodsCanUse = const goodsCanUse =
limitTimeDiscountRes.foodType == 1 || limitTimeDiscountRes.foodType == 1 ||
canUseFoods.includes("" + goods[idKey]); canUseFoods.includes(`${goods[idKey]}`);
if (!goodsCanUse) { if (!goodsCanUse) {
return false; return false;
} }
@@ -59,10 +60,12 @@ export function returnPrice(args) {
idKey = "product_id", idKey = "product_id",
} = args; } = args;
const canUseFoods = (limitTimeDiscountRes.foods || "").split(","); const canUseFoods = (limitTimeDiscountRes.foods || "").split(",");
const includesGoods =
limitTimeDiscountRes.foodType == 1 ||
canUseFoods.includes("" + goods[idKey]);
shopInfo = shopInfo || {}; shopInfo = shopInfo || {};
shopUserInfo = shopUserInfo || {}; shopUserInfo = shopUserInfo || {};
if (shopUserInfo.isMemberPrice == 1 && shopUserInfo.isVip == 1 && shopInfo.isMemberPrice==1) {
if (shopUserInfo.isMemberPrice == 1 && shopUserInfo.isVip == 1) {
const memberPrice = goods.memberPrice || goods.salePrice; const memberPrice = goods.memberPrice || goods.salePrice;
//是会员而且启用会员价 //是会员而且启用会员价
@@ -70,10 +73,7 @@ export function returnPrice(args) {
//使用限时折扣 //使用限时折扣
//限时折扣优先 //限时折扣优先
if (limitTimeDiscountRes.discountPriority == "limit-time") { if (limitTimeDiscountRes.discountPriority == "limit-time") {
if ( if (includesGoods) {
limitTimeDiscountRes.foodType == 1 ||
canUseFoods.includes("" + goods[idKey])
) {
return returnLimitPrice({ return returnLimitPrice({
price: goods.salePrice, price: goods.salePrice,
limitTimeDiscountRes, limitTimeDiscountRes,
@@ -82,7 +82,10 @@ export function returnPrice(args) {
return memberPrice; return memberPrice;
} }
} }
if (limitTimeDiscountRes.discountPriority == "vip-price") { if (
limitTimeDiscountRes.discountPriority == "vip-price" &&
includesGoods
) {
if (goods.memberPrice * 1 > 0) { if (goods.memberPrice * 1 > 0) {
//会员优先 //会员优先
return memberPrice; return memberPrice;
@@ -95,6 +98,8 @@ export function returnPrice(args) {
return price; return price;
} }
} else {
return memberPrice;
} }
} else { } else {
//是会员没有限时折扣 //是会员没有限时折扣
@@ -103,12 +108,7 @@ export function returnPrice(args) {
} else { } else {
// console.log('不是会员或者没有启用会员价',goods,limitTimeDiscountRes); // console.log('不是会员或者没有启用会员价',goods,limitTimeDiscountRes);
//不是会员或者没有启用会员价 //不是会员或者没有启用会员价
if ( if (limitTimeDiscountRes && limitTimeDiscountRes.id && includesGoods) {
limitTimeDiscountRes &&
limitTimeDiscountRes.id &&
(limitTimeDiscountRes.foodType == 1 ||
canUseFoods.includes("" + goods[idKey]))
) {
const price = returnLimitPrice({ const price = returnLimitPrice({
price: goods.salePrice, price: goods.salePrice,
limitTimeDiscountRes, limitTimeDiscountRes,