From 40d232528ba66ecfb75a41ffa22a18e40799243c Mon Sep 17 00:00:00 2001 From: aldoEMatamala Date: Mon, 31 Aug 2026 15:57:03 -0300 Subject: [PATCH] feat(HUDS-216:Resumen del paciente: Estudios Complementarios --- initialize.ts | 1 + .../estudios-complementarios.controller.ts | 154 ++++++++++++++++++ .../estudios-complementarios.routes.ts | 35 ++++ .../huds/estudios-complementarios/index.ts | 2 + 4 files changed, 192 insertions(+) create mode 100644 modules/huds/estudios-complementarios/estudios-complementarios.controller.ts create mode 100644 modules/huds/estudios-complementarios/estudios-complementarios.routes.ts create mode 100644 modules/huds/estudios-complementarios/index.ts diff --git a/initialize.ts b/initialize.ts index 63bd7a141a..dc0d851699 100644 --- a/initialize.ts +++ b/initialize.ts @@ -105,6 +105,7 @@ export function initAPI(app: Express) { app.use('/api/modules/gestor-usuarios', require('./modules/gestor-usuarios').UsuariosRouter); app.use('/api/modules/gestor-usuarios', require('./modules/gestor-usuarios').PerfilesRouter); app.use('/api/modules/registro-novedades', require('./modules/registro-novedades').NovedadesRouter); + app.use('/api/modules/huds/estudios-complementarios', require('./modules/huds/estudios-complementarios').EstudiosComplementariosRouter); app.use('/api/modules/huds', require('./modules/huds').HudsAccesoRouter); app.use('/api/modules/webhook', require('./modules/webhook').WebhookRouter); app.use('/api/modules/webhook', require('./modules/webhook/webhooklog').WebhookLogRouter); diff --git a/modules/huds/estudios-complementarios/estudios-complementarios.controller.ts b/modules/huds/estudios-complementarios/estudios-complementarios.controller.ts new file mode 100644 index 0000000000..5e27372d79 --- /dev/null +++ b/modules/huds/estudios-complementarios/estudios-complementarios.controller.ts @@ -0,0 +1,154 @@ +import { Types } from 'mongoose'; +import * as moment from 'moment'; +import { Constantes } from '../../constantes/constantes.schema'; +import { PacienteCtr } from '../../../core-v2/mpi/paciente/paciente.routes'; +import { makeFs } from '../../cda/schemas/CDAFiles'; +import { Prestacion } from '../../rup/schemas/prestacion'; + +export async function getEstudiosComplementarios(idPaciente: string, options: { fechaDesde?: string | Date; fechaHasta?: string | Date } = {}) { + if (!Types.ObjectId.isValid(idPaciente)) { + return []; + } + + const paciente: any = await PacienteCtr.findById(idPaciente); + if (!paciente) { + return []; + } + + const pacienteIdsRaw = [ + paciente._id || paciente.id, + ...(paciente.vinculos || []), + ...(paciente.idPacientePrincipal ? [paciente.idPacientePrincipal] : []) + ]; + const pacienteIds = pacienteIdsRaw.filter(Boolean).map(id => (typeof id === 'string' ? new Types.ObjectId(id) : id)); + + // 1. Cargar constante de límite de años (por defecto 1 año) + let limiteAnios = 1; + const constanteLimite: any = await Constantes.findOne({ + $or: [ + { key: 'estudios-complementarios-limite-anios' }, + { nombre: 'estudios-complementarios-limite-anios' } + ] + }); + if (constanteLimite) { + const valStr = constanteLimite.nombre || constanteLimite.source; + const parsed = parseInt(valStr, 10); + if (!isNaN(parsed) && parsed > 0) { + limiteAnios = parsed; + } + } + + // 2. Cargar constante de tipos de prestaciones/conceptos (por defecto Ecografías: "359659005") + // let conceptIds: string[] = ['359659005'];90226004 pap + let conceptIds: string[] = ['90226004']; + const constanteConceptos: any = await Constantes.findOne({ + $or: [ + { key: 'estudios-complementarios-conceptos' }, + { nombre: 'estudios-complementarios-conceptos' } + ] + }); + if (constanteConceptos) { + const sourceVal = constanteConceptos.source || constanteConceptos.nombre || constanteConceptos.value; + if (Array.isArray(sourceVal)) { + conceptIds = sourceVal.map(c => String(c)); + } else if (typeof sourceVal === 'string') { + try { + const parsed = JSON.parse(sourceVal); + if (Array.isArray(parsed)) { + conceptIds = parsed.map(c => String(c)); + } else { + conceptIds = sourceVal.split(',').map(s => s.trim()).filter(Boolean); + } + } catch (e) { + conceptIds = sourceVal.split(',').map(s => s.trim()).filter(Boolean); + } + } + } + + // 3. Definir rango temporal + const fechaDesde = options.fechaDesde + ? moment(options.fechaDesde).startOf('day').toDate() + : moment().subtract(limiteAnios, 'years').startOf('day').toDate(); + + const fechaHasta = options.fechaHasta + ? moment(options.fechaHasta).endOf('day').toDate() + : moment().endOf('day').toDate(); + + // 4. Buscar CDAs en GridFS + const CDAFiles = makeFs(); + const cdaQuery: any = { + 'metadata.paciente': { $in: pacienteIds }, + 'metadata.cdaId': null, + 'metadata.fecha': { $gte: fechaDesde, $lte: fechaHasta } + }; + if (conceptIds.length > 0) { + cdaQuery['metadata.prestacion.snomed.conceptId'] = { $in: conceptIds }; + } + + const cdaDocs = await CDAFiles.find(cdaQuery).sort({ 'metadata.fecha': -1 }).toArray(); + const cdaList = cdaDocs.map((item: any) => { + const meta = item.metadata || {}; + return { + id: item._id, + fecha: meta.fecha, + efector: { + id: meta.organizacion?._id || meta.organizacion?.id, + nombre: meta.organizacion?.nombre || meta.organizacion?.name + }, + tipoPrestacion: { + conceptId: meta.prestacion?.snomed?.conceptId, + term: meta.prestacion?.snomed?.term, + fsn: meta.prestacion?.snomed?.fsn + }, + tipo: 'cda', + accesoHuds: { + id: item._id, + tipo: 'cda' + } + }; + }); + + // 5. Buscar prestaciones RUP validadas (con agenda o fuera de agenda) + const prestacionQuery: any = { + 'paciente.id': { $in: pacienteIds }, + 'estadoActual.tipo': 'validada', + $or: [ + { 'ejecucion.fecha': { $gte: fechaDesde, $lte: fechaHasta } }, + { 'estadoActual.createdAt': { $gte: fechaDesde, $lte: fechaHasta } } + ] + }; + if (conceptIds.length > 0) { + prestacionQuery['solicitud.tipoPrestacion.conceptId'] = { $in: conceptIds }; + } + + const rupDocs: any[] = await Prestacion.find(prestacionQuery); + const rupList = rupDocs.map(p => { + const raw = p.toJSON ? p.toJSON() : p; + const lastState = raw.estados && raw.estados.length ? raw.estados[raw.estados.length - 1] : raw.estadoActual; + return { + id: raw._id, + fecha: raw.ejecucion?.fecha || lastState?.createdAt || raw.solicitud?.fecha, + efector: { + id: raw.solicitud?.organizacion?.id || raw.ejecucion?.organizacion?.id, + nombre: raw.solicitud?.organizacion?.nombre || raw.ejecucion?.organizacion?.nombre + }, + tipoPrestacion: { + conceptId: raw.solicitud?.tipoPrestacion?.conceptId, + term: raw.solicitud?.tipoPrestacion?.term, + fsn: raw.solicitud?.tipoPrestacion?.fsn + }, + tipo: 'rup', + accesoHuds: { + id: raw._id, + tipo: 'rup' + } + }; + }); + + // 6. Unificar y ordenar por fecha descendente + const result = [...cdaList, ...rupList].sort((a, b) => { + return moment(b.fecha).diff(moment(a.fecha)); + }); + + return result; +} diff --git a/modules/huds/estudios-complementarios/estudios-complementarios.routes.ts b/modules/huds/estudios-complementarios/estudios-complementarios.routes.ts new file mode 100644 index 0000000000..061660ddfe --- /dev/null +++ b/modules/huds/estudios-complementarios/estudios-complementarios.routes.ts @@ -0,0 +1,35 @@ +import * as express from 'express'; +import { Auth } from '../../../auth/auth.class'; +import { getEstudiosComplementarios } from './estudios-complementarios.controller'; + +const router = express.Router(); + +router.get('/paciente/:idPaciente', Auth.authenticate(), async (req: any, res) => { + try { + const idPaciente = req.params.idPaciente; + const options = { + fechaDesde: req.query.fechaDesde, + fechaHasta: req.query.fechaHasta + }; + const resultado = await getEstudiosComplementarios(idPaciente, options); + return res.json(resultado); + } catch (err: any) { + return res.status(500).json({ message: err.message }); + } +}); + +router.get('/:idPaciente', Auth.authenticate(), async (req: any, res) => { + try { + const idPaciente = req.params.idPaciente; + const options = { + fechaDesde: req.query.fechaDesde, + fechaHasta: req.query.fechaHasta + }; + const resultado = await getEstudiosComplementarios(idPaciente, options); + return res.json(resultado); + } catch (err: any) { + return res.status(500).json({ message: err.message }); + } +}); + +export const EstudiosComplementariosRouter = router; diff --git a/modules/huds/estudios-complementarios/index.ts b/modules/huds/estudios-complementarios/index.ts new file mode 100644 index 0000000000..86cdb8c3dd --- /dev/null +++ b/modules/huds/estudios-complementarios/index.ts @@ -0,0 +1,2 @@ +export { getEstudiosComplementarios } from './estudios-complementarios.controller'; +export { EstudiosComplementariosRouter } from './estudios-complementarios.routes';