"""固定成本路由 实现固定成本的 CRUD 操作 """ from typing import List, Optional from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy import select, func from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db from app.models.fixed_cost import FixedCost from app.schemas.common import ResponseModel, PaginatedData, ErrorCode from app.schemas.fixed_cost import ( FixedCostCreate, FixedCostUpdate, FixedCostResponse, CostType, AllocationMethod, ) router = APIRouter() @router.get("", response_model=ResponseModel[PaginatedData[FixedCostResponse]]) async def get_fixed_costs( page: int = Query(1, ge=1, description="页码"), page_size: int = Query(20, ge=1, le=100, description="每页数量"), year_month: Optional[str] = Query(None, description="年月筛选"), cost_type: Optional[CostType] = Query(None, description="类型筛选"), is_active: Optional[bool] = Query(None, description="是否启用筛选"), db: AsyncSession = Depends(get_db), ): """获取固定成本列表""" query = select(FixedCost) if year_month: query = query.where(FixedCost.year_month == year_month) if cost_type: query = query.where(FixedCost.cost_type == cost_type.value) if is_active is not None: query = query.where(FixedCost.is_active == is_active) query = query.order_by(FixedCost.year_month.desc(), FixedCost.id) # 分页 offset = (page - 1) * page_size query = query.offset(offset).limit(page_size) result = await db.execute(query) fixed_costs = result.scalars().all() # 统计总数 count_query = select(func.count(FixedCost.id)) if year_month: count_query = count_query.where(FixedCost.year_month == year_month) if cost_type: count_query = count_query.where(FixedCost.cost_type == cost_type.value) if is_active is not None: count_query = count_query.where(FixedCost.is_active == is_active) total_result = await db.execute(count_query) total = total_result.scalar() or 0 return ResponseModel( data=PaginatedData( items=[FixedCostResponse.model_validate(f) for f in fixed_costs], total=total, page=page, page_size=page_size, total_pages=(total + page_size - 1) // page_size, ) ) @router.get("/summary", response_model=ResponseModel) async def get_fixed_costs_summary( year_month: str = Query(..., description="年月"), db: AsyncSession = Depends(get_db), ): """获取指定月份的固定成本汇总""" query = select(FixedCost).where( FixedCost.year_month == year_month, FixedCost.is_active == True, ) result = await db.execute(query) fixed_costs = result.scalars().all() # 按类型汇总 summary_by_type = {} total_amount = 0 for cost in fixed_costs: cost_type = cost.cost_type if cost_type not in summary_by_type: summary_by_type[cost_type] = 0 summary_by_type[cost_type] += float(cost.monthly_amount) total_amount += float(cost.monthly_amount) return ResponseModel( data={ "year_month": year_month, "total_amount": total_amount, "by_type": summary_by_type, "count": len(fixed_costs), } ) @router.get("/{fixed_cost_id}", response_model=ResponseModel[FixedCostResponse]) async def get_fixed_cost( fixed_cost_id: int, db: AsyncSession = Depends(get_db), ): """获取单个固定成本详情""" result = await db.execute(select(FixedCost).where(FixedCost.id == fixed_cost_id)) fixed_cost = result.scalar_one_or_none() if not fixed_cost: raise HTTPException( status_code=404, detail={"code": ErrorCode.NOT_FOUND, "message": "固定成本不存在"} ) return ResponseModel(data=FixedCostResponse.model_validate(fixed_cost)) @router.post("", response_model=ResponseModel[FixedCostResponse]) async def create_fixed_cost( data: FixedCostCreate, db: AsyncSession = Depends(get_db), ): """创建固定成本""" fixed_cost = FixedCost(**data.model_dump()) db.add(fixed_cost) await db.flush() await db.refresh(fixed_cost) return ResponseModel(message="创建成功", data=FixedCostResponse.model_validate(fixed_cost)) @router.put("/{fixed_cost_id}", response_model=ResponseModel[FixedCostResponse]) async def update_fixed_cost( fixed_cost_id: int, data: FixedCostUpdate, db: AsyncSession = Depends(get_db), ): """更新固定成本""" result = await db.execute(select(FixedCost).where(FixedCost.id == fixed_cost_id)) fixed_cost = result.scalar_one_or_none() if not fixed_cost: raise HTTPException( status_code=404, detail={"code": ErrorCode.NOT_FOUND, "message": "固定成本不存在"} ) update_data = data.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(fixed_cost, field, value) await db.flush() await db.refresh(fixed_cost) return ResponseModel(message="更新成功", data=FixedCostResponse.model_validate(fixed_cost)) @router.delete("/{fixed_cost_id}", response_model=ResponseModel) async def delete_fixed_cost( fixed_cost_id: int, db: AsyncSession = Depends(get_db), ): """删除固定成本""" result = await db.execute(select(FixedCost).where(FixedCost.id == fixed_cost_id)) fixed_cost = result.scalar_one_or_none() if not fixed_cost: raise HTTPException( status_code=404, detail={"code": ErrorCode.NOT_FOUND, "message": "固定成本不存在"} ) await db.delete(fixed_cost) return ResponseModel(message="删除成功")