🔑 Administración

Panel de Administración

El panel de Administración concentra la configuración del sistema y los tableros de control: usuarios internos, laboratorios cliente, tipos de servicio, parámetros, el log de auditoría, las notificaciones automáticas, los KPIs de gestión y la integración con Odoo. Es la consola de gobierno del sistema — casi todo lo que se toca acá queda registrado en el audit trail.

Quién puede entrar

El acceso al panel no lo determina el campo "rol" del usuario (que es una etiqueta libre, de texto), sino un booleano dedicado del token: es_admin_local. Solo los usuarios con ese flag en true ven el panel y pueden operar sus acciones administrativas.

⚖️
Un único gate de administrador: es_admin_local

El sistema no infiere permisos de administrador a partir del texto del rol. La puerta es el booleano es_admin_local del token. Escribir "Administrador" en el campo de rol de un usuario no le da acceso al panel; hay que marcar la casilla "Admin local" en su ficha. Del mismo modo, setearle una contraseña a alguien no lo promueve a administrador.

Las 7 pestañas del panel

El panel se organiza en siete pestañas. "Sistema" no es una pestaña propia: es un sub-toggle dentro de Parámetros.

PestañaFunción principal
KPIs / MétricasTableros de gestión (solo lectura): totales, GMP vs correctivos, vencidos, comparativos.
UsuariosAlta, edición y archivado de usuarios internos (@ion-target.com); designación de administradores.
TiposTipos de servicio y su periodicidad por defecto.
LaboratoriosLaboratorios cliente y su vínculo con Odoo (empresa).
ParámetrosPares clave/valor de configuración + sub-toggle "Sistema" (estado de controles).
LogsAudit trail append-only con filtros, diff y correlation ID.
NotificacionesResúmenes de vencimientos GMP/STD y envíos manuales de reportes.

Usuarios

Lista únicamente los usuarios internos de ION-target (correo @ion-target.com). Desde acá se dan de alta, se editan, se archivan y se restauran, y se designa quién es administrador.

Campos del alta / edición

CampoObligatorioDetalle
Nombre✅ Sí
Apellido✅ Sí
Email✅ SíÚnico en el sistema; debe ser corporativo (@ion-target.com).
RolEtiqueta libre (texto). No otorga permisos; es descriptivo.
Sector✅ SíÁrea interna del usuario.
Odoo User IDVincula la ficha a la cuenta interna de Odoo (res.users).
Admin localCheckbox. Si se marca, la contraseña pasa a ser obligatoria y de ≥ 8 caracteres. Es lo que setea es_admin_local.
⚠️
Contraseña ≠ administrador

Setear o cambiar una contraseña no promueve al usuario a administrador. La condición de admin la fija exclusivamente la casilla "Admin local" (que a su vez exige una contraseña de al menos 8 caracteres). Sin esa casilla, aunque tenga contraseña, el usuario no ve el panel.

Acciones sobre usuarios

AcciónEndpointCondiciones
ListarGET /admin/usuariosSolo usuarios internos (@ion-target.com).
CrearPOST /admin/usuariosNombre, apellido, email (único) y sector obligatorios. Si "Admin local" → contraseña ≥ 8.
EditarPUT /admin/usuarios/{id}Mismas validaciones.
ArchivarPATCH /admin/usuarios/{id}/archivarMotivo obligatorio.
RestaurarPATCH /admin/usuarios/{id}/restaurar
EliminarDELETE405No existe borrado físico: solo archivado.

Laboratorios

Administra los laboratorios cliente y, sobre todo, su vínculo con la empresa en Odoo. La estructura interna de sectores y usuarios de cada laboratorio se gestiona en el módulo Laboratorios, no acá.

CampoObligatorioDetalle
Nombre✅ SíNombre del cliente.
DirecciónTexto libre.
TeléfonoTexto libre.
EmailContacto del laboratorio.
UbicaciónURL de Google Maps.
Odoo Partner IDSe elige con un buscador que consulta GET /odoo/empresas. Vincula el laboratorio a la empresa en Odoo.
ℹ️
Los sectores no se editan acá

La grilla muestra el conteo de sectores de cada laboratorio como referencia, pero crear/editar sectores y usuarios de sector se hace en el módulo Laboratorios.

AcciónEndpointCondiciones
ListarGET /admin/laboratorios
CrearPOST /admin/laboratoriosNombre obligatorio.
EditarPUT /admin/laboratorios/{id}
Archivar / RestaurarPATCH /admin/laboratorios/{id}/archivar · /restaurarArchivar pide motivo.
Buscar empresa OdooGET /odoo/empresasAlimenta el buscador de Odoo Partner ID.

Tipos de servicio

Define los tipos de servicio disponibles y su periodicidad. Son 11 tipos GMP. Las categorías AT (Asistencia Técnica) y RB (Reparación) corresponden a asistencias (trabajos correctivos), no a servicios GMP planificados.

