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-clipboard3": "^2.0.0",
"vue-i18n": "^11.1.0", "vue-i18n": "^11.1.0",
"vue-router": "^4.5.0", "vue-router": "^4.5.0",
"ysk-utils": "^1.0.5" "ysk-utils": "^1.0.12"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^19.7.1", "@commitlint/cli": "^19.7.1",

View File

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

View File

@@ -76,7 +76,6 @@ import shopApi from "@/api/account/shop";
import consumeDiscountApi from "@/api/market/consumeDiscount"; import consumeDiscountApi from "@/api/market/consumeDiscount";
import HeaderCard from "../components/headerCard.vue"; import HeaderCard from "../components/headerCard.vue";
import DialogPlans from "./components/dialog-plans.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 { ref, reactive, watch, toRaw, getCurrentInstance, onMounted } from "vue";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useRouter } from "vue-router"; 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 { ref, reactive, watch, toRaw, getCurrentInstance, onMounted } from "vue";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import a from "@/utils/test";
const inputStyle = { const inputStyle = {
width: "340px", width: "340px",