chore: curate monthly assessment evidence and scripts
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
from ast import parse, walk, Call, Constant, keyword
|
||||
from collections import defaultdict
|
||||
from datetime import datetime, date
|
||||
from pathlib import Path
|
||||
import re
|
||||
import shutil
|
||||
|
||||
import openpyxl
|
||||
import pymysql
|
||||
|
||||
|
||||
OUTPUT = Path('/Users/kkfluous/Downloads/7月核算结果/7月考核车辆多源里程汇总.xlsx')
|
||||
BACKUP = Path('/Users/kkfluous/Downloads/7月核算结果/7月考核车辆多源里程汇总_GPS全量回补前.xlsx')
|
||||
|
||||
|
||||
def norm(value):
|
||||
return re.sub(r'\s+', '', str(value or '')).upper()
|
||||
|
||||
|
||||
def db_config():
|
||||
tree = parse(Path('/Users/kkfluous/Downloads/replace_gps_jun.py').read_text())
|
||||
for node in walk(tree):
|
||||
if not isinstance(node, Call) or getattr(node.func, 'attr', None) != 'connect':
|
||||
continue
|
||||
values = {}
|
||||
for item in node.keywords:
|
||||
if isinstance(item, keyword) and isinstance(item.value, Constant):
|
||||
values[item.arg] = item.value.value
|
||||
if {'host', 'user', 'password', 'database'} <= values.keys():
|
||||
return values
|
||||
raise RuntimeError('未找到既有GPS数据库配置')
|
||||
|
||||
|
||||
wb = openpyxl.load_workbook(OUTPUT)
|
||||
ws = wb.active
|
||||
header_row = next(r for r in range(1, 8) if ws.cell(r, 12).value == 'GPS里程(km)')
|
||||
data_start = header_row + 1
|
||||
plates = sorted({norm(ws.cell(r, 2).value) for r in range(data_start, ws.max_row + 1) if ws.cell(r, 2).value})
|
||||
|
||||
cfg = db_config()
|
||||
cfg.update(charset='utf8mb4', connect_timeout=8, read_timeout=30, write_timeout=30)
|
||||
conn = pymysql.connect(**cfg)
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
placeholders = ','.join(['%s'] * len(plates))
|
||||
cur.execute(
|
||||
f'''SELECT plate_number, dates, total_mileage
|
||||
FROM ln_vehicle_g7_mileage
|
||||
WHERE dates >= %s AND dates <= %s
|
||||
AND plate_number IN ({placeholders})''',
|
||||
[date(2026, 7, 1), date(2026, 7, 31), *plates],
|
||||
)
|
||||
db_rows = cur.fetchall()
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
daily = defaultdict(dict)
|
||||
for plate, day, raw_mileage in db_rows:
|
||||
if isinstance(day, datetime):
|
||||
day = day.date()
|
||||
daily[norm(plate)][day] = float(raw_mileage or 0) / 100000.0
|
||||
|
||||
if not BACKUP.exists():
|
||||
shutil.copy2(OUTPUT, BACKUP)
|
||||
|
||||
filled = []
|
||||
still_missing = []
|
||||
for row in range(data_start, ws.max_row + 1):
|
||||
cell = ws.cell(row, 12)
|
||||
if cell.value != '无来源':
|
||||
continue
|
||||
plate = norm(ws.cell(row, 2).value)
|
||||
start = ws.cell(row, 4).value
|
||||
end = ws.cell(row, 5).value
|
||||
if isinstance(start, datetime):
|
||||
start = start.date()
|
||||
if isinstance(end, datetime):
|
||||
end = end.date()
|
||||
matched = [value for day, value in daily.get(plate, {}).items() if start <= day <= end]
|
||||
if matched:
|
||||
cell.value = round(sum(matched), 2)
|
||||
cell.number_format = '#,##0.0'
|
||||
filled.append((plate, start, end, cell.value))
|
||||
else:
|
||||
still_missing.append((plate, start, end))
|
||||
|
||||
ws['A1'] = (
|
||||
'1. 纯氢里程(km)、纯电里程(km)来源于广州平台统计,TBOX里程来源于车机上报的仪表盘里程统计,'
|
||||
'GPS里程优先使用两份7月GPS日明细,缺失车辆由GPS数据库每日里程按考核区间回补;测试车辆以7月最终考核源表已确认GPS为准\n'
|
||||
'2. 广州平台总里程(km)=纯氢里程(km)+纯电里程(km)\n'
|
||||
'3. 已确认广州平台暂未接入86辆普货车数据;所有GPS来源均无对应记录时标记为“无来源”'
|
||||
)
|
||||
wb.save(OUTPUT)
|
||||
|
||||
print({
|
||||
'database_rows': len(db_rows),
|
||||
'database_plates': len(daily),
|
||||
'backfilled_records': len(filled),
|
||||
'remaining_missing_records': len(still_missing),
|
||||
'remaining_missing_plates': len({x[0] for x in still_missing}),
|
||||
})
|
||||
Reference in New Issue
Block a user