import uuid from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, func from sqlalchemy.exc import IntegrityError from app.domains.tenants.models import Tenant from app.domains.auth.models import User async def list_tenants(db: AsyncSession) -> list[dict]: """Return all tenants with user counts.""" result = await db.execute( select( Tenant, func.count(User.id).label("user_count"), ) .outerjoin(User, User.tenant_id == Tenant.id) .group_by(Tenant.id) .order_by(Tenant.created_at) ) rows = result.all() tenants = [] for tenant, user_count in rows: tenants.append({"tenant": tenant, "user_count": user_count}) return tenants async def get_tenant(db: AsyncSession, tenant_id: uuid.UUID) -> Tenant | None: result = await db.execute(select(Tenant).where(Tenant.id == tenant_id)) return result.scalar_one_or_none() async def create_tenant(db: AsyncSession, name: str, slug: str, is_active: bool = True) -> Tenant: tenant = Tenant(name=name, slug=slug, is_active=is_active) db.add(tenant) await db.commit() await db.refresh(tenant) return tenant async def update_tenant( db: AsyncSession, tenant_id: uuid.UUID, name: str | None = None, slug: str | None = None, is_active: bool | None = None, ) -> Tenant | None: tenant = await get_tenant(db, tenant_id) if not tenant: return None if name is not None: tenant.name = name if slug is not None: tenant.slug = slug if is_active is not None: tenant.is_active = is_active await db.commit() await db.refresh(tenant) return tenant async def delete_tenant(db: AsyncSession, tenant_id: uuid.UUID) -> bool: """Delete a tenant. Returns False if tenant has users or does not exist.""" tenant = await get_tenant(db, tenant_id) if not tenant: return False # Check for users result = await db.execute( select(func.count(User.id)).where(User.tenant_id == tenant_id) ) user_count = result.scalar_one() if user_count > 0: return False await db.delete(tenant) await db.commit() return True