chore: curate monthly assessment evidence and scripts
This commit is contained in:
@@ -0,0 +1,258 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
用本地GPS数据(G7日里程 + 东方北斗月里程)替换125辆测试车辆的实际行驶里程。
|
||||
测试里程 = TBOX - GPS(负数为0)。
|
||||
"""
|
||||
import openpyxl, os, shutil, xlrd
|
||||
from datetime import datetime, date, timedelta
|
||||
from openpyxl.styles import PatternFill, Font, Alignment, Border, Side
|
||||
from openpyxl.utils import get_column_letter
|
||||
|
||||
os.chdir('/Users/kkfluous/Downloads')
|
||||
|
||||
SRC = '租赁任务考核_2026年6月 (1).xlsx'
|
||||
DST = '租赁任务考核_2026年6月.xlsx'
|
||||
GPS_DIR = 'gps里程汇总2026年1-6月 3'
|
||||
|
||||
# ========== 读取125辆测试车辆清单 ==========
|
||||
TEST_FILE = '/Users/kkfluous/Library/Containers/com.tencent.xinWeChat/Data/Documents/xwechat_files/wxid_1704407055112_3af8/temp/RWTemp/2026-07/65b41c10aa83cabb7a365b2b8437c1c7/6月测试车辆.xlsx'
|
||||
wb_test = openpyxl.load_workbook(TEST_FILE, data_only=True)
|
||||
ws_test = wb_test.active
|
||||
TEST_PLATES = set()
|
||||
for row in ws_test.iter_rows(min_row=2, values_only=True):
|
||||
for ci in range(len(row)):
|
||||
p = str(row[ci]).strip() if row[ci] else ''
|
||||
if p and p != 'None' and len(p) >= 7:
|
||||
TEST_PLATES.add(p)
|
||||
wb_test.close()
|
||||
print(f"测试车辆清单: {len(TEST_PLATES)}辆")
|
||||
|
||||
# ========== Step 1: 加载G7 GPS日里程 ==========
|
||||
print("\n加载G7 GPS日里程...")
|
||||
g7_wb = openpyxl.load_workbook(f'{GPS_DIR}/G7/202606_G7.xlsx')
|
||||
g7_ws = g7_wb.active
|
||||
gps_daily = {} # plate -> [day1, day2, ..., day30]
|
||||
for row in g7_ws.iter_rows(min_row=2, values_only=True):
|
||||
plate = str(row[0]).strip() if row[0] else ''
|
||||
if not plate or plate not in TEST_PLATES:
|
||||
continue
|
||||
daily = [float(row[c]) if row[c] else 0 for c in range(3, 33)]
|
||||
gps_daily[plate] = daily
|
||||
g7_wb.close()
|
||||
print(f"G7覆盖: {len(gps_daily)}辆测试车")
|
||||
|
||||
# ========== Step 2: 加载东方北斗GPS月里程 ==========
|
||||
print("加载东方北斗GPS月里程...")
|
||||
df_wb = openpyxl.load_workbook(f'{GPS_DIR}/东方北斗/202606_东方北斗.xlsx')
|
||||
df_ws = df_wb.active
|
||||
gps_monthly = {} # plate -> monthly_total_km
|
||||
for row in df_ws.iter_rows(min_row=4, values_only=True):
|
||||
plate = str(row[5]).strip() if row[5] else ''
|
||||
if not plate or plate not in TEST_PLATES:
|
||||
continue
|
||||
monthly = float(row[10]) if row[10] else 0
|
||||
gps_monthly[plate] = monthly
|
||||
df_wb.close()
|
||||
print(f"东方北斗覆盖: {len(gps_monthly)}辆测试车")
|
||||
|
||||
# ========== Step 3: 读取源文件,执行GPS替换 ==========
|
||||
print("\n执行GPS替换...")
|
||||
|
||||
# 备份
|
||||
BAK = '租赁任务考核_2026年6月_备份_0715.xlsx'
|
||||
if os.path.exists(DST):
|
||||
shutil.copy2(DST, BAK)
|
||||
|
||||
shutil.copy2(SRC, DST)
|
||||
|
||||
wb = openpyxl.load_workbook(DST)
|
||||
ws = wb['业务考核视图']
|
||||
h = [c.value for c in next(ws.iter_rows(min_row=1, max_row=1))]
|
||||
print(f"源文件: {ws.max_row}行, {len(h)}列")
|
||||
|
||||
# 读取所有记录
|
||||
recs = []
|
||||
for row in ws.iter_rows(min_row=2, values_only=True):
|
||||
r = dict(zip(h, row))
|
||||
r['row_num'] = len(recs) + 2
|
||||
recs.append(r)
|
||||
|
||||
test_recs = [r for r in recs if r['车牌号'] in TEST_PLATES]
|
||||
print(f"测试车辆记录: {len(test_recs)}条 ({len(set(r['车牌号'] for r in test_recs))}辆)")
|
||||
|
||||
# 添加列
|
||||
if '原TBOX里程(km)' not in h:
|
||||
tbox_new_col = ws.max_column + 1
|
||||
test_new_col = ws.max_column + 2
|
||||
ws.cell(row=1, column=tbox_new_col, value='原TBOX里程(km)')
|
||||
ws.cell(row=1, column=test_new_col, value='测试里程(km)')
|
||||
h_new = [c.value for c in next(ws.iter_rows(min_row=1, max_row=1))]
|
||||
else:
|
||||
h_new = h
|
||||
|
||||
actual_idx = h_new.index('实际行驶里程(km)') + 1
|
||||
tbox_idx = h_new.index('原TBOX里程(km)') + 1
|
||||
test_idx = h_new.index('测试里程(km)') + 1
|
||||
rate_idx = h_new.index('完成率(%)') + 1
|
||||
qualified_idx = h_new.index('是否达标') + 1
|
||||
|
||||
yellow_fill = PatternFill(start_color='FFFF00', end_color='FFFF00', fill_type='solid')
|
||||
|
||||
replaced_g7 = 0
|
||||
replaced_df = 0
|
||||
no_gps = 0
|
||||
total_test_km = 0
|
||||
total_gps_km = 0
|
||||
total_tbox_km = 0
|
||||
|
||||
for r in test_recs:
|
||||
plate = r['车牌号']
|
||||
rn = r['row_num']
|
||||
|
||||
# 获取考核区间
|
||||
start_date = r.get('考核开始日期')
|
||||
end_date = r.get('考核结束日期')
|
||||
|
||||
gps_total = None
|
||||
source = None
|
||||
|
||||
# 优先用G7日数据
|
||||
if plate in gps_daily:
|
||||
daily = gps_daily[plate]
|
||||
try:
|
||||
sd = start_date.date() if hasattr(start_date, 'date') else datetime.strptime(str(start_date)[:10], '%Y-%m-%d').date()
|
||||
ed = end_date.date() if hasattr(end_date, 'date') else datetime.strptime(str(end_date)[:10], '%Y-%m-%d').date()
|
||||
except:
|
||||
sd = date(2026, 6, 1)
|
||||
ed = date(2026, 6, 30)
|
||||
|
||||
gps_total = 0
|
||||
for day_offset in range(30):
|
||||
day = date(2026, 6, 1) + timedelta(days=day_offset)
|
||||
if sd <= day <= ed:
|
||||
gps_total += daily[day_offset]
|
||||
gps_total = round(gps_total, 1)
|
||||
source = 'G7'
|
||||
replaced_g7 += 1
|
||||
|
||||
# 其次用东方北斗月里程
|
||||
elif plate in gps_monthly:
|
||||
# 东方北斗只有月度合计,考核区间一般都是整月
|
||||
gps_total = gps_monthly[plate]
|
||||
source = '东方北斗'
|
||||
replaced_df += 1
|
||||
|
||||
if gps_total is None:
|
||||
no_gps += 1
|
||||
continue
|
||||
|
||||
# 原TBOX里程 = 当前实际行驶里程
|
||||
tbox_val = float(ws.cell(row=rn, column=actual_idx).value or 0)
|
||||
|
||||
# 测试里程 = TBOX - GPS(负数为0)
|
||||
test_km = max(0, round(tbox_val - gps_total, 1))
|
||||
|
||||
# 写入
|
||||
ws.cell(row=rn, column=tbox_idx, value=tbox_val)
|
||||
ws.cell(row=rn, column=test_idx, value=test_km)
|
||||
ws.cell(row=rn, column=actual_idx, value=gps_total)
|
||||
|
||||
# 标记黄色
|
||||
for c in range(1, ws.max_column + 1):
|
||||
ws.cell(row=rn, column=c).fill = yellow_fill
|
||||
|
||||
# 重算完成率
|
||||
target = float(r.get('应考核里程(km)') or 0)
|
||||
pct = round(gps_total / target * 100, 2) if target > 0 else 0
|
||||
qualified = '达标' if gps_total >= target and target > 0 else '未达标'
|
||||
ws.cell(row=rn, column=rate_idx, value=pct)
|
||||
ws.cell(row=rn, column=qualified_idx, value=qualified)
|
||||
|
||||
total_test_km += test_km
|
||||
total_gps_km += gps_total
|
||||
total_tbox_km += tbox_val
|
||||
|
||||
print(f"\n替换统计:")
|
||||
print(f" G7日数据: {replaced_g7}条")
|
||||
print(f" 东方北斗月数据: {replaced_df}条")
|
||||
print(f" 无GPS数据: {no_gps}条")
|
||||
print(f" TBOX总里程: {total_tbox_km:.1f}")
|
||||
print(f" GPS总里程: {total_gps_km:.1f}")
|
||||
print(f" 测试总里程: {total_test_km:.1f}")
|
||||
|
||||
# ========== Step 4: TBOX回填(非测试车辆) ==========
|
||||
print("\nTBOX回填(非测试车辆)...")
|
||||
filled = 0
|
||||
for row_idx in range(2, ws.max_row + 1):
|
||||
tbox_val = ws.cell(row=row_idx, column=tbox_idx).value
|
||||
actual_val = ws.cell(row=row_idx, column=actual_idx).value
|
||||
test_val = ws.cell(row=row_idx, column=test_idx).value
|
||||
if (tbox_val is None or float(tbox_val) == 0):
|
||||
if test_val is None or float(test_val) == 0:
|
||||
ws.cell(row=row_idx, column=tbox_idx, value=float(actual_val) if actual_val else 0)
|
||||
filled += 1
|
||||
print(f"TBOX回填: {filled}条")
|
||||
|
||||
# ========== Step 5: 列序排版 ==========
|
||||
print("\n列序排版...")
|
||||
target_order = [
|
||||
'车牌号', '考核年份', '考核月份', '部门名称', '销售经理', '客户名称',
|
||||
'合同编号', '项目名称', '考核目标ID', '考核目标', '考核开始日期', '考核结束日期',
|
||||
'考核天数', '应考核里程(km)', '原TBOX里程(km)', '实际行驶里程(km)', '测试里程(km)',
|
||||
'完成率(%)', '是否达标', '考核状态', '交车日期', '预计还车日期', '实际还车日期'
|
||||
]
|
||||
|
||||
h_cur = [c.value for c in next(ws.iter_rows(min_row=1, max_row=1))]
|
||||
all_rows = []
|
||||
for row_idx in range(1, ws.max_row + 1):
|
||||
row_data = {}
|
||||
for c in range(1, ws.max_column + 1):
|
||||
row_data[h_cur[c-1]] = ws.cell(row=row_idx, column=c).value
|
||||
all_rows.append(row_data)
|
||||
|
||||
# Clear
|
||||
for r in range(1, ws.max_row + 1):
|
||||
for c in range(1, ws.max_column + 1):
|
||||
ws.cell(row=r, column=c, value=None)
|
||||
|
||||
thin_border = Border(left=Side(style='thin'), right=Side(style='thin'),
|
||||
top=Side(style='thin'), bottom=Side(style='thin'))
|
||||
header_fill = PatternFill(start_color='4472C4', end_color='4472C4', fill_type='solid')
|
||||
header_font = Font(name='宋体', size=10, bold=True, color='FFFFFF')
|
||||
data_font = Font(name='宋体', size=10)
|
||||
|
||||
for i, col_name in enumerate(target_order):
|
||||
c = i + 1
|
||||
cell = ws.cell(row=1, column=c, value=col_name)
|
||||
cell.font = header_font
|
||||
cell.fill = header_fill
|
||||
cell.alignment = Alignment(horizontal='center', vertical='center')
|
||||
cell.border = thin_border
|
||||
|
||||
for row_idx, row_data in enumerate(all_rows[1:], start=2):
|
||||
for i, col_name in enumerate(target_order):
|
||||
c = i + 1
|
||||
val = row_data.get(col_name)
|
||||
cell = ws.cell(row=row_idx, column=c, value=val)
|
||||
cell.font = data_font
|
||||
cell.alignment = Alignment(vertical='center')
|
||||
cell.border = thin_border
|
||||
if col_name in ['考核开始日期', '考核结束日期', '交车日期', '预计还车日期', '实际还车日期']:
|
||||
cell.number_format = 'yyyy-mm-dd h:mm:ss'
|
||||
if row_data.get('测试里程(km)') and float(row_data.get('测试里程(km)', 0) or 0) != 0:
|
||||
cell.fill = yellow_fill
|
||||
|
||||
for i in range(len(target_order)):
|
||||
ws.column_dimensions[get_column_letter(i+1)].width = 15
|
||||
|
||||
wb.save(DST)
|
||||
wb.close()
|
||||
|
||||
print(f"列序排版: {len(target_order)}列")
|
||||
print(f"\n{'='*60}")
|
||||
print(f"GPS替换完成!")
|
||||
print(f"测试车辆: {len(TEST_PLATES)}辆 -> 源数据{len(test_recs)}条记录")
|
||||
print(f"GPS来源: G7({replaced_g7}条) + 东方北斗({replaced_df}条)")
|
||||
print(f"测试总里程: {total_test_km:.1f} km")
|
||||
print(f"已保存: {DST}")
|
||||
print(f"{'='*60}")
|
||||
Reference in New Issue
Block a user