from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from pydantic import BaseModel, ConfigDict, EmailStr from typing import List, Optional import uuid from app.core.database import get_db from app.models.tenant import Tenant, TenantStatus from app.api import deps router = APIRouter() class TenantBase(BaseModel): name: str slug: str domain: Optional[str] = None contact_email: Optional[EmailStr] = None contact_phone: Optional[str] = None class TenantCreate(TenantBase): pass class TenantUpdate(BaseModel): name: Optional[str] = None slug: Optional[str] = None domain: Optional[str] = None contact_email: Optional[EmailStr] = None contact_phone: Optional[str] = None status: Optional[TenantStatus] = None class TenantResponse(TenantBase): id: uuid.UUID status: TenantStatus model_config = ConfigDict(from_attributes=True) @router.get("/", response_model=List[TenantResponse]) async def read_tenants( skip: int = 0, limit: int = 100, db: AsyncSession = Depends(get_db), current_user = Depends(deps.get_current_active_superuser) ): query = select(Tenant).offset(skip).limit(limit) result = await db.execute(query) return result.scalars().all() @router.post("/", response_model=TenantResponse) async def create_tenant( tenant: TenantCreate, db: AsyncSession = Depends(get_db), current_user = Depends(deps.get_current_active_superuser) ): # Check existing slug query = select(Tenant).where(Tenant.slug == tenant.slug) result = await db.execute(query) if result.scalar_one_or_none(): raise HTTPException(status_code=400, detail="Tenant slug already exists") db_tenant = Tenant(**tenant.model_dump()) db.add(db_tenant) await db.commit() await db.refresh(db_tenant) return db_tenant @router.get("/{tenant_id}", response_model=TenantResponse) async def read_tenant( tenant_id: uuid.UUID, db: AsyncSession = Depends(get_db), current_user = Depends(deps.get_current_active_superuser) ): tenant = await db.get(Tenant, tenant_id) if not tenant: raise HTTPException(status_code=404, detail="Tenant not found") return tenant @router.put("/{tenant_id}", response_model=TenantResponse) async def update_tenant( tenant_id: uuid.UUID, tenant_in: TenantUpdate, db: AsyncSession = Depends(get_db), current_user = Depends(deps.get_current_active_superuser) ): tenant = await db.get(Tenant, tenant_id) if not tenant: raise HTTPException(status_code=404, detail="Tenant not found") update_data = tenant_in.model_dump(exclude_unset=True) if "status" in update_data: # Convertir string a enum TenantStatus status_value = update_data.pop("status") if isinstance(status_value, str): tenant.status = TenantStatus(status_value) else: tenant.status = status_value for field, value in update_data.items(): setattr(tenant, field, value) await db.commit() await db.refresh(tenant) return tenant @router.delete("/{tenant_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_tenant( tenant_id: uuid.UUID, db: AsyncSession = Depends(get_db), current_user = Depends(deps.get_current_active_superuser) ): """Eliminar un cliente (tenant) por ID.""" tenant = await db.get(Tenant, tenant_id) if not tenant: raise HTTPException(status_code=404, detail="Tenant not found") await db.delete(tenant) await db.commit() return {"message": "Tenant deleted successfully"}