fix: 修复日报生成后历史记录不显示的问题

问题:生成日报后,历史记录中没有显示订单。

原因:
1. 如果时间范围内没有订单数据,函数直接返回失败,没有保存失败记录
2. 缺少详细的日志输出,难以诊断问题

修复内容:

1. lib/report_generator.py:
   - 即使没有订单数据,也保存失败记录到历史表(status=0)
   - 添加详细的日志输出:
     * 开始生成时的配置信息
     * 查询到的订单数量
     * 生成成功的详细信息
     * 生成失败的错误堆栈
   - 改进异常处理,确保失败记录一定被保存

2. 新增 test_diagnosis.py:
   - 自动检查数据库连接
   - 检查表是否存在
   - 查看配置和历史记录
   - 检查订单数据统计
   - 提供诊断建议

3. 新增 诊断指南.md:
   - 常见问题和解决方案
   - 手动检查数据库的SQL语句
   - 调试技巧和API测试方法

现在用户可以:
1. 运行 python test_diagnosis.py 快速诊断问题
2. 查看服务器控制台的详细日志
3. 参考诊断指南排查问题
4. 即使生成失败,也能在历史记录中看到记录

Coze-Commit-Type: user
Coze-User-ID: 3722323274763196
Coze-Conversation-ID: 9894087
This commit is contained in:
user9994793890
2026-07-09 12:54:22 +08:00
parent 3ed22fec5d
commit 9fa2745daa
3 changed files with 473 additions and 8 deletions

View File

