feat: 规范报表名称格式,添加补单检测,设置充电量为必选字段
Coze-Commit-Type: user Coze-User-ID: 3722323274763196 Coze-Conversation-ID: 9894087
This commit is contained in:
@@ -376,6 +376,11 @@ def generate_daily_report(config_id, start_time=None, end_time=None):
|
|||||||
for order in orders:
|
for order in orders:
|
||||||
order['data_source'] = '驿来特'
|
order['data_source'] = '驿来特'
|
||||||
|
|
||||||
|
# 检查是否有补单记录(finish_type = 2 表示补单结束)
|
||||||
|
has_supplement = any(order.get('finish_type') == 2 for order in orders)
|
||||||
|
if has_supplement:
|
||||||
|
print(f"[日报生成] 检测到补单记录,将在文件名中添加标记")
|
||||||
|
|
||||||
# 检查是否需要合并特来电数据
|
# 检查是否需要合并特来电数据
|
||||||
merge_telecom = config.get('merge_telecom', 0)
|
merge_telecom = config.get('merge_telecom', 0)
|
||||||
telecom_vehicle_no = config.get('telecom_vehicle_no', '')
|
telecom_vehicle_no = config.get('telecom_vehicle_no', '')
|
||||||
@@ -390,6 +395,9 @@ def generate_daily_report(config_id, start_time=None, end_time=None):
|
|||||||
# 将特来电数据添加到订单列表
|
# 将特来电数据添加到订单列表
|
||||||
orders.extend(telecom_orders)
|
orders.extend(telecom_orders)
|
||||||
print(f"[日报生成] 合并后总订单数: {len(orders)}")
|
print(f"[日报生成] 合并后总订单数: {len(orders)}")
|
||||||
|
# 检查特来电数据中是否有补单记录
|
||||||
|
if not has_supplement:
|
||||||
|
has_supplement = any(order.get('finish_type') == 2 for order in telecom_orders)
|
||||||
|
|
||||||
if not orders:
|
if not orders:
|
||||||
# 即使没有数据,也保存一条失败记录
|
# 即使没有数据,也保存一条失败记录
|
||||||
@@ -455,7 +463,8 @@ def generate_daily_report(config_id, start_time=None, end_time=None):
|
|||||||
start_time=start_time_str,
|
start_time=start_time_str,
|
||||||
end_time=end_time_str,
|
end_time=end_time_str,
|
||||||
id_name_maps=id_name_maps,
|
id_name_maps=id_name_maps,
|
||||||
field_custom_names=config.get('field_custom_names')
|
field_custom_names=config.get('field_custom_names'),
|
||||||
|
has_supplement=has_supplement
|
||||||
)
|
)
|
||||||
|
|
||||||
print(f"[日报生成] Excel文件已生成: {file_path}")
|
print(f"[日报生成] Excel文件已生成: {file_path}")
|
||||||
@@ -530,13 +539,14 @@ def generate_daily_report(config_id, start_time=None, end_time=None):
|
|||||||
|
|
||||||
def generate_excel(orders, selected_fields, sum_fields, sum_results,
|
def generate_excel(orders, selected_fields, sum_fields, sum_results,
|
||||||
config_name, split_name, start_time, end_time,
|
config_name, split_name, start_time, end_time,
|
||||||
id_name_maps=None, field_custom_names=None):
|
id_name_maps=None, field_custom_names=None, has_supplement=False):
|
||||||
"""
|
"""
|
||||||
生成Excel文件
|
生成Excel文件
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
id_name_maps: ID到名称的映射字典,格式为 {field_name: {id_value: name_value}}
|
id_name_maps: ID到名称的映射字典,格式为 {field_name: {id_value: name_value}}
|
||||||
field_custom_names: 字段自定义名头字典,格式为 {field_key: custom_name}
|
field_custom_names: 字段自定义名头字典,格式为 {field_key: custom_name}
|
||||||
|
has_supplement: 是否有补单记录
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str: 文件路径
|
str: 文件路径
|
||||||
@@ -547,9 +557,17 @@ def generate_excel(orders, selected_fields, sum_fields, sum_results,
|
|||||||
reports_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'public', 'reports')
|
reports_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'public', 'reports')
|
||||||
os.makedirs(reports_dir, exist_ok=True)
|
os.makedirs(reports_dir, exist_ok=True)
|
||||||
|
|
||||||
# 生成文件名
|
# 生成文件名 - 格式:配置名称_几月几日消费记录.xlsx
|
||||||
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
# 从 end_time 提取日期(格式:2026-07-13 08:00:00)
|
||||||
filename = f'daily_report_{config_name}_{split_name}_{timestamp}.xlsx'
|
try:
|
||||||
|
end_dt = datetime.strptime(end_time, '%Y-%m-%d %H:%M:%S')
|
||||||
|
date_str = f'{end_dt.month}月{end_dt.day}日'
|
||||||
|
except:
|
||||||
|
date_str = datetime.now().strftime('%m月%d日')
|
||||||
|
|
||||||
|
# 如果有补单,添加标记
|
||||||
|
supplement_suffix = '_有补单' if has_supplement else ''
|
||||||
|
filename = f'{config_name}_{date_str}消费记录{supplement_suffix}.xlsx'
|
||||||
file_path = os.path.join(reports_dir, filename)
|
file_path = os.path.join(reports_dir, filename)
|
||||||
|
|
||||||
# 创建工作簿
|
# 创建工作簿
|
||||||
|
|||||||
@@ -351,6 +351,27 @@
|
|||||||
border: 1px solid #bee5eb;
|
border: 1px solid #bee5eb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.checkbox-item.required-field {
|
||||||
|
background: #fff3cd;
|
||||||
|
border: 1px solid #ffc107;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-item.required-field:hover {
|
||||||
|
background: #fff3cd;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.required-badge {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 2px 6px;
|
||||||
|
background: #ffc107;
|
||||||
|
color: #000;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.checkbox-item input[type="checkbox"] {
|
.checkbox-item input[type="checkbox"] {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
@@ -1177,14 +1198,19 @@
|
|||||||
const fieldsList = document.getElementById('fields-list');
|
const fieldsList = document.getElementById('fields-list');
|
||||||
const sumFieldsList = document.getElementById('sum-fields-list');
|
const sumFieldsList = document.getElementById('sum-fields-list');
|
||||||
|
|
||||||
fieldsList.innerHTML = allFields.map(field => `
|
fieldsList.innerHTML = allFields.map(field => {
|
||||||
<div class="checkbox-item ${selectedFields.includes(field.key) ? 'checked' : ''}" onclick="toggleCheckboxItem(this)">
|
const isSelected = selectedFields.includes(field.key);
|
||||||
<input type="checkbox" value="${field.key}"
|
const isRequired = field.key === 'charge_degree'; // 充电量为必选字段
|
||||||
${selectedFields.includes(field.key) ? 'checked' : ''}
|
return `
|
||||||
onchange="onFieldCheckboxChange(this)">
|
<div class="checkbox-item ${isSelected ? 'checked' : ''} ${isRequired ? 'required-field' : ''}" onclick="${isRequired ? '' : 'toggleCheckboxItem(this)'}">
|
||||||
<label>${field.display}</label>
|
<input type="checkbox" value="${field.key}"
|
||||||
</div>
|
${isSelected ? 'checked' : ''}
|
||||||
`).join('');
|
${isRequired ? 'disabled checked' : ''}
|
||||||
|
onchange="onFieldCheckboxChange(this)">
|
||||||
|
<label>${field.display}${isRequired ? ' <span class="required-badge">必选</span>' : ''}</label>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}).join('');
|
||||||
|
|
||||||
// 初始化求和字段列表(只显示已选字段中的可求和字段)
|
// 初始化求和字段列表(只显示已选字段中的可求和字段)
|
||||||
refreshSumFieldsList(selectedFields, sumFields);
|
refreshSumFieldsList(selectedFields, sumFields);
|
||||||
@@ -1201,6 +1227,12 @@
|
|||||||
|
|
||||||
// 字段 checkbox 变化时更新求和字段列表和已选字段顺序
|
// 字段 checkbox 变化时更新求和字段列表和已选字段顺序
|
||||||
function onFieldCheckboxChange(cb) {
|
function onFieldCheckboxChange(cb) {
|
||||||
|
// 防止取消选择必选字段(充电量)
|
||||||
|
if (cb.value === 'charge_degree' && !cb.checked) {
|
||||||
|
cb.checked = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const item = cb.closest('.checkbox-item');
|
const item = cb.closest('.checkbox-item');
|
||||||
if (item) item.classList.toggle('checked', cb.checked);
|
if (item) item.classList.toggle('checked', cb.checked);
|
||||||
|
|
||||||
@@ -1651,6 +1683,11 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 确保充电量为必选字段
|
||||||
|
if (!selectedFields.includes('charge_degree')) {
|
||||||
|
selectedFields.push('charge_degree');
|
||||||
|
}
|
||||||
|
|
||||||
// 验证合并特来电配置
|
// 验证合并特来电配置
|
||||||
if (mergeTelecom && splitType !== 'company_id') {
|
if (mergeTelecom && splitType !== 'company_id') {
|
||||||
alert('合并特来电数据仅支持按企业拆分');
|
alert('合并特来电数据仅支持按企业拆分');
|
||||||
|
|||||||
Reference in New Issue
Block a user