V3.0.0 叠加客户亏损筛选,生成最终发放记录
新增功能: - 读取1月/2月亏损表,按客户名称匹配考核数据 - 车辆考核追踪新增列:客户名称、客户是否亏损、考核应发、最终发放、未发放原因 - 月汇总新增亏损筛选section:亏损拦截/未匹配/最终发放/汇总 - 3月无亏损表,全部正常发放 - 亏损拦截不补发 规则:客户亏损→该客户下所有车不发;未匹配→标注待人工确认 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
108
excel_writer.py
108
excel_writer.py
@@ -162,14 +162,44 @@ def write_calc_process_mar(wb, G1, G2, G3, feb_data):
|
||||
c5,R(cbp3) if cbp3>0 else 0,R(total) if total>0 else 0]); rn+=1
|
||||
AW(ws)
|
||||
|
||||
def write_summary_jan(wb, records):
|
||||
def write_summary_jan(wb, records, loss_data=None, plate_client=None):
|
||||
ws = wb.create_sheet('1月汇总')
|
||||
jan_dl=[{'车牌':r['车牌号'],'销售':r['销售经理'],'部门':r['部门名称'],'额':r['奖金']} for r in records if r['是否达标']=='达标']
|
||||
rn=write_sec(ws,1,'1月达标奖励',jan_dl)
|
||||
rn=write_sec(ws,1,'1月达标奖励(考核应发)',jan_dl)
|
||||
|
||||
if loss_data is not None:
|
||||
# 亏损拦截
|
||||
blocked = []
|
||||
passed = []
|
||||
unmatched = []
|
||||
for d in jan_dl:
|
||||
client = (plate_client or {}).get(d['车牌'], '')
|
||||
status = loss_data.get(client, '未匹配') if client else '未匹配'
|
||||
if status == '是':
|
||||
blocked.append({**d, '客户': client})
|
||||
elif status == '未匹配':
|
||||
unmatched.append({**d, '客户': client})
|
||||
else:
|
||||
passed.append(d)
|
||||
|
||||
rn = write_sec(ws, rn, '亏损拦截(客户亏损不发放)', blocked if blocked else [])
|
||||
rn = write_sec(ws, rn, '未匹配亏损表(需人工确认)', unmatched if unmatched else [])
|
||||
rn = write_sec(ws, rn, '最终发放', passed)
|
||||
|
||||
ws.cell(row=rn, column=1, value='汇总').font=Font(bold=True, size=11); rn+=1
|
||||
total_考核 = sum(d['额'] for d in jan_dl)
|
||||
total_拦截 = sum(d['额'] for d in blocked)
|
||||
total_未匹配 = sum(d['额'] for d in unmatched)
|
||||
total_最终 = sum(d['额'] for d in passed)
|
||||
WR(ws, rn, ['考核应发', R(total_考核)]); rn+=1
|
||||
WR(ws, rn, ['亏损拦截', R(total_拦截)]); rn+=1
|
||||
WR(ws, rn, ['未匹配(待确认)', R(total_未匹配)]); rn+=1
|
||||
WR(ws, rn, ['最终发放', R(total_最终)]); ws.cell(row=rn,column=1).font=Font(bold=True); rn+=2
|
||||
|
||||
write_total(ws,rn,1,{'达标':jan_dl})
|
||||
AW(ws)
|
||||
|
||||
def write_summary_month(wb, month, month_data, section_names):
|
||||
def write_summary_month(wb, month, month_data, section_names, loss_data=None, plate_client=None):
|
||||
ws = wb.create_sheet(f'{month}月汇总')
|
||||
rn=1
|
||||
for i,cat in enumerate(section_names):
|
||||
@@ -178,7 +208,47 @@ def write_summary_month(wb, month, month_data, section_names):
|
||||
'当月':f'{"三" if month==2 else "四"}、{month}月当月奖励',
|
||||
f'累计补发{month}月':f'{"四" if month==2 else "五"}、累计达标补发{month}月'}
|
||||
rn=write_sec(ws,rn,label_map.get(cat,cat),month_data.get(cat,[]))
|
||||
|
||||
# 考核应发合计
|
||||
write_total(ws,rn,month,month_data)
|
||||
# 找最后一行
|
||||
rn = ws.max_row + 2
|
||||
|
||||
if loss_data is not None:
|
||||
# 合并所有发放记录
|
||||
all_dl = []
|
||||
for cat, dl in month_data.items():
|
||||
all_dl.extend(dl)
|
||||
|
||||
blocked = []; passed = []; unmatched = []
|
||||
for d in all_dl:
|
||||
client = (plate_client or {}).get(d['车牌'], '')
|
||||
status = loss_data.get(client, '未匹配') if client else '未匹配'
|
||||
if status == '是':
|
||||
blocked.append(d)
|
||||
elif status == '未匹配':
|
||||
unmatched.append(d)
|
||||
else:
|
||||
passed.append(d)
|
||||
|
||||
ws.cell(row=rn, column=1, value='═══ 亏损筛选 ═══').font=Font(bold=True, size=12); rn+=2
|
||||
rn = write_sec(ws, rn, '亏损拦截(客户亏损不发放)', blocked)
|
||||
rn = write_sec(ws, rn, '未匹配亏损表(需人工确认)', unmatched)
|
||||
rn = write_sec(ws, rn, '最终发放', passed)
|
||||
|
||||
total_考核 = sum(d['额'] for d in all_dl)
|
||||
total_拦截 = sum(d['额'] for d in blocked)
|
||||
total_未匹配 = sum(d['额'] for d in unmatched)
|
||||
total_最终 = sum(d['额'] for d in passed)
|
||||
|
||||
ws.cell(row=rn, column=1, value='亏损筛选汇总').font=Font(bold=True, size=11); rn+=1
|
||||
WR(ws, rn, ['考核应发合计', R(total_考核)]); rn+=1
|
||||
WR(ws, rn, ['亏损拦截金额', R(total_拦截)]); rn+=1
|
||||
WR(ws, rn, ['未匹配金额(待确认)', R(total_未匹配)]); rn+=1
|
||||
WR(ws, rn, ['最终应发合计', R(total_最终)])
|
||||
ws.cell(row=rn,column=1).font=Font(bold=True, size=12)
|
||||
ws.cell(row=rn,column=2).font=Font(bold=True, size=12)
|
||||
|
||||
AW(ws)
|
||||
|
||||
# ============================================================
|
||||
@@ -339,7 +409,7 @@ def write_salesperson_sheet(wb, person, dept, settle_month, D, G, month_data, ve
|
||||
# 新增:车辆考核追踪sheet
|
||||
# ============================================================
|
||||
|
||||
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, loss_data=None, plate_client=None):
|
||||
ws = wb.create_sheet('车辆考核追踪')
|
||||
from calc_engine import VEHICLE_TARGET_MAP, DAYS
|
||||
|
||||
@@ -360,7 +430,11 @@ def write_vehicle_tracking_sheet(wb, settle_month, G, master_vehicles, vehicle_p
|
||||
headers += [f'{m}月应考核', f'{m}月实际', f'{m}月达标']
|
||||
if settle_month >= 2:
|
||||
headers += ['累计应完成','累计实际','累计达标']
|
||||
headers += ['本月发放金额','发放类型','已发期数','已发金额','剩余期数']
|
||||
if loss_data is not None:
|
||||
headers += ['客户名称','客户是否亏损','考核应发','最终发放','未发放原因']
|
||||
else:
|
||||
headers += ['本月发放金额','发放类型']
|
||||
headers += ['已发期数','已发金额','剩余期数']
|
||||
WH(ws, headers)
|
||||
ws.freeze_panes = 'H2' # 冻结车辆信息+业务员列
|
||||
|
||||
@@ -445,12 +519,26 @@ def write_vehicle_tracking_sheet(wb, settle_month, G, master_vehicles, vehicle_p
|
||||
|
||||
# 本月发放(该业务员的)
|
||||
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]
|
||||
考核应发 = sum(p['金额'] for p in tp) if tp else 0
|
||||
pay_types = ', '.join(p['类型'] for p in tp) if tp else ''
|
||||
|
||||
if loss_data is not None:
|
||||
# 有亏损表:加客户名称、亏损状态、考核应发、最终发放、未发放原因
|
||||
client = (plate_client or {}).get(plate, '')
|
||||
loss_status = loss_data.get(client, '未匹配') if client else '未匹配'
|
||||
if loss_status == '是':
|
||||
final_amt = 0
|
||||
reason = '客户亏损不发放' if 考核应发 > 0 else ''
|
||||
elif loss_status == '未匹配':
|
||||
final_amt = 0
|
||||
reason = '未匹配亏损表' if 考核应发 > 0 else ''
|
||||
else:
|
||||
final_amt = 考核应发
|
||||
reason = ''
|
||||
row += [client, loss_status, R(考核应发), R(final_amt), reason]
|
||||
else:
|
||||
row += [0, '']
|
||||
# 无亏损表:直接发放
|
||||
row += [R(考核应发), pay_types]
|
||||
|
||||
# 奖金池(整车,只在第一行显示)
|
||||
if pi == 0:
|
||||
|
||||
Reference in New Issue
Block a user