Skip to content

RUP - Doble firma: pre-validación de informes - #2332

Open
sychus wants to merge 11 commits into
masterfrom
RUP-doble-firma-prevalidacion
Open

sychus wants to merge 11 commits into
masterfrom
RUP-doble-firma-prevalidacion

Conversation

@sychus

@sychus sychus commented Oct 19, 2026 •

Copy link
Copy Markdown

Note

TL;DR — Agrega la pre-validación (doble firma) de informes RUP: un médico residente puede dejar su firma sobre un informe antes de que el médico de planta lo valide. Es opcional, no cambia el estado de la prestación y no modifica el flujo de validación actual.

🎫 Ticket ninguno (sin key de tracker)
🧭 Tipo feat — doble firma de informes RUP
💥 Alcance Prestaciones RUP: permisos y firmas. Estados y validación quedan intactos.
🧪 Verificado npx jest modules/rup/prevalidacion.test.ts → ✅ 13/13; tsc --noEmit → ✅; flujo completo por API → ✅; build completo → ⚠️ no ejecutado (convención del entorno local)

Por qué

En hospitales escuela el informe lo elabora un médico residente y lo valida un médico de planta, pero hoy la prestación tiene un único firmante: quien presiona "Validar". No hay forma de registrar la firma del residente. Este cambio introduce una firma de pre-validación, opcional, sin tocar el proceso de validación. Diseño y decisiones en el ADR docs/rup/0001-doble-firma-informe.md (incluido en este PR y actualizado con cada ajuste de la revisión).

Qué cambió

  • Permiso — nuevo permiso rup:prevalidacion:<tipoPrestacion>, el que se asigna a los residentes (auth/permisos.ts).
  • Modelo de firmas — lista firmasPrevalidacion con snapshot de profesional, rol y matrícula; índice para estadística por firmante (modules/rup/schemas/prestacion.ts).
  • Sin estado nuevo — la pre-validación no cambia el estado: la prestación sigue en ejecucion y acumula firmas. La app muestra la cantidad como badge. (En una iteración anterior existía el estado pendienteValidacion; se eliminó por feedback de los usuarios, ver "Historial de la revisión".)
  • Operaciones — prevalidacion (agrega firma con $push atómico, tope y anti-duplicado forzados en el filtro) y quitarPrevalidacion (saca una firma) en el PATCH /prestaciones/:id (modules/rup/routes/prestacion.ts). Ninguna transiciona estado.
  • Tope de firmas — rup.maxFirmasPrevalidacion (4) en config.ts; la app lo obtiene de GET /modules/rup/prevalidacion/config → { maxFirmasPrevalidacion } para no duplicarlo.
  • Reglas de firma — la API rechaza la pre-validación de usuarios con rup:validacion (deben validar); quitarPrevalidacion rechaza quitar una firma ajena sin permiso de validación. La matrícula del snapshot usa searchMatriculas (vigencia, posgrado, matrícula externa), con el mismo formato que el PDF.
  • Romper validación — al volver a ejecucion se limpian las firmas de pre-validación (quedan en prestacionesHistorial); los residentes vuelven a pre-validar si corresponde.
  • Rol del firmante — derivado de permisos en un único punto deriveRolFirmante (modules/rup/controllers/prestacion.ts).
  • Fix — GET /prestaciones/servicio-intermedio hacía ObjectId('*') con permisos comodín y tiraba el proceso; ahora descarta valores que no sean ObjectId válido (modules/rup/routes/prestacion.ts).

Cómo probar

  1. Asignar a un usuario residente rup:prevalidacion:<tipo> (sin rup:validacion) y a otro rup:validacion:<tipo>.
  2. Residente pre-valida una prestación en ejecucion → queda en ejecucion con su firma en firmasPrevalidacion. → ✅ observado
  3. Un segundo residente pre-valida la misma → se suma su firma, sigue en ejecucion. → ⚠️ pendiente de re-verificar tras el cambio del 2026-10-31
  4. Residente quita su firma → sigue en ejecucion con una firma menos. → ⚠️ pendiente de re-verificar tras el cambio del 2026-10-31
  5. El de planta valida → validada, conservando las firmas previas. → ✅ observado
  6. El de planta rompe la validación → vuelve a ejecucion sin firmas previas; los residentes pueden volver a pre-validar. → ⚠️ pendiente de re-verificar tras el cambio del 2026-10-31

Automatizado: npx jest modules/rup/prevalidacion.test.ts → ✅ 13/13. tsc --noEmit → ✅. Suite completa → ⚠️ no ejecutada localmente (convención del entorno).

