Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c43c00e73 | ||
|
|
f2de5d5500 | ||
|
|
54ecbc352f | ||
|
|
cdc4cec2ff | ||
|
|
8c2f4e73dd | ||
|
|
e47cc00b3d |
@@ -169,6 +169,16 @@ def collect_vehicle_payments(G, feb_data, mar_data):
|
|||||||
for i, r in enumerate(records): r['期数'] = i + 1
|
for i, r in enumerate(records): r['期数'] = i + 1
|
||||||
return payments, info
|
return payments, info
|
||||||
|
|
||||||
|
# (归属公司+车型) → 考核目标 映射,用于补全无考核记录的车辆
|
||||||
|
VEHICLE_TARGET_MAP = {
|
||||||
|
('广州开发区交投氢能运营管理有限公司', '4.5吨冷链车'): ('交投190辆4.5T冷链车', 3000, 150),
|
||||||
|
('广州开发区交投氢能运营管理有限公司', '4.5吨货车'): ('交投40辆4.5T普货', 3000, 150),
|
||||||
|
('羚牛氢能科技(广东)有限公司', '4.5吨冷链车'): ('羚牛136辆4.5T冷链车', 5000, 260),
|
||||||
|
('羚牛氢能科技(广东)有限公司', '18吨双飞翼货车'): ('羚牛100辆18T', 6000, 1000),
|
||||||
|
('现代氢能科技(广州)有限公司', '4.5吨货车'): ('恒运50辆4.5T普货', 5000, 260),
|
||||||
|
('现代氢能科技(广州)有限公司', '4.5吨货车'): ('恒运50辆4.5T普货', 5000, 260),
|
||||||
|
}
|
||||||
|
|
||||||
def read_master_vehicles(fp='里程任务考核_Q1汇总.xlsx'):
|
def read_master_vehicles(fp='里程任务考核_Q1汇总.xlsx'):
|
||||||
"""从现有Q1汇总文件读取全量车辆台账"""
|
"""从现有Q1汇总文件读取全量车辆台账"""
|
||||||
wb = openpyxl.load_workbook(fp, data_only=True)
|
wb = openpyxl.load_workbook(fp, data_only=True)
|
||||||
|
|||||||
144
excel_writer.py
144
excel_writer.py
@@ -186,7 +186,8 @@ def write_summary_month(wb, month, month_data, section_names):
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
def write_salesperson_sheet(wb, person, dept, settle_month, D, G, month_data, vehicle_payments):
|
def write_salesperson_sheet(wb, person, dept, settle_month, D, G, month_data, vehicle_payments):
|
||||||
ws = wb.create_sheet(f'业务员_{person}')
|
short_dept = dept.replace('业务','') if '业务' in dept else dept
|
||||||
|
ws = wb.create_sheet(f'{short_dept}-{person}')
|
||||||
ws.cell(row=1,column=1,value=f'{person} | {dept} | {settle_month}月绩效对账单').font=Font(bold=True,size=14)
|
ws.cell(row=1,column=1,value=f'{person} | {dept} | {settle_month}月绩效对账单').font=Font(bold=True,size=14)
|
||||||
|
|
||||||
plates = set()
|
plates = set()
|
||||||
@@ -340,46 +341,145 @@ def write_salesperson_sheet(wb, person, dept, settle_month, D, G, month_data, ve
|
|||||||
|
|
||||||
def write_vehicle_tracking_sheet(wb, settle_month, G, master_vehicles, vehicle_payments, vehicle_info):
|
def write_vehicle_tracking_sheet(wb, settle_month, G, master_vehicles, vehicle_payments, vehicle_info):
|
||||||
ws = wb.create_sheet('车辆考核追踪')
|
ws = wb.create_sheet('车辆考核追踪')
|
||||||
headers = ['车牌号','车架号','归属公司','车型','考核目标','月度奖励金额']
|
from calc_engine import VEHICLE_TARGET_MAP
|
||||||
|
|
||||||
|
wrap_top = Alignment(wrap_text=True, vertical='top')
|
||||||
|
center_top = Alignment(horizontal='center', vertical='top')
|
||||||
|
# 颜色
|
||||||
|
green_font = Font(color='006100')
|
||||||
|
green_fill = PatternFill(start_color='C6EFCE', end_color='C6EFCE', fill_type='solid')
|
||||||
|
red_font = Font(color='9C0006')
|
||||||
|
red_fill = PatternFill(start_color='FFC7CE', end_color='FFC7CE', fill_type='solid')
|
||||||
|
grey_fill = PatternFill(start_color='F2F2F2', end_color='F2F2F2', fill_type='solid')
|
||||||
|
blue_fill = PatternFill(start_color='DAEEF3', end_color='DAEEF3', fill_type='solid')
|
||||||
|
gold_fill = PatternFill(start_color='FFF2CC', end_color='FFF2CC', fill_type='solid')
|
||||||
|
|
||||||
|
# 表头
|
||||||
|
headers = ['车牌号','车架号','归属公司','车型','考核目标','月度奖励']
|
||||||
|
month_start_col = len(headers) # 月度考核开始列(0-indexed)
|
||||||
for m in range(1, settle_month+1):
|
for m in range(1, settle_month+1):
|
||||||
headers += [f'{m}月业务员',f'{m}月应考核',f'{m}月实际',f'{m}月达标']
|
headers.append(f'{m}月考核明细')
|
||||||
|
cum_start_col = len(headers)
|
||||||
if settle_month >= 2:
|
if settle_month >= 2:
|
||||||
headers += ['累计应完成','累计实际','累计达标']
|
headers += ['累计里程/目标','累计达标']
|
||||||
headers += ['本月发放金额','发放给谁','发放类型','累计已发期数','累计已发金额','剩余可发期数']
|
pay_start_col = len(headers)
|
||||||
|
headers += ['本月发放明细','已发期数','已发金额','剩余期数']
|
||||||
WH(ws, headers)
|
WH(ws, headers)
|
||||||
|
|
||||||
|
# 冻结首行+首列
|
||||||
|
ws.freeze_panes = 'B2'
|
||||||
|
|
||||||
rn=2
|
rn=2
|
||||||
for mv in master_vehicles:
|
for mv in master_vehicles:
|
||||||
plate=mv['车牌号']
|
plate=mv['车牌号']
|
||||||
info=vehicle_info.get(plate, {})
|
info=vehicle_info.get(plate, {})
|
||||||
pays=vehicle_payments.get(plate, [])
|
pays=vehicle_payments.get(plate, [])
|
||||||
|
|
||||||
|
target_name = info.get('考核目标','')
|
||||||
|
monthly_bonus = info.get('月度奖励',0)
|
||||||
|
if not target_name:
|
||||||
|
company = mv.get('归属公司','')
|
||||||
|
vtype = mv.get('车型确定','')
|
||||||
|
mapped = VEHICLE_TARGET_MAP.get((company, vtype))
|
||||||
|
if mapped:
|
||||||
|
target_name, _, monthly_bonus = mapped
|
||||||
|
|
||||||
row=[plate,mv.get('车架号',''),mv.get('归属公司',''),mv.get('车型确定',''),
|
row=[plate,mv.get('车架号',''),mv.get('归属公司',''),mv.get('车型确定',''),
|
||||||
info.get('考核目标',''),info.get('月度奖励',0) or '']
|
target_name or '',monthly_bonus or '']
|
||||||
|
|
||||||
cum_t=0; cum_a=0
|
cum_t=0; cum_a=0
|
||||||
|
month_qualified = {} # {月份: bool}
|
||||||
for m in range(1, settle_month+1):
|
for m in range(1, settle_month+1):
|
||||||
mgs=[(k,g) for k,g in G.get(m,{}).items() if k[0]==plate]
|
mgs=[(k,g) for k,g in G.get(m,{}).items() if k[0]==plate]
|
||||||
if mgs:
|
if mgs:
|
||||||
persons=', '.join(sorted(set(g['销售'] for _,g in mgs)))
|
lines = []
|
||||||
ts=sum(g['应考核'] for _,g in mgs); As=sum(g['实际'] for _,g in mgs)
|
any_q = False
|
||||||
q='达标' if any(g['有达标'] for _,g in mgs) else '未达标'
|
for _,g in sorted(mgs, key=lambda x: x[0][1]):
|
||||||
cum_t+=ts; cum_a+=As
|
t=g['应考核']; a=g['实际']
|
||||||
row+=[persons,R(ts),R(As),q]
|
cum_t+=t; cum_a+=a
|
||||||
|
q = g['有达标']
|
||||||
|
if q: any_q = True
|
||||||
|
sd = g['部门'].replace('业务','') if '业务' in g.get('部门','') else g.get('部门','')
|
||||||
|
lines.append(f"{sd}-{g['销售']}: {R(a,0)}/{R(t,0)} {'✓' if q else '✗'}")
|
||||||
|
row.append('\n'.join(lines))
|
||||||
|
month_qualified[m] = any_q
|
||||||
else:
|
else:
|
||||||
row+=['','','','']
|
row.append('')
|
||||||
if settle_month>=2:
|
month_qualified[m] = None # 无数据
|
||||||
row+=[R(cum_t),R(cum_a),'达标' if (cum_a>=cum_t and cum_t>0) else '未达标']
|
|
||||||
|
|
||||||
# 本月发放(截至settle_month)
|
cum_q = False
|
||||||
|
if settle_month>=2:
|
||||||
|
cum_q = cum_a>=cum_t and cum_t>0
|
||||||
|
row+=[f'{R(cum_a,0)}/{R(cum_t,0)}', '✓ 达标' if cum_q else '✗ 未达标']
|
||||||
|
|
||||||
|
# 本月发放
|
||||||
tp=[p for p in pays if p['结算月']==settle_month]
|
tp=[p for p in pays if p['结算月']==settle_month]
|
||||||
if tp:
|
if tp:
|
||||||
row+=[R(sum(p['金额'] for p in tp)),', '.join(sorted(set(p['业务员'] for p in tp))),
|
pay_lines = []
|
||||||
', '.join(sorted(set(p['类型'] for p in tp)))]
|
for p in sorted(tp, key=lambda x: x['业务员']):
|
||||||
|
pd = p.get('部门','').replace('业务','') if '业务' in p.get('部门','') else p.get('部门','')
|
||||||
|
pay_lines.append(f"{pd}-{p['业务员']}: {R(p['金额'])}元 ({p['类型']})")
|
||||||
|
row.append('\n'.join(pay_lines))
|
||||||
else:
|
else:
|
||||||
row+=[0,'','']
|
row.append('')
|
||||||
|
|
||||||
# 奖金池(截至settle_month)
|
|
||||||
pays_to_date=[p for p in pays if p['结算月']<=settle_month]
|
pays_to_date=[p for p in pays if p['结算月']<=settle_month]
|
||||||
tp_count=len(pays_to_date); tp_amt=sum(p['金额'] for p in pays_to_date)
|
tp_count=len(pays_to_date); tp_amt=sum(p['金额'] for p in pays_to_date)
|
||||||
row+=[tp_count,R(tp_amt) if tp_amt>0 else 0,12-tp_count]
|
row+=[f'{tp_count}/12', R(tp_amt) if tp_amt>0 else 0, 12-tp_count]
|
||||||
WR(ws,rn,row); rn+=1
|
|
||||||
AW(ws)
|
WR(ws,rn,row)
|
||||||
|
|
||||||
|
# --- 美化 ---
|
||||||
|
# 车辆基本信息列:浅灰底色
|
||||||
|
for ci in range(1, month_start_col+1):
|
||||||
|
ws.cell(row=rn, column=ci).fill = grey_fill
|
||||||
|
|
||||||
|
# 月度考核列:达标绿底/未达标红底
|
||||||
|
for mi, m in enumerate(range(1, settle_month+1)):
|
||||||
|
col = month_start_col + mi + 1
|
||||||
|
cell = ws.cell(row=rn, column=col)
|
||||||
|
cell.alignment = wrap_top
|
||||||
|
if month_qualified.get(m) == True:
|
||||||
|
cell.fill = green_fill; cell.font = green_font
|
||||||
|
elif month_qualified.get(m) == False:
|
||||||
|
cell.fill = red_fill; cell.font = red_font
|
||||||
|
|
||||||
|
# 累计列
|
||||||
|
if settle_month >= 2:
|
||||||
|
cum_cell = ws.cell(row=rn, column=cum_start_col+2) # 累计达标列
|
||||||
|
if cum_q:
|
||||||
|
cum_cell.fill = green_fill; cum_cell.font = Font(bold=True, color='006100')
|
||||||
|
elif cum_t > 0:
|
||||||
|
cum_cell.fill = red_fill; cum_cell.font = Font(bold=True, color='9C0006')
|
||||||
|
|
||||||
|
# 发放列:有发放金底
|
||||||
|
pay_cell = ws.cell(row=rn, column=pay_start_col+1)
|
||||||
|
pay_cell.alignment = wrap_top
|
||||||
|
if tp:
|
||||||
|
pay_cell.fill = gold_fill
|
||||||
|
|
||||||
|
# 奖金池:已发期数列
|
||||||
|
period_cell = ws.cell(row=rn, column=pay_start_col+2)
|
||||||
|
period_cell.alignment = center_top
|
||||||
|
if tp_count > 0:
|
||||||
|
period_cell.fill = blue_fill; period_cell.font = Font(bold=True)
|
||||||
|
|
||||||
|
rn+=1
|
||||||
|
|
||||||
|
# 列宽
|
||||||
|
col_widths = {'A':12,'B':20,'C':20,'D':12,'E':20,'F':8}
|
||||||
|
for col_letter, w in col_widths.items():
|
||||||
|
ws.column_dimensions[col_letter].width = w
|
||||||
|
# 月度考核列宽
|
||||||
|
for mi in range(settle_month):
|
||||||
|
col_letter = chr(ord('G') + mi)
|
||||||
|
ws.column_dimensions[col_letter].width = 30
|
||||||
|
# 剩余列自动
|
||||||
|
remaining_start = ord('G') + settle_month
|
||||||
|
for i in range(8):
|
||||||
|
cl = chr(remaining_start + i)
|
||||||
|
if cl <= 'Z':
|
||||||
|
ws.column_dimensions[cl].width = 16
|
||||||
|
|
||||||
|
# 自动筛选
|
||||||
|
ws.auto_filter.ref = f"A1:{chr(ord('A')+len(headers)-1)}1"
|
||||||
|
|||||||
8
main.py
8
main.py
@@ -74,13 +74,13 @@ for settle_month in [1, 2, 3]:
|
|||||||
else:
|
else:
|
||||||
write_summary_month(wb, 3, mar_data, ['结转','补发1月','补发2月','当月','累计补发3月'])
|
write_summary_month(wb, 3, mar_data, ['结转','补发1月','补发2月','当月','累计补发3月'])
|
||||||
|
|
||||||
# Sheet 5-16: 业务员
|
# Sheet 5: 车辆考核追踪
|
||||||
|
write_vehicle_tracking_sheet(wb, settle_month, G, master_vehicles, vehicle_payments, vehicle_info)
|
||||||
|
|
||||||
|
# Sheet 6-17: 业务员
|
||||||
for person in sorted(all_persons.keys()):
|
for person in sorted(all_persons.keys()):
|
||||||
write_salesperson_sheet(wb, person, all_persons[person], settle_month, D, G, month_data, vehicle_payments)
|
write_salesperson_sheet(wb, person, all_persons[person], settle_month, D, G, month_data, vehicle_payments)
|
||||||
|
|
||||||
# Sheet 17: 车辆考核追踪
|
|
||||||
write_vehicle_tracking_sheet(wb, settle_month, G, master_vehicles, vehicle_payments, vehicle_info)
|
|
||||||
|
|
||||||
# 删除默认空sheet
|
# 删除默认空sheet
|
||||||
if 'Sheet' in wb.sheetnames:
|
if 'Sheet' in wb.sheetnames:
|
||||||
del wb['Sheet']
|
del wb['Sheet']
|
||||||
|
|||||||
Reference in New Issue
Block a user