Skip to main content

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

EntidadTabla / schemaQué es
PatientcustomerLa persona beneficiaria
PatientInformationcustomerDatos ampliados del paciente
PatientAgreementcustomerLa credencial: el vínculo con un financiador
AgreementconfigurationEl convenio, que pertenece a un Insurance
InsuranceconfigurationEl financiador
PatientAgreementElementCategorycustomerLa cartilla: módulo + prestador responsable, por credencial
ContactNumbercustomerTelé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.
UGL y agencia no van en el alta

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-agreement valida 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.

Efecto en cascada

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.

De acá sale la regla MÓDULO vs COMÚN

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

PantallaQué hace
patients/searchBuscador con pestañas Local y Sistema (el padrón scrapeado), filtro por financiador y export a Excel
patients/altaABM del paciente
patients/bulk-searchBúsqueda masiva
patients/:patientIdDetalle: 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 un JOIN directo.
  • Baja lógica siempre: ACTIVE = false + ENDDATE = now().
  • Los pacientes viejos pueden tener COMPANYID sin poblar; con el filtro fail-closed, un usuario no privilegiado no los ve. Es dato faltante, no bug de la query.