add backend source code
This commit is contained in:
216
backend/app/api/v1/finance.py
Normal file
216
backend/app/api/v1/finance.py
Normal file
@@ -0,0 +1,216 @@
|
||||
"""
|
||||
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": "删除成功"}
|
||||
Reference in New Issue
Block a user