Historial de la revisión

  • 2026-10-21 — tope movido a config.ts; ADR con metadata y en docs/rup/; rechazo de pre-validación con rup:validacion; matrícula vía searchMatriculas; limpieza de firmas al romper validación.
  • 2026-10-31 — feedback de usuarios: se elimina el estado pendienteValidacion (generaba problemas con los flujos existentes gateados por ejecucion); la pre-validación ya no transiciona y quitarPrevalidacion tampoco. El enum de estados vuelve a ser el original. ADR enmendado.

Riesgo y rollback

  • Alcance: aditivo. Prestaciones sin firmasPrevalidacion (históricas) se resuelven en lectura con el validador como firmante único; no requieren migración. No se agregan estados.
  • Migraciones: crear el índice en entornos con autoIndex desactivado: db.prestaciones.createIndex({ "firmasPrevalidacion.profesional.id": 1 }, { sparse: true }). El permiso rup:prevalidacion se asigna a residentes (administración, no migración).
  • Entornos de prueba: si quedaron prestaciones en pendienteValidacion de una versión anterior de esta rama, fallan al guardar por validación de enum. Volverlas a ejecucion: db.prestaciones.updateMany({ 'estadoActual.tipo': 'pendienteValidacion' }, { $set: { 'estadoActual.tipo': 'ejecucion', 'estados.$[e].tipo': 'ejecucion' } }, { arrayFilters: [{ 'e.tipo': 'pendienteValidacion' }] }). No aplica a producción: el estado nunca llegó.
  • Feature flag: ninguno; el botón/flujo aparece solo si el usuario tiene el permiso.
  • Rollback: revertir el PR. El índice se puede dropear; los campos nuevos no afectan prestaciones existentes.

Notas para el revisor

Tip

Empezá por: el case 'prevalidacion' en modules/rup/routes/prestacion.ts (push atómico, sin transición de estado).

  • La validación no se modifica: el validador se deriva de estadoActual.createdBy; el campo firmaValidacion queda diferido. Hacer cumplir un permiso de validación en la API sigue siendo un punto abierto del ADR (riesgo con internación).
  • El rol es un snapshot derivado de permisos; ver el principio general de gateo documentado en el ADR (todo gateo por "creador o validación" debe contemplar también pre-validación).
  • Acompaña al PR de andes/app con la interfaz: RUP - Doble firma: pre-validación de informes app#3429.

Agrega el flujo de pre-validación (doble firma) de informes RUP:
- permiso rup:prevalidacion:<tipo> y estado pendienteValidacion
- lista firmasPrevalidacion con push atómico, tope 4 y anti-duplicado
- operaciones prevalidacion y quitarPrevalidacion en el PATCH de prestaciones
- rol del firmante derivado de permisos (deriveRolFirmante), con matrícula
- fix: ObjectId sobre comodín en servicio-intermedio
- actualiza ADR 0001
Comment thread docs/rup/0001-doble-firma-informe.md Resolved
Comment thread modules/rup/routes/prestacion.ts Resolved
admitePrevalidacion, formatearMatriculas, usuarioAuditoria e
historialParaUpdateAtomico, con tests unitarios.
- La matrícula de la firma reutiliza searchMatriculas (vigencia, baja,
  posgrado y matrícula externa), con el mismo formato que el informe PDF.
- quitarPrevalidacion rechaza quitar una firma ajena sin rup:validacion
  (antes ignoraba firmaProfesionalId y quitaba la propia en silencio).
- quitarPrevalidacion: $pull condicionado a que la firma exista y vuelta a
  ejecucion solo si la lista sigue vacía (evita perder firmas concurrentes).
- Persiste la entrada de historial de solicitud (prestaciones top) y
  updatedAt/updatedBy, que se perdían por no pasar por data.save().
Pre-validación y validación son excluyentes (ADR 0001); antes la
exclusión solo existía en la UI y la API aceptaba la firma como 'validador'.
@sychus
sychus requested a review from Pela2silveira October 21, 2026 22:11
La pre-validación ya no cambia el estado de la prestación: sigue en
ejecución y acumula firmas en firmasPrevalidacion. Se elimina
pendienteValidacion del enum de estados, quitarPrevalidacion opera en
ejecución y no transiciona, y el push de firmas deja de necesitar el
reintento por cambio de estado.

Se actualiza el ADR 0001 con la enmienda del 2026-10-31: eliminación del
estado y de la cola de pendientes, y la regla real del botón Validar
(se oculta solo a quien tiene rup:prevalidacion; rup:validacion nunca fue
requisito para validar).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants