2026-07-13 15:43:03 +08:00
|
|
|
|
"""
|
|
|
|
|
|
日报生成和历史记录 API
|
|
|
|
|
|
"""
|
|
|
|
|
|
import os
|
|
|
|
|
|
import json
|
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
from flask import request, jsonify, send_from_directory
|
|
|
|
|
|
from lib.db import execute_query, execute_update
|
|
|
|
|
|
from lib.report_generator import generate_daily_report
|
2026-07-15 16:01:06 +08:00
|
|
|
|
from lib.logger import log_info, log_error, log_warning
|
2026-07-13 15:43:03 +08:00
|
|
|
|
from . import report_bp
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@report_bp.route('/report/generate', methods=['POST'])
|
|
|
|
|
|
def generate_report():
|
|
|
|
|
|
"""生成日报"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
data = request.json
|
|
|
|
|
|
config_id = data.get('config_id')
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_info(f'[报表API] 生成日报,配置ID: {config_id}', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
|
|
|
|
|
|
if not config_id:
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_warning('[报表API] 生成日报失败:未选择配置', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
return jsonify({'success': False, 'message': '请选择配置'}), 400
|
|
|
|
|
|
|
|
|
|
|
|
# 解析时间参数
|
|
|
|
|
|
start_time = None
|
|
|
|
|
|
end_time = None
|
|
|
|
|
|
|
|
|
|
|
|
if data.get('start_time'):
|
|
|
|
|
|
start_time = datetime.strptime(data['start_time'], '%Y-%m-%d %H:%M:%S')
|
|
|
|
|
|
if data.get('end_time'):
|
|
|
|
|
|
end_time = datetime.strptime(data['end_time'], '%Y-%m-%d %H:%M:%S')
|
|
|
|
|
|
|
|
|
|
|
|
result = generate_daily_report(config_id, start_time, end_time)
|
|
|
|
|
|
|
|
|
|
|
|
if result['success']:
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_info(f'[报表API] 日报生成成功,订单数: {result.get("total_orders", 0)}', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
return jsonify(result)
|
|
|
|
|
|
else:
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_warning(f'[报表API] 日报生成失败: {result.get("message", "")}', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
return jsonify(result), 400
|
|
|
|
|
|
except Exception as e:
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_error(f'[报表API] 生成日报异常: {e}', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
return jsonify({'success': False, 'message': str(e)}), 500
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@report_bp.route('/report/history', methods=['GET'])
|
|
|
|
|
|
def get_report_history():
|
|
|
|
|
|
"""获取日报生成历史"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
page = int(request.args.get('page', 1))
|
|
|
|
|
|
page_size = int(request.args.get('page_size', 20))
|
|
|
|
|
|
start_date = request.args.get('start_date')
|
|
|
|
|
|
end_date = request.args.get('end_date')
|
2026-07-21 13:30:04 +08:00
|
|
|
|
status = request.args.get('status')
|
|
|
|
|
|
log_info(f'[报表API] 获取历史记录,第{page}页,状态: {status or "全部"},日期范围: {start_date or "开始"} ~ {end_date or "结束"}', 'api')
|
2026-07-15 16:01:06 +08:00
|
|
|
|
|
2026-07-13 15:43:03 +08:00
|
|
|
|
offset = (page - 1) * page_size
|
|
|
|
|
|
|
|
|
|
|
|
# 构建查询条件
|
|
|
|
|
|
where_clauses = []
|
|
|
|
|
|
params = []
|
|
|
|
|
|
|
|
|
|
|
|
if start_date:
|
|
|
|
|
|
where_clauses.append('DATE(start_time) >= %s')
|
|
|
|
|
|
params.append(start_date)
|
|
|
|
|
|
|
|
|
|
|
|
if end_date:
|
|
|
|
|
|
where_clauses.append('DATE(end_time) <= %s')
|
|
|
|
|
|
params.append(end_date)
|
|
|
|
|
|
|
2026-07-21 13:30:04 +08:00
|
|
|
|
if status is not None and status != '':
|
|
|
|
|
|
where_clauses.append('status = %s')
|
|
|
|
|
|
params.append(int(status))
|
|
|
|
|
|
|
2026-07-13 15:43:03 +08:00
|
|
|
|
where_sql = ' AND '.join(where_clauses) if where_clauses else '1=1'
|
|
|
|
|
|
|
|
|
|
|
|
# 查询总数
|
|
|
|
|
|
total_result = execute_query(
|
|
|
|
|
|
f'SELECT COUNT(*) as total FROM t_daily_report_history WHERE {where_sql}',
|
|
|
|
|
|
tuple(params)
|
|
|
|
|
|
)
|
|
|
|
|
|
total = total_result[0]['total']
|
|
|
|
|
|
|
|
|
|
|
|
# 查询数据
|
|
|
|
|
|
history = execute_query(
|
|
|
|
|
|
f'SELECT * FROM t_daily_report_history WHERE {where_sql} ORDER BY create_time DESC LIMIT %s OFFSET %s',
|
|
|
|
|
|
tuple(params) + (page_size, offset)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# 解析 JSON 字段并确保 file_path 正确
|
|
|
|
|
|
for item in history:
|
|
|
|
|
|
item['sum_results'] = json.loads(item['sum_results']) if item['sum_results'] else {}
|
|
|
|
|
|
# 确保 file_path 是字符串
|
|
|
|
|
|
if item['file_path'] is None:
|
|
|
|
|
|
item['file_path'] = ''
|
|
|
|
|
|
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_info(f'[报表API] 获取到 {len(history)} 条历史记录,共 {total} 条', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
return jsonify({
|
|
|
|
|
|
'success': True,
|
|
|
|
|
|
'data': {
|
|
|
|
|
|
'list': history,
|
|
|
|
|
|
'total': total,
|
|
|
|
|
|
'page': page,
|
|
|
|
|
|
'page_size': page_size
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
except Exception as e:
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_error(f'[报表API] 获取历史记录失败: {e}', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
return jsonify({'success': False, 'message': str(e)}), 500
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@report_bp.route('/report/history/<int:history_id>', methods=['DELETE'])
|
|
|
|
|
|
def delete_report_history(history_id):
|
|
|
|
|
|
"""删除单个历史记录"""
|
|
|
|
|
|
try:
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_info(f'[报表API] 删除历史记录,ID: {history_id}', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
# 先查询文件路径
|
|
|
|
|
|
result = execute_query(
|
|
|
|
|
|
'SELECT file_path FROM t_daily_report_history WHERE id = %s',
|
|
|
|
|
|
(history_id,)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if result:
|
|
|
|
|
|
file_path = result[0].get('file_path', '')
|
|
|
|
|
|
# 删除文件
|
|
|
|
|
|
if file_path and os.path.exists(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', 'public', file_path.lstrip('/'))):
|
|
|
|
|
|
os.remove(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', 'public', file_path.lstrip('/')))
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_info(f'[报表API] 已删除报表文件: {file_path}', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
|
|
|
|
|
|
# 删除数据库记录
|
|
|
|
|
|
execute_update('DELETE FROM t_daily_report_history WHERE id = %s', (history_id,))
|
|
|
|
|
|
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_info(f'[报表API] 历史记录删除成功,ID: {history_id}', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
return jsonify({'success': True, 'message': '删除成功'})
|
|
|
|
|
|
except Exception as e:
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_error(f'[报表API] 删除历史记录失败: {e}', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
return jsonify({'success': False, 'message': str(e)}), 500
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@report_bp.route('/report/history/batch-delete', methods=['POST'])
|
|
|
|
|
|
def batch_delete_report_history():
|
|
|
|
|
|
"""批量删除历史记录"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
data = request.get_json()
|
|
|
|
|
|
ids = data.get('ids', [])
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_info(f'[报表API] 批量删除历史记录,数量: {len(ids)}', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
|
|
|
|
|
|
if not ids:
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_warning('[报表API] 批量删除失败:未选择记录', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
return jsonify({'success': False, 'message': '请选择要删除的记录'}), 400
|
|
|
|
|
|
|
|
|
|
|
|
# 查询文件路径
|
|
|
|
|
|
results = execute_query(
|
|
|
|
|
|
f'SELECT file_path FROM t_daily_report_history WHERE id IN ({",".join(["%s"] * len(ids))})',
|
|
|
|
|
|
tuple(ids)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# 删除文件
|
2026-07-15 16:01:06 +08:00
|
|
|
|
deleted_files = 0
|
2026-07-13 15:43:03 +08:00
|
|
|
|
for result in results:
|
|
|
|
|
|
file_path = result.get('file_path', '')
|
|
|
|
|
|
if file_path and os.path.exists(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', 'public', file_path.lstrip('/'))):
|
|
|
|
|
|
os.remove(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', 'public', file_path.lstrip('/')))
|
2026-07-15 16:01:06 +08:00
|
|
|
|
deleted_files += 1
|
|
|
|
|
|
|
|
|
|
|
|
log_info(f'[报表API] 已删除 {deleted_files} 个报表文件', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
|
|
|
|
|
|
# 删除数据库记录
|
|
|
|
|
|
execute_update(
|
|
|
|
|
|
f'DELETE FROM t_daily_report_history WHERE id IN ({",".join(["%s"] * len(ids))})',
|
|
|
|
|
|
tuple(ids)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_info(f'[报表API] 批量删除成功,共 {len(ids)} 条记录', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
return jsonify({'success': True, 'message': f'成功删除 {len(ids)} 条记录'})
|
|
|
|
|
|
except Exception as e:
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_error(f'[报表API] 批量删除历史记录失败: {e}', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
return jsonify({'success': False, 'message': str(e)}), 500
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@report_bp.route('/report/history/<int:history_id>/download', methods=['GET'])
|
|
|
|
|
|
def download_report_by_id(history_id):
|
|
|
|
|
|
"""根据 ID 下载历史记录"""
|
|
|
|
|
|
try:
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_info(f'[报表API] 下载报表,历史记录ID: {history_id}', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
# 查询历史记录
|
|
|
|
|
|
result = execute_query(
|
|
|
|
|
|
'SELECT file_path, split_name, report_date FROM t_daily_report_history WHERE id = %s',
|
|
|
|
|
|
(history_id,)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if not result:
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_warning(f'[报表API] 下载报表失败:记录不存在,ID: {history_id}', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
return jsonify({'success': False, 'message': '记录不存在'}), 404
|
|
|
|
|
|
|
|
|
|
|
|
file_path = result[0]['file_path']
|
|
|
|
|
|
if not file_path:
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_warning(f'[报表API] 下载报表失败:文件路径为空,ID: {history_id}', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
return jsonify({'success': False, 'message': '文件不存在'}), 404
|
|
|
|
|
|
|
|
|
|
|
|
# 构建完整路径
|
|
|
|
|
|
full_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', 'public', file_path.lstrip('/'))
|
|
|
|
|
|
|
|
|
|
|
|
if not os.path.exists(full_path):
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_warning(f'[报表API] 下载报表失败:文件不存在,路径: {full_path}', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
return jsonify({'success': False, 'message': '文件不存在'}), 404
|
|
|
|
|
|
|
|
|
|
|
|
# 返回文件
|
|
|
|
|
|
directory = os.path.dirname(full_path)
|
|
|
|
|
|
filename = os.path.basename(full_path)
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_info(f'[报表API] 报表下载成功: {filename}', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
return send_from_directory(directory, filename, as_attachment=True)
|
|
|
|
|
|
except Exception as e:
|
2026-07-15 16:01:06 +08:00
|
|
|
|
log_error(f'[报表API] 下载报表失败: {e}', 'api')
|
2026-07-13 15:43:03 +08:00
|
|
|
|
return jsonify({'success': False, 'message': str(e)}), 500
|