Agent-02 每日经营分析
版本: v1.0
概述: 基于ClickHouse数据湖,每日生成经营分析日报
1. Agent职责
| 维度 | 说明 |
|---|---|
| 名称 | daily-report-agent |
| 执行时间 | T+1 08:00 |
| 推送渠道 | 企业微信 / 钉钉 / 邮件 |
| 接收人 | 店长 / 区域经理 / 总部 |
核心模块
| 模块 | 说明 |
|---|---|
| KPI分析 | 销售额/毛利/环比/同比 |
| 爆款分析 | TOP10热销 + 库存可售天数 |
| 异常预警 | 品类波动/缺货/积压 |
| 员工绩效 | 销售排名/达成率 |
| AI建议 | 基于数据异常自动生成 |
2. 核心KPI计算SQL
-- 每日核心KPI汇总
SELECT
toDate(order_date) AS date,
COUNT(DISTINCT order_no) AS order_count,
SUM(total_amount) AS daily_sales,
SUM(total_amount) - SUM(cost_amount) AS daily_profit,
(SUM(total_amount) - SUM(cost_amount)) / NULLIF(SUM(total_amount), 0) * 100 AS gross_margin_pct,
SUM(CASE WHEN payment_method = 'credit' THEN total_amount ELSE 0 END) AS credit_sales,
COUNT(DISTINCT customer_id) AS customer_count
FROM sales_order
WHERE toDate(order_date) = today() - 1
AND order_status NOT IN ('cancelled', 'returned')
GROUP BY toDate(order_date);
-- 环比计算
WITH today_kpi AS (
SELECT SUM(total_amount) AS sales FROM sales_order WHERE toDate(order_date) = today() - 1
),
yesterday_kpi AS (
SELECT SUM(total_amount) AS sales FROM sales_order WHERE toDate(order_date) = today() - 2
)
SELECT
(t.sales - y.sales) / NULLIF(y.sales, 0) * 100 AS sales_growth_pct
FROM today_kpi t, yesterday_kpi y;
3. 爆款分析SQL
-- 爆款产品TOP10(含库存可售天数)
SELECT
p.product_code,
p.product_name,
p.category,
SUM(s.quantity) AS total_qty,
SUM(s.quantity * s.unit_price) AS total_sales,
ROUND(SUM(s.quantity * (s.unit_price - s.cost_price)) / NULLIF(SUM(s.quantity * s.unit_price), 0) * 100, 2) AS profit_margin,
i.current_stock,
i.current_stock / NULLIF(s.avg_daily_sales, 0) AS stock_days_remaining
FROM sales_order_detail s
JOIN product_master p ON s.product_id = p.product_id
LEFT JOIN inventory_current i ON s.product_id = i.product_id
LEFT JOIN (
SELECT product_id, AVG(daily_sales) AS avg_daily_sales
FROM (
SELECT product_id, SUM(quantity)/7 AS daily_sales
FROM sales_order_detail
WHERE order_date >= today() - 30
GROUP BY product_id, toDate(order_date)
)
GROUP BY product_id
) s2 ON s.product_id = s2.product_id
WHERE toDate(s.order_date) = today() - 1
GROUP BY p.product_code, p.product_name, p.category, i.current_stock, s2.avg_daily_sales
ORDER BY total_sales DESC
LIMIT 10;
4. 库存预警SQL
-- 库存预警:缺货 + 临期 + 积压
SELECT
p.product_code,
p.product_name,
i.current_stock,
i.safe_stock,
s.avg_daily_sales,
CASE
WHEN i.current_stock = 0 THEN '🔴 缺货'
WHEN i.current_stock < i.safe_stock THEN '🟠 库存不足'
WHEN i.current_stock > i.safe_stock * 3 THEN '🟡 积压'
WHEN p.expiry_date < today() + INTERVAL 30 DAY THEN '🟠 临期'
ELSE '🟢 正常'
END AS alert_status
FROM inventory_current i
JOIN product_master p ON i.product_id = p.product_id
LEFT JOIN (
SELECT product_id, SUM(quantity)/30 AS avg_daily_sales
FROM sales_order_detail
WHERE order_date >= today() - 30
GROUP BY product_id
) s ON i.product_id = s.product_id
WHERE i.warehouse_id = 'MAIN_WH'
AND (
i.current_stock = 0
OR i.current_stock < i.safe_stock
OR i.current_stock > i.safe_stock * 3
OR (p.expiry_date IS NOT NULL AND p.expiry_date < today() + INTERVAL 30 DAY)
)
ORDER BY alert_status, i.current_stock ASC;
5. 员工绩效SQL
-- 员工当日绩效排名
SELECT
e.employee_name,
e.department,
COUNT(DISTINCT s.order_no) AS order_count,
SUM(s.total_amount) AS total_sales,
SUM(s.total_amount - s.cost_amount) AS total_profit,
ROUND(SUM(s.total_amount - s.cost_amount) / NULLIF(SUM(s.total_amount), 0) * 100, 2) AS profit_margin,
COUNT(DISTINCT s.customer_id) AS customer_count,
SUM(CASE WHEN s.payment_status = 'collected' THEN s.total_amount ELSE 0 END) / NULLIF(SUM(s.total_amount), 0) * 100 AS collection_rate
FROM sales_order s
JOIN employee_info e ON s.salesperson_id = e.employee_id
WHERE toDate(s.order_date) = today() - 1
AND s.order_status NOT IN ('cancelled')
GROUP BY e.employee_name, e.department
ORDER BY total_sales DESC
LIMIT 10;
6. AI改善建议(自动生成逻辑)
基于以上分析结果,AI自动生成改善建议:
💡 AI今日改善建议
1. 【库存预警】
- 🔴 缺货商品:水泥42.5、螺纹钢Φ12,建议立即补货
- 🟠 库存不足:PPR管25mm,库存可售天数仅2天,需3天内补货
2. 【销售波动】
- 📉 五金工具类销售额环比下降32%,需关注
- 📈 钢材类销售额环比增长45%,可适当提高备货量
3. 【回款提醒】
- 🟠 客户"XX装饰"逾期15天,金额28000元,建议跟进催收
4. 【员工绩效】
- 🌟 员工李明今日销售额最高(32800元),目标达成率125%
- ⚠️ 员工王强客单价偏低,建议加强产品组合推荐培训
7. 调度配置
# APScheduler日报任务配置
scheduler.add_job(
func='report_tasks:daily_business_report',
trigger=CronTrigger(hour=8, minute=0, misfire_grace_time=60),
id='daily_business_report',
name='每日经营日报',
kwargs={
'report_date': 'T-1',
'store_id': 'STORE_001',
'recipients': ['store_manager', 'region_manager'],
'channels': ['wechat_work', 'email']
}
)