增加尖峰平谷找平功能,修改消息提示

This commit is contained in:
2026-08-02 10:50:38 +08:00
parent 17b7cd27b9
commit c5fcda3511
10 changed files with 433 additions and 95 deletions

View File

@@ -60,6 +60,13 @@ def create_config():
show_custom_service_fee = 1 if data.get('show_custom_service_fee') else 0
show_total_amount = 1 if data.get('show_total_amount') else 0
total_amount_name = data.get('total_amount_name')
# 找平电量开关默认开启1=开启0=关闭)
# 当数据中的'未在前端传递时默认为1开启保持与历史配置的兼容性
balance_electricity = data.get('balance_electricity')
if balance_electricity is None:
balance_electricity = 1
else:
balance_electricity = 1 if balance_electricity else 0
if not config_name or not split_type or not split_value:
log_warning('[配置API] 创建配置失败:缺少必填字段', 'api')
@@ -81,9 +88,9 @@ def create_config():
(id, config_name, split_type, split_value, split_name, selected_fields,
sum_fields, time_periods, merge_telecom, telecom_vehicle_no, field_custom_names,
show_monthly_total, custom_service_fee_price, custom_service_fee_name,
show_custom_service_fee, show_total_amount, total_amount_name,
show_custom_service_fee, show_total_amount, total_amount_name, balance_electricity,
is_active, sort_order, create_time, update_time)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 1, %s, NOW(), NOW())
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 1, %s, NOW(), NOW())
"""
params = (
@@ -104,6 +111,7 @@ def create_config():
show_custom_service_fee,
show_total_amount,
total_amount_name if total_amount_name else None,
balance_electricity,
sort_order
)
@@ -148,6 +156,12 @@ def update_config(config_id):
show_custom_service_fee = 1 if data.get('show_custom_service_fee') else 0
show_total_amount = 1 if data.get('show_total_amount') else 0
total_amount_name = data.get('total_amount_name')
# 找平电量开关默认开启1=开启0=关闭)
balance_electricity = data.get('balance_electricity')
if balance_electricity is None:
balance_electricity = 1
else:
balance_electricity = 1 if balance_electricity else 0
# 查询原配置,检查拆分是否变化
old_configs = execute_query('SELECT * FROM t_daily_report_config WHERE id = %s', (config_id,))
@@ -162,6 +176,7 @@ def update_config(config_id):
merge_telecom = %s, telecom_vehicle_no = %s, field_custom_names = %s,
show_monthly_total = %s, custom_service_fee_price = %s, custom_service_fee_name = %s,
show_custom_service_fee = %s, show_total_amount = %s, total_amount_name = %s,
balance_electricity = %s,
update_time = NOW()
WHERE id = %s
"""
@@ -183,6 +198,7 @@ def update_config(config_id):
show_custom_service_fee,
show_total_amount,
total_amount_name if total_amount_name else None,
balance_electricity,
config_id
)
@@ -257,8 +273,8 @@ def copy_config(config_id):
# 插入新配置
execute_insert(
'''INSERT INTO t_daily_report_config
(id, config_name, split_type, split_value, split_name, selected_fields, sum_fields, time_periods, merge_telecom, telecom_vehicle_no, field_custom_names, show_monthly_total, custom_service_fee_price, custom_service_fee_name, show_custom_service_fee, show_total_amount, total_amount_name, is_active, sort_order, create_time, update_time)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW(), NOW())''',
(id, config_name, split_type, split_value, split_name, selected_fields, sum_fields, time_periods, merge_telecom, telecom_vehicle_no, field_custom_names, show_monthly_total, custom_service_fee_price, custom_service_fee_name, show_custom_service_fee, show_total_amount, total_amount_name, balance_electricity, is_active, sort_order, create_time, update_time)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW(), NOW())''',
(
new_id,
new_name,
@@ -277,6 +293,8 @@ def copy_config(config_id):
original.get('show_custom_service_fee', 0),
original.get('show_total_amount', 0),
original.get('total_amount_name'),
# 找平电量复制原配置的设置若原配置无此字段NULL则默认开启(1)
original.get('balance_electricity') if original.get('balance_electricity') is not None else 1,
original['is_active'],
sort_order
)

View File

@@ -182,6 +182,15 @@ def init_database_tables():
"total_amount_name VARCHAR(100) NULL COMMENT '实收金额报表表头名称'",
'total_amount_name'
)
# 给配置表增加 balance_electricity 字段(是否找平电量)
# 当尖+峰+平+谷之和不等于充电电量时,以充电电量为准进行找平
# 找平顺序:谷 → 平 → 峰 → 尖(加到第一个有值的时段上)
_add_column_if_not_exists(
't_daily_report_config',
"balance_electricity TINYINT NULL DEFAULT 1 COMMENT '是否找平电量(0=否,1=是)'",
'balance_electricity'
)
# 创建全局配置表
create_global_config_table = """

View File

@@ -285,6 +285,70 @@ def calculate_time_period_electricity(orders, time_periods_config):
return result
def balance_time_period_electricity(orders):
"""
找平分时段电量
正常情况下:充电电量(charge_degree) = 尖电量 + 峰电量 + 平电量 + 谷电量
但平台导出数据时,四者之和可能不等于充电电量。
本函数以充电电量(charge_degree)为准,将差额加到对应时段上。
找平原则(按优先级顺序):
1. 有谷电量(>0) → 差额加到谷上
2. 没谷有平电量(>0) → 差额加到平上
3. 没平有峰电量(>0) → 差额加到峰上
4. 都没有 → 差额加到尖上
Args:
orders: 订单数据列表(会原地修改 sharp/peak/flat/valley_electricity 字段)
Returns:
int: 实际找平的订单数
"""
balanced_count = 0
for order in orders:
# 获取充电电量(作为基准)
charge_degree = order.get('charge_degree')
if charge_degree is None or charge_degree == '':
continue
try:
charge_degree = float(charge_degree)
except (ValueError, TypeError):
continue
# 获取各时段电量
sharp = float(order.get('sharp_electricity', 0) or 0)
peak = float(order.get('peak_electricity', 0) or 0)
flat = float(order.get('flat_electricity', 0) or 0)
valley = float(order.get('valley_electricity', 0) or 0)
# 计算四时段之和
period_sum = round(sharp + peak + flat + valley, 3)
# 计算差额
diff = round(charge_degree - period_sum, 3)
# 如果差额为0不需要找平
if abs(diff) < 0.001:
continue
# 按优先级找平:谷 → 平 → 峰 → 尖
if valley > 0:
order['valley_electricity'] = round(valley + diff, 3)
elif flat > 0:
order['flat_electricity'] = round(flat + diff, 3)
elif peak > 0:
order['peak_electricity'] = round(peak + diff, 3)
else:
order['sharp_electricity'] = round(sharp + diff, 3)
balanced_count += 1
return balanced_count
def get_beijing_time():
"""获取北京时间"""
beijing_tz = pytz.timezone('Asia/Shanghai')
@@ -592,6 +656,19 @@ def generate_daily_report(config_id, start_time=None, end_time=None):
log_info(f"[日报生成] 已计算 {len(time_period_electricity)} 条订单的分时段电量", 'report')
# 找平分时段电量
# 当配置开启了找平电量功能时,以充电电量(charge_degree)为准,
# 将尖+峰+平+谷之和与充电电量的差额,按 谷→平→峰→尖 的优先级加到对应时段上
balance_electricity_enabled = config.get('balance_electricity')
# 兼容历史配置NULL 或未设置时默认开启
if balance_electricity_enabled is None:
balance_electricity_enabled = 1
if balance_electricity_enabled == 1:
balanced_count = balance_time_period_electricity(orders)
if balanced_count > 0:
log_info(f"[日报生成] 找平电量:共处理 {balanced_count} 条订单的分时段电量差额", 'report')
# 计算虚拟字段(自定义服务费、自定义实收总金额)并添加到订单数据中
# 这样求和数据才能正确计算这些字段的总和
has_custom_service_fee = config.get('custom_service_fee_price') is not None and str(config.get('custom_service_fee_price', '')).strip() != ''