""" 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 ( FinanceRecordCreate, FinanceRecordUpdate, FinanceRecordResponse, DepartmentBalance, CategorySummary, ResponseBase ) from app.services.finance_service import FinanceService from app.models.finance import RevenueCategory, ExpenseCategory, FinanceType from app.models.models import User router = APIRouter(prefix="/finance", tags=["财务核算"]) @router.get("/revenue", summary="获取科室收入") async def get_revenue( department_id: Optional[int] = Query(None, description="科室ID"), period_year: Optional[int] = Query(None, description="年度"), period_month: Optional[int] = Query(None, description="月份"), db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_active_user) ): """获取科室收入列表""" data = await FinanceService.get_department_revenue( db, department_id, period_year, period_month ) return { "code": 200, "message": "success", "data": data } @router.get("/expense", summary="获取科室支出") async def get_expense( department_id: Optional[int] = Query(None, description="科室ID"), period_year: Optional[int] = Query(None, description="年度"), period_month: Optional[int] = Query(None, description="月份"), db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_active_user) ): """获取科室支出列表""" data = await FinanceService.get_department_expense( db, department_id, period_year, period_month ) return { "code": 200, "message": "success", "data": data } @router.get("/balance", summary="获取收支结余") async def get_balance( department_id: Optional[int] = Query(None, description="科室ID"), period_year: Optional[int] = Query(None, description="年度"), period_month: Optional[int] = Query(None, description="月份"), db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_active_user) ): """获取科室收支结余""" data = await FinanceService.get_department_balance( db, department_id, period_year, period_month ) return { "code": 200, "message": "success", "data": data } @router.get("/revenue/by-category", summary="按类别统计收入") async def get_revenue_by_category( department_id: Optional[int] = Query(None, description="科室ID"), period_year: Optional[int] = Query(None, description="年度"), period_month: Optional[int] = Query(None, description="月份"), db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_active_user) ): """按类别统计收入""" data = await FinanceService.get_revenue_by_category( db, department_id, period_year, period_month ) return { "code": 200, "message": "success", "data": data } @router.get("/expense/by-category", summary="按类别统计支出") async def get_expense_by_category( department_id: Optional[int] = Query(None, description="科室ID"), period_year: Optional[int] = Query(None, description="年度"), period_month: Optional[int] = Query(None, description="月份"), db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_active_user) ): """按类别统计支出""" data = await FinanceService.get_expense_by_category( db, department_id, period_year, period_month ) return { "code": 200, "message": "success", "data": data } @router.get("/summary", summary="获取科室财务汇总") async def get_department_summary( period_year: int = Query(..., description="年度"), period_month: int = Query(..., ge=1, le=12, description="月份"), db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_active_user) ): """获取所有科室的财务汇总""" data = await FinanceService.get_department_summary( db, period_year, period_month ) return { "code": 200, "message": "success", "data": data } @router.get("/categories", summary="获取财务类别") async def get_categories( current_user: User = Depends(get_current_active_user) ): """获取收入和支出类别""" revenue_categories = [ {"value": cat.value, "label": label} for cat, label in FinanceService.REVENUE_LABELS.items() ] expense_categories = [ {"value": cat.value, "label": label} for cat, label in FinanceService.EXPENSE_LABELS.items() ] return { "code": 200, "message": "success", "data": { "revenue": revenue_categories, "expense": expense_categories } } @router.post("", summary="创建财务记录") async def create_finance_record( record_data: FinanceRecordCreate, db: AsyncSession = Depends(get_db), current_user: Annotated[User, Depends(get_current_manager_user)] = None ): """创建财务记录(需要管理员或经理权限)""" # 验证类别 if record_data.finance_type == FinanceType.REVENUE: valid_categories = [cat.value for cat in RevenueCategory] else: valid_categories = [cat.value for cat in ExpenseCategory] if record_data.category not in valid_categories: raise HTTPException( status_code=400, detail=f"无效的类别: {record_data.category}" ) record = await FinanceService.create_finance_record( db, department_id=record_data.department_id, finance_type=record_data.finance_type, category=record_data.category, amount=record_data.amount, period_year=record_data.period_year, period_month=record_data.period_month, source=record_data.source, remark=record_data.remark ) return {"code": 200, "message": "创建成功", "data": {"id": record.id}} @router.put("/{record_id}", summary="更新财务记录") async def update_finance_record( record_id: int, record_data: FinanceRecordUpdate, db: AsyncSession = Depends(get_db), current_user: Annotated[User, Depends(get_current_manager_user)] = None ): """更新财务记录(需要管理员或经理权限)""" record = await FinanceService.update_finance_record( db, record_id, **record_data.model_dump(exclude_unset=True) ) if not record: raise HTTPException(status_code=404, detail="财务记录不存在") return {"code": 200, "message": "更新成功"} @router.delete("/{record_id}", summary="删除财务记录") async def delete_finance_record( record_id: int, db: AsyncSession = Depends(get_db), current_user: Annotated[User, Depends(get_current_manager_user)] = None ): """删除财务记录(需要管理员或经理权限)""" success = await FinanceService.delete_finance_record(db, record_id) if not success: raise HTTPException(status_code=404, detail="财务记录不存在") return {"code": 200, "message": "删除成功"}