From 5c4ae682b2cdd3c9a2c84f819e2675b1f99c4405 Mon Sep 17 00:00:00 2001 From: laucharin Date: Wed, 23 Apr 2025 15:04:06 -0300 Subject: [PATCH] feat(RUP): nuevo recurso RecetaDispositivo --- initialize.ts | 1 + modules/recetas/index.ts | 3 +- modules/recetas/receta-dispositivo.routes.ts | 23 +++ modules/recetas/receta-dispositivo.schema.ts | 88 ++++++++++++ .../{recetas.error.ts => receta.error.ts} | 0 .../{recetas.routes.ts => receta.routes.ts} | 6 +- .../{receta-schema.ts => receta.schema.ts} | 10 +- ...cetasController.ts => recetaController.ts} | 4 +- modules/rup/controllers/rup.events.ts | 135 +++++++++++------- 9 files changed, 212 insertions(+), 58 deletions(-) create mode 100644 modules/recetas/receta-dispositivo.routes.ts create mode 100644 modules/recetas/receta-dispositivo.schema.ts rename modules/recetas/{recetas.error.ts => receta.error.ts} (100%) rename modules/recetas/{recetas.routes.ts => receta.routes.ts} (96%) rename modules/recetas/{receta-schema.ts => receta.schema.ts} (96%) rename modules/recetas/{recetasController.ts => recetaController.ts} (99%) diff --git a/initialize.ts b/initialize.ts index 25d4c6237d..9b35dfc32f 100644 --- a/initialize.ts +++ b/initialize.ts @@ -120,6 +120,7 @@ export function initAPI(app: Express) { app.use('/api/modules', require('./modules/semaforo/').SemaforoRouter); app.use('/api/modules', require('./modules/constantes').ConstantesRouter); app.use('/api/modules', require('./modules/recetas').RecetasRouter); + app.use('/api/modules', require('./modules/recetas').RecetaDispositivoRouter); if (configPrivate.hosts.BI_QUERY) { app.use( diff --git a/modules/recetas/index.ts b/modules/recetas/index.ts index 771ee85768..694fdd2c89 100644 --- a/modules/recetas/index.ts +++ b/modules/recetas/index.ts @@ -1 +1,2 @@ -export { RecetasRouter } from './recetas.routes'; +export { RecetasRouter } from './receta.routes'; +export { RecetaDispositivoRouter } from './receta-dispositivo.routes'; diff --git a/modules/recetas/receta-dispositivo.routes.ts b/modules/recetas/receta-dispositivo.routes.ts new file mode 100644 index 0000000000..f7cf0994a4 --- /dev/null +++ b/modules/recetas/receta-dispositivo.routes.ts @@ -0,0 +1,23 @@ +import { MongoQuery, ResourceBase } from '@andes/core'; +import { Auth } from '../../auth/auth.class'; +import { RecetaDispositivo } from './receta-dispositivo.schema'; + +class RecetaDispositivoResource extends ResourceBase { + Model = RecetaDispositivo; + resourceName = 'recetaDispositivo'; + routesEnable = ['get, post']; + middlewares = [Auth.authenticate()]; + searchFileds = { + paciente: { + field: 'paciente.id', + fn: MongoQuery.equalMatch + }, + documento: { + field: 'paciente.documento', + fn: MongoQuery.equalMatch + } + }; +} + +export const RecetaDispositivoCtr = new RecetaDispositivoResource({}); +export const RecetaDispositivoRouter = RecetaDispositivoCtr.makeRoutes(); diff --git a/modules/recetas/receta-dispositivo.schema.ts b/modules/recetas/receta-dispositivo.schema.ts new file mode 100644 index 0000000000..1045a72dd6 --- /dev/null +++ b/modules/recetas/receta-dispositivo.schema.ts @@ -0,0 +1,88 @@ +import { AuditPlugin } from '@andes/mongoose-plugin-audit'; +import * as mongoose from 'mongoose'; +import { PacienteSubSchema } from '../../core-v2/mpi/paciente/paciente.schema'; +import { SnomedConcept } from '../rup/schemas/snomed-concept'; +import { estadosSchema, estadoDispensaSchema, sistemaSchema } from './receta.schema'; + + +const dispositivoSchema = new mongoose.Schema({ + concepto: SnomedConcept, + cantidad: Number, + tratamientoProlongado: Boolean, + tiempoTratamiento: mongoose.SchemaTypes.Mixed +}); + +export const recetaDispositivoSchema = new mongoose.Schema({ + organizacion: { + id: mongoose.SchemaTypes.ObjectId, + nombre: String + }, + profesional: { + id: mongoose.SchemaTypes.ObjectId, + nombre: String, + apellido: String, + documento: String, + profesion: String, + matricula: Number, + especialidad: String, + }, + fechaRegistro: Date, + fechaPrestacion: Date, + idPrestacion: String, + idRegistro: String, + diagnostico: SnomedConcept, + dispositivo: dispositivoSchema, + dispensa: [ + { + idDispensaApp: String, + fecha: Date, + dispositivo: [{ + cantidad: Number, + descripcion: String, + dispositivo: mongoose.SchemaTypes.Mixed, + cantidadEnvases: Number, + observacion: { + type: String, + required: false + } + }], + organizacion: { + id: String, + nombre: String + }, + } + ], + estados: [estadosSchema], + estadoActual: estadosSchema, + estadosDispensa: [estadoDispensaSchema], + estadoDispensaActual: estadoDispensaSchema, + paciente: PacienteSubSchema, + renovacion: String, + appNotificada: [{ app: sistemaSchema, fecha: Date }], + origenExterno: { + id: String, // id receta creada por sistema que no es Andes + app: sistemaSchema, + fecha: Date + } +}); + +recetaDispositivoSchema.pre('save', function (next) { + const recetaDispositivo: any = this; + + if (recetaDispositivo.estados && recetaDispositivo.estados.length > 0) { + recetaDispositivo.estadoActual = recetaDispositivo.estados[recetaDispositivo.estados.length - 1]; + } + if (recetaDispositivo.estadosDispensa && recetaDispositivo.estadosDispensa.length > 0) { + recetaDispositivo.estadoDispensaActual = recetaDispositivo.estadosDispensa[recetaDispositivo.estadosDispensa.length - 1]; + } + + next(); +}); + +recetaDispositivoSchema.plugin(AuditPlugin); + +recetaDispositivoSchema.index({ + idPrestacion: 1, +}); + +export const RecetaDispositivo = mongoose.model('prescripcionInsumos', recetaDispositivoSchema, 'prescripcionInsumos'); diff --git a/modules/recetas/recetas.error.ts b/modules/recetas/receta.error.ts similarity index 100% rename from modules/recetas/recetas.error.ts rename to modules/recetas/receta.error.ts diff --git a/modules/recetas/recetas.routes.ts b/modules/recetas/receta.routes.ts similarity index 96% rename from modules/recetas/recetas.routes.ts rename to modules/recetas/receta.routes.ts index 20803b2daf..c7a365dc84 100644 --- a/modules/recetas/recetas.routes.ts +++ b/modules/recetas/receta.routes.ts @@ -1,9 +1,9 @@ import { asyncHandler, Request, Response } from '@andes/api-tool'; import { MongoQuery, ResourceBase } from '@andes/core'; import { Auth } from '../../auth/auth.class'; -import { Receta } from './receta-schema'; -import { buscarRecetas, getMotivosReceta, setEstadoDispensa, suspender, actualizarAppNotificada, cancelarDispensa, crearReceta } from './recetasController'; -import { ParamsIncorrect } from './recetas.error'; +import { Receta } from './receta.schema'; +import { buscarRecetas, getMotivosReceta, setEstadoDispensa, suspender, actualizarAppNotificada, cancelarDispensa, crearReceta } from './recetaController'; +import { ParamsIncorrect } from './receta.error'; class RecetasResource extends ResourceBase { Model = Receta; diff --git a/modules/recetas/receta-schema.ts b/modules/recetas/receta.schema.ts similarity index 96% rename from modules/recetas/receta-schema.ts rename to modules/recetas/receta.schema.ts index 9689f85a39..1ed9583b1a 100644 --- a/modules/recetas/receta-schema.ts +++ b/modules/recetas/receta.schema.ts @@ -15,7 +15,7 @@ export const motivosRecetaSchema = new mongoose.Schema({ } }); -const estadosSchema = new mongoose.Schema({ +export const estadosSchema = new mongoose.Schema({ tipo: { type: String, enum: ['pendiente', 'vigente', 'finalizada', 'vencida', 'suspendida', 'rechazada'], @@ -48,12 +48,13 @@ const estadosSchema = new mongoose.Schema({ estadosSchema.plugin(AuditPlugin); -const sistemaSchema = { + +export const sistemaSchema = { type: String, enum: ['sifaho', 'recetar'] }; -const cancelarSchema = new mongoose.Schema({ +export const cancelarSchema = new mongoose.Schema({ idDispensaApp: { type: String, required: false @@ -67,7 +68,8 @@ const cancelarSchema = new mongoose.Schema({ nombre: String } }); -const estadoDispensaSchema = new mongoose.Schema({ + +export const estadoDispensaSchema = new mongoose.Schema({ tipo: { type: String, enum: ['sin-dispensa', 'dispensada', 'dispensa-parcial'], diff --git a/modules/recetas/recetasController.ts b/modules/recetas/recetaController.ts similarity index 99% rename from modules/recetas/recetasController.ts rename to modules/recetas/recetaController.ts index 86eff6db5a..41644055b5 100644 --- a/modules/recetas/recetasController.ts +++ b/modules/recetas/recetaController.ts @@ -1,8 +1,8 @@ import { Types } from 'mongoose'; import { Auth } from '../../auth/auth.class'; import { searchMatriculas } from '../../core/tm/controller/profesional'; -import { MotivosReceta, Receta } from './receta-schema'; -import { ParamsIncorrect, RecetaNotFound, RecetaNotEdit } from './recetas.error'; +import { MotivosReceta, Receta } from './receta.schema'; +import { ParamsIncorrect, RecetaNotFound, RecetaNotEdit } from './receta.error'; import * as moment from 'moment'; import { getReceta } from './services/receta'; import { updateLog, informarLog, createLog } from './recetaLogs'; diff --git a/modules/rup/controllers/rup.events.ts b/modules/rup/controllers/rup.events.ts index 3d6e740835..92d1ffad7a 100644 --- a/modules/rup/controllers/rup.events.ts +++ b/modules/rup/controllers/rup.events.ts @@ -1,17 +1,19 @@ import { EventCore } from '@andes/event-bus'; -import { getProfesionActualizada } from '../../recetas/recetasController'; +import { getProfesionActualizada } from '../../recetas/recetaController'; import * as moment from 'moment'; -import { Receta } from '../../recetas/receta-schema'; +import { userScheduler } from '../../../config.private'; +import { Receta } from '../../recetas/receta.schema'; import { rupEventsLog as logger } from './rup.events.log'; +import { RecetaDispositivo } from '../../recetas/receta-dispositivo.schema'; -const conceptIds = ['33633005', '103742009']; // Receta y renovación de receta +const conceptIdsMedicamento = ['33633005', '103742009']; // Receta y renovación de receta de MEDICAMENTOS +const conceptIdsDispositivo = ['313047003']; // Receta de DISPOSITIVOS (INSUMOS) EventCore.on('prestacion:receta:create', async (prestacion) => { try { if (prestacion.prestacion) { prestacion = prestacion.prestacion; } - const idPrestacion = prestacion.id; const registros = prestacion.ejecucion.registros; const profPrestacion = prestacion.solicitud.profesional; @@ -33,53 +35,90 @@ EventCore.on('prestacion:receta:create', async (prestacion) => { }; for (const registro of registros) { - if (conceptIds.includes(registro.concepto.conceptId)) { - for (const medicamento of registro.valor.medicamentos) { - let receta: any = await Receta.findOne( - { - 'medicamento.concepto.conceptId': medicamento.generico.conceptId, - idRegistro: registro._id, - }); - - if (!receta) { - receta = new Receta(); - } - receta.organizacion = organizacion; - receta.profesional = profesional; - receta.fechaRegistro = moment(prestacion.ejecucion.fecha).toDate(); - receta.fechaPrestacion = moment(prestacion.ejecucion.fecha).toDate(); - receta.idPrestacion = idPrestacion; - receta.idRegistro = registro._id; - receta.diagnostico = medicamento.diagnostico; - receta.medicamento = { - concepto: medicamento.generico, - presentacion: medicamento.presentacion.term, - unidades: medicamento.unidades, - cantidad: medicamento.cantidad, - cantEnvases: medicamento.cantEnvases, - dosisDiaria: { - dosis: medicamento.dosisDiaria.dosis, - intervalo: medicamento.dosisDiaria.intervalo, - dias: medicamento.dosisDiaria.dias, - notaMedica: medicamento.dosisDiaria.notaMedica - }, - tratamientoProlongado: medicamento.tratamientoProlongado, - tiempoTratamiento: medicamento.tiempoTratamiento, - tipoReceta: medicamento.tipoReceta || 'simple', - serie: medicamento.serie, - numero: medicamento.numero - }; - receta.estados = [{ tipo: 'vigente' }]; - receta.estadoActual = { tipo: 'vigente' }; - receta.estadosDispensa = [{ tipo: 'sin-dispensa', fecha: moment().toDate() }]; - receta.estadoDispensaActual = { tipo: 'sin-dispensa', fecha: moment().toDate() }; - receta.paciente = prestacion.paciente; - receta.audit(prestacion.createdBy); - await receta.save(); - } + if (conceptIdsMedicamento.includes(registro.concepto.conceptId)) { + const medicamentos = registro.valor.medicamentos; + await saveRecetaMedicamentos(organizacion, profesional, prestacion, registro, medicamentos); + } else if (conceptIdsDispositivo.includes(registro.concepto.conceptId)) { + const dispositivos = registro.valor.dispositivos; + await saveRecetaDispositivos(organizacion, profesional, prestacion, registro, dispositivos); } } } catch (err) { logger.error('prestacion:receta:create', prestacion, err); } }); + +/** + * Por cada medicamento genera un nuevo documento en la coleccion 'receta' + */ +async function saveRecetaMedicamentos(organizacion, profesional, prestacion, registro, medicamentos) { + for (const medicamento of medicamentos) { + let receta: any = await Receta.findOne({ idPrestacion: 0 }); + if (!receta) { + receta = new Receta(); + } + receta.organizacion = organizacion; + receta.profesional = profesional; + receta.fechaRegistro = moment(prestacion.ejecucion.fecha).toDate(); + receta.fechaPrestacion = moment(prestacion.ejecucion.fecha).toDate(); + receta.idPrestacion = prestacion.id; + receta.idRegistro = registro._id; + receta.diagnostico = medicamento.diagnostico; + receta.medicamento = { + concepto: medicamento.generico, + presentacion: medicamento.presentacion.term, + unidades: medicamento.unidades, + cantidad: medicamento.cantidad, + cantEnvases: medicamento.cantEnvases, + dosisDiaria: { + dosis: medicamento.dosisDiaria.dosis, + intervalo: medicamento.dosisDiaria.intervalo, + dias: medicamento.dosisDiaria.dias, + notaMedica: medicamento.dosisDiaria.notaMedica + }, + tratamientoProlongado: medicamento.tratamientoProlongado, + tiempoTratamiento: medicamento.tiempoTratamiento, + tipoReceta: medicamento.tipoReceta || 'simple', + serie: medicamento.serie, + numero: medicamento.numero + }; + receta.estados = [{ tipo: 'vigente' }]; + receta.estadoActual = { tipo: 'vigente' }; + receta.estadosDispensa = [{ tipo: 'sin-dispensa', fecha: moment().toDate() }]; + receta.estadoDispensaActual = { tipo: 'sin-dispensa', fecha: moment().toDate() }; + receta.paciente = prestacion.paciente; + receta.audit(prestacion.createdBy); + await receta.save(); + } +} + +/** + * Por cada dispositivo recetado genera un nuevo documento en la coleccion 'prescripcionInsumos' + */ +async function saveRecetaDispositivos(organizacion, profesional, prestacion, registro, dispositivos) { + for (const dispositivo of dispositivos) { + let recetaDispositivo: any = await RecetaDispositivo.findOne({ idPrestacion: 0 }); + if (!recetaDispositivo) { + recetaDispositivo = new RecetaDispositivo(); + } + recetaDispositivo.organizacion = organizacion; + recetaDispositivo.profesional = profesional; + recetaDispositivo.fechaRegistro = moment(prestacion.ejecucion.fecha).toDate(); + recetaDispositivo.fechaPrestacion = moment(prestacion.ejecucion.fecha).toDate(); + recetaDispositivo.idPrestacion = prestacion.id; + recetaDispositivo.idRegistro = registro._id; + recetaDispositivo.dispositivo = { + concepto: dispositivo.generico, + cantidad: dispositivo.cantidad, + tratamientoProlongado: dispositivo.tratamientoProlongado, + tiempoTratamiento: dispositivo.tiempoTratamiento, + }; + recetaDispositivo.estados = [{ tipo: 'vigente' }]; + recetaDispositivo.estadoActual = { tipo: 'vigente' }; + recetaDispositivo.estadosDispensa = [{ tipo: 'sin-dispensa', fecha: moment().toDate() }]; + recetaDispositivo.estadoDispensaActual = { tipo: 'sin-dispensa', fecha: moment().toDate() }; + recetaDispositivo.paciente = prestacion.paciente; + recetaDispositivo.audit(userScheduler); + await recetaDispositivo.save(); + } +}