150 lines
5.4 KiB
Python
150 lines
5.4 KiB
Python
#!/usr/bin/env python3
|
|
"""按月生成独立Excel文件 - 里程考核绩效,支持1-7月"""
|
|
import os, openpyxl
|
|
from calc_engine import *
|
|
from excel_writer import *
|
|
|
|
os.chdir('/Users/kkfluous/Downloads')
|
|
JULY_SOURCE = os.environ.get('JULY_SOURCE', os.path.join('7月核算结果', '租赁任务考核_2026年7月.xlsx'))
|
|
JULY_OUTPUT_DIR = os.environ.get('JULY_OUTPUT_DIR', '7月核算结果')
|
|
|
|
# 读取1-7月;7月优先读取核算结果目录内已完成GPS干预的源表
|
|
print("读取源数据...")
|
|
months = []
|
|
for m in range(1, 8):
|
|
fp = JULY_SOURCE if m == 7 else f'租赁任务考核_2026年{m}月.xlsx'
|
|
if os.path.exists(fp):
|
|
months.append(m)
|
|
D = {}
|
|
for m in months:
|
|
fp = JULY_SOURCE if m == 7 else f'租赁任务考核_2026年{m}月.xlsx'
|
|
D[m] = read_file(fp, m)
|
|
print(f" {m}月: {len(D[m])}条")
|
|
|
|
# 分组
|
|
G = {m: grp(D[m], m) for m in months}
|
|
|
|
# 1月初始化
|
|
calc_jan_carryover(G[1])
|
|
all_data = {}
|
|
all_data[1] = {'当月': [{'车牌':k[0],'销售':g['销售'],'部门':g['部门'],'额':g['奖金']}
|
|
for k,g in G[1].items() if g['奖金'] > 0]}
|
|
|
|
# 逐月计算: 2→7
|
|
for m in range(2, 8):
|
|
if m not in G:
|
|
continue
|
|
data_m, G[m] = calc_month(m, G, all_data, G[m-1], G[m])
|
|
|
|
# 钱婧已离职:从2026年7月起所有结转、当月、补发及累计补发均不再发放。
|
|
all_data[7] = {
|
|
cat: [item for item in items if item.get('销售') != '钱婧']
|
|
for cat, items in all_data[7].items()
|
|
}
|
|
|
|
# 发放追踪
|
|
vehicle_payments, vehicle_info = collect_vehicle_payments(G, all_data)
|
|
master_vehicles = read_master_vehicles()
|
|
|
|
# 亏损表
|
|
print("\n读取亏损表...")
|
|
loss_data = {}
|
|
for m in months:
|
|
ld = read_loss_data(m)
|
|
if ld:
|
|
loss_clients = sum(1 for v in ld.values() if v == '是')
|
|
print(f" {m}月: {len(ld)}个客户, 其中亏损{loss_clients}个")
|
|
loss_data[m] = ld
|
|
else:
|
|
# 无亏损表的月份不管亏损全发 → 构造全'否'的代理
|
|
from collections import defaultdict as dd
|
|
ld_tmp = dd(lambda: '否')
|
|
for r in D[m]:
|
|
c = r.get('客户名称')
|
|
if c: ld_tmp[c] = '否'
|
|
print(f" {m}月: 无亏损表,按全部不亏损处理(全发)")
|
|
loss_data[m] = ld_tmp
|
|
|
|
# 车牌→客户名称映射
|
|
plate_client = get_vehicle_client_map(D)
|
|
|
|
# 所有业务员
|
|
all_persons = {}
|
|
for m in G:
|
|
for k, g in G[m].items():
|
|
all_persons[g['销售']] = g['部门']
|
|
|
|
# 打印汇总
|
|
print("\n考核应发汇总:")
|
|
grand = 0
|
|
for m in months:
|
|
total_m = sum(sum(d['额'] for d in v) for v in all_data[m].values())
|
|
grand += total_m
|
|
print(f" {m}月: {total_m:.2f}")
|
|
print(f" 合计: {grand:.2f}")
|
|
|
|
# ============================================================
|
|
# 按月生成(只生成7月)
|
|
# ============================================================
|
|
for settle_month in [7]:
|
|
print(f"\n生成 {settle_month}月核算文件...")
|
|
wb = openpyxl.Workbook()
|
|
|
|
# 当月数据
|
|
month_data = all_data[settle_month]
|
|
|
|
# Sheet 1: 考核奖励规则
|
|
write_rules_sheet(wb)
|
|
|
|
# Sheet 2: 里程明细
|
|
write_detail_sheet(wb, D[settle_month], settle_month)
|
|
|
|
# Sheet 3: 计算过程
|
|
write_calc_process_generic(wb, settle_month, G, all_data)
|
|
|
|
# Sheet 5: 车辆考核追踪
|
|
write_vehicle_tracking_sheet(wb, settle_month, G, master_vehicles, vehicle_payments, vehicle_info, loss_data[settle_month], plate_client)
|
|
|
|
# Sheet 6: 奖金发放记录(叠加亏损筛选,补发查对应月盈亏)
|
|
# 不做任何亏损拦截,全发
|
|
class _AllPass:
|
|
def get(self, _k, _d=None): return '否'
|
|
def __bool__(self): return True
|
|
payment_records = build_payment_records(settle_month, month_data, {m: _AllPass() for m in months}, plate_client)
|
|
write_payment_record_sheet(wb, settle_month, payment_records)
|
|
|
|
# Sheet 7: 月汇总。离职人员仅当月奖金转给现销售,其余结转/补发不发;
|
|
# 发放记录和个人明细仍保留原归属,方便审计。
|
|
resignation_transfer = {'赵连飞': '刘念念', '伍仲文': '钟祥', '岑彦': '钟祥'}
|
|
summary_records = []
|
|
for rec in payment_records:
|
|
item = dict(rec)
|
|
sales = item.get('业务员') or item.get('销售人员') or item.get('销售')
|
|
ptype = item.get('发放类型') or item.get('类型')
|
|
if sales in resignation_transfer:
|
|
if ptype != '当月':
|
|
continue
|
|
new_sales = resignation_transfer[sales]
|
|
if '业务员' in item: item['业务员'] = new_sales
|
|
if '销售人员' in item: item['销售人员'] = new_sales
|
|
if '销售' in item: item['销售'] = new_sales
|
|
summary_records.append(item)
|
|
write_summary_from_records(wb, settle_month, summary_records)
|
|
|
|
# 业务员sheets
|
|
for person in sorted(all_persons.keys()):
|
|
write_salesperson_sheet(wb, person, all_persons[person], settle_month, D, G, month_data, vehicle_payments)
|
|
|
|
if 'Sheet' in wb.sheetnames:
|
|
del wb['Sheet']
|
|
|
|
for old in ['二部-赵连飞', '六部-伍仲文', '六部-岑彦', '三部-钱婧']:
|
|
if old in wb.sheetnames:
|
|
wb[old].title = f'【已离职】{old}'
|
|
wb.move_sheet(wb[f'【已离职】{old}'], offset=len(wb.sheetnames))
|
|
|
|
os.makedirs(JULY_OUTPUT_DIR, exist_ok=True)
|
|
fname = os.path.join(JULY_OUTPUT_DIR, f'里程任务考核_{settle_month}月核算.xlsx')
|
|
wb.save(fname)
|
|
print(f" ✅ {fname} ({len(wb.sheetnames)} sheets)")
|