from typing import List from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from app.core.bx_auth import BxUserContext, get_bx_current_user from app.core.database import get_db from app.core.tenant_context import get_tenant_no from app.schemas.bx.common import ApiResponse from app.schemas.bx.expense_item import ExpenseItemCreate, ExpenseItemOut, ExpenseItemUpdate from app.services.bx.expense_item import ExpenseItemService router = APIRouter(prefix="/expense-items", tags=["费用项目管理"]) @router.get("/tree", response_model=ApiResponse[List[ExpenseItemOut]]) def get_expense_item_tree( db: Session = Depends(get_db), user: BxUserContext = Depends(get_bx_current_user), ): tenant_no = get_tenant_no(db, user.to_tenant_user_dict()) tree = ExpenseItemService.get_item_tree(db, tenant_no, user=user) return ApiResponse(data=[ExpenseItemOut.model_validate(i) for i in tree]) @router.get("/{item_id}", response_model=ApiResponse[ExpenseItemOut]) def get_expense_item( item_id: str, db: Session = Depends(get_db), user: BxUserContext = Depends(get_bx_current_user), ): tenant_no = get_tenant_no(db, user.to_tenant_user_dict()) item = ExpenseItemService.get_by_id(db, item_id, tenant_no, user=user) if not item: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="费用项目不存在") return ApiResponse(data=ExpenseItemOut.model_validate(item)) @router.post("/", response_model=ApiResponse[ExpenseItemOut]) def create_expense_item( body: ExpenseItemCreate, db: Session = Depends(get_db), user: BxUserContext = Depends(get_bx_current_user), ): try: item = ExpenseItemService.create(db, body.model_dump(exclude_unset=True), user=user) db.commit() db.refresh(item) except ValueError as exc: db.rollback() raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc return ApiResponse(data=ExpenseItemOut.model_validate(item)) @router.put("/{item_id}", response_model=ApiResponse[ExpenseItemOut]) def update_expense_item( item_id: str, body: ExpenseItemUpdate, db: Session = Depends(get_db), user: BxUserContext = Depends(get_bx_current_user), ): try: item = ExpenseItemService.update( db, item_id, body.model_dump(exclude_unset=True), user=user ) if not item: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="费用项目不存在") db.commit() db.refresh(item) except ValueError as exc: db.rollback() raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc return ApiResponse(data=ExpenseItemOut.model_validate(item)) @router.delete("/{item_id}", response_model=ApiResponse[None]) def delete_expense_item( item_id: str, db: Session = Depends(get_db), user: BxUserContext = Depends(get_bx_current_user), ): tenant_no = get_tenant_no(db, user.to_tenant_user_dict()) item = ExpenseItemService.get_by_id(db, item_id, tenant_no, user=user) if not item: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="费用项目不存在") ExpenseItemService.soft_delete(db, item_id, user=user) db.commit() return ApiResponse(data=None)