""" 事業部管理 API """ from typing import List from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from app.db.session import get_db from app.models.business_unit import BusinessUnit from app.schemas.business_unit import ( BusinessUnitCreate, BusinessUnitUpdate, BusinessUnitResponse, BusinessUnitListItem, ) from app.schemas.department import DepartmentListItem from app.schemas.response import MessageResponse router = APIRouter() @router.get("/", response_model=List[BusinessUnitListItem]) def get_business_units( db: Session = Depends(get_db), include_inactive: bool = False, ): """ 獲取事業部列表 Args: include_inactive: 是否包含停用的事業部 """ query = db.query(BusinessUnit) if not include_inactive: query = query.filter(BusinessUnit.is_active == True) business_units = query.order_by(BusinessUnit.id).all() return [BusinessUnitListItem.model_validate(bu) for bu in business_units] @router.get("/{business_unit_id}", response_model=BusinessUnitResponse) def get_business_unit( business_unit_id: int, db: Session = Depends(get_db), ): """ 獲取事業部詳情 """ business_unit = db.query(BusinessUnit).filter( BusinessUnit.id == business_unit_id ).first() if not business_unit: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Business unit with id {business_unit_id} not found" ) response = BusinessUnitResponse.model_validate(business_unit) response.departments_count = len(business_unit.departments) response.employees_count = business_unit.employee_identities.count() return response @router.post("/", response_model=BusinessUnitResponse, status_code=status.HTTP_201_CREATED) def create_business_unit( business_unit_data: BusinessUnitCreate, db: Session = Depends(get_db), ): """ 創建事業部 檢查: - code 唯一性 - email_domain 唯一性 """ # 檢查 code 是否已存在 existing_code = db.query(BusinessUnit).filter( BusinessUnit.code == business_unit_data.code ).first() if existing_code: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"Business unit code '{business_unit_data.code}' already exists" ) # 檢查 email_domain 是否已存在 existing_domain = db.query(BusinessUnit).filter( BusinessUnit.email_domain == business_unit_data.email_domain ).first() if existing_domain: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"Email domain '{business_unit_data.email_domain}' already exists" ) # 創建事業部 business_unit = BusinessUnit(**business_unit_data.model_dump()) db.add(business_unit) db.commit() db.refresh(business_unit) # TODO: 創建審計日誌 response = BusinessUnitResponse.model_validate(business_unit) response.departments_count = 0 response.employees_count = 0 return response @router.put("/{business_unit_id}", response_model=BusinessUnitResponse) def update_business_unit( business_unit_id: int, business_unit_data: BusinessUnitUpdate, db: Session = Depends(get_db), ): """ 更新事業部 注意: code 和 email_domain 不可修改 (在 Schema 中已限制) """ business_unit = db.query(BusinessUnit).filter( BusinessUnit.id == business_unit_id ).first() if not business_unit: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Business unit with id {business_unit_id} not found" ) # 更新欄位 update_data = business_unit_data.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(business_unit, field, value) db.commit() db.refresh(business_unit) # TODO: 創建審計日誌 response = BusinessUnitResponse.model_validate(business_unit) response.departments_count = len(business_unit.departments) response.employees_count = business_unit.employee_identities.count() return response @router.delete("/{business_unit_id}", response_model=MessageResponse) def delete_business_unit( business_unit_id: int, db: Session = Depends(get_db), ): """ 停用事業部 注意: 這是軟刪除,只將 is_active 設為 False """ business_unit = db.query(BusinessUnit).filter( BusinessUnit.id == business_unit_id ).first() if not business_unit: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Business unit with id {business_unit_id} not found" ) # 檢查是否有活躍的員工 active_employees = business_unit.employee_identities.filter_by(is_active=True).count() if active_employees > 0: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"Cannot deactivate business unit with {active_employees} active employees" ) business_unit.is_active = False db.commit() # TODO: 創建審計日誌 return MessageResponse( message=f"Business unit '{business_unit.name}' has been deactivated" ) @router.get("/{business_unit_id}/departments", response_model=List[DepartmentListItem]) def get_business_unit_departments( business_unit_id: int, db: Session = Depends(get_db), ): """ 獲取事業部的所有部門 """ business_unit = db.query(BusinessUnit).filter( BusinessUnit.id == business_unit_id ).first() if not business_unit: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Business unit with id {business_unit_id} not found" ) return [DepartmentListItem.model_validate(dept) for dept in business_unit.departments]