- Todos los strings de branding actualizados:
- "AALN" / "AALN Law" → "AAL"
- "Arias, Abrego, López & Noriega" → "Arias, Abrego & López"
- "M. Noriega" (placeholder en sample card del landing) → "M. Arias"
- Website link cambia de aalnlaw.com a aal-law.com en landing
y footer del portal
- Filenames de exportación a Excel/PDF: *_AALN → *_AAL
- Footer del PDF compartido (DonnaExport.toPDF) actualizado
- Mensajes de denegación de OAuth callback actualizados
- README refleja nuevo nombre y URL del firm
OAuth sigue aceptando @aal-law.com y @aalnlaw.com como dominios
válidos (configurado en /etc/donna/donna.env) para no romper logins
durante la transición de correos.
- Apps.catalog() ahora recibe isSocio y emite "Reporte de Horas"
(todos) y "Panel de Control" (solo socios/admin)
- Eliminado el placeholder "Directorio de Clientes"
- Removidos los iconos de reloj y engranaje del header en home,
tramites, escrituras, calendario, horas y admin (la navegación
ahora pasa por las tarjetas del portal)
- Iconos clock y gear agregados a la función icon() del home
- Lista con eventos del día agrupados: manuales, escrituras, trámites
- Visibilidad: eventos manuales y escrituras → todos los usuarios;
trámites legales → solo creador, abogado nombrado o involucrado
(mismo canView() que en el módulo de trámites)
- Cada evento es clickable y navega al módulo correspondiente
(/calendario, /escrituras/?edit=ID, /tramites/?edit=CODIGO)
- Cards muestran: título + cliente + abogado + estatus, con tags
de tipo y departamento; eventos manuales muestran rango horario
y creador
NUEVA APP /horas/
* public/horas/index.php — Bootstrap::inject del view
* public/horas/api.php — endpoint GET ?action=list que retorna:
- entries: entradas detalladas con join a tramites_legales (link,
título, cliente, departamento, estatus)
- by_user: agregado por persona (solo socio/admin)
- avail_users: dropdown de usuarios para filtrar (solo socio/admin)
- total_hrs, is_socio, my_name
Filtros: ?from=YYYY-MM-DD, ?to=YYYY-MM-DD, ?user=ID
* views/horas.html — UI con:
- Header estandarizado (Portal, sync, user-chip, gear si socio, logout)
- Toolbar de filtros: rango de fechas + dropdown usuario (solo socio)
+ atajos rápidos (Hoy / Semana / Mes / Año / Todo)
- KPIs: Total horas, Entradas, Personas con horas (socio)
- Tarjetas "Por persona" (solo socio), click filtra por ese usuario
- Tabla detalle con link al trámite (?edit=CODIGO) + departamento +
horas en h:mm + descripción
VISIBILIDAD
* Abogado/usuario ve solo sus horas (match por h.abogado = mi_name).
* Socio/admin ve todas las horas. Puede filtrar por persona.
* Admin oculto del dropdown de personas (queries excluyen role=admin).
ICONO DE RELOJ EN HEADERS
* Agregado .btn-clock (alias visual de .btn-gear) en:
escrituras.html, tramites.html, calendario.html, admin.html,
horas.html, public/index.php (landing).
* Posición: al lado del user-chip, antes del gear/logout.
* Visible para todos los autenticados (no restringido por rol).
BUG FIX
* admin.html: el filtro <select id="f-activo"> y el modal <input id="f-activo">
tenían el MISMO id. document.getElementById devolvía el select (primer en
DOM order) y la lectura .checked siempre era undefined → JSON enviaba el
valor stale del select. Renombré el filtro a `f-activo-filter`.
REFACTOR: drop apellido, usar Nombre Completo
* Migración 007: copia apellido→name para placeholders, migra
escrituras_tramites.abogado y tramites_legales.abogado a usar nombre
completo, DROP COLUMN apellido + índice.
* Lookups: abogadoApellidos() → abogadoNames() filtra socios+abogados
activos con name no vacío.
* Auth.php: drop método apellido(), agregado userName().
* tramites/api.php: visibilidad usa users.name = t.abogado.
* admin/api.php: drop apellido en create/update payloads.
* admin.html: drop columna y campo Apellido del table y form.
* Bootstrap envía window.DONNA.abogados con nombres completos.
LANDING (index.php)
* Gear icon en dash-header visible solo si Auth::isSocio() (chequeo
server-side, sin flash de JS).
CLEANUP
* Eliminado logging de debug en admin/api.php que se agregó para
diagnosticar el bug del activo.
PERMISOS (sin cambios — confirmación)
* Trámites Legales: solo socio/abogado pueden crear (canCreate() ya lo
enforza desde 2db8f23).
* Escrituras: cualquier rol autenticado puede crear (escrituras/api.php
nunca tuvo restricción).
Setup completo del portal interno donna.aal-law.com:
* Landing público con OAuth login + grid de apps autenticado
* Flujo OAuth2 contra Mailcow (mail.aal-law.com)
* Sesiones SSO compartidas en el dominio (cookie donna_session, 8h)
* Whitelist de dominios aal-law.com / aalnlaw.com
* App "Control de Escrituras" migrada desde ZH-Consultores/control-escrituras
(mismo schema, mismo frontend, ahora con shared Auth/Db/Config libs)
* Migraciones SQL para users, escrituras_tramites, escrituras_historial
* Caddy on :80 con rewrite extless → .php
* Backup diario MariaDB (systemd timer + script) con retención 14d
* Documentación de arquitectura en README + infra files en docs/infra