""" 求和数据管理 API """ from flask import request, jsonify from lib.sum_data_collector import ( collect_sum_data_from_history, get_sum_data_list, add_sum_data, update_sum_data, delete_sum_data, batch_delete_sum_data, get_monthly_charge_degree_total, export_sum_data_to_excel ) from lib.logger import log_info, log_error, log_warning from . import sum_data_bp @sum_data_bp.route('/sum-data/collect', methods=['POST']) def collect_sum_data(): """从历史记录采集求和数据""" try: data = request.get_json(silent=True) or {} history_id = data.get('history_id') start_date = data.get('start_date') end_date = data.get('end_date') log_info(f'[求和数据API] 采集求和数据,历史记录ID: {history_id or "全部"},日期范围: {start_date or "开始"} ~ {end_date or "结束"}', 'api') result = collect_sum_data_from_history(history_id, start_date, end_date) if result['success']: log_info(f'[求和数据API] 采集成功: {result["message"]}', 'api') return jsonify(result) else: log_warning(f'[求和数据API] 采集失败: {result["message"]}', 'api') return jsonify(result), 400 except Exception as e: log_error(f'[求和数据API] 采集异常: {e}', 'api') return jsonify({'success': False, 'message': str(e)}), 500 @sum_data_bp.route('/sum-data', methods=['GET']) def list_sum_data(): """查询求和数据列表""" try: page_param = request.args.get('page') page = int(page_param) if page_param else None page_size = int(request.args.get('page_size', 20)) start_date = request.args.get('start_date') end_date = request.args.get('end_date') config_id = request.args.get('config_id') config_name = request.args.get('config_name') sum_field_key = request.args.get('sum_field_key') data_source = request.args.get('data_source') # 当 page_size 较大时(>=1000),跳过 COUNT 查询以优化性能 skip_count = page_size >= 1000 log_info(f'[求和数据API] 查询求和数据列表,page={page}, page_size={page_size}, skip_count={skip_count}', 'api') result = get_sum_data_list( page=page, page_size=page_size, start_date=start_date, end_date=end_date, config_id=config_id, config_name=config_name, sum_field_key=sum_field_key, data_source=data_source, skip_count=skip_count ) if result['success']: log_info(f'[求和数据API] 查询成功,共{len(result["data"]["list"])}条记录', 'api') return jsonify(result) else: return jsonify(result), 400 except Exception as e: log_error(f'[求和数据API] 查询求和数据列表失败: {e}', 'api') return jsonify({'success': False, 'message': str(e)}), 500 @sum_data_bp.route('/sum-data', methods=['POST']) def create_sum_data(): """手动添加求和数据""" try: data = request.json log_info('[求和数据API] 手动添加求和数据', 'api') result = add_sum_data(data) if result['success']: log_info(f'[求和数据API] 添加成功,ID: {result.get("id", "")}', 'api') return jsonify(result) else: return jsonify(result), 400 except Exception as e: log_error(f'[求和数据API] 添加求和数据失败: {e}', 'api') return jsonify({'success': False, 'message': str(e)}), 500 @sum_data_bp.route('/sum-data/', methods=['PUT']) def update_sum_data_api(sum_data_id): """更新求和数据""" try: data = request.json log_info(f'[求和数据API] 更新求和数据,ID: {sum_data_id}, 请求数据: {data}', 'api') result = update_sum_data(sum_data_id, data) if result['success']: log_info(f'[求和数据API] 更新成功,ID: {sum_data_id}', 'api') return jsonify(result) else: log_warning(f'[求和数据API] 更新失败,ID: {sum_data_id}, 原因: {result["message"]}', 'api') return jsonify(result), 400 except Exception as e: log_error(f'[求和数据API] 更新求和数据失败: {e}', 'api') return jsonify({'success': False, 'message': str(e)}), 500 @sum_data_bp.route('/sum-data/', methods=['DELETE']) def delete_sum_data_api(sum_data_id): """删除求和数据""" try: log_info(f'[求和数据API] 删除求和数据,ID: {sum_data_id}', 'api') result = delete_sum_data(sum_data_id) if result['success']: log_info(f'[求和数据API] 删除成功,ID: {sum_data_id}', 'api') return jsonify(result) else: return jsonify(result), 400 except Exception as e: log_error(f'[求和数据API] 删除求和数据失败: {e}', 'api') return jsonify({'success': False, 'message': str(e)}), 500 @sum_data_bp.route('/sum-data/batch-delete', methods=['POST']) def batch_delete_sum_data_api(): """批量删除求和数据""" try: data = request.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 result = batch_delete_sum_data(ids) if result['success']: log_info(f'[求和数据API] 批量删除成功,{result["message"]}', 'api') return jsonify(result) else: return jsonify(result), 400 except Exception as e: log_error(f'[求和数据API] 批量删除求和数据失败: {e}', 'api') return jsonify({'success': False, 'message': str(e)}), 500 @sum_data_bp.route('/sum-data/batch-query', methods=['POST']) def batch_query_sum_data(): """根据ID列表或条件批量查询求和数据""" try: data = request.json ids = data.get('ids', []) conditions = data.get('conditions', {}) from lib.db import execute_query # 支持按ID列表查询 if ids: log_info(f'[求和数据API] 按ID批量查询求和数据,ID数量: {len(ids)}', 'api') placeholders = ','.join(['%s'] * len(ids)) sql = f'SELECT * FROM t_daily_report_sum_data WHERE id IN ({placeholders})' result = execute_query(sql, tuple(ids)) return jsonify({ 'success': True, 'data': result }) # 支持按条件查询 if conditions: log_info(f'[求和数据API] 按条件查询求和数据,条件: {conditions}', 'api') where_clauses = [] params = [] for key, value in conditions.items(): if value is not None and value != '': where_clauses.append(f'{key} = %s') params.append(value) if not where_clauses: return jsonify({'success': False, 'message': '请提供有效的查询条件'}), 400 sql = f'SELECT * FROM t_daily_report_sum_data WHERE {" AND ".join(where_clauses)}' result = execute_query(sql, tuple(params)) return jsonify({ 'success': True, 'data': result }) return jsonify({'success': False, 'message': '请提供ID列表或查询条件'}), 400 except Exception as e: log_error(f'[求和数据API] 批量查询求和数据失败: {e}', 'api') return jsonify({'success': False, 'message': str(e)}), 500 @sum_data_bp.route('/sum-data/batch-add', methods=['POST']) def batch_add_sum_data(): """批量添加求和数据""" try: data = request.json fields = data.get('fields', []) log_info(f'[求和数据API] 批量添加求和数据,字段数量: {len(fields)}', 'api') if not fields: return jsonify({'success': False, 'message': '请至少添加一个字段'}), 400 from lib.sum_data_collector import batch_add_sum_data result = batch_add_sum_data(data) if result['success']: log_info(f'[求和数据API] 批量添加成功,添加{result["count"]}条记录', 'api') return jsonify(result) else: return jsonify(result), 400 except Exception as e: log_error(f'[求和数据API] 批量添加求和数据失败: {e}', 'api') return jsonify({'success': False, 'message': str(e)}), 500 @sum_data_bp.route('/sum-data/monthly-total', methods=['GET']) def monthly_charge_degree_total(): """获取指定配置当月充电电量累计(从sum_data表查询,对账后的数据) 参数: config_id: 配置ID(可选,不传则查所有配置总和) month: 月份,格式 YYYY-MM(可选,默认当月) """ try: config_id = request.args.get('config_id') month = request.args.get('month') log_info(f'[求和数据API] 查询月度累计,配置ID: {config_id or "全部"},月份: {month or "当月"}', 'api') result = get_monthly_charge_degree_total(config_id, month) if result['success']: log_info(f'[求和数据API] 查询成功,累计电量: {result["data"]["total_degree"]} kWh', 'api') return jsonify(result) else: return jsonify(result), 400 except Exception as e: log_error(f'[求和数据API] 查询月度累计失败: {e}', 'api') return jsonify({'success': False, 'message': str(e)}), 500 @sum_data_bp.route('/sum-data/export', methods=['GET']) def export_sum_data(): """导出求和数据为Excel 参数: start_date: 开始日期(可选) end_date: 结束日期(可选) config_id: 配置ID(可选) data_source: 数据来源(可选) keyword: 配置名称关键词(可选) """ try: start_date = request.args.get('start_date') end_date = request.args.get('end_date') config_id = request.args.get('config_id') data_source = request.args.get('data_source') keyword = request.args.get('keyword') log_info(f'[求和数据API] 导出求和数据,日期范围: {start_date or "开始"} ~ {end_date or "结束"}', 'api') result = export_sum_data_to_excel( start_date=start_date, end_date=end_date, config_id=config_id, data_source=data_source, keyword=keyword ) if result['success']: log_info(f'[求和数据API] 导出成功,共{result.get("total", 0)}条记录', 'api') return jsonify(result) else: return jsonify(result), 400 except Exception as e: log_error(f'[求和数据API] 导出求和数据失败: {e}', 'api') return jsonify({'success': False, 'message': str(e)}), 500