Files
2026-02-28 15:06:52 +08:00

217 lines
7.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 (
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": "删除成功"}