add: 增加新客立减和计算公式测试

This commit is contained in:
2025-09-17 09:19:12 +08:00
parent a66de31f1b
commit 171c81eea6
8 changed files with 1603 additions and 86 deletions

View File

@@ -67,7 +67,7 @@
"vue-clipboard3": "^2.0.0",
"vue-i18n": "^11.1.0",
"vue-router": "^4.5.0",
"ysk-utils": "^1.0.5"
"ysk-utils": "^1.0.12"
},
"devDependencies": {
"@commitlint/cli": "^19.7.1",

View File

@@ -4,7 +4,9 @@ import orderApi from "@/api/order/order";
import { useUserStoreHook } from "@/store/modules/user";
import { customTruncateToTwoDecimals } from '@/utils/tools'
import productApi from "@/api/product/index";
import yskUtils from 'ysk-utils'
const { OrderPriceCalculator } = yskUtils
console.log(OrderPriceCalculator)
const shopUser = useUserStoreHook();
export interface CartsState {
id: string | number;
@@ -22,11 +24,6 @@ export const useCartsStore = defineStore("carts", () => {
let dinnerType = ref<string>('dine-in');
//就餐模式 先付 后付
const isPayBefore = computed(() => {
return shopUser.userInfo.registerType == 'before' ? true : false;
});
//是否启用会员价
const useVipPrice = computed(() => {
@@ -42,22 +39,21 @@ export const useCartsStore = defineStore("carts", () => {
//当前购物车数据
const list = useStorage<any[]>("carts", []);
//历史订单数据
// const oldOrder = useStorage<any>("Instead_olold_order", {
// detailMap: [],
// originAmount: 0
// });
const oldOrder = ref({
const oldOrder = useStorage<any>("Instead_olold_order", {
detailMap: [],
originAmount: 0
})
});
//代客下单页面商品缓存
const goods = useStorage<any[]>("Instead_goods", []);
async function getGoods(query: any) {
const res = await productApi.list({
const res = await productApi.getPage({
page: 1,
size: 999,
status: "on_sale",
...query,
});
goods.value = res.filter((v: { type: string }) => v.type != 'coupon');
goods.value = res.records;
setGoodsMap(goods.value)
}
@@ -135,11 +131,9 @@ export const useCartsStore = defineStore("carts", () => {
})
//返回打包数量称重商品打包数量最大为1
function returnCartPackNumber(cur: any) {
const maxReturnNum = cur.number - (cur.returnNum || 0);
let pack_number = (dinnerType.value == 'take-out' ? cur.number : cur.pack_number * 1);
console.log(cur)
let pack_number = (dinnerType.value == 'take-out' ? cur.number : cur.pack_number * 1)
pack_number = (cur.product_type == 'weight' && pack_number > 1) ? 1 : pack_number;
pack_number = Math.min(maxReturnNum, pack_number);
pack_number = pack_number <= 0 ? 0 : pack_number
return pack_number * 1
}
//打包数量
@@ -247,7 +241,7 @@ export const useCartsStore = defineStore("carts", () => {
const price = (cur.discount_sale_amount * 1 || cur.salePrice || 0)
return acc + cur.number * (discount_sale_amount || (useVipPrice.value ? memberPrice : price))
}, 0)
return (money + packFee.value * 1 + oldOrderMoney.value * 1).toFixed(2)
return (money + packFee.value + oldOrderMoney.value * 1).toFixed(2)
})
//只算商品的总价
const goodsTotal = computed(() => {
@@ -264,7 +258,7 @@ export const useCartsStore = defineStore("carts", () => {
const cartNumber = list.value.reduce((acc: number, cur: any) => {
return acc + cur.number * 1
}, 0)
const giftNumber = giftList.value.reduce((acc: number, cur: any) => {
const giftNumber = list.value.reduce((acc: number, cur: any) => {
return acc + cur.number * 1
}, 0)
let oldNumber = 0
@@ -284,11 +278,11 @@ export const useCartsStore = defineStore("carts", () => {
return;
}
const newNumber = item.number * 1 + step * 1;
let pack_number = newNumber < item.pack_number ? (item.pack_number * 1 + step * 1) : item.pack_number * 1;
let pack_number = newNumber < item.pack_number ? (item.pack_number * 1 + step * 1) : item.pack_number;
if (dinnerType.value == 'take-out') {
pack_number = newNumber
}
if (item.product_type == 'weight' && item.pack_number * 1 >= 1) {
if (item.product_type == 'weight') {
pack_number = 1
}
update({ ...item, number: newNumber, pack_number });
@@ -308,8 +302,11 @@ export const useCartsStore = defineStore("carts", () => {
})
return
}
selPlaceNum.value = -1;
isOldOrder.value = false;
if (cart.is_gift) {
isSelGift.value = true
} else {
isSelGift.value = false
}
if (cart.is_gift) {
isSelGift.value = true
@@ -320,7 +317,6 @@ export const useCartsStore = defineStore("carts", () => {
isSelGift.value = false
selListIndex.value = list.value.findIndex((item: CartsState) => item.id === cart.id);
}
}
@@ -336,8 +332,7 @@ export const useCartsStore = defineStore("carts", () => {
product_name: "",
remark: "",
sku_id: '',
product_type: '',
suitNum: 1
product_type: ''
}
//当前购物车直接添加
function cartsPush(data: any) {
@@ -377,10 +372,6 @@ export const useCartsStore = defineStore("carts", () => {
cart_id
});
}
//清空历史订单
function clearHistory() {
sendMessage('clearOrder', {});
}
function del(data: any) {
@@ -394,7 +385,7 @@ export const useCartsStore = defineStore("carts", () => {
return sendMessage('del', data);
}
const pack_number = dinnerType.value == 'take-out' ? data.number : data.pack_number
sendMessage('edit', { ...data, suitNum, pack_number });
sendMessage('edit', { ...data, pack_number });
}
function updateTag(key: string, val: any, cart: CartsState = selCart.value) {
const skuData = cart.skuData || { suitNum: 1 }
@@ -408,7 +399,6 @@ export const useCartsStore = defineStore("carts", () => {
const msg = { ...cart, [key]: val }
if (key == 'number' && dinnerType.value == 'take-out') {
msg.pack_number == val
msg.suitNum == skuData.suitNum
}
sendMessage('edit', msg);
@@ -462,15 +452,8 @@ export const useCartsStore = defineStore("carts", () => {
//获取历史订单
async function getOldOrder(table_code: string | number) {
const res = await orderApi.getHistoryList({ tableCode: table_code })
console.log('getOldOrder');
console.log(res);
if (res) {
setOldOrder(res)
} else {
oldOrder.value = {
detailMap: [],
originAmount: 0
}
}
}
@@ -512,22 +495,12 @@ export const useCartsStore = defineStore("carts", () => {
for (let i in data) {
newData[i] = data[i].map((v: any) => {
const skuData = getProductDetails({ product_id: v.productId, sku_id: v.skuId })
console.log(skuData)
console.log(v)
return {
...v,
...skuData,
skuData: {
...skuData,
salePrice: v.price,
memberPrice: v.memberPrice
},
placeNum: v.placeNum,
number: v.num,
id: v.id,
salePrice: v.price,
memberPrice: v.memberPrice,
pack_number: v.packNumber,
discount_sale_amount: v.discountSaleAmount * 1 || 0,
is_print: v.isPrint,
@@ -538,12 +511,10 @@ export const useCartsStore = defineStore("carts", () => {
product_name: v.productName,
sku_name: v.skuName,
sku_id: v.skuId,
product_type: v.productType,
packFee: v.packAmount,
product_type: v.productType
}
})
}
console.log('newData', newData)
return newData
}
@@ -573,7 +544,7 @@ export const useCartsStore = defineStore("carts", () => {
if ($oldOrder) {
setOldOrder($oldOrder)
} else {
oldOrder.value = { detailMap: [], originAmount: 0 }
oldOrder.value = { detailMap: [] }
}
// console.log('oldOrder.detailMap', oldOrder.value.detailMap)
@@ -593,19 +564,9 @@ export const useCartsStore = defineStore("carts", () => {
console.log("初始化参数", initParams);
WebSocketManager.subscribeToTopic(initParams, (msg) => {
console.log("收到消息:", msg);
console.log([...list.value, ...giftList.value])
if (msg.hasOwnProperty('status') && msg.status != 1) {
if (msg.type === 'no_suit_num' && selListIndex.value != -1) {
return ElMessageBox.confirm(`${list.value[selListIndex.value].name}库存不足`, '提示', {
confirmButtonText: '确定',
callback: (action: string) => {
if (action == 'confirm') {
list.value.splice(selListIndex.value, 1)
}
}
});
}
return ElMessage.error(msg.message || msg.msg || '操作失败')
return ElMessage.error(msg.message || '操作失败')
}
if (msg && msg.data) {
if (Array.isArray(msg.data) && msg.data.length && msg.data[0].table_code) {
@@ -636,7 +597,7 @@ export const useCartsStore = defineStore("carts", () => {
v[key] = skuData[key];
});
} else {
// del({ id: v.id })
del({ id: v.id })
return false
}
return !v.is_gift
@@ -666,13 +627,10 @@ export const useCartsStore = defineStore("carts", () => {
return ElMessage.warning(msg.message || '该商品已存在')
}
const skuData = getProductDetails({ product_id: msg.data.product_id, sku_id: msg.data.sku_id })
if (skuData || msg.data.is_temporary) {
const newGoods = { ...skuData, ...msg.data }
console.log('newGoods', newGoods)
list.value.push(newGoods)
return ElMessage.success(msg.message || '添加成功')
}
}
if (msg.operate_type === "manage_edit") {
@@ -723,9 +681,6 @@ export const useCartsStore = defineStore("carts", () => {
if (msg.operate_type === "batch") {
concocatSocket({ ...$initParams, table_code: table_code.value })
}
if (msg.operate_type === "manage_clearOrder") {
getOldOrder(msg.data.table_code)
}
if (msg.operate_type === "product_update") {
console.log('商品更新')
init($initParams, oldOrder.value)
@@ -747,7 +702,6 @@ export const useCartsStore = defineStore("carts", () => {
WebSocketManager.sendMessage(msg);
}
return {
clearHistory,
disconnect,
dinnerType,
changePack,
@@ -781,7 +735,7 @@ export const useCartsStore = defineStore("carts", () => {
changeTable,
rotTable,
getGoods,
setGoodsMap, isPayBefore
setGoodsMap
};
});

1357
src/utils/goods.ts Normal file

File diff suppressed because it is too large Load Diff

210
src/utils/test.ts Normal file
View File

@@ -0,0 +1,210 @@
import { OrderPriceCalculator, GoodsType, BackendCoupon, ActivityConfig, CouponType } from "./goods";
// 修正后的测试数据严格匹配BaseCartItem类型
const testGoodsList = [
{
// 核心修正1product_type使用GoodsType枚举替代原product_type字符串
product_type: GoodsType.NORMAL, // "sku"类型归类为普通商品
// 核心修正2isTemporary/isGift从数字转为布尔值
isTemporary: false,
isGift: false,
// 核心修正3discountSaleAmount从字符串转为数字
discountSaleAmount: 0,
// 原有字段(保持不变)
salePrice: 2,
memberPrice: 2,
coverImg: "https://czg-oss.oss-cn-hangzhou.aliyuncs.com/catering/store/9660.png",
name: "多规格起售3",
specInfo: "常温",
packFee: 1,
type: "sku",
skuData: {
barCode: "88888888888888888888",
costPrice: 2,
coverImg: "",
createTime: "2025-03-27 16:23:49",
id: "2451",
isDel: 0,
isGrounding: 1,
isPauseSale: 0,
isSale: 1,
isSoldStock: 0,
lowPrice: 2,
memberPrice: 2,
name: "常温",
originPrice: 2,
productId: "946",
realSalesNumber: 0,
salePrice: 2,
shopId: "29",
specInfo: "常温",
suitNum: 3,
updateTime: "2025-03-27 16:23:49",
weight: 0,
},
id: 18264,
shop_id: 29,
table_code: "APC36217948",
sku_id: 2451,
product_id: 946,
product_name: "",
sku_name: "",
number: 4,
pack_number: 0,
discount_sale_note: "",
is_print: 1,
is_wait_call: 0,
pro_group_info: "",
remark: "",
create_time: "2025-09-16 16:00:25",
update_time: null,
},
{
// 核心修正1package类型映射为GoodsType.PACKAGE
product_type: GoodsType.PACKAGE,
// 核心修正2布尔值转换
isTemporary: false,
isGift: false,
// 核心修正3字符串转数字
discountSaleAmount: 5,
// 原有字段
salePrice: 11,
memberPrice: 22,
coverImg: "https://czg-oss.oss-cn-hangzhou.aliyuncs.com/catering/store/8351.png",
name: "蜜雪冰城",
specInfo: "",
packFee: 555,
type: "package",
skuData: {
barCode: "291739694712255",
costPrice: 0,
coverImg: "",
createTime: "2025-02-16 16:36:46",
id: "2383",
isDel: 0,
isGrounding: 1,
isPauseSale: 0,
isSale: 1,
isSoldStock: 0,
lowPrice: 11,
memberPrice: 22,
name: "",
originPrice: 11,
productId: "943",
realSalesNumber: 0,
salePrice: 11,
shopId: "29",
specInfo: "",
suitNum: 33,
updateTime: null,
weight: 0,
},
id: 18263,
shop_id: 29,
table_code: "APC36217948",
sku_id: 2383,
product_id: 943,
product_name: "",
sku_name: "",
number: 35,
pack_number: 1,
discount_sale_note: "",
is_print: 1,
is_wait_call: 0,
pro_group_info: "",
remark: "",
create_time: "2025-09-16 15:59:59",
update_time: "2025-09-16 16:00:48",
},
{
// 核心修正1空字符串product_type映射为GoodsType.EMPTY
product_type: GoodsType.EMPTY,
// 核心修正2临时菜标记为true
isTemporary: true,
isGift: false,
// 核心修正3折扣金额为数字
discountSaleAmount: 1,
// 补充必需字段salePrice临时菜原价
salePrice: 1,
// 原有字段
id: 18265,
shop_id: 29,
table_code: "APC36217948",
sku_id: -999,
product_id: -18293045,
product_name: "临时菜",
sku_name: "",
number: 1,
pack_number: 0,
discount_sale_note: "",
is_print: 1,
is_wait_call: 0,
pro_group_info: "",
remark: "",
create_time: "2025-09-16 16:00:57",
update_time: null,
},
];
// 修正testCartOrder的key与商品id匹配确保排序正确
const testCartOrder = {
"18264": 1717200000000, // 对应第一个商品id
"18263": 1717200100000, // 对应第二个商品id
"18265": 1717200200000, // 对应第三个商品id
};
// 其他配置保持不变
const testBackendCoupons: BackendCoupon[] = [
{
id: 1,
title: "满减券",
couponType: 1,
fullAmount: 2,
discountAmount: 1,
foods: '946',
useType: 'dine-in,pickup',
useShopType: 'all',
validType: 'custom',
validStartTime: '2025-09-16 16:00:00',
validEndTime: '2025-09-30 16:00:00',
useDays: '周一,周二,周三,周四,周五',
useTimeType: 'all',
},
];
const testOrderConfig = {
currentStoreId: "101",
isMember: false,
memberDiscountRate: 0.95,
userPoints: 0,
pointDeductionRule: {
pointsPerYuan: 100,
maxDeductionAmount: 50,
},
seatFeeConfig: {
isEnabled: false,
pricePerPerson: 3,
personCount: 2,
},
merchantReduction: 10,
additionalFee: 0,
};
const testActivities: ActivityConfig[] = [];
const testCurrentTime = new Date("2024-06-01 12:00:00");
// 调用函数(此时类型完全匹配)
const result = OrderPriceCalculator.calculateOrderCostSummary(
testGoodsList,
"dine-in",
testBackendCoupons,
testActivities,
testOrderConfig,
testCartOrder,
testCurrentTime
);
console.log("计算结果:", result);
export default {}

View File

@@ -11,9 +11,7 @@
<el-form-item label="赠送成长值" required>
<el-input v-model="form.reward" placeholder="开通后立刻获得经验" type="number" />
</el-form-item>
<el-form-item label="赠送优惠券">
<CouponLists v-model="form.couponList" />
</el-form-item>
<el-form-item label="周期时间" required>
<div class="flex">
<el-input-number
@@ -40,8 +38,6 @@
</template>
<script setup>
import CouponLists from "./coup-lists.vue";
import { ref, toRaw } from "vue";
import { ElMessage } from "element-plus";
// 控制主弹窗显示

View File

@@ -76,7 +76,6 @@ import shopApi from "@/api/account/shop";
import consumeDiscountApi from "@/api/market/consumeDiscount";
import HeaderCard from "../components/headerCard.vue";
import DialogPlans from "./components/dialog-plans.vue";
import CouponLists from "./components/coup-lists.vue";
import { ref, reactive, watch, toRaw, getCurrentInstance, onMounted } from "vue";
import { ElMessage } from "element-plus";
import { useRouter } from "vue-router";

View File

@@ -324,6 +324,7 @@ import CouponLists from "./components/coup-lists.vue";
import { ref, reactive, watch, toRaw, getCurrentInstance, onMounted } from "vue";
import { ElMessage } from "element-plus";
import { useRouter } from "vue-router";
import a from "@/utils/test";
const inputStyle = {
width: "340px",