From 223395b43053fffec1c8e75f4cfd65d9335ffe7b Mon Sep 17 00:00:00 2001 From: Ernesto Herrera Date: Thu, 16 Jul 2026 18:05:44 -0600 Subject: [PATCH] =?UTF-8?q?feat(core):=20compa=C3=B1=C3=ADa=20por=20tenant?= =?UTF-8?q?=20(1:1)=20en=20my-companies=20para=20desbloquear=20el=20dashbo?= =?UTF-8?q?ard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit get_my_companies devolvía [] (STUB) → sin compañía activa el CRM bloqueaba todo. Modelo: una empresa por tenant (company_id = tenant_id, como el agente de carga). Asegura el vínculo user↔tenant↔company; los permisos se resuelven en /permissions/me (bootstrap de super_admin al primer usuario). Co-Authored-By: Claude Opus 4.8 (1M context) --- backend/api/v1/modules/core/auth/routes.py | 46 ++++++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/backend/api/v1/modules/core/auth/routes.py b/backend/api/v1/modules/core/auth/routes.py index f566340..7473724 100644 --- a/backend/api/v1/modules/core/auth/routes.py +++ b/backend/api/v1/modules/core/auth/routes.py @@ -402,10 +402,16 @@ async def dev_login(): @router.get("/my-companies") async def get_my_companies( current_user: dict = Depends(get_current_user), + db: Session = Depends(get_core_db), ): """ Retorna las compañías accesibles para el usuario actual. - STUB: implementa con tu modelo de compañías. + + Modelo del CRM: una compañía por tenant (1:1) — el ``company_id`` coincide con + el ``tenant_id``. Cada agente de carga (tenant) opera como una empresa. Se + garantiza el vínculo usuario↔tenant↔company; los permisos de la empresa se + resuelven en ``/permissions/me`` (bootstrap de super_admin al primer usuario). + En dev-local retorna una compañía ficticia para que el dashboard funcione. """ from core.config import settings @@ -415,8 +421,42 @@ async def get_my_companies( "id": settings.DEV_LOCAL_AUTH_COMPANY_ID, "name": "Empresa Dev Local", "tenant_id": settings.DEV_LOCAL_AUTH_TENANT_ID, + "rfc": None, + "logo": None, "is_active": True, }] - # Implementa aquí la consulta real a tu tabla de compañías. - return [] + from core.security import ( + resolve_effective_tenant_id_from_user, + _ensure_user_tenant_for_company, + ) + from api.v1.modules.core.tenants.models import Tenant + + tenant_id = resolve_effective_tenant_id_from_user(current_user) + if not tenant_id: + return [] + + tenant = db.query(Tenant).filter(Tenant.id == int(tenant_id)).first() + name = ( + (tenant.name if tenant else None) + or current_user.get("tenant_slug") + or "Mi empresa" + ) + + # Garantizar el vínculo usuario↔tenant↔company (company_id = tenant_id). + user_id = current_user.get("sub") or current_user.get("id") + if user_id: + try: + _ensure_user_tenant_for_company(db, str(user_id), int(tenant_id), int(tenant_id)) + except Exception as exc: + logger = __import__("logging").getLogger(__name__) + logger.warning("no se pudo asegurar user_tenant (no bloquea): %s", exc) + + return [{ + "id": int(tenant_id), + "name": name, + "tenant_id": int(tenant_id), + "rfc": None, + "logo": None, + "is_active": True, + }]