from typing import List, Optional from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy import text from sqlalchemy.orm import Session from app.core.database import get_db from app.models.tenant import Tenant from app.models.result import TenantScheduleResult from app.schemas.tenant import TenantCreate, TenantUpdate, TenantResponse, TenantStatusLight router = APIRouter(prefix="/tenants", tags=["tenants"]) def _get_lights(db: Session, tenant_id: int) -> Optional[TenantStatusLight]: result = ( db.query(TenantScheduleResult) .filter(TenantScheduleResult.tenant_id == tenant_id) .order_by(TenantScheduleResult.recorded_at.desc()) .first() ) if not result: return None return TenantStatusLight( sso_result=result.sso_result, mailbox_result=result.mailbox_result, nc_result=result.nc_result, office_result=result.office_result, quota_usage=result.quota_usage, ) @router.get("", response_model=List[TenantResponse]) def list_tenants( is_active: Optional[bool] = Query(None), db: Session = Depends(get_db), ): q = db.query(Tenant) if is_active is not None: q = q.filter(Tenant.is_active == is_active) tenants = q.order_by(Tenant.id).all() result = [] for t in tenants: resp = TenantResponse.model_validate(t) resp.lights = _get_lights(db, t.id) result.append(resp) return result @router.post("", response_model=TenantResponse, status_code=201) def create_tenant(payload: TenantCreate, db: Session = Depends(get_db)): if db.query(Tenant).filter(Tenant.code == payload.code).first(): raise HTTPException(status_code=409, detail="Tenant code already exists") if db.query(Tenant).filter(Tenant.domain == payload.domain).first(): raise HTTPException(status_code=409, detail="Domain already exists") tenant = Tenant(**payload.model_dump()) db.add(tenant) db.commit() db.refresh(tenant) resp = TenantResponse.model_validate(tenant) resp.lights = None return resp @router.get("/{tenant_id}", response_model=TenantResponse) def get_tenant(tenant_id: int, db: Session = Depends(get_db)): tenant = db.get(Tenant, tenant_id) if not tenant: raise HTTPException(status_code=404, detail="Tenant not found") resp = TenantResponse.model_validate(tenant) resp.lights = _get_lights(db, tenant_id) return resp @router.put("/{tenant_id}", response_model=TenantResponse) def update_tenant(tenant_id: int, payload: TenantUpdate, db: Session = Depends(get_db)): tenant = db.get(Tenant, tenant_id) if not tenant: raise HTTPException(status_code=404, detail="Tenant not found") for field, value in payload.model_dump(exclude_none=True).items(): setattr(tenant, field, value) db.commit() db.refresh(tenant) resp = TenantResponse.model_validate(tenant) resp.lights = _get_lights(db, tenant_id) return resp @router.delete("/{tenant_id}", status_code=204) def delete_tenant(tenant_id: int, db: Session = Depends(get_db)): tenant = db.get(Tenant, tenant_id) if not tenant: raise HTTPException(status_code=404, detail="Tenant not found") db.delete(tenant) db.commit()