Files
hospital_performance/backend/app/api/v1/salary.py
2026-02-28 15:06:52 +08:00

156 lines
6.3 KiB
Python

"""
API路由 - 工资核算管理
"""
from typing import Annotated, Optional
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.database import get_db
from app.core.security import get_current_active_user, get_current_manager_user
from app.schemas.schemas import (
SalaryRecordCreate, SalaryRecordUpdate, SalaryRecordResponse,
ResponseBase
)
from app.services.salary_service import SalaryService
from app.models.models import User
router = APIRouter(prefix="/salary", tags=["工资核算"])
@router.get("", summary="获取工资记录列表")
async def get_salary_records(
staff_id: Optional[int] = Query(None, description="员工ID"),
department_id: Optional[int] = Query(None, description="科室ID"),
period_year: Optional[int] = Query(None, description="年度"),
period_month: Optional[int] = Query(None, description="月份"),
status: Optional[str] = Query(None, description="状态"),
page: int = Query(1, ge=1, description="页码"),
page_size: int = Query(20, ge=1, le=100, description="每页数量"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_active_user)
):
"""获取工资记录列表"""
records, total = await SalaryService.get_list(
db, staff_id, department_id, period_year, period_month, status, page, page_size
)
result = []
for record in records:
item = SalaryRecordResponse.model_validate(record).model_dump()
item["staff_name"] = record.staff.name if record.staff else None
item["department_name"] = record.staff.department.name if record.staff and record.staff.department else None
result.append(item)
return {
"code": 200,
"message": "success",
"data": result,
"total": total,
"page": page,
"page_size": page_size
}
@router.get("/{record_id}", summary="获取工资记录详情")
async def get_salary_record(
record_id: int,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_active_user)
):
"""获取工资记录详情"""
record = await SalaryService.get_by_id(db, record_id)
if not record:
raise HTTPException(status_code=404, detail="工资记录不存在")
result = SalaryRecordResponse.model_validate(record).model_dump()
result["staff_name"] = record.staff.name if record.staff else None
result["department_name"] = record.staff.department.name if record.staff and record.staff.department else None
return {"code": 200, "message": "success", "data": result}
@router.post("", summary="创建工资记录")
async def create_salary_record(
record_data: SalaryRecordCreate,
db: AsyncSession = Depends(get_db),
current_user: Annotated[User, Depends(get_current_manager_user)] = None
):
"""创建工资记录(需要管理员或经理权限)"""
record = await SalaryService.create(db, record_data)
return {"code": 200, "message": "创建成功", "data": {"id": record.id}}
@router.put("/{record_id}", summary="更新工资记录")
async def update_salary_record(
record_id: int,
record_data: SalaryRecordUpdate,
db: AsyncSession = Depends(get_db),
current_user: Annotated[User, Depends(get_current_manager_user)] = None
):
"""更新工资记录(需要管理员或经理权限)"""
record = await SalaryService.update(db, record_id, record_data)
if not record:
raise HTTPException(status_code=400, detail="无法更新,记录不存在或状态不允许")
return {"code": 200, "message": "更新成功", "data": {"id": record.id}}
@router.post("/generate", summary="根据考核生成工资")
async def generate_salary(
staff_id: int = Query(..., description="员工ID"),
period_year: int = Query(..., description="年度"),
period_month: int = Query(..., description="月份"),
db: AsyncSession = Depends(get_db),
current_user: Annotated[User, Depends(get_current_manager_user)] = None
):
"""根据考核记录生成工资记录(需要管理员或经理权限)"""
record = await SalaryService.generate_from_assessment(
db, staff_id, period_year, period_month
)
if not record:
raise HTTPException(status_code=400, detail="无法生成,未找到已确认的考核记录或已存在工资记录")
return {"code": 200, "message": "生成成功", "data": {"id": record.id}}
@router.post("/batch-generate", summary="批量生成工资")
async def batch_generate_salary(
department_id: int = Query(..., description="科室ID"),
period_year: int = Query(..., description="年度"),
period_month: int = Query(..., description="月份"),
db: AsyncSession = Depends(get_db),
current_user: Annotated[User, Depends(get_current_manager_user)] = None
):
"""为科室批量生成工资记录(需要管理员或经理权限)"""
records = await SalaryService.batch_generate_for_department(
db, department_id, period_year, period_month
)
return {
"code": 200,
"message": f"成功生成 {len(records)} 条工资记录",
"data": {"count": len(records)}
}
@router.post("/{record_id}/confirm", summary="确认工资")
async def confirm_salary(
record_id: int,
db: AsyncSession = Depends(get_db),
current_user: Annotated[User, Depends(get_current_manager_user)] = None
):
"""确认工资(需要管理员或经理权限)"""
record = await SalaryService.confirm(db, record_id)
if not record:
raise HTTPException(status_code=400, detail="无法确认,记录不存在或状态不允许")
return {"code": 200, "message": "确认成功"}
@router.post("/batch-confirm", summary="批量确认工资")
async def batch_confirm_salary(
period_year: int = Query(..., description="年度"),
period_month: int = Query(..., description="月份"),
department_id: Optional[int] = Query(None, description="科室ID"),
db: AsyncSession = Depends(get_db),
current_user: Annotated[User, Depends(get_current_manager_user)] = None
):
"""批量确认工资(需要管理员或经理权限)"""
count = await SalaryService.batch_confirm(db, period_year, period_month, department_id)
return {"code": 200, "message": f"成功确认 {count} 条工资记录", "data": {"count": count}}