增加求和采集和细节修改
This commit is contained in:
409
lib/sum_data_collector.py
Normal file
409
lib/sum_data_collector.py
Normal file
@@ -0,0 +1,409 @@
|
||||
"""
|
||||
日报求和数据采集与管理
|
||||
"""
|
||||
import json
|
||||
from datetime import datetime
|
||||
from lib.db import execute_query, execute_update, execute_insert
|
||||
from lib.field_mapping import get_field_display_name
|
||||
|
||||
|
||||
def collect_sum_data_from_history(history_id=None):
|
||||
"""
|
||||
从历史记录中采集求和数据并写入求和数据表
|
||||
充电电量(charge_degree)是必须采集的,其他求和字段有就采集,没有就不采集
|
||||
|
||||
Args:
|
||||
history_id: 历史记录ID(可选,不填则采集所有成功的历史记录)
|
||||
|
||||
Returns:
|
||||
dict: 采集结果
|
||||
"""
|
||||
try:
|
||||
# 查询历史记录
|
||||
if history_id:
|
||||
history_list = execute_query(
|
||||
'SELECT * FROM t_daily_report_history WHERE id = %s AND status = 1',
|
||||
(history_id,)
|
||||
)
|
||||
else:
|
||||
history_list = execute_query(
|
||||
'SELECT * FROM t_daily_report_history WHERE status = 1 ORDER BY create_time DESC'
|
||||
)
|
||||
|
||||
if not history_list:
|
||||
return {'success': False, 'message': '没有找到符合条件的历史记录'}
|
||||
|
||||
collected_count = 0
|
||||
skipped_count = 0
|
||||
|
||||
for history in history_list:
|
||||
sum_results = history.get('sum_results')
|
||||
|
||||
# 解析 sum_results JSON
|
||||
if isinstance(sum_results, str):
|
||||
sum_results = json.loads(sum_results) if sum_results else {}
|
||||
elif sum_results is None:
|
||||
sum_results = {}
|
||||
|
||||
# 强制确保有充电电量(charge_degree)
|
||||
if 'charge_degree' not in sum_results or sum_results['charge_degree'] is None:
|
||||
# 从订单表重新计算充电电量
|
||||
try:
|
||||
charge_degree = _calculate_charge_degree(history)
|
||||
if charge_degree is not None:
|
||||
sum_results['charge_degree'] = charge_degree
|
||||
print(f"[采集] 历史记录 {history['id']} 补充计算充电电量: {charge_degree} kWh")
|
||||
except Exception as calc_error:
|
||||
print(f"[采集] 历史记录 {history['id']} 计算充电电量失败: {calc_error}")
|
||||
|
||||
# 如果还是没有任何求和数据,跳过
|
||||
if not sum_results:
|
||||
skipped_count += 1
|
||||
continue
|
||||
|
||||
# 先删除该历史记录对应的旧数据(避免重复)
|
||||
execute_update(
|
||||
'''DELETE FROM t_daily_report_sum_data
|
||||
WHERE report_date = %s AND config_id = %s AND split_value = %s AND data_source = 'auto'
|
||||
''',
|
||||
(history['report_date'], history['config_id'], history['split_value'])
|
||||
)
|
||||
|
||||
# 逐条插入求和字段数据
|
||||
for field_key, field_value in sum_results.items():
|
||||
sum_data_id = int(datetime.now().timestamp() * 1000000) + collected_count
|
||||
sql = '''
|
||||
INSERT INTO t_daily_report_sum_data
|
||||
(id, report_date, config_id, config_name, split_type, split_value, split_name,
|
||||
sum_field_key, sum_field_name, sum_value, total_orders, data_source, remark,
|
||||
create_time, update_time)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW(), NOW())
|
||||
'''
|
||||
params = (
|
||||
sum_data_id,
|
||||
history['report_date'],
|
||||
history['config_id'],
|
||||
history.get('config_name', ''),
|
||||
history.get('split_type', ''),
|
||||
history.get('split_value', ''),
|
||||
history.get('split_name', ''),
|
||||
field_key,
|
||||
get_field_display_name(field_key),
|
||||
float(field_value) if field_value is not None else 0,
|
||||
history.get('total_orders', 0),
|
||||
'auto',
|
||||
f'从历史记录自动采集,历史ID: {history["id"]}'
|
||||
)
|
||||
execute_insert(sql, params)
|
||||
collected_count += 1
|
||||
|
||||
return {
|
||||
'success': True,
|
||||
'message': f'采集完成,共采集 {collected_count} 条求和数据,跳过 {skipped_count} 条无求和数据的记录'
|
||||
}
|
||||
except Exception as e:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return {'success': False, 'message': f'采集失败: {str(e)}'}
|
||||
|
||||
|
||||
def _calculate_charge_degree(history):
|
||||
"""
|
||||
从订单表中计算指定历史记录对应的充电电量总和
|
||||
|
||||
Args:
|
||||
history: 历史记录字典
|
||||
|
||||
Returns:
|
||||
float: 充电电量总和(保留三位小数),失败返回 None
|
||||
"""
|
||||
try:
|
||||
split_type = history.get('split_type', '')
|
||||
split_value = history.get('split_value', '')
|
||||
start_time = history.get('start_time', '')
|
||||
end_time = history.get('end_time', '')
|
||||
|
||||
if not split_type or not split_value or not start_time or not end_time:
|
||||
return None
|
||||
|
||||
# 检查是否为多选值(逗号分隔)
|
||||
split_values = [v.strip() for v in str(split_value).split(',') if v.strip()]
|
||||
|
||||
if len(split_values) > 1:
|
||||
placeholders = ', '.join(['%s'] * len(split_values))
|
||||
sql = f"""
|
||||
SELECT SUM(charge_degree) as total_degree
|
||||
FROM t_equipment_charge_order
|
||||
WHERE state = 3
|
||||
AND report_time >= %s
|
||||
AND report_time < %s
|
||||
AND {split_type} IN ({placeholders})
|
||||
"""
|
||||
params = [start_time, end_time] + split_values
|
||||
else:
|
||||
sql = f"""
|
||||
SELECT SUM(charge_degree) as total_degree
|
||||
FROM t_equipment_charge_order
|
||||
WHERE state = 3
|
||||
AND report_time >= %s
|
||||
AND report_time < %s
|
||||
AND {split_type} = %s
|
||||
"""
|
||||
params = [start_time, end_time, split_value]
|
||||
|
||||
result = execute_query(sql, tuple(params))
|
||||
if result and result[0].get('total_degree') is not None:
|
||||
return round(float(result[0]['total_degree']), 3)
|
||||
|
||||
return 0.0
|
||||
except Exception as e:
|
||||
print(f"[计算充电电量] 失败: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def get_sum_data_list(page=1, page_size=20, report_date=None, config_id=None,
|
||||
config_name=None, sum_field_key=None, data_source=None):
|
||||
"""
|
||||
查询求和数据列表
|
||||
|
||||
Args:
|
||||
page: 页码
|
||||
page_size: 每页大小
|
||||
report_date: 报表日期(可选)
|
||||
config_id: 配置ID(可选)
|
||||
config_name: 配置名称(可选,模糊搜索)
|
||||
sum_field_key: 求和字段键名(可选)
|
||||
data_source: 数据来源(可选)
|
||||
|
||||
Returns:
|
||||
dict: 查询结果
|
||||
"""
|
||||
try:
|
||||
offset = (page - 1) * page_size
|
||||
|
||||
where_clauses = ['1=1']
|
||||
params = []
|
||||
|
||||
if report_date:
|
||||
where_clauses.append('report_date = %s')
|
||||
params.append(report_date)
|
||||
|
||||
if config_id:
|
||||
where_clauses.append('config_id = %s')
|
||||
params.append(config_id)
|
||||
|
||||
if config_name:
|
||||
where_clauses.append('config_name LIKE %s')
|
||||
params.append(f'%{config_name}%')
|
||||
|
||||
if sum_field_key:
|
||||
where_clauses.append('sum_field_key = %s')
|
||||
params.append(sum_field_key)
|
||||
|
||||
if data_source:
|
||||
where_clauses.append('data_source = %s')
|
||||
params.append(data_source)
|
||||
|
||||
where_sql = ' AND '.join(where_clauses)
|
||||
|
||||
# 查询总数
|
||||
total_result = execute_query(
|
||||
f'SELECT COUNT(*) as total FROM t_daily_report_sum_data WHERE {where_sql}',
|
||||
tuple(params)
|
||||
)
|
||||
total = total_result[0]['total']
|
||||
|
||||
# 查询数据
|
||||
list_result = execute_query(
|
||||
f'''SELECT * FROM t_daily_report_sum_data
|
||||
WHERE {where_sql}
|
||||
ORDER BY report_date DESC, config_id, id DESC
|
||||
LIMIT %s OFFSET %s''',
|
||||
tuple(params) + (page_size, offset)
|
||||
)
|
||||
|
||||
return {
|
||||
'success': True,
|
||||
'data': {
|
||||
'list': list_result,
|
||||
'total': total,
|
||||
'page': page,
|
||||
'page_size': page_size
|
||||
}
|
||||
}
|
||||
except Exception as e:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return {'success': False, 'message': str(e)}
|
||||
|
||||
|
||||
def add_sum_data(data):
|
||||
"""
|
||||
手动添加求和数据
|
||||
|
||||
Args:
|
||||
data: 求和数据字典
|
||||
|
||||
Returns:
|
||||
dict: 操作结果
|
||||
"""
|
||||
try:
|
||||
sum_data_id = int(datetime.now().timestamp() * 1000)
|
||||
sql = '''
|
||||
INSERT INTO t_daily_report_sum_data
|
||||
(id, report_date, config_id, config_name, split_type, split_value, split_name,
|
||||
sum_field_key, sum_field_name, sum_value, total_orders, data_source, remark,
|
||||
create_time, update_time)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW(), NOW())
|
||||
'''
|
||||
params = (
|
||||
sum_data_id,
|
||||
data.get('report_date', ''),
|
||||
data.get('config_id'),
|
||||
data.get('config_name', ''),
|
||||
data.get('split_type', ''),
|
||||
data.get('split_value', ''),
|
||||
data.get('split_name', ''),
|
||||
data.get('sum_field_key', ''),
|
||||
data.get('sum_field_name', ''),
|
||||
float(data.get('sum_value', 0)),
|
||||
data.get('total_orders', 0),
|
||||
'manual',
|
||||
data.get('remark', '')
|
||||
)
|
||||
execute_insert(sql, params)
|
||||
return {'success': True, 'message': '添加成功', 'id': sum_data_id}
|
||||
except Exception as e:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return {'success': False, 'message': str(e)}
|
||||
|
||||
|
||||
def update_sum_data(sum_data_id, data):
|
||||
"""
|
||||
更新求和数据
|
||||
|
||||
Args:
|
||||
sum_data_id: 求和数据ID
|
||||
data: 更新的数据字典
|
||||
|
||||
Returns:
|
||||
dict: 操作结果
|
||||
"""
|
||||
try:
|
||||
update_fields = []
|
||||
params = []
|
||||
|
||||
if 'report_date' in data:
|
||||
update_fields.append('report_date = %s')
|
||||
params.append(data['report_date'])
|
||||
|
||||
if 'config_id' in data:
|
||||
update_fields.append('config_id = %s')
|
||||
params.append(data['config_id'])
|
||||
|
||||
if 'config_name' in data:
|
||||
update_fields.append('config_name = %s')
|
||||
params.append(data['config_name'])
|
||||
|
||||
if 'split_type' in data:
|
||||
update_fields.append('split_type = %s')
|
||||
params.append(data['split_type'])
|
||||
|
||||
if 'split_value' in data:
|
||||
update_fields.append('split_value = %s')
|
||||
params.append(data['split_value'])
|
||||
|
||||
if 'split_name' in data:
|
||||
update_fields.append('split_name = %s')
|
||||
params.append(data['split_name'])
|
||||
|
||||
if 'sum_field_key' in data:
|
||||
update_fields.append('sum_field_key = %s')
|
||||
params.append(data['sum_field_key'])
|
||||
|
||||
if 'sum_field_name' in data:
|
||||
update_fields.append('sum_field_name = %s')
|
||||
params.append(data['sum_field_name'])
|
||||
|
||||
if 'sum_value' in data:
|
||||
update_fields.append('sum_value = %s')
|
||||
params.append(float(data['sum_value']))
|
||||
|
||||
if 'total_orders' in data:
|
||||
update_fields.append('total_orders = %s')
|
||||
params.append(data['total_orders'])
|
||||
|
||||
if 'remark' in data:
|
||||
update_fields.append('remark = %s')
|
||||
params.append(data['remark'])
|
||||
|
||||
if not update_fields:
|
||||
return {'success': False, 'message': '没有需要更新的字段'}
|
||||
|
||||
update_fields.append('update_time = NOW()')
|
||||
params.append(sum_data_id)
|
||||
|
||||
sql = f'''
|
||||
UPDATE t_daily_report_sum_data
|
||||
SET {', '.join(update_fields)}
|
||||
WHERE id = %s
|
||||
'''
|
||||
rowcount = execute_update(sql, tuple(params))
|
||||
|
||||
if rowcount > 0:
|
||||
return {'success': True, 'message': '更新成功'}
|
||||
else:
|
||||
return {'success': False, 'message': '记录不存在'}
|
||||
except Exception as e:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return {'success': False, 'message': str(e)}
|
||||
|
||||
|
||||
def delete_sum_data(sum_data_id):
|
||||
"""
|
||||
删除求和数据
|
||||
|
||||
Args:
|
||||
sum_data_id: 求和数据ID
|
||||
|
||||
Returns:
|
||||
dict: 操作结果
|
||||
"""
|
||||
try:
|
||||
rowcount = execute_update(
|
||||
'DELETE FROM t_daily_report_sum_data WHERE id = %s',
|
||||
(sum_data_id,)
|
||||
)
|
||||
if rowcount > 0:
|
||||
return {'success': True, 'message': '删除成功'}
|
||||
else:
|
||||
return {'success': False, 'message': '记录不存在'}
|
||||
except Exception as e:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return {'success': False, 'message': str(e)}
|
||||
|
||||
|
||||
def batch_delete_sum_data(ids):
|
||||
"""
|
||||
批量删除求和数据
|
||||
|
||||
Args:
|
||||
ids: ID列表
|
||||
|
||||
Returns:
|
||||
dict: 操作结果
|
||||
"""
|
||||
try:
|
||||
placeholders = ', '.join(['%s'] * len(ids))
|
||||
rowcount = execute_update(
|
||||
f'DELETE FROM t_daily_report_sum_data WHERE id IN ({placeholders})',
|
||||
tuple(ids)
|
||||
)
|
||||
return {'success': True, 'message': f'成功删除 {rowcount} 条记录'}
|
||||
except Exception as e:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return {'success': False, 'message': str(e)}
|
||||
Reference in New Issue
Block a user