El reto
Las historias clínicas electrónicas suelen vivir en plataformas pesadas de hospital que no encajan con la realidad de un consultorio individual: licencias caras, instalaciones complejas, datos del médico mezclados con los de otros usuarios y un portal de paciente que muchas veces ni siquiera existe.
FichaMedica nace como proyecto de I+D para responder a una pregunta concreta: ¿cómo se vería una ficha clínica electrónica diseñada multi-tenant desde el primer commit, donde cada médico administra sus pacientes en aislamiento estricto y el paciente tiene su propio portal sin acceso al panel del médico?
La solución
FichaMedica es un sistema multi-tenant row-level: toda tabla con dueño lleva doctor_id, el JWT carga el tenant del que escribe o lee, y cada query filtra obligatoriamente por ese tenant antes de devolver una fila. Sobre esa base modelamos 9 entidades del dominio clínico (doctores, pacientes, consultas, recetas, análisis, imágenes, signos vitales, citas, horarios) con relaciones cruzadas y eager-loading optimizado.
Lo que cubre la app
- Dashboard rico — KPIs del consultorio (pacientes, consultas, recetas, análisis, imágenes), gráfico diario de consultas de 15 días dibujado en SVG inline (sin librerías de charts), distribución por edad/sexo, pacientes con flags clínicos, top diagnósticos, top exámenes, próximas citas y galería de imágenes recientes.
- Agenda con calendario semanal — bloques de horario laboral por día con soporte de turnos partidos, validación dura de “dentro del horario” + check de overlap al crear o editar citas, bloques posicionados absolutamente sobre la grilla horaria.
- Workflow Atender cita → consulta — un click cierra la cita y abre el form de consulta prellenado con motivo y fecha, enlazando ambos registros en una sola transacción y refetcheando el dashboard automáticamente.
- Signos vitales con interpretación automática — IMC calculado al vuelo y 14 flags clínicos en español (fiebre, hipertensión, taquicardia, hipoxemia, obesidad I/II/III, dolor severo, etc.) basados en thresholds estándar.
- Análisis de laboratorio con flags — cada resultado se compara contra rangos de referencia y se etiqueta
normal/low/high/abnormalautomáticamente; conteos por análisis y agregado en el dashboard. - Imágenes médicas con URLs presignadas — el navegador hace upload directo a MinIO vía PUT presignado (no pasa por el backend), GET presignado con TTL de 15 min para visualización, lightbox modal con visor en fondo oscuro.
- Portal del paciente — namespace
/portalcon 6 endpoints read-only scoped aluser_iddel principal, UI propia con degradado cyan→sky→indigo y secciones para citas, consultas con vitales, recetas, análisis con flags e imágenes.
Decisiones técnicas que importan
- Multi-tenancy estricto desde la base de datos —
doctor_idobligatorio, validación de tenant en cada uno de los 50+ endpoints REST, sin filtración cross-tenant verificada manualmente. - OpenAPI auto-generado por FastAPI, paginación server-side en todos los listados grandes, validación de bordes con Pydantic.
- Imágenes fuera de la BD: MinIO con URLs presignadas para upload y visualización; CORS configurado para preflight; el backend solo orquesta los presigned URLs sin nunca tocar el binario.
- Charts hechos a mano (Tailwind + SVG inline) en vez de meter Recharts/Chart.js — bundle más liviano y control total del look.
- Generación de data demo escalable: importer de Synthea (mapea 1.000 pacientes sintéticos CSV al schema), localización con nombres/emails/teléfonos hispánicos, traducción ES de diagnósticos SNOMED, descarga de imágenes médicas reales desde Wikimedia Commons API con fallback a picsum.
- Despliegue 100% reproducible:
docker compose uplevanta Postgres + MinIO + backend con hot-reload + frontend con hot-reload + migraciones Alembic auto-aplicadas + seed idempotente.
Resultados
- Demo end-to-end navegable con 26 pacientes, 945 consultas, 410 recetas, 2 análisis curados con flags, 7 imágenes médicas reales y agenda activa con citas linkeadas a consultas — todo accesible desde el dashboard, la ficha de paciente y el portal.
- Workflow médico ↔ paciente cerrado: el doctor agenda → atiende → genera consulta + vitales + recetas + análisis + imágenes; el paciente loguea con sus credenciales y ve toda su historia en su portal sin acceso al panel del médico ni a datos de otros tenants.
- 50+ endpoints REST con OpenAPI auto-generado, paginación server-side y validación de tenant en cada uno.
Por qué importa
FichaMedica es un caso de I+D propio que valida un patrón que llevamos a custom apps reales: multi-tenancy row-level desde el primer commit, separación clara de paneles por rol, almacenamiento de archivos vía URLs presignadas para no cargar al backend, y data demo realista que permite mostrar la plataforma con números creíbles desde el día uno. Lo que aprendimos acá lo aplicamos directo cuando un cliente del sector salud — o de cualquier vertical que necesite aislamiento de tenants estricto — nos pide un sistema parecido con su lógica específica.



