初始化

This commit is contained in:
2026-04-13 14:22:31 +08:00
commit 7cf0a75603
78 changed files with 10702 additions and 0 deletions

View File

@@ -0,0 +1,604 @@
from datetime import date, datetime
from decimal import Decimal
from typing import Optional, Dict, List, Any
from sqlalchemy.orm import Session
from sqlalchemy import func, and_
import json
from app.models import (
Employee, SecondaryAgent, ProductCategory, PerformanceRecord,
CalculationResult, User
)
def get_period_dates(period: str, year: int, month: Optional[int] = None,
quarter: Optional[int] = None) -> tuple:
"""
根据周期类型获取开始和结束日期
Returns:
tuple: (start_date, end_date, period_key)
"""
if period == "monthly":
if month is None:
raise ValueError("月度周期需要提供month参数")
start_date = date(year, month, 1)
if month == 12:
end_date = date(year + 1, 1, 1)
else:
end_date = date(year, month + 1, 1)
period_key = f"{year}-{month:02d}"
elif period == "quarterly":
if quarter is None:
raise ValueError("季度周期需要提供quarter参数")
start_month = (quarter - 1) * 3 + 1
end_month = quarter * 3 + 1
start_date = date(year, start_month, 1)
if end_month > 12:
end_date = date(year + 1, 1, 1)
else:
end_date = date(year, end_month, 1)
period_key = f"{year}-Q{quarter}"
elif period == "half_yearly":
start_date = date(year, 1, 1)
end_date = date(year, 7, 1)
period_key = f"{year}-H1"
elif period == "yearly":
start_date = date(year, 1, 1)
end_date = date(year + 1, 1, 1)
period_key = f"{year}"
else:
raise ValueError(f"不支持的周期类型: {period}")
return start_date, end_date, period_key
def get_target_by_period(employee: Employee, period: str) -> Decimal:
"""根据周期类型获取员工目标"""
if period == "monthly":
return employee.monthly_target or Decimal("0")
elif period == "quarterly":
return employee.quarterly_target or Decimal("0")
elif period == "half_yearly":
return employee.half_year_target or Decimal("0")
elif period == "yearly":
return employee.yearly_target or Decimal("0")
return Decimal("0")
def get_rebate_rate_by_period(category: ProductCategory, period: str) -> Decimal:
"""根据周期类型获取返点比例"""
if period == "monthly":
return category.monthly_rebate or Decimal("0")
elif period == "quarterly":
return category.quarterly_rebate or category.monthly_rebate or Decimal("0")
elif period == "half_yearly":
return category.quarterly_rebate or category.monthly_rebate or Decimal("0")
elif period == "yearly":
return category.quarterly_rebate or category.monthly_rebate or Decimal("0")
return Decimal("0")
def calculate_employee_income(
db: Session,
employee_id: int,
period: str,
year: int,
month: Optional[int] = None,
quarter: Optional[int] = None,
save_result: bool = True
) -> Dict[str, Any]:
"""
计算员工在指定周期的收益
计算逻辑:
1. 获取员工业绩数据根据period筛选
2. 计算完成率 = 总业绩 / 目标
3. 绩效奖金 = 1000 * min(完成率, 1.0) 如果完成率>=50%否则0
4. 个人提成 = 业绩按分类汇总 * 各分类提成比例
5. 代理提成 = 二级代理业绩总和 * 0.01
6. 总收入 = 底薪 + 绩效奖金 + 个人提成 + 代理提成
Args:
db: 数据库会话
employee_id: 员工ID
period: 周期类型 (monthly/quarterly/half_yearly/yearly)
year: 年份
month: 月份(月度周期需要)
quarter: 季度(季度周期需要)
save_result: 是否保存计算结果到数据库
Returns:
计算结果字典
"""
# 获取员工信息
employee = db.query(Employee).filter(Employee.id == employee_id).first()
if not employee:
raise ValueError(f"员工不存在: {employee_id}")
# 获取周期日期范围
start_date, end_date, period_key = get_period_dates(period, year, month, quarter)
# 获取目标金额
target_amount = get_target_by_period(employee, period)
# 1. 获取员工业绩数据(个人业绩)
personal_records = db.query(PerformanceRecord).filter(
and_(
PerformanceRecord.employee_id == employee_id,
PerformanceRecord.record_type == "employee",
PerformanceRecord.record_date >= start_date,
PerformanceRecord.record_date < end_date
)
).all()
# 按分类汇总个人业绩
category_performance = {}
total_personal_performance = Decimal("0")
for record in personal_records:
category_id = record.category_id
amount = record.amount or Decimal("0")
total_personal_performance += amount
if category_id not in category_performance:
category_performance[category_id] = {
"amount": Decimal("0"),
"category_name": record.category.name if record.category else "未知分类"
}
category_performance[category_id]["amount"] += amount
# 2. 获取二级代理业绩数据
agent_records = db.query(PerformanceRecord).filter(
and_(
PerformanceRecord.employee_id == employee_id,
PerformanceRecord.record_type == "agent",
PerformanceRecord.record_date >= start_date,
PerformanceRecord.record_date < end_date
)
).all()
total_agent_performance = Decimal("0")
for record in agent_records:
total_agent_performance += record.amount or Decimal("0")
# 计算总业绩
total_performance = total_personal_performance + total_agent_performance
# 3. 计算完成率
completion_rate = Decimal("0")
if target_amount > 0:
completion_rate = (total_performance / target_amount) * 100
# 4. 计算绩效奖金
performance_bonus = Decimal("0")
if completion_rate >= 50:
rate = min(completion_rate / 100, Decimal("1.0"))
performance_bonus = Decimal("1000") * rate
# 5. 计算个人提成
personal_commission = Decimal("0")
commission_details = []
for category_id, data in category_performance.items():
category = db.query(ProductCategory).filter(ProductCategory.id == category_id).first()
if category:
commission_rate = category.commission_rate or Decimal("0")
commission = data["amount"] * commission_rate
personal_commission += commission
commission_details.append({
"category_id": category_id,
"category_name": data["category_name"],
"amount": float(data["amount"]),
"commission_rate": float(commission_rate),
"commission": float(commission)
})
# 6. 计算代理提成二级代理业绩的1%
agent_commission_rate = Decimal("0.01")
agent_commission = total_agent_performance * agent_commission_rate
# 7. 计算总收入
base_salary = employee.base_salary or Decimal("0")
total_income = base_salary + performance_bonus + personal_commission + agent_commission
# 计算公司相关数据
company_rebate = Decimal("0")
for category_id, data in category_performance.items():
category = db.query(ProductCategory).filter(ProductCategory.id == category_id).first()
if category:
rebate_rate = get_rebate_rate_by_period(category, period)
company_rebate += data["amount"] * rebate_rate
# 公司成本
company_cost = total_income # 员工成本
# 代理分成成本
agent_share_cost = Decimal("0")
for record in agent_records:
if record.agent:
share_rate = record.agent.profit_share_rate or Decimal("0.60")
agent_share_cost += (record.amount or Decimal("0")) * share_rate
company_cost += agent_share_cost
# 公司利润
company_profit = company_rebate - company_cost
# 构建详情JSON
detail_json = {
"personal_performance": {
"total": float(total_personal_performance),
"by_category": commission_details
},
"agent_performance": {
"total": float(total_agent_performance),
"commission_rate": float(agent_commission_rate),
"commission": float(agent_commission)
},
"target": {
"amount": float(target_amount),
"completion_rate": float(completion_rate)
},
"bonus_calculation": {
"threshold": 50,
"max_bonus": 1000,
"actual_bonus": float(performance_bonus)
}
}
result = {
"employee_id": employee_id,
"employee_name": employee.user.name if employee.user else "",
"period": period,
"year": year,
"month": month,
"quarter": quarter,
"period_key": period_key,
"period_start_date": start_date.isoformat(),
"period_end_date": end_date.isoformat(),
"total_performance": float(total_performance),
"target_amount": float(target_amount),
"completion_rate": float(completion_rate),
"base_salary": float(base_salary),
"performance_bonus": float(performance_bonus),
"personal_commission": float(personal_commission),
"agent_commission": float(agent_commission),
"total_income": float(total_income),
"company_rebate": float(company_rebate),
"company_cost": float(company_cost),
"company_profit": float(company_profit),
"agent_performance": float(total_agent_performance),
"agent_share_amount": float(agent_share_cost),
"detail": detail_json
}
# 保存计算结果到数据库
if save_result:
calc_result = CalculationResult(
employee_id=employee_id,
calc_period=period,
calc_year=year,
calc_month=month,
calc_quarter=quarter,
period_start_date=start_date,
period_end_date=end_date,
total_performance=total_performance,
target_amount=target_amount,
completion_rate=completion_rate,
base_salary=base_salary,
performance_bonus=performance_bonus,
personal_commission=personal_commission,
agent_commission=agent_commission,
total_income=total_income,
company_rebate=company_rebate,
company_cost=company_cost,
company_profit=company_profit,
agent_performance=total_agent_performance,
agent_share_amount=agent_share_cost,
detail_json=json.dumps(detail_json, ensure_ascii=False)
)
db.add(calc_result)
db.commit()
db.refresh(calc_result)
result["calculation_id"] = calc_result.id
return result
def calculate_company_profit(
db: Session,
period: str,
year: int,
month: Optional[int] = None,
quarter: Optional[int] = None,
save_result: bool = False
) -> Dict[str, Any]:
"""
计算公司在指定周期的收益
计算逻辑:
1. 获取所有员工业绩
2. 公司返点 = 业绩按分类汇总 * 各分类返点比例
3. 公司成本 = 所有员工(底薪+绩效+提成) + 代理分成
4. 公司利润 = 返点 - 成本
Args:
db: 数据库会话
period: 周期类型
year: 年份
month: 月份
quarter: 季度
save_result: 是否保存结果
Returns:
计算结果字典
"""
# 获取周期日期范围
start_date, end_date, period_key = get_period_dates(period, year, month, quarter)
# 获取所有员工
employees = db.query(Employee).join(User).filter(User.status == 1).all()
total_company_rebate = Decimal("0")
total_company_cost = Decimal("0")
total_agent_share = Decimal("0")
employee_results = []
# 获取所有业绩记录
all_records = db.query(PerformanceRecord).filter(
and_(
PerformanceRecord.record_date >= start_date,
PerformanceRecord.record_date < end_date
)
).all()
# 按分类汇总业绩
category_totals = {}
for record in all_records:
if record.record_type == "employee":
cat_id = record.category_id
if cat_id not in category_totals:
category_totals[cat_id] = Decimal("0")
category_totals[cat_id] += record.amount or Decimal("0")
# 计算公司返点
rebate_details = []
for cat_id, amount in category_totals.items():
category = db.query(ProductCategory).filter(ProductCategory.id == cat_id).first()
if category:
rebate_rate = get_rebate_rate_by_period(category, period)
rebate = amount * rebate_rate
total_company_rebate += rebate
rebate_details.append({
"category_id": cat_id,
"category_name": category.name,
"amount": float(amount),
"rebate_rate": float(rebate_rate),
"rebate": float(rebate)
})
# 计算每个员工的收益和代理分成
for employee in employees:
try:
emp_result = calculate_employee_income(
db, employee.id, period, year, month, quarter, save_result=False
)
total_company_cost += Decimal(str(emp_result["total_income"]))
total_agent_share += Decimal(str(emp_result["agent_share_amount"]))
employee_results.append({
"employee_id": employee.id,
"employee_name": emp_result["employee_name"],
"total_income": emp_result["total_income"],
"agent_share": emp_result["agent_share_amount"]
})
except Exception as e:
# 跳过计算失败的员工
continue
# 总成本
total_cost = total_company_cost + total_agent_share
# 公司利润
company_profit = total_company_rebate - total_cost
result = {
"period": period,
"year": year,
"month": month,
"quarter": quarter,
"period_key": period_key,
"period_start_date": start_date.isoformat(),
"period_end_date": end_date.isoformat(),
"total_rebate": float(total_company_rebate),
"total_employee_cost": float(total_company_cost),
"total_agent_share": float(total_agent_share),
"total_cost": float(total_cost),
"company_profit": float(company_profit),
"employee_count": len(employee_results),
"rebate_details": rebate_details,
"employee_details": employee_results
}
return result
def calculate_agent_profit(
db: Session,
agent_id: int,
period: str,
year: int,
month: Optional[int] = None,
quarter: Optional[int] = None
) -> Dict[str, Any]:
"""
计算二级代理在指定周期的收益
计算逻辑:
代理分成 = 代理业绩 * 代理分佣比例(默认60%)
Args:
db: 数据库会话
agent_id: 代理ID
period: 周期类型
year: 年份
month: 月份
quarter: 季度
Returns:
计算结果字典
"""
# 获取代理信息
agent = db.query(SecondaryAgent).filter(SecondaryAgent.id == agent_id).first()
if not agent:
raise ValueError(f"代理不存在: {agent_id}")
# 获取周期日期范围
start_date, end_date, period_key = get_period_dates(period, year, month, quarter)
# 获取代理业绩
agent_records = db.query(PerformanceRecord).filter(
and_(
PerformanceRecord.agent_id == agent_id,
PerformanceRecord.record_date >= start_date,
PerformanceRecord.record_date < end_date
)
).all()
total_performance = Decimal("0")
performance_details = []
for record in agent_records:
amount = record.amount or Decimal("0")
total_performance += amount
performance_details.append({
"record_id": record.id,
"date": record.record_date.isoformat() if record.record_date else None,
"amount": float(amount),
"customer_name": record.customer_name,
"order_no": record.order_no
})
# 计算代理分成
profit_share_rate = agent.profit_share_rate or Decimal("0.60")
profit_share_amount = total_performance * profit_share_rate
result = {
"agent_id": agent_id,
"agent_name": agent.company_name,
"contact_name": agent.contact_name,
"employee_id": agent.employee_id,
"employee_name": agent.employee.user.name if agent.employee and agent.employee.user else "",
"period": period,
"year": year,
"month": month,
"quarter": quarter,
"period_key": period_key,
"period_start_date": start_date.isoformat(),
"period_end_date": end_date.isoformat(),
"total_performance": float(total_performance),
"profit_share_rate": float(profit_share_rate),
"profit_share_amount": float(profit_share_amount),
"performance_count": len(agent_records),
"performance_details": performance_details
}
return result
def get_calculation_history(
db: Session,
employee_id: Optional[int] = None,
period: Optional[str] = None,
year: Optional[int] = None,
page: int = 1,
page_size: int = 20
) -> Dict[str, Any]:
"""获取计算历史列表"""
query = db.query(CalculationResult)
if employee_id:
query = query.filter(CalculationResult.employee_id == employee_id)
if period:
query = query.filter(CalculationResult.calc_period == period)
if year:
query = query.filter(CalculationResult.calc_year == year)
total = query.count()
results = query.order_by(
CalculationResult.calc_year.desc(),
CalculationResult.created_at.desc()
).offset((page - 1) * page_size).limit(page_size).all()
items = []
for result in results:
items.append({
"id": result.id,
"employee_id": result.employee_id,
"employee_name": result.employee.user.name if result.employee and result.employee.user else "",
"calc_period": result.calc_period,
"calc_year": result.calc_year,
"calc_month": result.calc_month,
"calc_quarter": result.calc_quarter,
"period_start_date": result.period_start_date.isoformat() if result.period_start_date else None,
"period_end_date": result.period_end_date.isoformat() if result.period_end_date else None,
"total_performance": float(result.total_performance) if result.total_performance else 0,
"target_amount": float(result.target_amount) if result.target_amount else 0,
"completion_rate": float(result.completion_rate) if result.completion_rate else 0,
"total_income": float(result.total_income) if result.total_income else 0,
"company_profit": float(result.company_profit) if result.company_profit else 0,
"created_at": result.created_at.isoformat() if result.created_at else None
})
return {
"items": items,
"total": total,
"page": page,
"page_size": page_size
}
def get_calculation_detail(db: Session, calculation_id: int) -> Optional[Dict[str, Any]]:
"""获取计算历史详情"""
result = db.query(CalculationResult).filter(CalculationResult.id == calculation_id).first()
if not result:
return None
detail = None
if result.detail_json:
try:
detail = json.loads(result.detail_json)
except:
detail = None
return {
"id": result.id,
"employee_id": result.employee_id,
"employee_name": result.employee.user.name if result.employee and result.employee.user else "",
"calc_period": result.calc_period,
"calc_year": result.calc_year,
"calc_month": result.calc_month,
"calc_quarter": result.calc_quarter,
"period_start_date": result.period_start_date.isoformat() if result.period_start_date else None,
"period_end_date": result.period_end_date.isoformat() if result.period_end_date else None,
"total_performance": float(result.total_performance) if result.total_performance else 0,
"target_amount": float(result.target_amount) if result.target_amount else 0,
"completion_rate": float(result.completion_rate) if result.completion_rate else 0,
"base_salary": float(result.base_salary) if result.base_salary else 0,
"performance_bonus": float(result.performance_bonus) if result.performance_bonus else 0,
"personal_commission": float(result.personal_commission) if result.personal_commission else 0,
"agent_commission": float(result.agent_commission) if result.agent_commission else 0,
"total_income": float(result.total_income) if result.total_income else 0,
"company_rebate": float(result.company_rebate) if result.company_rebate else 0,
"company_cost": float(result.company_cost) if result.company_cost else 0,
"company_profit": float(result.company_profit) if result.company_profit else 0,
"agent_performance": float(result.agent_performance) if result.agent_performance else 0,
"agent_share_amount": float(result.agent_share_amount) if result.agent_share_amount else 0,
"detail": detail,
"created_at": result.created_at.isoformat() if result.created_at else None
}

View File

@@ -0,0 +1,369 @@
import pandas as pd
import io
from datetime import date, datetime
from typing import Optional, Dict, List, Any
from sqlalchemy.orm import Session
from sqlalchemy import func, and_
from app.models import Employee, SecondaryAgent, ProductCategory, PerformanceRecord, User
from app.services.calculate_service import (
calculate_employee_income, calculate_company_profit,
get_period_dates, get_rebate_rate_by_period
)
def export_employee_report(
db: Session,
employee_id: int,
period: str,
year: int,
month: Optional[int] = None
) -> tuple:
"""
导出员工收益明细Excel
Returns:
tuple: (excel_bytes, filename)
"""
# 计算员工收益
result = calculate_employee_income(db, employee_id, period, year, month, save_result=False)
# 获取周期日期范围
start_date, end_date, period_key = get_period_dates(period, year, month)
# 获取业绩明细
personal_records = db.query(PerformanceRecord).filter(
and_(
PerformanceRecord.employee_id == employee_id,
PerformanceRecord.record_type == "employee",
PerformanceRecord.record_date >= start_date,
PerformanceRecord.record_date < end_date
)
).all()
agent_records = db.query(PerformanceRecord).filter(
and_(
PerformanceRecord.employee_id == employee_id,
PerformanceRecord.record_type == "agent",
PerformanceRecord.record_date >= start_date,
PerformanceRecord.record_date < end_date
)
).all()
# 创建Excel writer
output = io.BytesIO()
with pd.ExcelWriter(output, engine='openpyxl') as writer:
# Sheet 1: 收益汇总
summary_data = {
'项目': [
'员工姓名',
'计算周期',
'业绩总额',
'目标金额',
'完成率(%)',
'底薪',
'绩效奖金',
'个人提成',
'代理提成',
'总收入',
'公司返点',
'公司成本',
'公司利润'
],
'金额': [
result['employee_name'],
result['period_key'],
result['total_performance'],
result['target_amount'],
f"{result['completion_rate']:.2f}",
result['base_salary'],
result['performance_bonus'],
result['personal_commission'],
result['agent_commission'],
result['total_income'],
result['company_rebate'],
result['company_cost'],
result['company_profit']
]
}
df_summary = pd.DataFrame(summary_data)
df_summary.to_excel(writer, sheet_name='收益汇总', index=False)
# Sheet 2: 个人业绩明细
if personal_records:
personal_data = []
for record in personal_records:
personal_data.append({
'日期': record.record_date,
'客户名称': record.customer_name or '',
'订单号': record.order_no or '',
'产品分类': record.category.name if record.category else '',
'业绩金额': float(record.amount or 0),
'提成比例': float(record.category.commission_rate or 0) if record.category else 0,
'提成金额': float(record.amount or 0) * float(record.category.commission_rate or 0) if record.category else 0
})
df_personal = pd.DataFrame(personal_data)
df_personal.to_excel(writer, sheet_name='个人业绩明细', index=False)
else:
pd.DataFrame({'提示': ['该周期内无个人业绩记录']}).to_excel(writer, sheet_name='个人业绩明细', index=False)
# Sheet 3: 代理业绩明细
if agent_records:
agent_data = []
for record in agent_records:
agent = record.agent
agent_data.append({
'日期': record.record_date,
'代理公司': agent.company_name if agent else '',
'客户名称': record.customer_name or '',
'订单号': record.order_no or '',
'产品分类': record.category.name if record.category else '',
'业绩金额': float(record.amount or 0),
'分佣比例': float(agent.profit_share_rate or 0.6) if agent else 0.6,
'分佣金额': float(record.amount or 0) * float(agent.profit_share_rate or 0.6) if agent else float(record.amount or 0) * 0.6
})
df_agent = pd.DataFrame(agent_data)
df_agent.to_excel(writer, sheet_name='代理业绩明细', index=False)
else:
pd.DataFrame({'提示': ['该周期内无代理业绩记录']}).to_excel(writer, sheet_name='代理业绩明细', index=False)
# Sheet 4: 提成明细
if result.get('detail') and result['detail'].get('personal_performance'):
commission_data = []
for item in result['detail']['personal_performance'].get('by_category', []):
commission_data.append({
'产品分类': item['category_name'],
'业绩金额': item['amount'],
'提成比例': item['commission_rate'],
'提成金额': item['commission']
})
if commission_data:
df_commission = pd.DataFrame(commission_data)
df_commission.to_excel(writer, sheet_name='提成明细', index=False)
output.seek(0)
filename = f"employee_report_{employee_id}_{period_key}.xlsx"
return output.getvalue(), filename
def export_company_report(
db: Session,
period: str,
year: int,
month: Optional[int] = None
) -> tuple:
"""
导出公司收益汇总Excel
Returns:
tuple: (excel_bytes, filename)
"""
# 计算公司收益
result = calculate_company_profit(db, period, year, month)
# 获取周期日期范围
start_date, end_date, period_key = get_period_dates(period, year, month)
# 创建Excel writer
output = io.BytesIO()
with pd.ExcelWriter(output, engine='openpyxl') as writer:
# Sheet 1: 公司收益汇总
summary_data = {
'项目': [
'计算周期',
'员工数量',
'总返点收入',
'员工成本',
'代理分成',
'总成本',
'公司利润'
],
'金额': [
result['period_key'],
result['employee_count'],
result['total_rebate'],
result['total_employee_cost'],
result['total_agent_share'],
result['total_cost'],
result['company_profit']
]
}
df_summary = pd.DataFrame(summary_data)
df_summary.to_excel(writer, sheet_name='公司收益汇总', index=False)
# Sheet 2: 返点明细
if result.get('rebate_details'):
rebate_data = []
for item in result['rebate_details']:
rebate_data.append({
'产品分类': item['category_name'],
'业绩金额': item['amount'],
'返点比例': item['rebate_rate'],
'返点金额': item['rebate']
})
df_rebate = pd.DataFrame(rebate_data)
df_rebate.to_excel(writer, sheet_name='返点明细', index=False)
# Sheet 3: 员工成本明细
if result.get('employee_details'):
emp_data = []
for item in result['employee_details']:
emp_data.append({
'员工ID': item['employee_id'],
'员工姓名': item['employee_name'],
'员工收入': item['total_income'],
'代理分成': item['agent_share']
})
df_emp = pd.DataFrame(emp_data)
df_emp.to_excel(writer, sheet_name='员工成本明细', index=False)
output.seek(0)
filename = f"company_report_{period_key}.xlsx"
return output.getvalue(), filename
def export_performance_report(
db: Session,
filters: Dict[str, Any]
) -> tuple:
"""
导出业绩报表Excel
Args:
filters: 筛选条件
- start_date: 开始日期
- end_date: 结束日期
- employee_id: 员工ID可选
- agent_id: 代理ID可选
- category_id: 分类ID可选
- record_type: 记录类型employee/agent
Returns:
tuple: (excel_bytes, filename)
"""
# 构建查询
query = db.query(PerformanceRecord)
# 应用筛选条件
if filters.get('start_date'):
query = query.filter(PerformanceRecord.record_date >= filters['start_date'])
if filters.get('end_date'):
query = query.filter(PerformanceRecord.record_date <= filters['end_date'])
if filters.get('employee_id'):
query = query.filter(PerformanceRecord.employee_id == filters['employee_id'])
if filters.get('agent_id'):
query = query.filter(PerformanceRecord.agent_id == filters['agent_id'])
if filters.get('category_id'):
query = query.filter(PerformanceRecord.category_id == filters['category_id'])
if filters.get('record_type'):
query = query.filter(PerformanceRecord.record_type == filters['record_type'])
records = query.order_by(PerformanceRecord.record_date.desc()).all()
# 创建Excel writer
output = io.BytesIO()
with pd.ExcelWriter(output, engine='openpyxl') as writer:
# Sheet 1: 业绩明细
if records:
data = []
total_amount = 0
for record in records:
amount = float(record.amount or 0)
total_amount += amount
employee_name = ""
if record.employee and record.employee.user:
employee_name = record.employee.user.name
agent_name = ""
if record.agent:
agent_name = record.agent.company_name
category_name = ""
if record.category:
category_name = record.category.name
data.append({
'ID': record.id,
'记录类型': '员工业绩' if record.record_type == 'employee' else '代理业绩',
'日期': record.record_date,
'员工': employee_name,
'代理': agent_name,
'产品分类': category_name,
'客户名称': record.customer_name or '',
'订单号': record.order_no or '',
'业绩金额': amount,
'备注': record.remark or ''
})
df = pd.DataFrame(data)
df.to_excel(writer, sheet_name='业绩明细', index=False)
# Sheet 2: 汇总统计
summary_data = {
'统计项': [
'记录总数',
'业绩总额',
'平均单笔业绩',
'员工业绩笔数',
'代理业绩笔数'
],
'数值': [
len(records),
total_amount,
round(total_amount / len(records), 2) if records else 0,
len([r for r in records if r.record_type == 'employee']),
len([r for r in records if r.record_type == 'agent'])
]
}
df_summary = pd.DataFrame(summary_data)
df_summary.to_excel(writer, sheet_name='汇总统计', index=False)
# Sheet 3: 按员工汇总
emp_summary = {}
for record in records:
emp_name = record.employee.user.name if record.employee and record.employee.user else '未知'
if emp_name not in emp_summary:
emp_summary[emp_name] = {'count': 0, 'amount': 0}
emp_summary[emp_name]['count'] += 1
emp_summary[emp_name]['amount'] += float(record.amount or 0)
emp_data = []
for name, stats in emp_summary.items():
emp_data.append({
'员工': name,
'业绩笔数': stats['count'],
'业绩总额': stats['amount']
})
df_emp = pd.DataFrame(emp_data)
df_emp.to_excel(writer, sheet_name='按员工汇总', index=False)
# Sheet 4: 按分类汇总
cat_summary = {}
for record in records:
cat_name = record.category.name if record.category else '未知'
if cat_name not in cat_summary:
cat_summary[cat_name] = {'count': 0, 'amount': 0}
cat_summary[cat_name]['count'] += 1
cat_summary[cat_name]['amount'] += float(record.amount or 0)
cat_data = []
for name, stats in cat_summary.items():
cat_data.append({
'产品分类': name,
'业绩笔数': stats['count'],
'业绩总额': stats['amount']
})
df_cat = pd.DataFrame(cat_data)
df_cat.to_excel(writer, sheet_name='按分类汇总', index=False)
else:
pd.DataFrame({'提示': ['无业绩记录']}).to_excel(writer, sheet_name='业绩明细', index=False)
output.seek(0)
# 生成文件名
date_str = datetime.now().strftime('%Y%m%d')
filename = f"performance_report_{date_str}.xlsx"
return output.getvalue(), filename