CampoDetalle
NombreNombre del tipo de servicio.
DescripciónTexto libre.
Periodicidad por defecto (meses)Cada cuántos meses se repite por defecto ese servicio; se usa para calcular el próximo vencimiento.
ℹ️
GMP vs. correctivo se decide por el nombre

La clasificación de un tipo como GMP o como correctivo (AT/RB) se resuelve por coincidencia de substring en el nombre, no con un campo dedicado. Por eso el nombre importa: cambiarlo puede cambiar cómo se clasifica.

AcciónEndpointCondiciones
ListarGET /admin/tipos-servicio
CrearPOST /admin/tipos-servicioNombre obligatorio.
EditarPUT /admin/tipos-servicio/{id}Editar uno archivado → 409.
Archivar / RestaurarPATCH /admin/tipos-servicio/{id}/archivar · /restaurarArchivar pide motivo.
EliminarDELETE405No hay borrado físico.

Parámetros del sistema

Pares clave / valor con edición inline. El guardado tiene efecto inmediato. El parámetro funcional principal es dias_alerta_vencimiento (por defecto 30), que fija con cuántos días de anticipación se consideran "próximos a vencer" los servicios.

ℹ️
El remitente de los correos no es un parámetro

El remitente de las notificaciones sale de la variable de entorno RESEND_FROM, no de un parámetro editable como "email_remitente". Del mismo modo, la copia (CC) a support@ion-target.com es fija en el código: no es un parámetro configurable. Cambiar valores en esta pantalla no altera el remitente ni el CC.

⚠️
Gap GMP: los cambios de parámetros no se auditan (hoy)

A diferencia del resto del sistema, modificar un parámetro no deja registro en el audit trail. Es una mejora pendiente. Mientras tanto, documentá los cambios de parámetros por fuera del sistema.

Sub-toggle "Sistema"

Dentro de Parámetros hay un toggle "Sistema" de solo lectura que muestra el estado de los controles de seguridad y cumplimiento: rol de aplicación de la base, RLS del log, algoritmo JWT, endpoint JWKS, duración de sesión, etc. No es editable.

Log de actividad

El audit trail del sistema: append-only con RLS. Los registros no se pueden modificar ni eliminar — ni siquiera el propietario ni un administrador. Cada evento lleva un correlation ID (que agrupa todos los pasos de una misma operación) y la IP de origen.

⚖️
Inmutable por diseño (21 CFR Part 11 / EMA Annex 11)

El log es de solo escritura, garantizado a nivel de base de datos mediante Row Level Security (RLS) en PostgreSQL: INSERT y SELECT permitidos, UPDATE y DELETE bloqueados para todo rol de aplicación. Ni el owner de la fila puede alterarla.

⚖️
Escritura de auditoría resiliente

El registro de auditoría se escribe en una sesión de base separada: si esa escritura llega a fallar, el evento cae a los logs de la aplicación en lugar de perderse silenciosamente o de tumbar la operación principal.

Qué ve cada quién

El administrador ve todos los eventos de todos los usuarios. Un técnico solo ve sus propias acciones.

Filtros disponibles

FiltroDetalle
Buscar (texto)Búsqueda libre sobre el registro.
AcciónTipo de evento (ver catálogo abajo).
EntidadTipo de objeto afectado.
UsuarioSolo administrador (el técnico no puede filtrar por otros).
Resultadook / error.
Desde / HastaRango de fechas.

Paginado de 50 registros por página. Cada fila tiene un botón para ver las diferencias (valor anterior vs. valor nuevo).

ℹ️
Exportar el log = ventana imprimible, no CSV

El botón de exportar del log abre una ventana imprimible (HTML → PDF). No descarga un CSV. La exportación a CSV pertenece al módulo KPIs, no al log.

Catálogo de acciones

LOGIN LOGOUT CREAR MODIFICAR ELIMINAR CAMBIO_ESTADO ARCHIVAR RESTAURAR GENERAR_PDF URL_INFORME_RECIBIDA ODOO_PUSH ODOO_PULL SYNC MIGRAR

Estructura de cada registro

  • correlation_id — UUID que agrupa los eventos de una misma operación.
  • usuario — quién ejecutó la acción.
  • acción — tipo de evento (catálogo de arriba).
  • entidad — tipo de objeto afectado.
  • entidad_id — ID del registro afectado.
  • valor_anterior / valor_nuevo — snapshot del cambio (alimenta el diff).
  • detalle — información adicional (motivo, contexto).
  • IP — dirección de origen.
  • resultado — ok / error.
  • fecha — timestamp del evento.

Notificaciones

Muestra resúmenes de vencimientos y permite disparar envíos manuales. Los resúmenes en pantalla son de solo lectura; los envíos (POST) son solo para administradores.

ElementoEndpointDetalle
Resumen vencimientos GMPGET /notificaciones/vencimientosServicios GMP próximos a vencer.
Resumen vencimientos STDGET /notificaciones/vencimientos-stdInstrumentos/estándares/solventes a 90 días.
Enviar alerta GMPPOST (solo admin)Envío manual del aviso de vencimientos GMP.
Enviar reporte mensualPOST (solo admin)Resumen mensual.
Enviar reporte STDPOST (solo admin)Vencimientos STD a 90 días.
Test de emailPOST (solo admin)Prueba de envío.
ℹ️
No hay lista de destinatarios configurable

