From 3ffc2176c84230637c6d8734080333a998ccee51 Mon Sep 17 00:00:00 2001 From: nicolasarana <90768149+nicolasarana@users.noreply.github.com> Date: Thu, 23 Jul 2026 12:11:45 -0300 Subject: [PATCH 1/4] CIT- Visibilidad de agendas de teleconsulta --- modules/mobileApp/routes/agendas.ts | 1 + modules/turnos/routes/agenda.ts | 5 +++++ modules/turnos/schemas/bloque.ts | 8 ++++++++ 3 files changed, 14 insertions(+) diff --git a/modules/mobileApp/routes/agendas.ts b/modules/mobileApp/routes/agendas.ts index b3666b7a47..7c2e511a5c 100644 --- a/modules/mobileApp/routes/agendas.ts +++ b/modules/mobileApp/routes/agendas.ts @@ -41,6 +41,7 @@ router.get('/agendasDisponibles', async (req: any, res, next) => { matchAgendas['bloques.restantesProgramados'] = { $gt: 0 }; matchAgendas['estado'] = 'publicada'; matchAgendas['dinamica'] = false; + matchAgendas['bloques.appMobile'] = true; if (reglas) { matchAgendas['$or'] = [ diff --git a/modules/turnos/routes/agenda.ts b/modules/turnos/routes/agenda.ts index 8992d67b6a..0202c6c18f 100644 --- a/modules/turnos/routes/agenda.ts +++ b/modules/turnos/routes/agenda.ts @@ -246,6 +246,11 @@ router.get('/agenda/:id?', async (req, res, next) => { query.where('bloques.turnos.estado').equals('asignado'); } + if (String(req.query.citasVirtuales) === 'true') { + query.where('bloques.citasVirtuales').equals(true); + } else if (String(req.query.citasVirtuales) === 'false') { + query.where('bloques.citasVirtuales').equals(false); + } if (req.query.turno) { query.where('bloques.turnos._id').equals(req.query.turno); } diff --git a/modules/turnos/schemas/bloque.ts b/modules/turnos/schemas/bloque.ts index 674acd0779..b072c00cb7 100644 --- a/modules/turnos/schemas/bloque.ts +++ b/modules/turnos/schemas/bloque.ts @@ -54,6 +54,14 @@ const bloqueSchema = new mongoose.Schema({ type: Number, default: 0 }, + citasVirtuales: { + type: Boolean, + default: false + }, + appMobile: { + type: Boolean, + default: false + }, restantesMobile: { type: Number, default: 0 From f0afee2570b2e5d6c23d1ab4a6c9e51d847420eb Mon Sep 17 00:00:00 2001 From: nicolasarana <90768149+nicolasarana@users.noreply.github.com> Date: Mon, 27 Jul 2026 13:10:48 -0300 Subject: [PATCH 2/4] =?UTF-8?q?fix=20-=20Mejora=20en=20c=C3=B3digo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/turnos/routes/agenda.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/modules/turnos/routes/agenda.ts b/modules/turnos/routes/agenda.ts index 0202c6c18f..eb6eebfda1 100644 --- a/modules/turnos/routes/agenda.ts +++ b/modules/turnos/routes/agenda.ts @@ -245,11 +245,9 @@ router.get('/agenda/:id?', async (req, res, next) => { if (req.query.tieneTurnosAsignados) { query.where('bloques.turnos.estado').equals('asignado'); } - - if (String(req.query.citasVirtuales) === 'true') { - query.where('bloques.citasVirtuales').equals(true); - } else if (String(req.query.citasVirtuales) === 'false') { - query.where('bloques.citasVirtuales').equals(false); + const citasVirtuales = String(req.query.citasVirtuales); + if (citasVirtuales === 'true' || citasVirtuales === 'false') { + query.where('bloques.citasVirtuales').equals(citasVirtuales === 'true'); } if (req.query.turno) { query.where('bloques.turnos._id').equals(req.query.turno); From 3b92239ef9e090cddfe175d9e8921fb745c0893b Mon Sep 17 00:00:00 2001 From: nicolasarana <90768149+nicolasarana@users.noreply.github.com> Date: Fri, 31 Jul 2026 12:19:03 -0300 Subject: [PATCH 3/4] =?UTF-8?q?fix=20-=20Correcci=C3=B3n=20error=20al=20an?= =?UTF-8?q?ular=20turno=20mobile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/turnos/controller/agenda.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/turnos/controller/agenda.ts b/modules/turnos/controller/agenda.ts index 79cebe7e68..11e710aa80 100644 --- a/modules/turnos/controller/agenda.ts +++ b/modules/turnos/controller/agenda.ts @@ -119,6 +119,7 @@ export async function liberarTurno(req, data, turno) { data.sobreturnos.splice(index, 1); } else { // Liberación de turno if (!data.dinamica) { + const emitidoPor = turno.emitidoPor; turno.estado = 'disponible'; turno.paciente = null; turno.tipoPrestacion = null; @@ -171,6 +172,10 @@ export async function liberarTurno(req, data, turno) { } } + if (emitidoPor && await esVirtual(emitidoPor)) { + bloque.restantesMobile = (bloque.restantesMobile || 0) + cant; + } + const fechaActualizar = moment().startOf('day').add(2, 'days'); // actualizamos turnos de la agenda si la hora de inicio esta dentro de las proxmas 48hs if (moment(data.horaInicio).isBefore(fechaActualizar)) { From 97471c8c3d42168eedf15233f47be088aa58c6d3 Mon Sep 17 00:00:00 2001 From: nicolasarana <90768149+nicolasarana@users.noreply.github.com> Date: Fri, 7 Aug 2026 10:40:41 -0300 Subject: [PATCH 4/4] =?UTF-8?q?fix=20-=20Correcci=C3=B3n=207/08?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/turnos/routes/agenda.ts | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/modules/turnos/routes/agenda.ts b/modules/turnos/routes/agenda.ts index eb6eebfda1..97ee29d341 100644 --- a/modules/turnos/routes/agenda.ts +++ b/modules/turnos/routes/agenda.ts @@ -21,6 +21,23 @@ import { tipoPrestacion } from '../../../core/tm/schemas/tipoPrestacion'; const router = express.Router(); +// Rechaza bloques de teleconsulta con todo el cupo asignado a turnos mobile pero sin ningún canal de atención seleccionado +function validarBloquesInvisibles(bloques): string | null { + if (!bloques) { + return null; + } + for (const bloque of bloques) { + const cupoMobile = Number(bloque.cupoMobile) || 0; + const cantidadTurnos = Number(bloque.cantidadTurnos) || 0; + const tienePrestacionTeleconsulta = (bloque.tipoPrestaciones || []).some(tp => tp.teleConsulta); + if (cupoMobile > 0 && cupoMobile === cantidadTurnos && tienePrestacionTeleconsulta && !bloque.appMobile && !bloque.citasVirtuales) { + const horaInicio = bloque.horaInicio ? moment(bloque.horaInicio).format('DD/MM/YYYY HH:mm') : 'sin horario'; + return `No se puede guardar la agenda: el bloque de las ${horaInicio} es de teleconsulta, tiene todo el cupo asignado a turnos mobile y no se seleccionó ningún canal de atención (appMobile ni citasVirtuales)`; + } + } + return null; +} + // devuelve los 10 ultimos turnos del paciente router.get('/agenda/paciente/:idPaciente', (req, res, next) => { @@ -245,10 +262,6 @@ router.get('/agenda/:id?', async (req, res, next) => { if (req.query.tieneTurnosAsignados) { query.where('bloques.turnos.estado').equals('asignado'); } - const citasVirtuales = String(req.query.citasVirtuales); - if (citasVirtuales === 'true' || citasVirtuales === 'false') { - query.where('bloques.citasVirtuales').equals(citasVirtuales === 'true'); - } if (req.query.turno) { query.where('bloques.turnos._id').equals(req.query.turno); } @@ -316,6 +329,11 @@ router.post('/agenda', async (req: any, res, next) => { return next(errorPrestaciones); } + const errorBloques = validarBloquesInvisibles(req.body.bloques); + if (errorBloques) { + return next(errorBloques); + } + const mensajesSolapamiento = await agendaCtrl.verificarSolapamiento(data); if (!mensajesSolapamiento.tipoError) { const dataSaved = await data.save(); @@ -410,6 +428,11 @@ router.put('/agenda/:id', async (req: any, res, next) => { return next(errorPrestaciones); } + const errorBloques = validarBloquesInvisibles(req.body.bloques); + if (errorBloques) { + return next(errorBloques); + } + const mensajesSolapamiento = await agendaCtrl.verificarSolapamiento(req.body); if (mensajesSolapamiento.tipoError) { objetoLog.err = mensajesSolapamiento;