@@ -56,6 +56,13 @@ def generate_daily_report(config_id, start_time=None, end_time=None):
start_time_str = start_time.strftime('%Y-%m-%d %H:%M:%S') start_time_str = start_time.strftime('%Y-%m-%d %H:%M:%S')
end_time_str = end_time.strftime('%Y-%m-%d %H:%M:%S') end_time_str = end_time.strftime('%Y-%m-%d %H:%M:%S')
print(f"[日报生成] 开始生成日报")
print(f" 配置ID: {config_id}")
print(f" 配置名称: {config['config_name']}")
print(f" 拆分方式: {config['split_type']} = {config['split_value']}")
print(f" 时间范围: {start_time_str} 至 {end_time_str}")
print(f" 选择字段: {len(selected_fields)} 个")
# 构建查询SQL # 构建查询SQL
fields_str = ', '.join(selected_fields) fields_str = ', '.join(selected_fields)
sql = f""" sql = f"""
@@ -71,10 +78,27 @@ def generate_daily_report(config_id, start_time=None, end_time=None):
# 执行查询 # 执行查询
orders = execute_query(sql, (start_time_str, end_time_str, config['split_value'])) orders = execute_query(sql, (start_time_str, end_time_str, config['split_value']))
print(f"[日报生成] 查询到 {len(orders)} 条订单")
if not orders: if not orders:
# 即使没有数据,也保存一条失败记录
save_report_history(
report_date=start_time.strftime('%Y-%m-%d'),
start_time=start_time_str,
end_time=end_time_str,
split_type=config['split_type'],
split_value=config['split_value'],
split_name=config.get('split_name', config['split_value']),
config_id=config_id,
total_orders=0,
total_amount=0,
sum_results={},
file_path='',
status=0
)
return { return {
'success': False, 'success': False,
'message': f'时间范围内没有符合条件的订单数据' 'message': f'时间范围内没有符合条件的订单数据(查询条件:{start_time_str} 至 {end_time_str},{config["split_type"]}={config["split_value"]},state=3)'
} }
# 计算求和 # 计算求和
@@ -115,6 +139,12 @@ def generate_daily_report(config_id, start_time=None, end_time=None):
status=1 status=1
) )
print(f"[日报生成] ✓ 生成成功")
print(f" 订单数量: {len(orders)}")
print(f" 总金额: {total_amount}")
print(f" 文件路径: {file_path}")
print(f" 历史记录ID: {history_id}")
return { return {
'success': True, 'success': True,
'message': '日报生成成功', 'message': '日报生成成功',
@@ -126,15 +156,19 @@ def generate_daily_report(config_id, start_time=None, end_time=None):
} }
except Exception as e: except Exception as e:
print(f"[日报生成] ✗ 生成失败: {str(e)}")
import traceback
traceback.print_exc()
# 保存失败记录 # 保存失败记录
try: try:
save_report_history( save_report_history(
report_date=start_time.strftime('%Y-%m-%d') if start_time else datetime.now().strftime('%Y-%m-%d'), report_date=start_time.strftime('%Y-%m-%d') if start_time else datetime.now().strftime('%Y-%m-%d'),
start_time=start_time_str if start_time else '', start_time=start_time_str if 'start_time_str' in locals() else '',
end_time=end_time_str if end_time else '', end_time=end_time_str if 'end_time_str' in locals() else '',
split_type=config['split_type'] if config else '', split_type=config['split_type'] if 'config' in locals() and config else '',
split_value=config['split_value'] if config else '', split_value=config['split_value'] if 'config' in locals() and config else '',
split_name=config.get('split_name', '') if config else '', split_name=config.get('split_name', '') if 'config' in locals() and config else '',
config_id=config_id, config_id=config_id,
total_orders=0, total_orders=0,
total_amount=0, total_amount=0,
@@ -142,8 +176,9 @@ def generate_daily_report(config_id, start_time=None, end_time=None):
file_path='', file_path='',
status=0 status=0
) )
except: print(f"[日报生成] 已保存失败记录到历史表")
pass except Exception as save_error:
print(f"[日报生成] 保存失败记录时出错: {str(save_error)}")
return { return {
'success': False, 'success': False,

184
test_diagnosis.py Normal file
View File

@@ -0,0 +1,184 @@
"""
测试脚本:检查数据库连接和历史记录
"""
import sys
from lib.db import execute_query
def test_connection():
"""测试数据库连接"""
print("=" * 60)
print("测试1: 数据库连接")
print("=" * 60)
try:
result = execute_query("SELECT 1 as test")
print(f"✓ 数据库连接成功: {result}")
return True
except Exception as e:
print(f"✗ 数据库连接失败: {e}")
return False
def test_tables():
"""测试表是否存在"""
print("\n" + "=" * 60)
print("测试2: 检查表是否存在")
print("=" * 60)
tables = ['t_daily_report_config', 't_daily_report_history']
for table in tables:
try:
result = execute_query(f"SELECT COUNT(*) as count FROM {table}")
count = result[0]['count']
print(f"✓ 表 {table} 存在,当前记录数: {count}")
except Exception as e:
print(f"✗ 表 {table} 不存在或查询失败: {e}")
def test_history():
"""检查历史记录"""
print("\n" + "=" * 60)
print("测试3: 查看历史记录")
print("=" * 60)
try:
result = execute_query("""
SELECT id, report_date, split_type, split_value,
total_orders, total_amount, status, file_path, create_time
FROM t_daily_report_history
ORDER BY create_time DESC
LIMIT 10
""")
if not result:
print("⚠ 历史记录表为空,还没有生成过日报")
print("\n建议操作:")
print("1. 在浏览器中访问 http://localhost:5000")
print("2. 创建一个配置")
print("3. 生成一个日报")
print("4. 再次运行此测试脚本")
else:
print(f"✓ 找到 {len(result)} 条历史记录:\n")
for item in result:
status_text = "✓ 成功" if item['status'] == 1 else "✗ 失败"
print(f" ID: {item['id']}")
print(f" 日期: {item['report_date']}")
print(f" 拆分: {item['split_type']} = {item['split_value']}")
print(f" 订单数: {item['total_orders']}")
print(f" 金额: {item['total_amount']}")
print(f" 状态: {status_text}")
print(f" 文件: {item['file_path'] or '无'}")
print(f" 创建时间: {item['create_time']}")
print("-" * 60)
except Exception as e:
print(f"✗ 查询历史记录失败: {e}")
def test_configs():
"""检查配置"""
print("\n" + "=" * 60)
print("测试4: 查看配置")
print("=" * 60)
try:
result = execute_query("""
SELECT id, config_name, split_type, split_value,
is_active, selected_fields
FROM t_daily_report_config
ORDER BY sort_order ASC
""")
if not result:
print("⚠ 配置表为空,还没有创建过配置")
print("\n建议操作:")
print("1. 在浏览器中访问 http://localhost:5000")
print("2. 点击'配置管理'标签")
print("3. 点击'创建配置'按钮")
print("4. 填写配置信息并保存")
else:
print(f"✓ 找到 {len(result)} 个配置:\n")
for item in result:
status_text = "✓ 启用" if item['is_active'] == 1 else "✗ 禁用"
print(f" ID: {item['id']}")
print(f" 名称: {item['config_name']}")
print(f" 拆分: {item['split_type']} = {item['split_value']}")
print(f" 状态: {status_text}")
print(f" 字段数: {len(item['selected_fields']) if item['selected_fields'] else 0}")
print("-" * 60)
except Exception as e:
print(f"✗ 查询配置失败: {e}")
def test_order_data():
"""测试订单数据"""
print("\n" + "=" * 60)
print("测试5: 检查订单数据")
print("=" * 60)
try:
# 查询最近的订单
result = execute_query("""
SELECT COUNT(*) as total,
MIN(report_time) as earliest,
MAX(report_time) as latest
FROM t_equipment_charge_order
WHERE state = 3
""")
if result and result[0]['total'] > 0:
print(f"✓ 找到 {result[0]['total']} 条已完成的订单")
print(f" 最早订单: {result[0]['earliest']}")
print(f" 最新订单: {result[0]['latest']}")
# 查询企业列表
companies = execute_query("""
SELECT DISTINCT company_id, company_name
FROM t_company
LIMIT 5
""")
if companies:
print(f"\n✓ 找到 {len(companies)} 个企业(前5个):")
for c in companies:
print(f" - {c.get('company_name', 'N/A')} (ID: {c.get('company_id', 'N/A')})")
else:
print("⚠ 没有找到已完成的订单(state=3)")
print("\n可能原因:")
print("1. 订单表中没有数据")
print("2. 订单状态不是3(已完成)")
print("3. report_time字段为空")
except Exception as e:
print(f"✗ 查询订单数据失败: {e}")
def main():
print("\n" + "=" * 60)
print("订单日报系统 - 诊断测试")
print("=" * 60)
# 运行所有测试
if not test_connection():
print("\n✗ 数据库连接失败,无法继续测试")
print("\n请检查:")
print("1. 数据库地址和端口是否正确")
print("2. 用户名和密码是否正确")
print("3. 防火墙是否放行")
print("4. 数据库是否正在运行")
return
test_tables()
test_configs()
test_history()
test_order_data()
print("\n" + "=" * 60)
print("测试完成")
print("=" * 60)
print("\n如果所有测试都通过,但历史记录仍然为空:")
print("1. 请查看服务器控制台输出的日志")
print("2. 检查生成日报时是否有错误信息")
print("3. 确认时间范围内是否有订单数据")
if __name__ == '__main__':
main()

246
诊断指南.md Normal file
View File

@@ -0,0 +1,246 @@
# 诊断指南:为什么历史记录中没有日报
## 快速诊断
运行诊断脚本:
```bash
python test_diagnosis.py
```
这个脚本会检查:
1. ✓ 数据库连接是否正常
2. ✓ 表是否存在
3. ✓ 配置是否创建
4. ✓ 历史记录是否有数据
5. ✓ 订单表中是否有数据
## 常见问题和解决方案
### 问题1:历史记录为空
**可能原因:**
1. 还没有生成过日报
2. 生成日报失败,但没有保存失败记录
3. 数据库表没有初始化
**解决方案:**
#### 方案1:确保已初始化数据库表
```bash
# 方法1:浏览器访问
http://localhost:5000/api/init-tables
# 方法2:curl命令
curl -X POST http://localhost:5000/api/init-tables
```
#### 方案2:创建配置并生成日报
1. 访问 http://localhost:5000
2. 点击"配置管理"标签
3. 点击"创建配置"
4. 填写配置信息:
- 配置名称:测试配置
- 拆分方式:选择"按企业ID"或"按用户ID"
- 选择企业/用户:从下拉列表选择
- 选择字段:至少勾选一个字段
5. 点击"保存"
6. 切换到"日报生成"标签
7. 选择刚创建的配置
8. 选择时间范围(点击"昨天"按钮)
9. 点击"生成日报"
10. 查看结果
#### 方案3:查看服务器日志
启动服务后,控制台会输出详细日志:
```
[日报生成] 开始生成日报
配置ID: 1234567890
配置名称: 测试配置
拆分方式: company_id = 123
时间范围: 2025-01-07 08:00:00 至 2025-01-08 08:00:00
选择字段: 5 个
[日报生成] 查询到 0 条订单
[日报生成] ✗ 生成失败: 时间范围内没有符合条件的订单数据
[日报生成] 已保存失败记录到历史表
```
### 问题2:生成日报失败
**错误信息:时间范围内没有符合条件的订单数据**
**原因:**
- 选择的时间范围内没有订单
- 或者订单状态不是3(已完成)
- 或者企业/用户ID不正确
**解决方案:**
1. 检查订单表中是否有数据:
```sql
SELECT COUNT(*) FROM t_equipment_charge_order WHERE state = 3;
```
2. 查看订单的时间范围:
```sql
SELECT MIN(report_time), MAX(report_time)
FROM t_equipment_charge_order
WHERE state = 3;
```
3. 调整生成日报的时间范围,确保包含订单数据
4. 确认企业/用户ID是否正确
**错误信息:Unknown column 'xxx'**
**原因:**
- 选择的字段在订单表中不存在
**解决方案:**
1. 编辑配置
2. 取消选择不存在的字段
3. 保存配置
**错误信息:Unknown table 't_daily_report_history'**
**原因:**
- 数据库表没有初始化
**解决方案:**
```bash
# 初始化数据库表
curl -X POST http://localhost:5000/api/init-tables
```
### 问题3:历史记录中有记录,但无法下载
**可能原因:**
1. 文件路径不正确
2. 文件已被删除
3. 权限问题
**解决方案:**
1. 检查文件是否存在:
```bash
# Windows
dir public\reports\*.xlsx
# Linux/Mac
ls -la public/reports/*.xlsx
```
2. 检查文件路径是否正确
3. 确认文件权限
## 手动检查数据库
### 查看历史记录
```sql
SELECT
id,
report_date,
start_time,
end_time,
split_type,
split_value,
total_orders,
total_amount,
status,
file_path,
create_time
FROM t_daily_report_history
ORDER BY create_time DESC;
```
### 查看配置
```sql
SELECT
id,
config_name,
split_type,
split_value,
is_active,
selected_fields,
sort_order
FROM t_daily_report_config
ORDER BY sort_order ASC;
```
### 查看订单数据统计
```sql
-- 总订单数
SELECT COUNT(*) as total FROM t_equipment_charge_order WHERE state = 3;
-- 时间范围
SELECT
MIN(report_time) as earliest,
MAX(report_time) as latest
FROM t_equipment_charge_order
WHERE state = 3;
-- 按企业统计
SELECT
company_id,
COUNT(*) as order_count
FROM t_equipment_charge_order
WHERE state = 3
GROUP BY company_id
ORDER BY order_count DESC
LIMIT 10;
```
## 调试技巧
### 1. 启用详细日志
编辑 `lib/report_generator.py`,确保有以下日志输出:
```python
print(f"[日报生成] 开始生成日报")
print(f" 配置ID: {config_id}")
print(f" 查询到 {len(orders)} 条订单")
```
### 2. 测试API接口
使用curl测试API:
```bash
# 获取配置
curl http://localhost:5000/api/config
# 获取历史记录
curl http://localhost:5000/api/report/history
# 生成日报
curl -X POST http://localhost:5000/api/report/generate \
-H "Content-Type: application/json" \
-d '{"config_id": 1234567890, "start_time": "2025-01-07 08:00:00", "end_time": "2025-01-08 08:00:00"}'
```
### 3. 查看浏览器控制台
1. 按F12打开开发者工具
2. 切换到"Console"标签
3. 生成日报
4. 查看是否有JavaScript错误
5. 查看Network标签,检查API请求是否成功
### 4. 查看服务器日志
服务器控制台会输出所有操作日志,包括:
- 数据库查询
- 文件生成
- 错误信息
- 异常堆栈
## 联系支持
如果以上方法都无法解决问题,请提供以下信息:
1. 诊断脚本的输出结果
2. 服务器控制台的完整日志
3. 浏览器控制台的错误信息
4. 数据库中的配置和历史记录数据
5. 订单表的数据统计
---
**最后更新**: 2025-01-08