Los reportes van automáticamente a todos los usuarios @ion-target.com activos, con CC fijo a support@ion-target.com. No existe una pantalla para elegir destinatarios: quién recibe se deriva de los usuarios internos activos.

Scheduler automático

El scheduler (APScheduler) corre el último día del mes a las 08:00 (hora Argentina) y envía dos correos:

1
Aviso GMP

Vencimientos GMP del mes siguiente.

2
Aviso STD

Vencimientos de instrumentos/estándares/solventes a 90 días.

KPIs / Métricas

Tablero de gestión de solo lectura, exclusivo de administradores (GET /analytics/opciones + GET /analytics/kpis). Reúne los indicadores del sistema con filtros por período y un modo comparativo.

KPIQué cuenta
TotalTotal de servicios del período.
GMPServicios GMP.
CorrectivosAsistencias AT/RB.
FinalizadosServicios en estado Finalizado OR Resuelto.
VencidosSolo GMP (las asistencias correctivas no tienen vencimiento).
Equipos / Clientes / TécnicosConteos distintos (ver nota de granularidad).
ℹ️
Granularidad: servicios vs. distintos

La unidad por defecto es el servicio (COUNT(*)). Las excepciones son Equipos, Clientes y Técnicos, que se cuentan como valores distintos (COUNT(DISTINCT)) — un mismo equipo o técnico no suma más de una vez.

Los gráficos (barras, torta, líneas) se dibujan en SVG a mano. El tablero exporta a CSV / PNG / PDF y ofrece un modo Comparativo de hasta 4 períodos (año, trimestre o rango de meses) con deltas porcentuales entre ellos.

Integración con Odoo

El sistema se integra con Odoo por webhook (entrada) y por sincronizaciones manuales (salida/actualización). Tras la revisión de seguridad CR-005, todos los endpoints que mutan o exponen datos requieren token.

⚖️
Webhook fail-closed

El webhook está protegido por un secreto en la URL: si no hay secreto configurado responde 503; si el secreto es inválido responde 403. La comparación se hace en tiempo constante (resistente a timing attacks).

OperaciónEndpointDetalle
Webhook de cambio de etapaPOST /odoo/webhook-stageLo dispara la automatización nativa de Odoo al cambiar de etapa (proyectos 12/13). Protegido por secreto.
Sincronizar usuariosPOST /odoo/sincronizar-usuariosCruza usuarios ITS con Odoo por email.
Sincronizar laboratoriosPOST /odoo/sincronizarActualiza laboratorios contra Odoo.
Empresas (buscador)GET /odoo/empresasAlimenta el buscador de Odoo Partner ID de Laboratorios.
ℹ️
El mapeo etapa → estado usa stage_id numérico

La correspondencia entre la etapa de Odoo y el estado en ITS se resuelve por el ID numérico de la etapa, no por su nombre — así es robusto a renombres en Odoo. Para AT/RB, la etapa "Finalizado" de Odoo equivale a "Resuelto" en ITS.


Preguntas frecuentes

Un técnico no entra al panel de Administración, ¿qué reviso?+
El acceso no depende del campo "rol" (que es una etiqueta libre), sino del booleano es_admin_local. En la ficha del usuario (Admin → Usuarios) marcá la casilla "Admin local", que además exige una contraseña de ≥ 8 caracteres. Escribir "Administrador" en el rol no habilita nada.
¿Cómo elimino un usuario, laboratorio o tipo de servicio?+
No se eliminan: se archivan (con motivo) y se pueden restaurar. La API responde 405 a cualquier DELETE. Es una decisión de cumplimiento GMP: no hay borrado físico, para no perder el historial.
Cambié un parámetro y las notificaciones siguen saliendo con el remitente incorrecto.+
El remitente no es un parámetro editable: sale de la variable de entorno RESEND_FROM. El CC a support@ion-target.com también es fijo en el código. Para cambiar el remitente hay que ajustar RESEND_FROM en el entorno del servidor, no en Parámetros.
¿A quién le llegan las notificaciones? ¿Puedo elegir destinatarios?+
No hay lista configurable. Los reportes van a todos los usuarios @ion-target.com activos, con CC fijo a support. Para que alguien deje de recibirlos, hay que archivar (o dar de baja) su usuario.
¿Puedo exportar el log de actividad a CSV?+
No. El botón de exportar del log abre una ventana imprimible (HTML → PDF). La exportación a CSV (junto con PNG y PDF) es del módulo KPIs / Métricas, no del log.
¿Por qué el KPI "Vencidos" solo muestra servicios GMP?+
Porque solo los servicios GMP tienen fecha de vencimiento (nacen de una periodicidad). Las asistencias correctivas AT/RB son trabajos puntuales sin vencimiento, así que no entran en ese indicador.