Browse Source

添加订单功能和测试页面

蛋吧eggbar
Trae AI 1 month ago
parent
commit
e3b01bb67c
  1. 643
      server-example/server-mysql.js

643
server-example/server-mysql.js

@ -381,6 +381,331 @@ app.get('/api/cover', async (req, res) => {
}
});
// 订单列表API端点 - 根据电话号码查询订单
app.post('/api/orders/list', async (req, res) => {
try {
const { phoneNumber, startDate, endDate, paymentStatus, page = 1, pageSize = 10 } = req.body;
console.log('获取订单列表请求:', { phoneNumber, startDate, endDate, paymentStatus, page, pageSize });
console.log('请求体完整内容:', req.body);
if (!phoneNumber) {
return res.status(400).json({
success: false,
code: 400,
message: '用户电话号码不能为空'
});
}
// 构建查询条件
const whereCondition = {
phone: phoneNumber
};
// 添加时间范围过滤
if (startDate) {
whereCondition.order_date = {
...whereCondition.order_date,
[Op.gte]: startDate
};
console.log('添加开始日期过滤:', startDate);
}
if (endDate) {
whereCondition.order_date = {
...whereCondition.order_date,
[Op.lte]: endDate
};
console.log('添加结束日期过滤:', endDate);
}
// 添加付款状态过滤
if (paymentStatus) {
whereCondition.payment_status = paymentStatus;
console.log('添加付款状态过滤:', paymentStatus);
}
console.log('最终查询条件:', whereCondition);
// 计算分页偏移量
const offset = (page - 1) * pageSize;
console.log('分页参数:', { page, pageSize, offset });
// 查询trade_library数据库中的订单主表,根据电话号码和时间范围过滤
const orders = await JdSalesMain.findAll({
where: whereCondition,
include: [
{
model: JdSalesSub,
as: 'subItems',
attributes: [
'sub_id',
'product_name',
'batch_no',
'unit',
'yolk',
'specification',
'sales_pieces',
'sales_weight',
'unit_price',
'sales_amount',
'discount_amount',
'rebate_amount',
'discount_reason'
]
}
],
order: [['order_date', 'DESC']],
limit: pageSize,
offset: offset
});
console.log('查询到的订单数量:', orders.length);
// 格式化响应数据
const formattedOrders = orders.map(order => {
const orderData = order.toJSON();
// 确保order_date是字符串格式
if (orderData.order_date instanceof Date) {
orderData.order_date = orderData.order_date.toISOString().split('T')[0];
}
// 确保数值字段正确格式化
orderData.total_pieces = parseInt(orderData.total_pieces) || 0;
orderData.total_weight = parseFloat(orderData.total_weight) || 0;
orderData.total_amount = parseFloat(orderData.total_amount) || 0;
// 格式化子项数据
if (orderData.subItems) {
orderData.subItems = orderData.subItems.map(subItem => ({
...subItem,
sales_pieces: parseInt(subItem.sales_pieces) || 0,
sales_weight: parseFloat(subItem.sales_weight) || 0,
unit_price: parseFloat(subItem.unit_price) || 0,
sales_amount: parseFloat(subItem.sales_amount) || 0,
discount_amount: parseFloat(subItem.discount_amount) || 0,
rebate_amount: parseFloat(subItem.rebate_amount) || 0
}));
}
return orderData;
});
res.status(200).json({
success: true,
code: 200,
message: '获取订单列表成功',
data: {
orders: formattedOrders,
totalCount: formattedOrders.length
}
});
} catch (error) {
console.error('获取订单列表失败:', error);
res.status(500).json({
success: false,
code: 500,
message: '获取订单列表失败: ' + error.message
});
}
});
// 订单详情API端点 - 根据订单ID查询订单详情
app.get('/api/orders/detail/:dataid', async (req, res) => {
try {
const { dataid } = req.params;
console.log('获取订单详情请求:', { dataid });
if (!dataid) {
return res.status(400).json({
success: false,
code: 400,
message: '订单ID不能为空'
});
}
// 查询订单详情
const order = await JdSalesMain.findOne({
where: {
dataid
},
include: [
{
model: JdSalesSub,
as: 'subItems',
attributes: [
'sub_id',
'product_name',
'batch_no',
'unit',
'yolk',
'specification',
'sales_pieces',
'sales_weight',
'unit_price',
'sales_amount',
'discount_amount',
'rebate_amount',
'discount_reason'
]
}
]
});
if (!order) {
return res.status(404).json({
success: false,
code: 404,
message: '订单不存在'
});
}
// 格式化响应数据
const orderData = order.toJSON();
// 确保order_date是字符串格式
if (orderData.order_date instanceof Date) {
orderData.order_date = orderData.order_date.toISOString().split('T')[0];
}
// 确保数值字段正确格式化
orderData.total_pieces = parseInt(orderData.total_pieces) || 0;
orderData.total_weight = parseFloat(orderData.total_weight) || 0;
orderData.total_amount = parseFloat(orderData.total_amount) || 0;
// 格式化子项数据
if (orderData.subItems) {
orderData.subItems = orderData.subItems.map(subItem => ({
...subItem,
sales_pieces: parseInt(subItem.sales_pieces) || 0,
sales_weight: parseFloat(subItem.sales_weight) || 0,
unit_price: parseFloat(subItem.unit_price) || 0,
sales_amount: parseFloat(subItem.sales_amount) || 0,
discount_amount: parseFloat(subItem.discount_amount) || 0,
rebate_amount: parseFloat(subItem.rebate_amount) || 0
}));
}
res.status(200).json({
success: true,
code: 200,
message: '获取订单详情成功',
data: orderData
});
} catch (error) {
console.error('获取订单详情失败:', error);
res.status(500).json({
success: false,
code: 500,
message: '获取订单详情失败: ' + error.message
});
}
});
// 订单统计API端点 - 获取完整的订单统计数据(不分页)
app.post('/api/orders/statistics', async (req, res) => {
try {
const { phoneNumber, startDate, endDate, paymentStatus } = req.body;
console.log('获取订单统计请求:', { phoneNumber, startDate, endDate, paymentStatus });
if (!phoneNumber) {
return res.status(400).json({
success: false,
code: 400,
message: '用户电话号码不能为空'
});
}
// 构建查询条件
const whereCondition = {
phone: phoneNumber
};
// 添加时间范围过滤
if (startDate) {
whereCondition.order_date = {
...whereCondition.order_date,
[Op.gte]: startDate
};
}
if (endDate) {
whereCondition.order_date = {
...whereCondition.order_date,
[Op.lte]: endDate
};
}
// 添加付款状态过滤
if (paymentStatus) {
whereCondition.payment_status = paymentStatus;
}
console.log('统计查询条件:', whereCondition);
// 查询所有符合条件的订单(不分页)
const allOrders = await JdSalesMain.findAll({
where: whereCondition,
order: [['order_date', 'DESC']]
});
console.log('统计查询到的订单数量:', allOrders.length);
// 计算统计信息
let totalOrders = allOrders.length;
let totalAmount = 0;
let totalPieces = 0;
let totalWeight = 0;
let unpaidAmount = 0;
let paidAmount = 0;
allOrders.forEach(order => {
const orderData = order.toJSON();
const amount = parseFloat(orderData.total_amount) || 0;
const pieces = parseInt(orderData.total_pieces) || 0;
const weight = parseFloat(orderData.total_weight) || 0;
totalAmount += amount;
totalPieces += pieces;
totalWeight += weight;
if (orderData.payment_status === '未收款') {
unpaidAmount += amount;
} else if (orderData.payment_status === '全款') {
paidAmount += amount;
}
});
const statistics = {
totalOrders,
totalAmount: Math.round(totalAmount * 100) / 100,
totalPieces,
totalWeight: Math.round(totalWeight * 1000) / 1000,
unpaidAmount: Math.round(unpaidAmount * 100) / 100,
paidAmount: Math.round(paidAmount * 100) / 100
};
console.log('计算的统计信息:', statistics);
res.status(200).json({
success: true,
code: 200,
message: '获取订单统计成功',
data: statistics
});
} catch (error) {
console.error('获取订单统计失败:', error);
res.status(500).json({
success: false,
code: 500,
message: '获取订单统计失败: ' + error.message
});
}
});
// 创建动态接口(已废弃 - 使用上面的实际实现)
app.post('/api/eggbar/posts/deprecated', async (req, res) => {
try {
@ -832,10 +1157,31 @@ const eggbarSequelize = new Sequelize(
}
);
// 4. trade_library数据源连接 - 用于订单查询
const tradeLibrarySequelize = new Sequelize(
'trade_library',
dbConfig.user,
dbConfig.password,
{
host: dbConfig.host,
port: dbConfig.port,
dialect: 'mysql',
pool: {
max: 10,
min: 0,
acquire: 30000,
idle: 10000
},
logging: console.log,
define: {
timestamps: false
},
timezone: '+08:00' // 设置时区为UTC+8
}
);
// 为保持兼容性,保留默认sequelize引用(指向wechat_app)
const sequelize = wechatAppSequelize;
// 定义会话模型
const ChatConversation = sequelize.define('ChatConversation', {
id: {
type: DataTypes.INTEGER,
@ -1753,6 +2099,222 @@ Cover.init({
timestamps: false
});
// 简道云销售订单主表模型(新添加)
class JdSalesMain extends Model { }
JdSalesMain.init({
dataid: {
type: DataTypes.STRING(50),
primaryKey: true,
allowNull: false,
comment: '主表自增主键(简道云插件关联用)'
},
sales_no: {
type: DataTypes.STRING(50),
allowNull: false,
unique: true,
comment: '销售单号(业务唯一编号)'
},
order_date: {
type: DataTypes.DATEONLY,
allowNull: false,
comment: '下单日期'
},
customer_company: {
type: DataTypes.STRING(200),
allowNull: false,
comment: '客户公司'
},
contact_person: {
type: DataTypes.STRING(100),
allowNull: false,
comment: '联系人'
},
phone: {
type: DataTypes.STRING(20),
allowNull: true,
comment: '联系电话(允许带区号等特殊字符,用字符串存储)'
},
salesman: {
type: DataTypes.STRING(100),
allowNull: true,
comment: '销售员'
},
merchandiser: {
type: DataTypes.STRING(100),
allowNull: true,
comment: '跟单员'
},
address: {
type: DataTypes.STRING(500),
allowNull: true,
comment: '地址'
},
total_pieces: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0,
comment: '总件数'
},
total_weight: {
type: DataTypes.DECIMAL(10, 3),
allowNull: false,
defaultValue: 0.000,
comment: '总斤数(保留3位小数)'
},
total_amount: {
type: DataTypes.DECIMAL(12, 2),
allowNull: false,
defaultValue: 0.00,
comment: '总金额(保留2位小数)'
},
vehicle_scale: {
type: DataTypes.STRING(100),
allowNull: true,
comment: '车辆规模'
},
payment_voucher: {
type: DataTypes.STRING(255),
allowNull: true,
comment: '支付凭证(存储照片路径)'
},
invoice: {
type: DataTypes.STRING(255),
allowNull: true,
comment: '发票(存储照片路径)'
},
payment_status: {
type: DataTypes.STRING(50),
allowNull: true,
comment: '付款状态(如:未付款/部分付款/已付清)'
},
order_status: {
type: DataTypes.STRING(50),
allowNull: true
},
chepai: {
type: DataTypes.STRING(255),
allowNull: true,
comment: '车牌'
}
}, {
sequelize: tradeLibrarySequelize,
modelName: 'JdSalesMain',
tableName: 'jd_sales_main',
timestamps: false,
indexes: [
{
unique: true,
fields: ['sales_no'],
name: 'idx_sales_no',
comment: '销售单号唯一索引(避免重复)'
}
]
});
// 简道云销售订单明细表模型(新添加)
class JdSalesSub extends Model { }
JdSalesSub.init({
sub_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
comment: '子表自增主键'
},
dataid: {
type: DataTypes.STRING(50),
allowNull: false,
comment: '关联主表dataid'
},
product_name: {
type: DataTypes.STRING(200),
allowNull: false,
comment: '产品名称'
},
batch_no: {
type: DataTypes.STRING(100),
allowNull: true,
comment: '批次号'
},
unit: {
type: DataTypes.STRING(50),
allowNull: true,
comment: '单位(件,斤)'
},
yolk: {
type: DataTypes.STRING(50),
allowNull: true,
comment: '蛋黄(描述信息)'
},
specification: {
type: DataTypes.STRING(100),
allowNull: true,
comment: '规格'
},
sales_pieces: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0,
comment: '销售件数'
},
sales_weight: {
type: DataTypes.DECIMAL(10, 3),
allowNull: false,
defaultValue: 0.000,
comment: '销售斤数(保留3位小数)'
},
unit_price: {
type: DataTypes.DECIMAL(10, 2),
allowNull: false,
defaultValue: 0.00,
comment: '单价(保留2位小数)'
},
purchase_price: {
type: DataTypes.DECIMAL(10, 2),
allowNull: true,
comment: '采购价(保留2位小数)'
},
sales_amount: {
type: DataTypes.DECIMAL(12, 2),
allowNull: false,
defaultValue: 0.00,
comment: '销售金额'
},
discount_amount: {
type: DataTypes.DECIMAL(10, 2),
allowNull: true,
defaultValue: 0.00,
comment: '优惠金额'
},
rebate_amount: {
type: DataTypes.DECIMAL(10, 2),
allowNull: true,
defaultValue: 0.00,
comment: '折扣金额'
},
purchase_amount: {
type: DataTypes.DECIMAL(12, 2),
allowNull: true,
comment: '采购金额'
},
discount_reason: {
type: DataTypes.STRING(500),
allowNull: true,
comment: '优惠原因'
}
}, {
sequelize: tradeLibrarySequelize,
modelName: 'JdSalesSub',
tableName: 'jd_sales_sub',
timestamps: false,
indexes: [
{
fields: ['dataid'],
name: 'idx_main_id',
comment: '关联主表索引(加速查询)'
}
]
});
// Eggbar 帖子模型 - 用于存储用户发布的动态
class EggbarPost extends Model { }
EggbarPost.init({
@ -1956,6 +2518,21 @@ UserManagement.belongsTo(User, {
as: 'user' // 管理信息所属用户
});
// 简道云销售订单主表和明细表的关联关系
JdSalesMain.hasMany(JdSalesSub, {
foreignKey: 'dataid',
sourceKey: 'dataid',
as: 'subItems',
onDelete: 'CASCADE',
onUpdate: 'CASCADE'
});
JdSalesSub.belongsTo(JdSalesMain, {
foreignKey: 'dataid',
targetKey: 'dataid',
as: 'mainOrder'
});
// 同步数据库模型到MySQL
async function syncDatabase() {
try {
@ -10435,6 +11012,68 @@ app.post('/api/evaluate/price', async (req, res) => {
}
});
// 订单查询接口 - 根据用户电话号码查询订单
app.get('/api/orders', async (req, res) => {
try {
const { phone } = req.query;
if (!phone) {
return res.status(400).json({
success: false,
code: 400,
message: '缺少phone参数'
});
}
console.log('查询订单:', { phone });
// 查询主表订单信息
const orders = await tradeLibrarySequelize.query(
`SELECT * FROM jd_sales_main WHERE phone = ? ORDER BY order_date DESC`,
{
replacements: [phone],
type: tradeLibrarySequelize.QueryTypes.SELECT
}
);
// 查询每个订单的子表信息
const ordersWithDetails = await Promise.all(orders.map(async (order) => {
const details = await tradeLibrarySequelize.query(
`SELECT * FROM jd_sales_sub WHERE dataid = ?`,
{
replacements: [order.dataid],
type: tradeLibrarySequelize.QueryTypes.SELECT
}
);
return {
...order,
details
};
}));
console.log('订单查询结果:', { count: ordersWithDetails.length });
res.json({
success: true,
code: 200,
message: '订单查询成功',
data: {
orders: ordersWithDetails,
total: ordersWithDetails.length
}
});
} catch (error) {
console.error('订单查询失败:', error);
res.status(500).json({
success: false,
code: 500,
message: '订单查询失败',
error: error.message
});
}
});
// 在服务器启动前执行商品联系人更新
updateProductContacts().then(() => {
console.log('\n📦 商品联系人信息更新完成!');

Loading…
Cancel
Save