mirror of
https://github.com/idrainformatica/PecFlow.git
synced 2026-06-16 12:45:42 +02:00
Multitenancy
This commit is contained in:
@@ -4,14 +4,15 @@ Servizio tenant – gestione organizzazioni (solo super_admin).
|
||||
|
||||
import uuid
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.core.exceptions import ConflictError, NotFoundError
|
||||
from app.core.security import hash_password
|
||||
from app.models.mailbox import Mailbox
|
||||
from app.models.tenant import Tenant
|
||||
from app.models.user import User
|
||||
from app.schemas.tenant import TenantCreateRequest, TenantUpdateRequest
|
||||
from app.schemas.tenant import TenantCreateRequest, TenantResponse, TenantUpdateRequest
|
||||
|
||||
|
||||
class TenantService:
|
||||
@@ -56,12 +57,72 @@ class TenantService:
|
||||
raise NotFoundError("tenant")
|
||||
return tenant
|
||||
|
||||
async def get_tenant_with_stats(self, tenant_id: uuid.UUID) -> TenantResponse:
|
||||
"""Restituisce il tenant con conteggi utenti e caselle."""
|
||||
tenant = await self.get_tenant(tenant_id)
|
||||
|
||||
user_count = (
|
||||
await self.db.execute(
|
||||
select(func.count(User.id)).where(
|
||||
User.tenant_id == tenant_id,
|
||||
User.is_active == True, # noqa: E712
|
||||
)
|
||||
)
|
||||
).scalar_one()
|
||||
|
||||
mailbox_count = (
|
||||
await self.db.execute(
|
||||
select(func.count(Mailbox.id)).where(
|
||||
Mailbox.tenant_id == tenant_id,
|
||||
Mailbox.status != "deleted",
|
||||
)
|
||||
)
|
||||
).scalar_one()
|
||||
|
||||
resp = TenantResponse.model_validate(tenant)
|
||||
resp.user_count = user_count
|
||||
resp.mailbox_count = mailbox_count
|
||||
return resp
|
||||
|
||||
async def list_tenants(self) -> list[Tenant]:
|
||||
result = await self.db.execute(
|
||||
select(Tenant).order_by(Tenant.created_at.desc())
|
||||
)
|
||||
return list(result.scalars().all())
|
||||
|
||||
async def list_tenants_with_stats(self) -> list[TenantResponse]:
|
||||
"""
|
||||
Restituisce tutti i tenant con conteggi utenti e caselle in una
|
||||
singola query efficiente (LEFT JOIN con GROUP BY).
|
||||
"""
|
||||
stmt = (
|
||||
select(
|
||||
Tenant,
|
||||
func.count(User.id.distinct()).label("user_count"),
|
||||
func.count(Mailbox.id.distinct()).label("mailbox_count"),
|
||||
)
|
||||
.outerjoin(
|
||||
User,
|
||||
(User.tenant_id == Tenant.id) & (User.is_active == True), # noqa: E712
|
||||
)
|
||||
.outerjoin(
|
||||
Mailbox,
|
||||
(Mailbox.tenant_id == Tenant.id) & (Mailbox.status != "deleted"),
|
||||
)
|
||||
.group_by(Tenant.id)
|
||||
.order_by(Tenant.created_at.desc())
|
||||
)
|
||||
|
||||
rows = (await self.db.execute(stmt)).all()
|
||||
result = []
|
||||
for row in rows:
|
||||
tenant_obj, user_count, mailbox_count = row
|
||||
resp = TenantResponse.model_validate(tenant_obj)
|
||||
resp.user_count = user_count or 0
|
||||
resp.mailbox_count = mailbox_count or 0
|
||||
result.append(resp)
|
||||
return result
|
||||
|
||||
async def update_tenant(
|
||||
self, tenant_id: uuid.UUID, data: TenantUpdateRequest
|
||||
) -> Tenant:
|
||||
|
||||
Reference in New Issue
Block a user