7 Commits
Author SHA1 Message Date
Soporte ZH Consultores 7e8500c7fb rebrand: AALN → AAL (Noriega salió de la sociedad)
- 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.
2026-06-04 22:56:31 -05:00
Soporte ZH Consultores eff590af47 feat(export): UI unificada de Excel + PDF en los 4 módulos
- Nuevos assets compartidos /assets/donna-export.{css,js}: botón
  "Exportar ▾" + menú dropdown Excel/PDF y helpers DonnaExport.toExcel
  / .toPDF / .attach / .buttonHtml
- escrituras: refactor de exportExcel/exportPDF para usar el módulo
  compartido (sin cambio de comportamiento)
- tramites: nuevo botón en la toolbar de cada tab (adm/corp/mig/lit),
  exporta los rows filtrados de ese tab; PDF excluye Involucrados
- calendario: nuevo botón al final de la toolbar, exporta visibleEvents()
  (respeta chips de origen y búsqueda)
- horas: reemplaza CSV server-side por XLSX client-side + agrega PDF;
  removida la acción ?action=export del api.php
2026-06-04 22:30:37 -05:00
Soporte ZH Consultores d9adfbae09 ui(home): horas y admin como módulos; quitar Directorio de Clientes
- 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
2026-06-04 21:25:47 -05:00
Soporte ZH Consultores d26ab5e855 feat(calendario): eventos manuales — reservas, cumpleaños, recordatorios
- Nueva tabla calendar_events (tipo, fecha, hora_inicio/fin, ubicación,
  descripción, creador) — migración 011
- API CRUD /calendario/api.php (list/create/update/delete) con AuditLog
- Permisos: cualquiera autenticado crea; solo creador o Socio/Admin
  edita y elimina
- UI calendario: chip "Eventos", botón "+ Nuevo evento" en toolbar y
  en vista Día, modal con tipo/fecha/horario/ubicación, opción
  "Todo el día"
- Detalle de evento manual muestra creador, horario y ubicación;
  acciones Editar/Eliminar inline (sin navegación) si tiene permiso
- Colores por tipo: reserva sala, cumpleaños, recordatorio, evento
2026-06-04 20:49:23 -05:00
Soporte ZH Consultores 72c04ad594 feat(horas): nuevo módulo Reporte de Horas + icono reloj en headers
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).
2026-06-05 00:56:10 +00:00
Soporte ZH Consultores 2db8f23ba5 feat(perms): permisología completa con 3 roles (Socio/Abogado/Usuario) + Panel de Control
ESQUEMA (migraciones 005 + 006)
* users: agrega role ENUM('socio','abogado','usuario'), apellido, activo, orden
* Seed: cabrego@aal-law.com como socio + 15 placeholders por apellido para
  poblar el dropdown "Abogado Solicitante" hasta que los reales se logueen.
* tramites_involucrados: tabla N:M (tramite_id, user_id) con CASCADE delete.

AUTH (src/Auth.php)
* userRow() cachea el row del usuario actual por request.
* role(), isSocio(), isAbogado(), canCreate(), canDelete(), requireSocio().
* completeLogin() retorna bool: false si user.activo=0 → callback muestra
  pantalla "cuenta deshabilitada" en lugar de loguear.

BOOTSTRAP (src/Bootstrap.php + src/Lookups.php)
* Bootstrap::inject(view) reemplaza readfile en los wrappers; inyecta
  <script>window.DONNA={me,name,role,isSocio,isAbogado,canCreate,canDelete,
  abogados,users}</script> antes de </head> para que el frontend tenga
  contexto sin requests extra.

TRAMITES — visibilidad + involucrados
* api.php: list filtra por (socio | creador | abogado solicitante mapped via
  users.apellido | involucrado) excepto socios que ven todo. Todas las
  mutaciones validan canView(). create/delete validan rol. Persiste
  involucrados vía syncInvolucrados().
* tramites.html: nueva columna "Involucrados" después de "Abogado", chip
  picker multi-select en el modal, gear icon (oculto a non-socios), oculta
  botones "+ Nuevo" y ✕ para usuarios sin permisos. Auto-incluye al
  creador como involucrado por defecto.
* Calendario y demás apps consumen el API filtrado → heredan la
  visibilidad sin código nuevo.

PANEL DE CONTROL (/admin/)
* index.php: requireSocio() + Bootstrap injection.
* api.php: list_users, create_user, update_user. Salvaguardas: el socio
  no puede demoverse ni desactivarse a sí mismo.
* admin.html: tabla unificada de usuarios con filtros, modal CRUD,
  resaltado de fila propia, placeholders identificados visualmente.

GEAR ICON
* Agregado en escrituras.html, tramites.html, calendario.html con
  display:none por defecto; JS lo revela si window.DONNA.isSocio.
* Link a /admin/.
2026-06-04 23:14:07 +00:00
Soporte ZH Consultores cd9dae98bb feat(calendario): app Calendario con 4 vistas + deep-link a apps origen
Cliente-side: el calendario hace fetch a /escrituras/api.php?action=list
y /tramites/api.php?action=list y agrega los eventos en memoria. Sin
backend nuevo (cero costo de mantenimiento, datos siempre frescos).

Eventos generados automáticamente:
* Escrituras → fecha_solicitud
* Trámites adm/corp/mig/lit → fecha_solicitud
* Trámites mig → fecha_vencimiento (resaltado como deadline)
* Trámites lit → fecha_termino (resaltado como deadline)

Vistas: Año (12 mini-meses con dots por evento + marca roja para
vencimientos), Mes (grid con chips ≤3 por día), Semana (7 columnas),
Día (lista de cards). Hoy resaltado en todas.

Resaltado de vencimientos:
* Vencido (días<0, status abierto) → rojo + animación flash
* ≤7d → naranja
* >7d → color por fuente

Funcionalidad adicional:
* Strip "Próximos vencimientos" con los 8 deadlines más urgentes
* KPIs: total · ≤7d · ≤30d · vencidos abiertos
* Filtros por fuente (chips) + búsqueda por texto
* Atajos: ←/→ mueve período, T hoy, Y/M/W/D cambia vista, Esc cierra
* Auto-refresh cada 60s en segundo plano (pausa si la modal está abierta)
* Misma barra superior estandarizada que Escrituras y Trámites

Popup ViewOnly al hacer click en un evento muestra ficha completa con
todos los campos relevantes según fuente y dept. Dos botones:
"Regresar al calendario" cierra · "Editar evento" navega a
/escrituras/?edit=ID o /tramites/?edit=CODIGO.

Deep-link: escrituras.html y tramites.html detectan ?edit=X al cargar
y auto-abren la modal de edición sobre esa fila. URL se limpia con
history.replaceState para que un refresh no re-abra la modal.

Apps.php: card placeholder "Agenda" reemplazada por "Calendario" live.
2026-05-11 20:48:20 +00:00