Files
ylt_diy/lib/api/report_api.py

218 lines
8.9 KiB
Python
Raw 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.

"""
日报生成和历史记录 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
from lib.logger import log_info, log_error, log_warning
from . import report_bp
@report_bp.route('/report/generate', methods=['POST'])
def generate_report():
"""生成日报"""
try:
data = request.json
config_id = data.get('config_id')
log_info(f'[报表API] 生成日报配置ID: {config_id}', 'api')
if not config_id:
log_warning('[报表API] 生成日报失败:未选择配置', 'api')
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']:
log_info(f'[报表API] 日报生成成功,订单数: {result.get("total_orders", 0)}', 'api')
return jsonify(result)
else:
log_warning(f'[报表API] 日报生成失败: {result.get("message", "")}', 'api')
return jsonify(result), 400
except Exception as e:
log_error(f'[报表API] 生成日报异常: {e}', 'api')
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')
status = request.args.get('status')
log_info(f'[报表API] 获取历史记录,第{page}页,状态: {status or "全部"},日期范围: {start_date or "开始"} ~ {end_date or "结束"}', 'api')
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)
if status is not None and status != '':
where_clauses.append('status = %s')
params.append(int(status))
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 *, total_amount AS total_degree 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'] = ''
log_info(f'[报表API] 获取到 {len(history)} 条历史记录,共 {total}', 'api')
return jsonify({
'success': True,
'data': {
'list': history,
'total': total,
'page': page,
'page_size': page_size
}
})
except Exception as e:
log_error(f'[报表API] 获取历史记录失败: {e}', 'api')
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:
log_info(f'[报表API] 删除历史记录ID: {history_id}', 'api')
# 先查询文件路径
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('/')))
log_info(f'[报表API] 已删除报表文件: {file_path}', 'api')
# 删除数据库记录
execute_update('DELETE FROM t_daily_report_history WHERE id = %s', (history_id,))
log_info(f'[报表API] 历史记录删除成功ID: {history_id}', 'api')
return jsonify({'success': True, 'message': '删除成功'})
except Exception as e:
log_error(f'[报表API] 删除历史记录失败: {e}', 'api')
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', [])
log_info(f'[报表API] 批量删除历史记录,数量: {len(ids)}', 'api')
if not ids:
log_warning('[报表API] 批量删除失败:未选择记录', 'api')
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)
)
# 删除文件
deleted_files = 0
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('/')))
deleted_files += 1
log_info(f'[报表API] 已删除 {deleted_files} 个报表文件', 'api')
# 删除数据库记录
execute_update(
f'DELETE FROM t_daily_report_history WHERE id IN ({",".join(["%s"] * len(ids))})',
tuple(ids)
)
log_info(f'[报表API] 批量删除成功,共 {len(ids)} 条记录', 'api')
return jsonify({'success': True, 'message': f'成功删除 {len(ids)} 条记录'})
except Exception as e:
log_error(f'[报表API] 批量删除历史记录失败: {e}', 'api')
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:
log_info(f'[报表API] 下载报表历史记录ID: {history_id}', 'api')
# 查询历史记录
result = execute_query(
'SELECT file_path, split_name, report_date FROM t_daily_report_history WHERE id = %s',
(history_id,)
)
if not result:
log_warning(f'[报表API] 下载报表失败记录不存在ID: {history_id}', 'api')
return jsonify({'success': False, 'message': '记录不存在'}), 404
file_path = result[0]['file_path']
if not file_path:
log_warning(f'[报表API] 下载报表失败文件路径为空ID: {history_id}', 'api')
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):
log_warning(f'[报表API] 下载报表失败:文件不存在,路径: {full_path}', 'api')
return jsonify({'success': False, 'message': '文件不存在'}), 404
# 返回文件
directory = os.path.dirname(full_path)
filename = os.path.basename(full_path)
log_info(f'[报表API] 报表下载成功: {filename}', 'api')
return send_from_directory(directory, filename, as_attachment=True)
except Exception as e:
log_error(f'[报表API] 下载报表失败: {e}', 'api')
return jsonify({'success': False, 'message': str(e)}), 500