/** * 统计分析控制器 * * 功能:处理数据分析和报表的业务逻辑 */ const Analytics = require('../models/Analytics'); const { success } = require('../utils/response'); const { ValidationError } = require('../middleware/errorHandler'); /** * 获取综合仪表盘数据 * GET /api/analytics/dashboard */ const getDashboard = async (req, res, next) => { try { const { start_date, end_date } = req.query; const dashboard = await Analytics.getDashboard( start_date || null, end_date || null ); res.json(success(dashboard, '获取仪表盘数据成功')); } catch (err) { next(err); } }; /** * 获取销售趋势 * GET /api/analytics/sales-trend */ const getSalesTrend = async (req, res, next) => { try { const { start_date, end_date } = req.query; console.log('📊 getSalesTrend 请求参数:', { start_date, end_date }); if (!start_date || !end_date) { throw new ValidationError('请提供开始日期和结束日期'); } const trend = await Analytics.getSalesTrend(start_date, end_date); console.log('📊 Model返回数据条数:', trend ? trend.length : 0); console.log('📊 数据样例:', trend ? trend.slice(0, 2) : 'null'); res.json(success({ period: { start_date, end_date }, data: trend }, '获取销售趋势成功')); } catch (err) { console.error('❌ getSalesTrend错误:', err); next(err); } }; /** * 获取热门菜品排行 * GET /api/analytics/top-dishes */ const getTopDishes = async (req, res, next) => { try { const { limit = 10, start_date, end_date } = req.query; const dishes = await Analytics.getTopDishes( parseInt(limit), start_date || null, end_date || null ); res.json(success({ count: dishes.length, dishes }, '获取热门菜品成功')); } catch (err) { next(err); } }; /** * 获取分类销售统计 * GET /api/analytics/category-sales */ const getCategorySales = async (req, res, next) => { try { const { start_date, end_date } = req.query; const categories = await Analytics.getCategorySales( start_date || null, end_date || null ); res.json(success({ count: categories.length, categories }, '获取分类销售统计成功')); } catch (err) { next(err); } }; /** * 获取营业时段分析 * GET /api/analytics/hourly-analysis */ const getHourlyAnalysis = async (req, res, next) => { try { const { start_date, end_date } = req.query; const hourlyData = await Analytics.getHourlyAnalysis( start_date || null, end_date || null ); res.json(success({ data: hourlyData }, '获取时段分析成功')); } catch (err) { next(err); } }; /** * 获取会员消费排行 * GET /api/analytics/top-members */ const getTopMembers = async (req, res, next) => { try { const { limit = 10, start_date, end_date } = req.query; const members = await Analytics.getTopMembers( parseInt(limit), start_date || null, end_date || null ); res.json(success({ count: members.length, members }, '获取会员排行成功')); } catch (err) { next(err); } }; /** * 获取订单类型统计 * GET /api/analytics/order-types */ const getOrderTypeStats = async (req, res, next) => { try { const { start_date, end_date } = req.query; const orderTypes = await Analytics.getOrderTypeStats( start_date || null, end_date || null ); res.json(success({ data: orderTypes }, '获取订单类型统计成功')); } catch (err) { next(err); } }; /** * 获取支付方式统计 * GET /api/analytics/payment-methods */ const getPaymentMethodStats = async (req, res, next) => { try { const { start_date, end_date } = req.query; const paymentMethods = await Analytics.getPaymentMethodStats( start_date || null, end_date || null ); res.json(success({ data: paymentMethods }, '获取支付方式统计成功')); } catch (err) { next(err); } }; /** * 获取月度对比报表 * GET /api/analytics/monthly-comparison */ const getMonthlyComparison = async (req, res, next) => { try { const { months = 6 } = req.query; const monthlyData = await Analytics.getMonthlyComparison(parseInt(months)); res.json(success({ months: parseInt(months), data: monthlyData }, '获取月度对比成功')); } catch (err) { next(err); } }; /** * 获取库存价值报表 * GET /api/analytics/inventory-value */ const getInventoryValue = async (req, res, next) => { try { const inventoryValue = await Analytics.getInventoryValue(); res.json(success(inventoryValue, '获取库存价值报表成功')); } catch (err) { next(err); } }; /** * 获取优惠券使用统计 * GET /api/analytics/coupon-stats */ const getCouponStats = async (req, res, next) => { try { const { start_date, end_date } = req.query; const couponStats = await Analytics.getCouponStats( start_date || null, end_date || null ); res.json(success({ count: couponStats.length, coupons: couponStats }, '获取优惠券统计成功')); } catch (err) { next(err); } }; /** * 获取预订转化率 * GET /api/analytics/reservation-conversion */ const getReservationConversion = async (req, res, next) => { try { const { start_date, end_date } = req.query; const conversion = await Analytics.getReservationConversion( start_date || null, end_date || null ); res.json(success(conversion, '获取预订转化率成功')); } catch (err) { next(err); } }; /** * 导出综合报表(CSV格式) * GET /api/analytics/export */ const exportReport = async (req, res, next) => { try { const { start_date, end_date, type = 'sales' } = req.query; if (!start_date || !end_date) { throw new ValidationError('请提供开始日期和结束日期'); } let data; let filename; switch (type) { case 'sales': data = await Analytics.getSalesTrend(start_date, end_date); filename = `sales_report_${start_date}_${end_date}.csv`; break; case 'dishes': data = await Analytics.getTopDishes(100, start_date, end_date); filename = `dishes_report_${start_date}_${end_date}.csv`; break; case 'members': data = await Analytics.getTopMembers(100, start_date, end_date); filename = `members_report_${start_date}_${end_date}.csv`; break; default: throw new ValidationError('无效的报表类型'); } // 生成CSV内容 if (data.length === 0) { throw new ValidationError('该时间段内没有数据'); } const headers = Object.keys(data[0]).join(','); const rows = data.map(row => Object.values(row).join(',')).join('\n'); const csv = `${headers}\n${rows}`; // 设置响应头 res.setHeader('Content-Type', 'text/csv; charset=utf-8'); res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); res.send('\ufeff' + csv); // 添加BOM以支持中文 } catch (err) { next(err); } }; // 导出所有控制器函数 module.exports = { getDashboard, getSalesTrend, getTopDishes, getCategorySales, getHourlyAnalysis, getTopMembers, getOrderTypeStats, getPaymentMethodStats, getMonthlyComparison, getInventoryValue, getCouponStats, getReservationConversion, exportReport };