Pacientes y credenciales
El paciente es la raíz del dominio. Todo lo demás —episodios, autorizaciones, prácticas, facturación— cuelga de él a través de una credencial.
El modelo
| Entidad | Tabla / schema | Qué es |
|---|---|---|
Patient | customer | La persona beneficiaria |
PatientInformation | customer | Datos ampliados del paciente |
PatientAgreement | customer | La credencial: el vínculo con un financiador |
Agreement | configuration | El convenio, que pertenece a un Insurance |
Insurance | configuration | El financiador |
PatientAgreementElementCategory | customer | La cartilla: módulo + prestador responsable, por credencial |
ContactNumber | customer | Teléfonos |
Unicidad del paciente: por empresa
Un paciente es único por (tipo de documento + documento + COMPANYID).
Consecuencias:
- La misma persona atendida por dos empresas distintas son dos filas de
Patient, una por empresa. No se comparte el registro. Ver Multi-tenant. - El género no participa de la clave. Dos filas que difieran solo en género son duplicados.
- Hay un índice único en la DB que respalda la regla. La validación de aplicación tiene que espejar la
expresión del índice exactamente, o el usuario ve un error crudo de Postgres (
23505) en vez del mensaje de negocio.
La UGL (unidad de gestión) y la agencia no son datos del paciente: viajan con la credencial. Un alta de paciente que las pida está desactualizada.
Credenciales (PatientAgreement)
Un paciente puede tener varias credenciales: distintos financiadores, o el mismo financiador con
convenios distintos a lo largo del tiempo. El episodio apunta a la credencial vigente
(AtentionProcess.PATIENTAGREEMENTID).
La credencial PAMI
Se compone de beneficio + gp (grado de parentesco) y se guarda concatenada en
PatientAgreement.healthcardnumber. Los adaptadores de autorización la parten o la matchean según el
origen del dato — ver Autorizaciones.
Credencial numérica: un flag por financiador
Algunos financiadores exigen credencial numérica. El flag es Insurance.NUMBERCREDENTIAL, y la
validación del campo en la UI es condicional al financiador elegido.
Cambiar el financiador de un episodio
Hay un componente compartido (proteus-financiador-modal) para ver y cambiar el financiador y la
credencial desde cualquier pantalla: detalle de internación, de ambulatorio, de paciente, alta de
episodio.
change-agreementvalida que la credencial nueva sea del mismo financiador. Cambiar de financiador es otro flujo.- La operación es sensible: define cómo se factura el episodio.
Borrar una credencial cierra episodios
Eliminar una credencial cierra los episodios abiertos cuya credencial vigente sea esa. Por eso la acción pide confirmación escrita (no un simple "¿seguro?") y se implementa en dos fases.
Borrar una credencial no es una operación de mantenimiento: cierra procesos de atención en curso, con su motivo de egreso correspondiente. Los motivos de egreso no vienen sembrados en todos los entornos, así que el flujo los crea si faltan.
La cartilla (cápita local por paciente)
PatientAgreementElementCategory es la tabla puente que guarda, por credencial, qué módulos
(ElementCategory) tiene preasignados el afiliado y qué prestador es responsable de cada uno
(RESPONSIBLE, texto libre).
Es dato local: se administra con un ABM y no deriva de lo que PAMI informa. Es distinto de las cápitas que PAMI asignó al afiliado, que son read-only y salen de cache Redis.
Una internación se factura como MÓDULO si la credencial tiene una cápita activa con
ElementCategory.code = '69' y RESPONSIBLE = 'HOSPITAL POSADAS'. Si no, COMÚN. La comparación
es literal: un typo en RESPONSIBLE cambia la facturación del episodio.
Las pantallas
| Pantalla | Qué hace |
|---|---|
patients/search | Buscador con pestañas Local y Sistema (el padrón scrapeado), filtro por financiador y export a Excel |
patients/alta | ABM del paciente |
patients/bulk-search | Búsqueda masiva |
patients/:patientId | Detalle: cápitas PAMI (read-only), credenciales, cartilla, teléfonos, documentos, comentarios |
Ambas pestañas del buscador paginan en el servidor. El export a Excel se genera por streaming, sin cargar todo en memoria.
Gotchas
- El financiador del paciente no es una columna — se llega vía
Patient → PatientAgreement → Agreement → Insurance. El filtro por financiador del buscador es una subconsulta, no unJOINdirecto. - Baja lógica siempre:
ACTIVE = false+ENDDATE = now(). - Los pacientes viejos pueden tener
COMPANYIDsin poblar; con el filtro fail-closed, un usuario no privilegiado no los ve. Es dato faltante, no bug de la query.