From e7ef2c4d51dc11eaad1272ee6032e593f973cdce Mon Sep 17 00:00:00 2001 From: silviroa Date: Wed, 15 Jul 2026 09:49:12 -0300 Subject: [PATCH 1/2] fix(CITAS): Agrega condicion para agendas con turnos del dia y mobile --- modules/mobileApp/routes/agendas.ts | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/modules/mobileApp/routes/agendas.ts b/modules/mobileApp/routes/agendas.ts index b3666b7a47..da1cc66947 100644 --- a/modules/mobileApp/routes/agendas.ts +++ b/modules/mobileApp/routes/agendas.ts @@ -20,6 +20,16 @@ router.get('/agendasDisponibles', async (req: any, res, next) => { const condiciones: any = await CondicionPaciente.find({ activo: true }); const reglas = []; let fieldRegla; + + if (req.user.type == 'paciente-token') { + const idPacienteQuery = req.query?.idPaciente; + const idPacienteToken = req.user.pacientes.find(p => String(p.id) === String(idPacienteQuery)); + + if (!idPacienteToken) { + return next(401); + } + } + if (req.query.idPaciente) { for (const condicion of condiciones) { const verificar = await verificarCondicionPaciente(condicion, req.query.idPaciente); @@ -38,11 +48,18 @@ router.get('/agendasDisponibles', async (req: any, res, next) => { } } matchAgendas['horaInicio'] = { $gt: new Date(moment().format('YYYY-MM-DD HH:mm')) }; - matchAgendas['bloques.restantesProgramados'] = { $gt: 0 }; + matchAgendas['$or'] = [ + { + 'bloques.restantesProgramados': { $gt: 0 }, + }, + { + 'bloques.restantesDelDia': { $gt: 0 } + } + ]; matchAgendas['estado'] = 'publicada'; matchAgendas['dinamica'] = false; - if (reglas) { + if (reglas?.length > 0) { matchAgendas['$or'] = [ { 'bloques.restantesMobile': { $gt: 0 }, From 683ec09b9d5ef23983ba3365cd07c210ea94a12e Mon Sep 17 00:00:00 2001 From: silviroa Date: Tue, 21 Jul 2026 11:32:35 -0300 Subject: [PATCH 2/2] fix(CITAS): Cambia restantes al liberar turno --- modules/mobileApp/routes/agendas.ts | 2 +- modules/turnos/controller/agenda.ts | 15 +++++++++--- modules/turnos/controller/turnosController.ts | 12 ++++++++++ modules/turnos/routes/turno.ts | 23 +++++-------------- 4 files changed, 31 insertions(+), 21 deletions(-) diff --git a/modules/mobileApp/routes/agendas.ts b/modules/mobileApp/routes/agendas.ts index da1cc66947..26de2de082 100644 --- a/modules/mobileApp/routes/agendas.ts +++ b/modules/mobileApp/routes/agendas.ts @@ -21,7 +21,7 @@ router.get('/agendasDisponibles', async (req: any, res, next) => { const reglas = []; let fieldRegla; - if (req.user.type == 'paciente-token') { + if (req.user.type === 'paciente-token') { const idPacienteQuery = req.query?.idPaciente; const idPacienteToken = req.user.pacientes.find(p => String(p.id) === String(idPacienteQuery)); diff --git a/modules/turnos/controller/agenda.ts b/modules/turnos/controller/agenda.ts index 79cebe7e68..2406f574bb 100644 --- a/modules/turnos/controller/agenda.ts +++ b/modules/turnos/controller/agenda.ts @@ -14,6 +14,7 @@ import { Prestacion } from '../../rup/schemas/prestacion'; import { Agenda, HistorialAgenda } from '../../turnos/schemas/agenda'; import { agendaLog, agendaJob } from '../citasLog'; import { SnomedCIE10Mapping } from './../../../core/term/controller/mapping'; +import { getAccesosVirtuales } from '../../turnos/controller/turnosController'; import * as cie10 from './../../../core/term/schemas/cie10'; import { ECLQueriesCtr } from './../../../core/tm/eclqueries.routes'; import { handleHttpRequest } from '../../../utils/requestHandler'; @@ -107,7 +108,10 @@ export function quitarTurnoDoble(req, data, tid = null) { // Turno y sobreturno export async function liberarTurno(req, data, turno) { const position = getPosition(req, data, turno._id); + const accesosVirtuales = await getAccesosVirtuales(); + const esMobile = accesosVirtuales.includes(String(turno.emitidoPor).toLowerCase()); const enEjecucion = await prestacionController.enEjecucion(turno); + const esHoy = moment(turno.horaInicio).isSame(moment(), 'day'); if (enEjecucion) { return false; } @@ -148,13 +152,15 @@ export async function liberarTurno(req, data, turno) { programados: data.bloques[position.indexBloque].turnos.filter(t => t.estado === 'asignado' && t.tipoTurno === 'programado').length || 0, delDia: data.bloques[position.indexBloque].turnos.filter(t => t.estado === 'asignado' && t.tipoTurno === 'delDia').length || 0, autocitados: data.bloques[position.indexBloque].turnos.filter(t => t.estado === 'asignado' && t.tipoTurno === 'profesional').length || 0, - gestion: data.bloques[position.indexBloque].turnos.filter(t => t.estado === 'asignado' && t.tipoTurno === 'gestion').length || 0 + gestion: data.bloques[position.indexBloque].turnos.filter(t => t.estado === 'asignado' && t.tipoTurno === 'gestion').length || 0, + mobile: data.bloques[position.indexBloque].turnos.filter(t => t.estado === 'asignado' && t.emitidoPor === 'appMobile').length || 0 }; const bloque = data.bloques[position.indexBloque]; const cuposMaximos = { gestion: getBloqueCupoMaximo(bloque, 'reservadoGestion'), profesional: getBloqueCupoMaximo(bloque, 'reservadoProfesional'), - programado: getBloqueCupoMaximo(bloque, 'accesoDirectoProgramado') + programado: getBloqueCupoMaximo(bloque, 'accesoDirectoProgramado'), + mobile: getBloqueCupoMaximo(bloque, 'cupoMobile') }; if (bloque.restantesGestion < (cuposMaximos.gestion - turnosAsignados.gestion)) { @@ -163,11 +169,14 @@ export async function liberarTurno(req, data, turno) { if (bloque.restantesProfesional < (cuposMaximos.profesional - turnosAsignados.autocitados)) { bloque.restantesProfesional = bloque.restantesProfesional + cant; } else { - if (bloque.restantesProgramados < (cuposMaximos.programado - turnosAsignados.programados)) { + if (!esHoy && bloque.restantesProgramados < (cuposMaximos.programado - turnosAsignados.programados)) { bloque.restantesProgramados = bloque.restantesProgramados + cant; } else { bloque.restantesDelDia = bloque.restantesDelDia + cant; } + if (esMobile && bloque.restantesMobile <= cuposMaximos.mobile) { + bloque.restantesMobile = bloque.restantesMobile + cant; + } } } diff --git a/modules/turnos/controller/turnosController.ts b/modules/turnos/controller/turnosController.ts index 8306db73ce..1cabb935b8 100644 --- a/modules/turnos/controller/turnosController.ts +++ b/modules/turnos/controller/turnosController.ts @@ -389,3 +389,15 @@ async function telefonoUnico() { return ''; } } + +export async function getAccesosVirtuales(): Promise { + try { + const constante: any = await Constantes.findOne({ key: 'accesos-virtuales' }); + if (constante && constante.nombre) { + return constante.nombre.split(',').map(s => s.trim().toLowerCase()); + } + } catch (err) { + log.error('acceso-constantes', { error: err.message }, userScheduler); + } + return ['appmobile', 'totem', 'misalud']; +} diff --git a/modules/turnos/routes/turno.ts b/modules/turnos/routes/turno.ts index 26fc4ae061..1f633f6e0b 100644 --- a/modules/turnos/routes/turno.ts +++ b/modules/turnos/routes/turno.ts @@ -171,24 +171,12 @@ router.patch('/turno/agenda/:idAgenda', async (req, res, next) => { }; */ -async function getAccesosVirtuales(): Promise { - try { - const constante: any = await Constantes.findOne({ key: 'accesos-virtuales' }); - if (constante && constante.nombre) { - return constante.nombre.split(',').map(s => s.trim().toLowerCase()); - } - } catch (err) { - log.error('acceso-constantes', { error: err.message }, userScheduler); - } - return ['appmobile', 'totem', 'misalud']; -} - router.patch('/turno/:idTurno/bloque/:idBloque/agenda/:idAgenda/', async (req: any, res, next) => { const continues = ValidateDarTurno.checkTurno(req.body); const pacienteTurno = req.body.paciente; if (continues.valid) { - const accesosVirtuales = await getAccesosVirtuales(); + const accesosVirtuales = await turnosController.getAccesosVirtuales(); const agendaRes: any = await getAgenda(req.body.idAgenda); const pacienteMPI = await PacienteCtr.findById(req.body.paciente.id) as any; @@ -238,7 +226,7 @@ router.patch('/turno/:idTurno/bloque/:idBloque/agenda/:idAgenda/', async (req: a programado: (esHoy && contieneAccesoDirecto) ? 0 : agendaRes.bloques[posBloque].restantesProgramados, gestion: (esHoy && contieneAccesoDirecto) ? 0 : agendaRes.bloques[posBloque].restantesGestion, profesional: (esHoy && contieneAccesoDirecto) ? 0 : agendaRes.bloques[posBloque].restantesProfesional, - mobile: esHoy ? 0 : (agendaRes as any).bloques[posBloque].restantesMobile, + mobile: (agendaRes as any).bloques[posBloque].restantesMobile, }; posTurno = (agendaRes as any).bloques[posBloque].turnos.findIndex(item => item._id.toString() === req.body.idTurno.toString()); @@ -287,9 +275,6 @@ router.patch('/turno/:idTurno/bloque/:idBloque/agenda/:idAgenda/', async (req: a if (countBloques.mobile > update['bloques.' + posBloque + '.restantesProgramados']) { update['bloques.' + posBloque + '.restantesMobile'] = countBloques.mobile - 1; } - if (req.body.emitidoPor && accesosVirtuales.includes(String(req.body.emitidoPor).toLowerCase())) { - update['bloques.' + posBloque + '.restantesMobile'] = countBloques.mobile - 1; - } break; case ('profesional'): update['bloques.' + posBloque + '.restantesProfesional'] = countBloques.profesional - 1; @@ -298,6 +283,10 @@ router.patch('/turno/:idTurno/bloque/:idBloque/agenda/:idAgenda/', async (req: a update['bloques.' + posBloque + '.restantesGestion'] = countBloques.gestion - 1; break; } + + if (req.body.emitidoPor && accesosVirtuales.includes(String(req.body.emitidoPor).toLowerCase())) { + update['bloques.' + posBloque + '.restantesMobile'] = countBloques.mobile - 1; + } const usuario = Auth.getAuditUser(req); const bloqueTurno = 'bloques.' + posBloque + '.turnos.' + posTurno;