From d307fa731543073aa420ec010b93b3457afadd51 Mon Sep 17 00:00:00 2001 From: aldo Date: Wed, 5 Nov 2025 08:25:39 -0300 Subject: [PATCH 1/2] feat(REC-138):ANDES: Mejoras en la suspencion de recetas --- modules/recetas/receta-schema.ts | 2 +- modules/recetas/recetas.routes.ts | 4 ++-- modules/recetas/recetasController.ts | 36 ++++++++++------------------ 3 files changed, 15 insertions(+), 27 deletions(-) diff --git a/modules/recetas/receta-schema.ts b/modules/recetas/receta-schema.ts index 0f24cf2cf..fcb699d53 100644 --- a/modules/recetas/receta-schema.ts +++ b/modules/recetas/receta-schema.ts @@ -19,7 +19,7 @@ export const motivosRecetaSchema = new mongoose.Schema({ const estadosSchema = new mongoose.Schema({ tipo: { type: String, - enum: ['pendiente', 'vigente', 'finalizada', 'vencida', 'suspendida', 'rechazada'], + enum: ['pendiente', 'vigente', 'finalizada', 'vencida', 'suspendida', 'rechazada','eliminada'], required: true, default: 'vigente' }, diff --git a/modules/recetas/recetas.routes.ts b/modules/recetas/recetas.routes.ts index e7e96a14f..61a4dba8a 100644 --- a/modules/recetas/recetas.routes.ts +++ b/modules/recetas/recetas.routes.ts @@ -46,13 +46,13 @@ export const patch = async (req, res) => { let result, status; const { recetaId, recetas, dataDispensa } = req.body; const app = req.user.app?.nombre ? req.user.app.nombre.toLowerCase() : ''; - if (!recetaId && !recetas) { + if ((!recetaId && !recetas)) { const error = new ParamsIncorrect(); res.status(error.status).json(error); } else { switch (operacion) { case 'suspender': - result = await suspender(recetas, req); + result = await suspender(recetaId, req); break; case 'dispensar': case 'dispensa-parcial': diff --git a/modules/recetas/recetasController.ts b/modules/recetas/recetasController.ts index 53714048d..69e9e2093 100644 --- a/modules/recetas/recetasController.ts +++ b/modules/recetas/recetasController.ts @@ -228,23 +228,18 @@ export async function obtenerRecetasPorGrupo(recetaIds) { } } -export async function suspender(recetas, req) { +export async function suspender(recetaId, req) { const motivo = req.body.motivo; const observacion = req.body.observacion; const profesional = req.body.profesional; try { - if (!recetas) { - throw new ParamsIncorrect(); - } - const recetasASuspender = await obtenerRecetasPorGrupo(recetas); - const promises = recetas.map(async (recetaId) => { - - const receta: any = await Receta.findById(recetaId); - - if (!receta) { - throw new RecetaNotFound(); - } - if (!receta.medicamento.tratamientoProlongado) { + const recetaR: any = await Receta.findById(recetaId); + const recetasASuspender = await Receta.find( { + 'medicamento.concepto.conceptId': recetaR.medicamento.concepto.conceptId, + idRegistro: recetaR.idRegistro + }); + const promises = recetasASuspender.map(async (receta: any) => { + if ((receta.estadoActual.tipo === 'vigente') || (receta.estadoDispensaActual.tipo === 'dispensa-parcial' && receta.estadoActual.tipo === 'pendiente')) { receta.estados.push({ tipo: 'suspendida', motivo, @@ -254,14 +249,10 @@ export async function suspender(recetas, req) { }); Auth.audit(receta, req); await receta.save(); - - const idRegistro = receta.idRegistro; - const medicamento = receta.medicamento?.concepto.conceptId; - await Receta.deleteMany({ idRegistro, 'medicamento.concepto.conceptId': medicamento, 'estadoActual.tipo': 'pendiente', 'estadoDispensaActual.tipo': 'sin-dispensa' }); } else { - if (recetasASuspender.some(r => r.id.toString() === receta.id.toString())) { + if (receta.estadoDispensaActual.tipo === 'sin-dispensa' && receta.estadoActual.tipo === 'pendiente') { receta.estados.push({ - tipo: 'suspendida', + tipo: 'eliminada', motivo, observacion, profesional, @@ -269,17 +260,14 @@ export async function suspender(recetas, req) { }); Auth.audit(receta, req); await receta.save(); - } else { - const _id = receta.id; - const medicamento = receta.medicamento?.concepto.conceptId; - await Receta.deleteOne({ _id }); } } }); await Promise.all(promises); + return { success: true }; } catch (error) { - await updateLog.error('suspender', { motivo, observacion, profesional, recetas }, error); + await updateLog.error('suspender', { motivo, observacion, profesional, recetaId }, error); return error; } } From 778f8d711038a5f6a0f2cacc1b5fff5c943aa9f2 Mon Sep 17 00:00:00 2001 From: mcele <19591224+MCele@users.noreply.github.com> Date: Fri, 20 Feb 2026 11:45:38 -0300 Subject: [PATCH 2/2] feat(recetas): estado suspendida en al menos una receta --- modules/recetas/recetasController.ts | 116 +++++++++------------------ 1 file changed, 39 insertions(+), 77 deletions(-) diff --git a/modules/recetas/recetasController.ts b/modules/recetas/recetasController.ts index 69e9e2093..a18498bb8 100644 --- a/modules/recetas/recetasController.ts +++ b/modules/recetas/recetasController.ts @@ -155,10 +155,12 @@ export async function buscarRecetas(req) { optOtros['estadoActual.tipo'] = { $in: includeOtros }; } options['$or'] = [optPendientes, optVigentes, optOtros].filter(o => o.hasOwnProperty('estadoActual.tipo')); - } else if (user.type === 'app-token') { - options['fechaRegistro'] = { $gte: fechaInicio, $lte: fechaFin }; + } else { + options['estadoActual.tipo'] = { $nin: ['eliminada'] }; + if (user.type === 'app-token') { + options['fechaRegistro'] = { $gte: fechaInicio, $lte: fechaFin }; + } } - let recetas: any = await Receta.find(options); if (!recetas.length) { return []; @@ -188,90 +190,52 @@ export async function buscarRecetas(req) { } } -/** - * Groups recetas by idRegistro and selects the one with the smallest ordenTratamiento from each group - * @param recetaIds Array of receta IDs - * @returns Array of selected recetas (one per group) - */ -export async function obtenerRecetasPorGrupo(recetaIds) { - try { - const recetasPromises = recetaIds.map(async (recetaId) => { - const receta: any = await Receta.findById(recetaId); - return receta; - }); - const recetas = await Promise.all(recetasPromises); - const grupos = {}; - recetas.forEach(receta => { - if (receta) { - const idRegistro = receta.idRegistro; - if (!grupos[idRegistro]) { - grupos[idRegistro] = []; - } - grupos[idRegistro].push(receta); - } - }); - - const recetasASuspender = []; - Object.values(grupos).forEach((grupo: any[]) => { - if (grupo.length > 0) { - const recetaMenorOrden = grupo.reduce((min, receta) => - receta.medicamento.ordenTratamiento < min.medicamento.ordenTratamiento ? receta : min - ); - recetasASuspender.push(recetaMenorOrden); - } - }); - - return recetasASuspender; - } catch (error) { - await updateLog.error('obtenerRecetasPorGrupo', { recetaIds }, error); - throw error; - } -} - export async function suspender(recetaId, req) { const motivo = req.body.motivo; const observacion = req.body.observacion; const profesional = req.body.profesional; try { const recetaR: any = await Receta.findById(recetaId); - const recetasASuspender = await Receta.find( { + const recetasASuspender = await Receta.find({ 'medicamento.concepto.conceptId': recetaR.medicamento.concepto.conceptId, - idRegistro: recetaR.idRegistro - }); - const promises = recetasASuspender.map(async (receta: any) => { - if ((receta.estadoActual.tipo === 'vigente') || (receta.estadoDispensaActual.tipo === 'dispensa-parcial' && receta.estadoActual.tipo === 'pendiente')) { - receta.estados.push({ - tipo: 'suspendida', - motivo, - observacion, - profesional, - fecha: new Date() - }); - Auth.audit(receta, req); - await receta.save(); - } else { - if (receta.estadoDispensaActual.tipo === 'sin-dispensa' && receta.estadoActual.tipo === 'pendiente') { - receta.estados.push({ - tipo: 'eliminada', - motivo, - observacion, - profesional, - fecha: new Date() - }); - Auth.audit(receta, req); - await receta.save(); - } + idRegistro: recetaR.idRegistro, + 'estadoActual.tipo': { $nin: ['vencida', 'finalizada'] } + }).sort({ fechaRegistro: -1 }); + + + if (recetasASuspender.length) { + const recetasSuspender = recetasASuspender.filter((r: any) => (r.estadoActual.tipo === 'vigente') || (r.estadoDispensaActual.tipo === 'dispensa-parcial' && r.estadoActual.tipo === 'pendiente')); + const recetasEliminar = recetasASuspender.filter((r: any) => (r.estadoDispensaActual.tipo === 'sin-dispensa' && r.estadoActual.tipo === 'pendiente')); + if (recetasSuspender.length === 0 && recetasEliminar.length !== 0) { + // en el tratamiento prolongado, al menos una receta debe quedar en estado suspendido + const recetaSusp = recetasEliminar.pop(); + recetasSuspender.push(recetaSusp); } - }); - await Promise.all(promises); + const recSusp = await Promise.all(await recetasUpdate(recetasSuspender, 'suspendida', motivo, observacion, profesional, req)); + + const rec = recSusp.concat(await Promise.all(await recetasUpdate(recetasEliminar, 'eliminada', motivo, observacion, profesional, req))); - return { success: true }; + return rec; + } + return recetasASuspender; } catch (error) { await updateLog.error('suspender', { motivo, observacion, profesional, recetaId }, error); return error; } } +async function recetasUpdate(recetas, estado, motivo, observacion, profesional, req) { + return recetas.map(async (receta: any) => { + receta.estados.push({ + tipo: estado, + motivo, + observacion, + profesional, + }); + Auth.audit(receta, req); + return await receta.save(); + }); +}; export async function getMotivosReceta(res) { try { @@ -683,7 +647,7 @@ export async function buscarRecetasPorProfesional(req) { filter['origenExterno.app'] = origenExternoApp; } if (excluirEstado) { - filter['estadoActual.tipo'] = { $ne: excluirEstado }; + filter['estadoActual.tipo'] = { $nin: excluirEstado }; } const recetas = await Receta.find(filter); return recetas; @@ -723,8 +687,7 @@ export async function actualizarEstadosRecetas(done) { for (const receta of recetasPendientes) { try { receta.estados.push({ - tipo: 'vigente', - fecha: moment().toDate(), + tipo: 'vigente' }); totalRecetasAVigentes++; Auth.audit(receta, userScheduler as any); @@ -746,8 +709,7 @@ export async function actualizarEstadosRecetas(done) { for (const receta of recetasVigentes) { try { receta.estados.push({ - tipo: 'vencida', - fecha: moment().toDate() + tipo: 'vencida' }); Auth.audit(receta, userScheduler as any); await receta.save();