Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a69ef2993 | ||
|
|
04b6035d52 | ||
|
|
4c43c00e73 | ||
|
|
f2de5d5500 | ||
|
|
54ecbc352f | ||
|
|
cdc4cec2ff | ||
|
|
8c2f4e73dd | ||
|
|
e47cc00b3d | ||
|
|
4273592160 | ||
|
|
1b7d25c821 |
@@ -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)
|
||||||
|
|||||||
377
excel_writer.py
377
excel_writer.py
@@ -186,111 +186,150 @@ 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.cell(row=1,column=1,value=f'{person} | {dept} | {settle_month}月考核').font=Font(bold=True,size=14)
|
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)
|
||||||
|
|
||||||
# 收集该人在1-settle_month中有记录的所有车牌
|
|
||||||
plates = set()
|
plates = set()
|
||||||
for m in range(1, settle_month+1):
|
for m in range(1, settle_month+1):
|
||||||
for k in G.get(m, {}):
|
for k in G.get(m, {}):
|
||||||
if k[1] == person: plates.add(k[0])
|
if k[1] == person: plates.add(k[0])
|
||||||
|
|
||||||
# 本月发放总额
|
|
||||||
person_total = sum(d['额'] for cat,dl in month_data.items() for d in dl if d['销售']==person)
|
person_total = sum(d['额'] for cat,dl in month_data.items() for d in dl if d['销售']==person)
|
||||||
ws.cell(row=2,column=1,value=f'本月考核车辆: {len(plates)}辆 | 本月发放合计: {R(person_total)}元').font=Font(bold=True,size=11)
|
ws.cell(row=2,column=1,value=f'本月考核车辆: {len(plates)}辆 | 本月发放合计: {R(person_total)}元').font=Font(bold=True,size=11)
|
||||||
|
|
||||||
rn = 4
|
# 表头:车辆信息 + 各月里程/目标 + 累计 + 奖金池
|
||||||
|
headers = ['车牌号','考核目标','月奖励']
|
||||||
|
for m in range(1, settle_month+1):
|
||||||
|
headers.append(f'{m}月里程/目标')
|
||||||
|
if settle_month >= 2:
|
||||||
|
headers += ['累计里程/目标']
|
||||||
|
headers.append('达标')
|
||||||
|
WH(ws, headers, 4)
|
||||||
|
|
||||||
|
rn = 5
|
||||||
for plate in sorted(plates):
|
for plate in sorted(plates):
|
||||||
# 车辆信息(取最近月的group)
|
|
||||||
g_cur = None
|
g_cur = None
|
||||||
for m in range(settle_month, 0, -1):
|
for m in range(settle_month, 0, -1):
|
||||||
g_cur = G.get(m, {}).get((plate, person))
|
g_cur = G.get(m, {}).get((plate, person))
|
||||||
if g_cur: break
|
if g_cur: break
|
||||||
if not g_cur: continue
|
if not g_cur: continue
|
||||||
|
|
||||||
first = g_cur['recs'][0]
|
first = g_cur['recs'][0]
|
||||||
|
mkm = g_cur['目标km']
|
||||||
|
|
||||||
ws.cell(row=rn,column=1,value=plate).font=Font(bold=True,size=11)
|
# 第1行:车辆信息 + 各月里程/目标
|
||||||
ws.cell(row=rn,column=2,value=first.get('合同编号',''))
|
row = [plate, first.get('考核目标',''), g_cur['奖励额']]
|
||||||
ws.cell(row=rn,column=3,value=first.get('客户名称',''))
|
|
||||||
ws.cell(row=rn,column=4,value=first.get('考核目标',''))
|
|
||||||
ws.cell(row=rn,column=5,value=f'月度目标{g_cur["目标km"]}km | 月奖励{g_cur["奖励额"]}元')
|
|
||||||
rn += 1
|
|
||||||
|
|
||||||
# 表头
|
|
||||||
headers = ['月份','考核天数','应考核里程','实际里程','完成率','达标','奖金','发放说明']
|
|
||||||
if settle_month >= 2:
|
|
||||||
headers += ['累计应完成','累计实际','累计达标']
|
|
||||||
WH(ws, headers, rn); rn += 1
|
|
||||||
|
|
||||||
# 每月一行
|
|
||||||
cum_t = 0; cum_a = 0
|
cum_t = 0; cum_a = 0
|
||||||
for m in range(1, settle_month+1):
|
for m in range(1, settle_month+1):
|
||||||
gm = G.get(m, {}).get((plate, person))
|
gm = G.get(m, {}).get((plate, person))
|
||||||
if not gm:
|
if gm:
|
||||||
WR(ws, rn, [f'{m}月','','','','','无记录']); rn+=1; continue
|
|
||||||
|
|
||||||
t=gm['应考核']; a=gm['实际']; cum_t+=t; cum_a+=a
|
t=gm['应考核']; a=gm['实际']; cum_t+=t; cum_a+=a
|
||||||
qual='达标' if gm['有达标'] else '未达标'
|
row.append(f'{R(a,0)}/{R(t,0)}')
|
||||||
rate=R(a/t*100,0) if t>0 else 0
|
else:
|
||||||
mkm=gm['目标km']
|
row.append('-')
|
||||||
|
if settle_month >= 2:
|
||||||
|
row.append(f'{R(cum_a,0)}/{R(cum_t,0)}')
|
||||||
|
cum_q = cum_a >= cum_t and cum_t > 0
|
||||||
|
# 达标判断:取settle_month的group
|
||||||
|
g_s = G.get(settle_month, {}).get((plate, person))
|
||||||
|
if g_s and g_s.get('有达标'):
|
||||||
|
row.append('达标')
|
||||||
|
elif cum_q:
|
||||||
|
row.append('累计达标')
|
||||||
|
else:
|
||||||
|
row.append('未达标')
|
||||||
|
WR(ws, rn, row)
|
||||||
|
ws.cell(row=rn, column=1).font = Font(bold=True)
|
||||||
|
rn += 1
|
||||||
|
|
||||||
# 发放金额和说明(动态生成,包含关键数字)
|
# 第2-N行:发放明细(历史已发 + 本月发放)
|
||||||
pay_amt=0; desc=''
|
WH(ws, ['', '发放项', '金额', '说明', '奖金池'], rn); rn += 1
|
||||||
if m == settle_month:
|
|
||||||
carry=gm.get('结转',0); bonus=gm.get('当月奖金',0)
|
pays = vehicle_payments.get(plate, [])
|
||||||
cum_bp=gm.get(f'累计补发{m}月',0)
|
pays_to_date = [p for p in pays if p['结算月'] <= settle_month]
|
||||||
excess=sum(r['多跑'] for r in gm['recs'] if r['是否达标']=='达标')
|
total_periods = len(pays_to_date)
|
||||||
|
|
||||||
|
# 历史已发(m < settle_month)
|
||||||
|
for m in range(1, settle_month):
|
||||||
|
gm = G.get(m, {}).get((plate, person))
|
||||||
|
# 查该月是否有发放记录
|
||||||
|
m_pays = [p for p in pays_to_date if p['结算月'] == m and p['业务员'] == person]
|
||||||
|
if m_pays:
|
||||||
|
amt = sum(p['金额'] for p in m_pays)
|
||||||
|
types = ', '.join(p['类型'] for p in m_pays)
|
||||||
|
WR(ws, rn, ['', f'{m}月: 已发', R(amt), types, ''])
|
||||||
|
elif gm:
|
||||||
|
# 有考核但未发
|
||||||
|
# 检查是否在后续月被补发过(settle_month之前)
|
||||||
|
bp_pays = [p for p in pays_to_date if p['对应考核月'] == m and p['业务员'] == person]
|
||||||
|
if bp_pays:
|
||||||
|
amt = sum(p['金额'] for p in bp_pays)
|
||||||
|
sm = bp_pays[0]['结算月']
|
||||||
|
WR(ws, rn, ['', f'{m}月: 已发', R(amt), f'{sm}月补发', ''])
|
||||||
|
else:
|
||||||
|
WR(ws, rn, ['', f'{m}月: 未发', 0, f'未达标(实际{R(gm["实际"],0)}<目标{R(gm["应考核"],0)})', ''])
|
||||||
|
else:
|
||||||
|
WR(ws, rn, ['', f'{m}月: 无记录', '', '', ''])
|
||||||
|
rn += 1
|
||||||
|
|
||||||
|
# 本月发放
|
||||||
|
g_s = G.get(settle_month, {}).get((plate, person), {})
|
||||||
|
if not isinstance(g_s, dict): g_s = {}
|
||||||
|
gm_s = G.get(settle_month, {}).get((plate, person))
|
||||||
|
plate_this_month = 0
|
||||||
|
|
||||||
|
# 结转
|
||||||
|
carry = g_s.get('结转', 0)
|
||||||
if carry > 0:
|
if carry > 0:
|
||||||
# 结转:上月多跑够整月
|
prev = settle_month - 1
|
||||||
prev=m-1
|
|
||||||
g_prev = G.get(prev, {}).get((plate, person))
|
g_prev = G.get(prev, {}).get((plate, person))
|
||||||
prev_excess = sum(r['多跑'] for r in g_prev['recs'] if r['是否达标'] == '达标') if g_prev else 0
|
prev_excess = sum(r['多跑'] for r in g_prev['recs'] if r['是否达标'] == '达标') if g_prev else 0
|
||||||
desc=f'{prev}月多跑{R(prev_excess,0)}≥{mkm},结转(完整月奖金)'
|
WR(ws, rn, ['', '结转', R(carry), f'{prev}月多跑{R(prev_excess,0)}≥{mkm},结转(完整月奖金)', ''])
|
||||||
pay_amt=carry
|
plate_this_month += carry; rn += 1
|
||||||
elif bonus>0:
|
|
||||||
desc='当月达标'
|
|
||||||
if excess>0 and int(excess//mkm)>=1:
|
|
||||||
desc+=f',多跑{R(excess,0)}≥{mkm}可结转'
|
|
||||||
pay_amt=bonus
|
|
||||||
elif cum_bp>0:
|
|
||||||
desc=f'1-{m}月累计{R(cum_a,0)}≥{R(cum_t,0)},累计达标补发'
|
|
||||||
pay_amt=cum_bp
|
|
||||||
elif gm.get('结转占位'):
|
|
||||||
desc='结转占位,本月不另发'
|
|
||||||
else:
|
|
||||||
desc=f'未达标(实际{R(a,0)}<目标{R(t,0)})'
|
|
||||||
else:
|
|
||||||
# 历史月份
|
|
||||||
if gm['有达标']:
|
|
||||||
pay_amt=gm.get('奖金',0)
|
|
||||||
desc=f'({m}月已发{R(pay_amt)})'
|
|
||||||
else:
|
|
||||||
desc=f'未达标(实际{R(a,0)}<目标{R(t,0)})'
|
|
||||||
|
|
||||||
row_data=[f'{m}月',gm['天数'],R(t),R(a),f'{rate}%',qual,R(pay_amt) if pay_amt>0 else 0,desc]
|
# 补发过去月份
|
||||||
if settle_month>=2:
|
|
||||||
cum_q='达标' if (cum_a>=cum_t and cum_t>0) else '未达标'
|
|
||||||
row_data+=[R(cum_t),R(cum_a),cum_q]
|
|
||||||
WR(ws,rn,row_data); rn+=1
|
|
||||||
|
|
||||||
# 补发行(当前月补发之前月份)
|
|
||||||
if settle_month >= 2:
|
|
||||||
g_s = G.get(settle_month, {}).get((plate, person), {})
|
|
||||||
for prev_m in range(1, settle_month):
|
for prev_m in range(1, settle_month):
|
||||||
bp_key = f'补发{prev_m}月'
|
bp_key = f'补发{prev_m}月'
|
||||||
bp_amt = g_s.get(bp_key, 0) if isinstance(g_s, dict) else 0
|
bp_amt = g_s.get(bp_key, 0)
|
||||||
if bp_amt > 0:
|
if bp_amt > 0:
|
||||||
desc=f'1-{settle_month}月累计{R(cum_a,0)}≥{R(cum_t,0)},补发{prev_m}月'
|
WR(ws, rn, ['', f'补发{prev_m}月', R(bp_amt), f'累计{R(cum_a,0)}≥{R(cum_t,0)}达标,补发{prev_m}月', ''])
|
||||||
row_data = [f'→补发{prev_m}月','','','','','',R(bp_amt),desc]
|
plate_this_month += bp_amt; rn += 1
|
||||||
if settle_month>=2: row_data += ['','','']
|
|
||||||
WR(ws,rn,row_data); rn+=1
|
|
||||||
|
|
||||||
# 奖金池
|
# 当月
|
||||||
pays = vehicle_payments.get(plate, [])
|
bonus = g_s.get('当月奖金', 0)
|
||||||
total_periods = len(pays)
|
if bonus > 0:
|
||||||
plate_this = sum(p['金额'] for p in pays if p['结算月']==settle_month and p['业务员']==person)
|
excess = sum(r['多跑'] for r in gm_s['recs'] if r['是否达标'] == '达标') if gm_s else 0
|
||||||
ws.cell(row=rn,column=1,value=f'小计: {R(plate_this)}元 | 奖金池: 已发{total_periods}期/共12期, 剩余{12-total_periods}期').font=Font(italic=True)
|
desc = '当月达标'
|
||||||
rn += 2
|
if excess > 0 and mkm > 0 and int(excess // mkm) >= 1:
|
||||||
|
desc += f',多跑{R(excess,0)}≥{mkm}可结转'
|
||||||
|
WR(ws, rn, ['', f'{settle_month}月当月', R(bonus), desc, ''])
|
||||||
|
plate_this_month += bonus; rn += 1
|
||||||
|
|
||||||
|
# 累计补发当月
|
||||||
|
cum_bp = g_s.get(f'累计补发{settle_month}月', 0)
|
||||||
|
if cum_bp > 0:
|
||||||
|
WR(ws, rn, ['', f'累计补发{settle_month}月', R(cum_bp), f'累计{R(cum_a,0)}≥{R(cum_t,0)}达标,补发{settle_month}月', ''])
|
||||||
|
plate_this_month += cum_bp; rn += 1
|
||||||
|
|
||||||
|
# 无发放
|
||||||
|
if plate_this_month == 0 and carry == 0:
|
||||||
|
if gm_s:
|
||||||
|
a_s = gm_s['实际']; t_s = gm_s['应考核']
|
||||||
|
if gm_s.get('结转占位'):
|
||||||
|
WR(ws, rn, ['', '本月不发', 0, '结转占位,本月不另发', ''])
|
||||||
|
else:
|
||||||
|
WR(ws, rn, ['', '本月不发', 0, f'未达标(实际{R(a_s,0)}<目标{R(t_s,0)}),累计也未达标', ''])
|
||||||
|
else:
|
||||||
|
WR(ws, rn, ['', '本月不发', 0, '本月无考核记录', ''])
|
||||||
|
rn += 1
|
||||||
|
|
||||||
|
# 本月合计 + 奖金池
|
||||||
|
pool_str = f'已发{total_periods}期/共12期,剩余{12-total_periods}期'
|
||||||
|
WR(ws, rn, ['', '本月合计', R(plate_this_month), '', pool_str])
|
||||||
|
ws.cell(row=rn, column=2).font = Font(bold=True)
|
||||||
|
ws.cell(row=rn, column=5).font = Font(italic=True)
|
||||||
|
rn += 2 # 空行
|
||||||
|
|
||||||
# 尾部
|
# 尾部
|
||||||
ws.cell(row=rn,column=1,value=f'{person} {settle_month}月合计: {len(plates)}辆车, 发放 {R(person_total)}元').font=Font(bold=True,size=12)
|
ws.cell(row=rn,column=1,value=f'{person} {settle_month}月合计: {len(plates)}辆车, 发放 {R(person_total)}元').font=Font(bold=True,size=12)
|
||||||
@@ -302,46 +341,184 @@ 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, DAYS
|
||||||
|
|
||||||
|
center_top = Alignment(horizontal='center', vertical='top', wrap_text=True)
|
||||||
|
left_top = Alignment(vertical='top', wrap_text=True)
|
||||||
|
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 = ['车牌号','车架号','归属公司','车型','考核目标','月度奖励','业务员']
|
||||||
|
info_cols = 6 # 前6列是车辆信息(需要合并)
|
||||||
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 += [f'{m}月应考核', f'{m}月实际', f'{m}月达标']
|
||||||
if settle_month >= 2:
|
if settle_month >= 2:
|
||||||
headers += ['累计应完成','累计实际','累计达标']
|
headers += ['累计应完成','累计实际','累计达标']
|
||||||
headers += ['本月发放金额','发放给谁','发放类型','累计已发期数','累计已发金额','剩余可发期数']
|
headers += ['本月发放金额','发放类型','已发期数','已发金额','剩余期数']
|
||||||
WH(ws, headers)
|
WH(ws, headers)
|
||||||
|
ws.freeze_panes = 'H2' # 冻结车辆信息+业务员列
|
||||||
|
|
||||||
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, [])
|
||||||
row=[plate,mv.get('车架号',''),mv.get('归属公司',''),mv.get('车型确定',''),
|
|
||||||
info.get('考核目标',''),info.get('月度奖励',0) or '']
|
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
|
||||||
|
|
||||||
|
# 收集该车所有(业务员) - 跨月去重
|
||||||
|
person_set = {}
|
||||||
|
for m in range(1, settle_month+1):
|
||||||
|
for k,g in G.get(m, {}).items():
|
||||||
|
if k[0] == plate:
|
||||||
|
person_set[k[1]] = g['部门']
|
||||||
|
persons = sorted(person_set.keys())
|
||||||
|
if not persons:
|
||||||
|
persons = [''] # 无考核记录也占一行
|
||||||
|
|
||||||
|
start_rn = rn
|
||||||
|
for pi, person in enumerate(persons):
|
||||||
|
sd = person_set.get(person,'').replace('业务','') if person else ''
|
||||||
|
person_label = f'{sd}-{person}' if person and sd else person
|
||||||
|
|
||||||
|
# 车辆信息(只在第一行写,后面留空等合并)
|
||||||
|
if pi == 0:
|
||||||
|
row_base = [plate, mv.get('车架号',''), mv.get('归属公司',''),
|
||||||
|
mv.get('车型确定',''), target_name or '', monthly_bonus or '']
|
||||||
|
else:
|
||||||
|
row_base = ['','','','','','']
|
||||||
|
|
||||||
|
row = row_base + [person_label]
|
||||||
|
|
||||||
|
# 每月数据(按该业务员的group)
|
||||||
cum_t = 0; cum_a = 0
|
cum_t = 0; cum_a = 0
|
||||||
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]
|
gm = G.get(m, {}).get((plate, person)) if person else None
|
||||||
if mgs:
|
if gm:
|
||||||
persons=', '.join(sorted(set(g['销售'] for _,g in mgs)))
|
# 逐条记录汇总(同人同月可能多条)
|
||||||
ts=sum(g['应考核'] for _,g in mgs); As=sum(g['实际'] for _,g in mgs)
|
t_sum = gm['应考核']; a_sum = gm['实际']
|
||||||
q='达标' if any(g['有达标'] for _,g in mgs) else '未达标'
|
cum_t += t_sum; cum_a += a_sum
|
||||||
cum_t+=ts; cum_a+=As
|
# 每条记录的达标情况
|
||||||
row+=[persons,R(ts),R(As),q]
|
rec_details = []
|
||||||
|
for rec in gm['recs']:
|
||||||
|
rq = rec['是否达标'] == '达标'
|
||||||
|
rec_details.append(f"{R(rec['实际行驶里程(km)'],0)}/{R(rec['应考核里程(km)'],0)}{'✓' if rq else '✗'}")
|
||||||
|
all_q = all(rec['是否达标'] == '达标' for rec in gm['recs'])
|
||||||
|
if len(gm['recs']) == 1:
|
||||||
|
detail = rec_details[0].split('✓')[0].split('✗')[0] # 只取数字
|
||||||
|
row += [R(t_sum), R(a_sum), '✓' if all_q else '✗']
|
||||||
else:
|
else:
|
||||||
row+=['','','','']
|
# 多条:显示汇总,但单元格内注明各条
|
||||||
|
row += [R(t_sum), R(a_sum), '\n'.join(rec_details)]
|
||||||
|
else:
|
||||||
|
row += ['', '', '']
|
||||||
|
|
||||||
|
# 累计
|
||||||
if settle_month >= 2:
|
if settle_month >= 2:
|
||||||
row+=[R(cum_t),R(cum_a),'达标' if (cum_a>=cum_t and cum_t>0) else '未达标']
|
if cum_t > 0:
|
||||||
|
cum_q = cum_a >= cum_t
|
||||||
# 本月发放(截至settle_month)
|
row += [R(cum_t), R(cum_a), '✓' if cum_q else '✗']
|
||||||
tp=[p for p in pays if p['结算月']==settle_month]
|
|
||||||
if tp:
|
|
||||||
row+=[R(sum(p['金额'] for p in tp)),', '.join(sorted(set(p['业务员'] for p in tp))),
|
|
||||||
', '.join(sorted(set(p['类型'] for p in tp)))]
|
|
||||||
else:
|
else:
|
||||||
row+=[0,'','']
|
row += ['', '', '']
|
||||||
|
cum_q = False
|
||||||
|
else:
|
||||||
|
cum_q = False
|
||||||
|
|
||||||
# 奖金池(截至settle_month)
|
# 本月发放(该业务员的)
|
||||||
|
tp = [p for p in pays if p['结算月'] == settle_month and p['业务员'] == person]
|
||||||
|
if tp:
|
||||||
|
amt = sum(p['金额'] for p in tp)
|
||||||
|
types = ', '.join(p['类型'] for p in tp)
|
||||||
|
row += [R(amt), types]
|
||||||
|
else:
|
||||||
|
row += [0, '']
|
||||||
|
|
||||||
|
# 奖金池(整车,只在第一行显示)
|
||||||
|
if pi == 0:
|
||||||
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
|
else:
|
||||||
AW(ws)
|
row += ['', '', '']
|
||||||
|
|
||||||
|
WR(ws, rn, row)
|
||||||
|
|
||||||
|
# 美化
|
||||||
|
# 车辆信息列灰底
|
||||||
|
for ci in range(1, info_cols + 1):
|
||||||
|
ws.cell(row=rn, column=ci).fill = grey_fill
|
||||||
|
|
||||||
|
# 月度达标列着色
|
||||||
|
for m in range(1, settle_month + 1):
|
||||||
|
col_base = info_cols + 1 + (m - 1) * 3 # 业务员列后面
|
||||||
|
qual_col = col_base + 3 # 达标列
|
||||||
|
cell = ws.cell(row=rn, column=qual_col)
|
||||||
|
cell.alignment = center_top
|
||||||
|
val = cell.value
|
||||||
|
if val and '✓' in str(val) and '✗' not in str(val):
|
||||||
|
cell.fill = green_fill; cell.font = green_font
|
||||||
|
elif val and '✗' in str(val):
|
||||||
|
cell.fill = red_fill; cell.font = red_font
|
||||||
|
|
||||||
|
# 累计达标着色
|
||||||
|
if settle_month >= 2:
|
||||||
|
cum_qual_col = info_cols + 1 + settle_month * 3 + 3 # 累计达标列
|
||||||
|
cell = ws.cell(row=rn, column=cum_qual_col)
|
||||||
|
if cell.value == '✓':
|
||||||
|
cell.fill = green_fill; cell.font = Font(bold=True, color='006100')
|
||||||
|
elif cell.value == '✗':
|
||||||
|
cell.fill = red_fill; cell.font = Font(bold=True, color='9C0006')
|
||||||
|
|
||||||
|
# 发放金底
|
||||||
|
pay_col = info_cols + 1 + settle_month * 3 + (3 if settle_month >= 2 else 0) + 1
|
||||||
|
if tp:
|
||||||
|
ws.cell(row=rn, column=pay_col).fill = gold_fill
|
||||||
|
|
||||||
|
# 奖金池蓝底
|
||||||
|
if pi == 0 and tp_count > 0:
|
||||||
|
pool_col = pay_col + 2
|
||||||
|
ws.cell(row=rn, column=pool_col).fill = blue_fill
|
||||||
|
ws.cell(row=rn, column=pool_col).font = Font(bold=True)
|
||||||
|
|
||||||
|
rn += 1
|
||||||
|
|
||||||
|
# 合并车辆信息列(如果多人)
|
||||||
|
if len(persons) > 1:
|
||||||
|
for ci in range(1, info_cols + 1):
|
||||||
|
ws.merge_cells(start_row=start_rn, start_column=ci,
|
||||||
|
end_row=start_rn + len(persons) - 1, end_column=ci)
|
||||||
|
ws.cell(row=start_rn, column=ci).alignment = Alignment(vertical='center', wrap_text=True)
|
||||||
|
# 奖金池列也合并
|
||||||
|
for offset in [2, 3, 4]: # 已发期数/已发金额/剩余期数
|
||||||
|
pool_col = pay_col + offset
|
||||||
|
ws.merge_cells(start_row=start_rn, start_column=pool_col,
|
||||||
|
end_row=start_rn + len(persons) - 1, end_column=pool_col)
|
||||||
|
|
||||||
|
# 列宽
|
||||||
|
col_widths = {'A':12,'B':18,'C':18,'D':10,'E':18,'F':8,'G':14}
|
||||||
|
for cl, w in col_widths.items():
|
||||||
|
ws.column_dimensions[cl].width = w
|
||||||
|
# 月度列
|
||||||
|
start = ord('H')
|
||||||
|
for m in range(settle_month):
|
||||||
|
for i in range(3):
|
||||||
|
cl = chr(start + m*3 + i)
|
||||||
|
if cl <= 'Z': ws.column_dimensions[cl].width = 12
|
||||||
|
# 剩余列
|
||||||
|
rem = start + settle_month * 3
|
||||||
|
for i in range(10):
|
||||||
|
cl = chr(rem + i)
|
||||||
|
if cl <= 'Z': ws.column_dimensions[cl].width = 14
|
||||||
|
|||||||
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