From c7dcd171eeb713c82114989d4daaecfb49ca0640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Consultor=C3=ADa=20Alcaraz=20Salazar?= Date: Tue, 8 Sep 2026 22:17:21 +0000 Subject: [PATCH] Fix pantalla en blanco al entrar: landing por rol cuando el Dashboard no es visible + matrices de menus coherentes --- frontend/src/App.tsx | 29 ++++++++++++++++--- frontend/src/lib/auth.tsx | 2 +- .../skeen_whatsapp/controllers/frontend.py | 9 +++--- odoo-addons/skeen_whatsapp/roles.py | 2 +- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index c0b6c35..5854c5f 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -39,7 +39,9 @@ const RequireAuth: FC<{ children: ReactNode; href: string }> = ({ children, href const { user, loading, canSee } = useAuth(); if (loading) return ; if (!user) return ; - if (!canSee(href)) return ; + // La ruta "/" se maneja en HomeRoute (calcula landing por rol) para evitar + // el bucle de redirecciones cuando el rol no tiene '/' en la matriz. + if (!canSee(href) && href !== '/') return ; return <>{children}; }; @@ -50,11 +52,30 @@ const LoginRoute: FC = () => { return ; }; -// Pantalla inicial por rol: el médico aterriza directo en su Agenda +// Pantalla inicial por rol: el médico aterriza directo en su Agenda. +// Si el rol no tiene acceso al Dashboard (matriz por rol), aterriza en la +// primera sección visible; si no tiene ninguna, muestra "Sin acceso" en +// lugar de redirigir a "/" en bucle (pantalla en blanco). +const LANDING_CANDIDATOS = [ + '/agenda', '/mis-ventas', '/pacientes', '/pos', '/visitas', '/consultas', + '/expedientes', '/medicos', '/servicios', '/ventas', '/pagos', '/monedero', + '/inventario', '/cortes', '/reportes', '/cumpleanos', '/wacrm/messages', + '/wacrm/leads', '/configuracion', +]; + const HomeRoute: FC = () => { - const { user } = useAuth(); + const { user, canSee } = useAuth(); if (user?.role === 'medico') return ; - return ; + if (canSee('/')) return ; + for (const href of LANDING_CANDIDATOS) { + if (canSee(href)) return ; + } + return ( +
+

Sin acceso a módulos

+

Tu usuario no tiene secciones habilitadas. Contacta al administrador.

+
+ ); }; const App: FC = () => { diff --git a/frontend/src/lib/auth.tsx b/frontend/src/lib/auth.tsx index 4940e50..dde65ab 100644 --- a/frontend/src/lib/auth.tsx +++ b/frontend/src/lib/auth.tsx @@ -23,7 +23,7 @@ const ROLE_RANK: Record = { // 'gerencia' (gerencia de la clínica) ve toda la operación excepto // /configuracion (solo admin del sistema), /mis-ventas, /cumpleanos y /wacrm/*. const MENU_ROLES: Record = { - '/': ['admin', 'recepcion', 'medico', 'lectura', 'gerencia'], + '/' : ['admin', 'medico', 'recepcion', 'enfermeria', 'cosmetologia', 'psicologa', 'farmacia', 'gerencia', 'marketing', 'lectura'], '/agenda': ['admin', 'recepcion', 'medico', 'gerencia'], '/mis-ventas': ['medico'], '/pacientes': ['admin', 'recepcion', 'medico', 'lectura', 'gerencia'], diff --git a/odoo-addons/skeen_whatsapp/controllers/frontend.py b/odoo-addons/skeen_whatsapp/controllers/frontend.py index 24875af..84bfcd0 100644 --- a/odoo-addons/skeen_whatsapp/controllers/frontend.py +++ b/odoo-addons/skeen_whatsapp/controllers/frontend.py @@ -94,10 +94,9 @@ class SkeenFrontendController(http.Controller): if not login or not password: return json_response({'status': 'error', 'message': 'Usuario y contraseña son obligatorios'}, 400) User = request.env['skeen.frontend.user'].sudo() - # Login insensible a mayúsculas/minúsculas (la gente escribe "Andrea"). - # =ilike trata % y _ como comodines: se quitan para buscar literal. - login_lookup = login.replace('%', '').replace('_', '') - user = User.search([('login', '=ilike', login_lookup), ('active', '=', True)], limit=1) + # Login insensible a mayúsculas/minúsculas: los logins guardados + # están en minúsculas, se busca la forma exacta en minúsculas. + user = User.search([('login', '=', login.lower()), ('active', '=', True)], limit=1) if not user or not user.check_password(password): return json_response({'status': 'error', 'message': 'Credenciales inválidas'}, 401) user.write({'last_login': fields.Datetime.now()}) @@ -134,7 +133,7 @@ class SkeenFrontendController(http.Controller): def auth_users_create(self, **kw): try: data = _parse_json_body() - login = (data.get('login') or '').strip() + login = (data.get('login') or '').strip().lower() name = (data.get('name') or '').strip() password = data.get('password') or '' role = data.get('role') or 'recepcion' diff --git a/odoo-addons/skeen_whatsapp/roles.py b/odoo-addons/skeen_whatsapp/roles.py index 77c2819..e8e3005 100644 --- a/odoo-addons/skeen_whatsapp/roles.py +++ b/odoo-addons/skeen_whatsapp/roles.py @@ -47,7 +47,7 @@ MENU_ROLES_KEY = 'skeen.menu_roles' # operación EXCEPTO /configuracion (solo admin del sistema), /mis-ventas, # /cumpleanos y /wacrm/*. DEFAULT_MENU_ROLES = { - '/': ['admin', 'recepcion', 'medico', 'lectura', 'gerencia'], + '/' : ['admin', 'medico', 'recepcion', 'enfermeria', 'cosmetologia', 'psicologa', 'farmacia', 'gerencia', 'marketing', 'lectura'], '/agenda': ['admin', 'recepcion', 'medico', 'gerencia'], '/mis-ventas': ['medico'], '/pacientes': ['admin', 'recepcion', 'medico', 'lectura', 'gerencia'],