dy-dashboard/README.md
2026-10-28 11:14:17 +08:00

456 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 蝶雅采购智能体平台
> 采购部 AI 项目数据源 — 库存/出库/产品/采购一站式数据管理平台
---
## 目录
- [系统架构](#系统架构)
- [数据库说明](#数据库说明)
- [API 接口一览](#api-接口一览)
- [数据更新流程](#数据更新流程)
- [运维指南](#运维指南)
- [版本管理](#版本管理)
- [部署](#部署)
---
## 系统架构
### 整体结构
```
┌──────────────────────────────────────────────────────────┐
│ 钉钉云盘 (DingTalk Drive) │
│ ┌──────────────────┐ ┌──────────────────────────────┐ │
│ │ 日出库数据源文件 │ │ 库存数据源文件 │ │
│ │ 20260609-wdt-cksj │ │ 20260609-wdt-kcmx-01.csv │ │
│ │ 20260609-tmgj-cksj│ │ 20260609-wdt-kcmx-02.csv... │ │
│ └────────┬─────────┘ └─────────────┬────────────────┘ │
└───────────┼──────────────────────────┼────────────────────┘
│ dws drive download │ dws drive download
▼ ▼
┌──────────────────────────────────────────────────────────┐
│ 本地CSV缓存(tmp_csv/) │
│ reimport.py batch_import_inventory.py │
│ │ │ │
│ ▼ ▼ │
│ ├───────── MySQL ─────────┤ │
│ │ dy_data 数据库 │ │
│ │ daily_outbound │ │
│ │ inventory_detail │ │
│ │ products / bom │ │
│ │ suppliers / warehouses │ │
│ │ purchase_orders │ │
│ └──────────┬──────────────┘ │
│ │ │
│ ▼ │
│ Flask Web 应用 (app.py) │
│ Port 18888 │
└──────────────────────────────────────────────────────────┘
│
▼
浏览器访问 → http://服务器IP:18888
```
### 项目目录说明
```
dy-dashboard/
├── app.py # Flask 入口
├── run.py # 启动脚本(开发/生产模式)
├── config.py # 数据库 & 应用配置
├── deploy.sh # 一键部署脚本
│
├── routes/ # Web 路由 / API
│ ├── auth.py # 登录/权限
│ ├── dashboard.py # 仪表盘
│ ├── data.py # 日出库数据
│ ├── inventory.py # 库存数据
│ ├── products.py # 产品/BOM/供应商
│ ├── purchase.py # 采购单
│ ├── warehouse.py # 仓库管理
│ └── users.py # 用户管理
│
├── services/ # 业务逻辑层
│ ├── db.py # 数据库连接池
│ ├── cache.py # 缓存机制 (RefreshableCache)
│ ├── forecast.py # 销售预测
│ ├── inventory_calc.py # 库存计算
│ ├── product_type.py # 产品分类
│ ├── sales_calc.py # 销量统计
│ └── simple_cache.py # 简易缓存
│
├── templates/ # HTML 模板
├── static/ # CSS/JS/图片
│
├── auto_update.py # 定时自动更新入口
├── reimport.py # 日出库数据导入(全量重刷)
├── batch_import_inventory.py # 库存导入(批量下载钉盘)
├── import_new_inventory.py # 库存增量导入(动态检测新文件)
├── sync_dingtalk.py # 钉盘同步工具
├── update_data.py # 钉盘增量更新
│
├── import_inventory.py # 单个库存文件导入
├── import_suppliers.py # 供应商导入
├── import_warehouses.py # 仓库导入
├── import_purchase_order*.py # 采购单导入
├── init_db.py # 数据库初始化
│
├── tmp_csv/ # 钉盘缓存CSV(可重新下载)
├── logs/ # 运行日志
├── venv/ # Python 虚拟环境
│
├── .gitignore
├── README.md
└── deploy.sh
```
---
## 数据库说明
### 表一览
| 表名 | 记录数 | 大小 | 用途 |
|------|--------|------|------|
| `inventory_detail` | ~86万 | 175MB | **日库存明细** — 每个仓库每天商品库存快照 |
| `daily_outbound` | ~7.5万 | 20MB | **日出库记录** — 各平台每日出库流水 |
| `products` | ~8,600 | 3.4MB | **产品基础信息** — 编号/名称/品牌/分类/跟单 |
| `suppliers` | 531 | 0.1MB | 供应商信息 |
| `warehouses` | 21 | — | 仓库对照表 |
| `bom` | 5,854 | 1.5MB | 物料清单(成品→包材) |
| `purchase_orders` | 2 | — | 采购单 |
| `purchase_order_items` | 2 | — | 采购单项 |
| `dashboard_users` | 34 | — | 平台用户 |
| `dashboard_logs` | 245 | — | 操作日志 |
| `role_permissions` | 66 | — | 角色权限 |
| `global_config` | 2 | — | 全局配置 |
| `sales_predict_config` | 9 | — | 预测配置 |
| `trend_config` | 9 | — | 趋势配置 |
| `user_column_schemes` | 7 | — | 用户列方案 |
### 核心表详解
#### `inventory_detail` — 日库存明细
| 字段 | 类型 | 说明 |
|------|------|------|
| `data_date` | date | 库存日期 |
| `source` | varchar | 数据来源(wdt = 旺店通) |
| `warehouse_code` | varchar | 仓库编码 |
| `product_code` | varchar | 货品编号 |
| `product_name` | varchar | 货品名称 |
| `brand` | varchar | 品牌 |
| `cost_price` | decimal | 成本价 |
| `available_qty` | int | **可用库存**(核心字段) |
| `production_in_transit` | int | 生产在途量 |
| `purchase_in_transit` | int | 采购在途 |
| `category1/2/3` | varchar | 三级类目 |
| `created_time` | datetime | 单品创建时间 |
> **重要**: 每天全量快照,按 `data_date + warehouse_code` 区分。每天约 1.9 万条。
#### `daily_outbound` — 日出库记录
| 字段 | 类型 | 说明 |
|------|------|------|
| `日期` | date | 出库日期 |
| `货品编号` | varchar | 产品编码 |
| `货品名称` | varchar | 产品名称 |
| `品牌` | varchar | 品牌 |
| `仓库` | varchar | 发货仓库 |
| `店铺` | varchar | 店铺名称 |
| `货品数量` | int | **出库数量** |
| `货品成本` | decimal | 出库成本 |
| `数据来源` | varchar | wdt/tmgj/jdbz/jdgj/jdjwt |
| `数据类型` | varchar | cksj |
> **注意**: 来源含多种平台(旺店通/天猫国际/京东泊紫/京东国际/京东洁维塔)
#### `products` — 产品基础信息
| 字段 | 类型 | 说明 |
|------|------|------|
| `product_code` | varchar(唯一) | 货品编号 |
| `product_name` | varchar | 货品名称 |
| `brand` | varchar | 品牌 |
| `product_type` | varchar | **产品类型**: 成品/包材/清库存/现货/赠品/物料/小样/其他 |
| `cost_price` | decimal | 成本价 |
| `category1/2/3` | varchar | 三级类目 |
| `supplier_name_match` | varchar | 供应商匹配名 |
| `procurement_follower` | varchar | 采购跟单人 |
| `procurement_planner` | varchar | 采购计划人 |
| `lead_time` | int | 生产周期(天) |
---
## API 接口一览
### 仪表盘
| 接口 | 方法 | 说明 |
|------|------|------|
| `/api/dashboard/stats` | GET | 仪表盘统计数据 |
### 库存
| 接口 | 方法 | 说明 |
|------|------|------|
| `/api/inventory/list` | GET | 库存明细列表(支持分页/筛选) |
| `/api/inventory/filters` | GET | 库存筛选选项(品牌/类目/日期/仓库) |
| `/api/inventory/export` | POST | 导出库存数据(CSV/Excel) |
| `/inventory` | GET | 库存页面 |
| `/inventory/finished` | GET | 成品库存页 |
| `/inventory/packaging` | GET | 包材库存页 |
### 日出库
| 接口 | 方法 | 说明 |
|------|------|------|
| `/api/data/list` | GET | 出库明细列表 |
| `/api/data/dates` | GET | 可选日期列表 |
| `/api/data/summary` | GET | 出库汇总统计 |
| `/api/data/summary-stats` | GET | 汇总图表数据 |
| `/api/data/sku-detail` | GET | SKU 出库详情 |
### 产品
| 接口 | 方法 | 说明 |
|------|------|------|
| `/api/products/list` | GET | 产品列表 |
| `/api/products/filters` | GET | 筛选选项 |
| `/api/product/update_fields` | POST | 更新产品字段 |
| `/api/product/batch_update` | POST | 批量更新 |
| `/api/bom/list` | GET | BOM 物料清单 |
| `/api/suppliers/list` | GET | 供应商列表 |
### 采购
| 接口 | 方法 | 说明 |
|------|------|------|
| `/api/purchase/pending_list` | GET | 待采购列表 |
| `/api/purchase/create_order` | POST | 创建采购单 |
| `/api/purchase/orders/list` | GET | 采购单列表 |
### 认证 & 用户
| 接口 | 方法 | 说明 |
|------|------|------|
| `/api/login` | POST | 登录 |
| `/api/logout` | POST | 退出 |
| `/api/profile` | GET | 个人信息 |
| `/api/users/list` | GET | 用户列表 |
| `/api/permissions/list` | GET | 权限列表 |
---
## 数据更新流程
### 数据流向
```
钉钉云盘 → dws下载 → tmp_csv/ → Python导入脚本 → MySQL → Flask API → 浏览器
```
### 更新方式
**方式一:全量自动更新**(推荐)
```bash
python3 auto_update.py
```
- 下载钉盘最新出库+库存CSV
- 全量重导入数据库
- 刷新系统缓存
- 建议配置定时任务每天 7:00 / 12:00 / 18:00 执行
**方式二:单独更新出库数据**
```bash
python3 reimport.py
```
- 扫描 `tmp_csv/` 下所有 `*cksj*.csv` 文件
- 清空 `daily_outbound` 表,全量重写
**方式三:单独更新库存数据**
```bash
# 全量
python3 batch_import_inventory.py
# 增量(只导入新文件)
python3 import_new_inventory.py
```
### 钉盘文件夹 ID
| 名称 | 文件夹ID | 说明 |
|------|---------|------|
| 日出库数据源文件 | `3NwLYZXWynyBjRB4tZjwNxDvVkyEqBQm` | 每日出库CSV |
| 库存数据源文件 | `NkDwLng8ZLGrXmrnFxYq3vRqVKMEvZBY` | 每日库存CSV(按仓库分文件) |
| 所属空间 | `28814565790` | 采购部AI项目数据源 |
---
## 运维指南
### 启动/停止
```bash
# 启动(开发模式)
cd /home/gxd/.openclaw/workspace/dy-dashboard
python3 app.py
# 启动(生产模式,推荐)
python3 run.py --prod
# 或使用 deploy.sh
bash deploy.sh
# 停止
kill $(lsof -t -i:18888)
```
### 查看日志
```bash
# 应用日志
tail -f logs/app.log
# 自动更新日志
tail -f logs/auto_update.log
# 访问日志
tail -f logs/access.log
```
### 刷新缓存
系统使用 `RefreshableCache` 机制。重启服务会自动刷新:
```bash
kill $(lsof -t -i:18888); sleep 2; python3 run.py --prod
```
### 数据校验
```bash
# 检查库存数据
mysql -u dy_app -p'***' dy_data -e "
SELECT data_date, COUNT(*) AS cnt, SUM(available_qty) AS total_avail
FROM inventory_detail
GROUP BY data_date ORDER BY data_date DESC LIMIT 5;"
# 检查出库数据
mysql -u dy_app -p'***' dy_data -e "
SELECT 日期, COUNT(*) AS cnt, SUM(货品数量) AS total_qty
FROM daily_outbound
GROUP BY 日期 ORDER BY 日期 DESC LIMIT 5;"
```
### 常见问题
**Q: 库存数据显示为0**
- 原因:导入脚本解析CSV时编码或列映射出错
- 解决:删除错误数据,重新从CSV导入
**Q: 出库数据缺少某天**
- 原因:当天CSV文件未下载
- 解决:手动从钉盘下载该文件放到 `tmp_csv/`,运行 `python3 reimport.py`
**Q: 页面访问 502/连接拒绝**
- 原因:服务未启动或崩溃
- 解决:`python3 run.py --prod` 重新启动
**Q: 定时更新没跑**
- 原因:crontab 未配置或服务器重启
- 解决:`crontab -e` 确认任务存在,或手动运行 `python3 auto_update.py`
### 模块命名规则
**新建 .py 文件前先检查:**
1. `ls services/*.py` 查看已有模块
2. `grep -rn "from services.\|import services."` 检查现有导入
3. 确认无冲突再新建
---
## 版本管理
### Git 标签
```bash
# 查看版本
git tag
# 查看当前版本详情
git log --oneline --decorate
# 切换到某个版本
git checkout v1.0
```
### 发版流程
```bash
# 1. 提交代码
git add -A
git commit -m "v1.1 - 修复xxx / 新增xxx"
# 2. 打标签
git tag -a v1.1 -m "v1.1 - 说明"
# 3. 导出对应版本的数据库
mysqldump -u dy_app -p'***' dy_data > dy_data_v1.1.sql
```
### 回滚
```bash
# 代码回滚
git reset --hard v1.0
# 数据库回滚(需要手动导入旧版本备份)
mysql -u dy_app -p'***' dy_data < dy_data_v1.0.sql
```
---
## 部署
### 新服务器部署
```bash
# 前置条件(Ubuntu)
sudo apt update && sudo apt install -y python3 python3-pip python3-venv mysql-server
# 解压项目
tar xzf dy-dashboard-package.tar.gz
cd dy-dashboard
# 一键部署
bash deploy.sh
```
`deploy.sh` 会自动完成:
1. ✅ 检测 Python/MySQL 环境
2. ✅ 创建数据库和用户
3. ✅ 导入数据(如果有 `dy_data_backup.sql`)
4. ✅ 创建 Python 虚拟环境并安装依赖
5. ✅ 启动 Gunicorn 服务
6. ✅ 配置定时更新任务
### 使用变量
| 配置项 | 默认值 | 位置 |
|--------|--------|------|
| 端口 | 18888 | `config.py` → `APP_PORT` |
| 数据库名 | dy_data | `config.py` → `DB_CONFIG.database` |
| 数据库用户 | dy_app | `config.py` → `DB_CONFIG.user` |
| 数据库密码 | dy_data_2026 | `config.py` → `DB_CONFIG.password` |
| 默认账号 | 甘旭东 | 数据库 `dashboard_users` 表 |
| 默认密码 | admin123 | 数据库 `dashboard_users` 表 |
---
### 相关链接
- 钉钉云盘空间ID: `28814565790`(采购部AI项目数据源)
- 日出库文件夹ID: `3NwLYZXWynyBjRB4tZjwNxDvVkyEqBQm`
- 库存文件夹ID: `NkDwLng8ZLGrXmrnFxYq3vRqVKMEvZBY`
- 项目路径: `/home/gxd/.openclaw/workspace/dy-dashboard/`
---
*最后更新: 2026-06-10 | v1.0*