diff --git a/src/controllers/prescription.controller.ts b/src/controllers/prescription.controller.ts index 49d570b..503796a 100644 --- a/src/controllers/prescription.controller.ts +++ b/src/controllers/prescription.controller.ts @@ -147,7 +147,7 @@ class PrescriptionController implements BaseController { }; public create = async (req: Request, res: Response): Promise => { - const { professional, patient, date, supplies, trimestral, ambito } = req.body; + const { professional, patient, date, supplies, trimestral, ambito, organizacion } = req.body; const myProfessional: IUser | null = await User.findOne({ _id: professional }); let myPatient: IPatient | null; if (ambito === 'publico') { @@ -188,12 +188,13 @@ class PrescriptionController implements BaseController { profesion: pg.profesion, codigoProfesion: pg.codigoProfesion, numeroMatricula: pg.numeroMatricula - })) : [] + })) : [], }, date, supplies: [sup], ambito, - trimestral + trimestral, + organizacion: organizacion || undefined }); let createAndes = false; if (ambito === 'publico') { @@ -219,11 +220,18 @@ class PrescriptionController implements BaseController { businessName: myProfessional?.businessName, cuil: myProfessional?.cuil, enrollment: myProfessional?.enrollment, + profesionGrado: myProfessional?.profesionGrado?.length ? myProfessional.profesionGrado.map((pg: any) => ({ + profesion: pg.profesion, + codigoProfesion: pg.codigoProfesion, + numeroMatricula: pg.numeroMatricula + })) : [], }, date: moment(date).add(30, 'days').toDate(), supplies: [sup], ambito, trimestral, + organizacion: organizacion || undefined + }); await newPrescription2.save(); allPrescription.push(newPrescription2); @@ -234,11 +242,18 @@ class PrescriptionController implements BaseController { businessName: myProfessional?.businessName, cuil: myProfessional?.cuil, enrollment: myProfessional?.enrollment, + profesionGrado: myProfessional?.profesionGrado?.length ? myProfessional.profesionGrado.map((pg: any) => ({ + profesion: pg.profesion, + codigoProfesion: pg.codigoProfesion, + numeroMatricula: pg.numeroMatricula + })) : [], }, date: moment(date).add(60, 'days').toDate(), supplies: [sup], ambito, trimestral, + organizacion: organizacion || undefined + }); await newPrescription3.save(); allPrescription.push(newPrescription3); @@ -271,7 +286,7 @@ class PrescriptionController implements BaseController { const prescriptionAndes = { idPrestacion: newPrescription._id.toString(), idRegistro: newPrescription._id.toString(), - fechaRegistro: newPrescription.date.toString(), + fechaRegistro: newPrescription.date.toISOString(), paciente: { id: patient.idMPI, nombre: patient.firstName, @@ -281,10 +296,12 @@ class PrescriptionController implements BaseController { obraSocial: patient.obraSocial || null, }, profesional: { - id: profesional?.idAndes ? profesional.idAndes : '' + id: profesional?.idAndes ? profesional.idAndes : '', }, organizacion: { - nombre: 'Recetar', + _id: newPrescription.organizacion?._id || null, + nombre: newPrescription.organizacion?.nombre || 'Recetar', + direccion: newPrescription.organizacion?.direccion || null, }, medicamento: { diagnostico: newPrescription.supplies[0].diagnostic, diff --git a/src/controllers/professional.controller.ts b/src/controllers/professional.controller.ts index 06a38dc..033feb3 100644 --- a/src/controllers/professional.controller.ts +++ b/src/controllers/professional.controller.ts @@ -2,95 +2,98 @@ import { Request, Response } from 'express'; import Professional from '../models/professional.model'; import IProfessional from '../interfaces/professional.interface'; import { BaseController } from '../interfaces/classes/base-controllers.interface'; +import axios from 'axios'; -class ProfessionalController implements BaseController{ +class ProfessionalController implements BaseController { - public index = async (req: Request, res: Response): Promise => { - const professionals: IProfessional[] = await Professional.find(); - return res.status(200).json({professionals}); - } + public index = async (req: Request, res: Response): Promise => { + const professionals: IProfessional[] = await Professional.find(); + return res.status(200).json({ professionals }); + }; - public create = async (req: Request, res: Response): Promise => { - const { dni, last_name, first_name, sex, image } = req.body; - const newProfessional: IProfessional = new Professional({ - dni, - last_name, - first_name, - sex, - image - }); - try{ - await newProfessional.save(); - return res.status(200).json({ newProfessional }); - }catch(err){ - console.log(err); - return res.status(500).json('Server Error'); - } - } + public create = async (req: Request, res: Response): Promise => { + const { dni, last_name, first_name, sex, image } = req.body; + const newProfessional: IProfessional = new Professional({ + dni, + last_name, + first_name, + sex, + image + }); + try { + await newProfessional.save(); + return res.status(200).json({ newProfessional }); + } catch (err) { + console.log(err); + return res.status(500).json('Server Error'); + } + }; - public show = async (req: Request, res: Response): Promise => { - try{ - const id: string = req.params.id; - const professional: IProfessional | null = await Professional.findOne({_id: id}); - return res.status(200).json(professional); - }catch(err){ - console.log(err); - return res.status(500).json('Server Error'); - } - } + public show = async (req: Request, res: Response): Promise => { + try { + const id: string = req.params.id; + const professional: IProfessional | null = await Professional.findOne({ _id: id }); + return res.status(200).json(professional); + } catch (err) { + console.log(err); + return res.status(500).json('Server Error'); + } + }; - public getByDni = async (req: Request, res: Response): Promise => { - try{ - const dni: string = req.params.dni; - const professional: IProfessional | null = await Professional.findOne({dni: dni}); - return res.status(200).json(professional); - }catch(err){ - console.log(err); - return res.status(500).json('Server Error'); - } - } + public getByDni = async (req: Request, res: Response): Promise => { + try { + const dni: string = req.params.dni; + const professional: IProfessional | null = await Professional.findOne({ dni }); + return res.status(200).json(professional); + } catch (err) { + console.log(err); + return res.status(500).json('Server Error'); + } + }; - public getByEnrollment = async (req: Request, res: Response): Promise => { - try{ - const enrollment: string = req.params.enrollment; - const professional: IProfessional | null = await Professional.findOne({enrollment: enrollment}); - return res.status(200).json(professional); - }catch(err){ - console.log(err); - return res.status(500).json('Server Error'); - } - } + public getByEnrollment = async (req: Request, res: Response): Promise => { + try { + const enrollment: string = req.params.enrollment; + const professional: IProfessional | null = await Professional.findOne({ enrollment }); + return res.status(200).json(professional); + } catch (err) { + console.log(err); + return res.status(500).json('Server Error'); + } + }; - public update = async (req: Request, res: Response) => { - try{ - const id: string = req.params.id; - const { dni, last_name, first_name, sex, image } = req.body; - await Professional.findByIdAndUpdate(id, { - dni, - last_name, - first_name, - sex, - image - }); - const professional = await Professional.findOne({_id: id}); - return res.status(200).json(professional); - } catch(err){ - console.log(err); - return res.status(500).json('Server Error'); - } - } + public update = async (req: Request, res: Response) => { + try { + const id: string = req.params.id; + const { dni, last_name, first_name, sex, image } = req.body; + await Professional.findByIdAndUpdate(id, { + dni, + last_name, + first_name, + sex, + image + }); + const professional = await Professional.findOne({ _id: id }); + return res.status(200).json(professional); + } catch (err) { + console.log(err); + return res.status(500).json('Server Error'); + } + }; + + public delete = async (req: Request, res: Response): Promise => { + try { + + const { id } = req.params; + await Professional.findByIdAndDelete(id); + return res.status(200).json('deleted'); + } catch (err) { + console.log(err); + return res.status(500).json('Server Error'); + } + }; - public delete = async (req: Request, res: Response): Promise => { - try{ - const { id } = req.params; - await Professional.findByIdAndDelete(id); - return res.status(200).json('deleted'); - }catch(err){ - console.log(err); - return res.status(500).json('Server Error'); - } - } } export default new ProfessionalController(); diff --git a/src/controllers/users.controller.ts b/src/controllers/users.controller.ts index 0948690..69d2821 100644 --- a/src/controllers/users.controller.ts +++ b/src/controllers/users.controller.ts @@ -2,6 +2,8 @@ import { Request, Response } from 'express'; import IUser from '../interfaces/user.interface'; import User from '../models/user.model'; import { renderHTML, MailOptions, sendMail } from '../utils/roboSender/sendEmail'; +import axios from 'axios'; + class UsersController { public index = async (req: Request, res: Response): Promise => { try { @@ -32,10 +34,10 @@ class UsersController { } const result = await User.findOneAndUpdate({ _id: req.body._id }, req.body, { new: true, projection: { password: 0, refreshToken: 0, authenticationToken: 0 } }).populate('roles', 'role'); - if (oldEmail && req.body.email && oldEmail !== req.body.email && result) { // Ejecutar el envío de email de forma asíncrona para no bloquear la respuesta this.sendEmailChangeNotification(result, oldEmail, req.body.email).catch(error => { + // eslint-disable-next-line no-console console.error('Error enviando notificación de cambio de email:', error); }); } @@ -103,7 +105,8 @@ class UsersController { createdAt: user.createdAt, updatedAt: user.updatedAt, lastLogin: user.lastLogin, - isActive: user.isActive + isActive: user.isActive, + organizaciones: user.organizaciones }); } catch (err) { @@ -156,6 +159,24 @@ class UsersController { console.error('Error enviando notificación de cambio de email:', error); } }; + + /** + * Busca en la coleccion Organizaciones TM en Andes por nombre + * @param req - nombre en params + * @param res - response con el listado de organizaciones que machea con el nombre buscado + * @returns lista de organizaciones + */ + public organizacionesAndes = async (req: Request, res: Response): Promise => { + try { + if (!req.query.nombre) { return res.status(400).json('Parámetro nombre es requerido'); } + const resp = await axios.get(`${process.env.ANDES_ENDPOINT}/core/tm/organizaciones?nombre=${req.query.nombre}&activo=true`, { headers: { Authorization: `${process.env.JWT_MPI_TOKEN}` } }); + return res.status(200).json(resp.data); + } catch (err) { + // eslint-disable-next-line no-console + console.log(err); + return res.status(500).json('Server Error'); + } + }; }; export default new UsersController; diff --git a/src/interfaces/patient.interface.ts b/src/interfaces/patient.interface.ts index b61442d..607840c 100644 --- a/src/interfaces/patient.interface.ts +++ b/src/interfaces/patient.interface.ts @@ -19,4 +19,5 @@ export default interface IPatient extends Document { updatedAt?: Date; idLocalInMPI?: boolean; // Indica si el paciente tiene ID local en Array de identificadores de MPI findOrCreate(patientParam: IPatient): Promise; + cuil?: string | null; } diff --git a/src/interfaces/prescription.interface.ts b/src/interfaces/prescription.interface.ts index 0ac39c1..13e7d0b 100644 --- a/src/interfaces/prescription.interface.ts +++ b/src/interfaces/prescription.interface.ts @@ -39,4 +39,9 @@ export default interface IPrescription extends Document { updatedAt?: Date; trimestral?: boolean; ambito?: string; + organizacion?: { + _id: string; + nombre: string; + direccion: string; + }; } diff --git a/src/interfaces/prescriptionAndes.interface.ts b/src/interfaces/prescriptionAndes.interface.ts index cfa57d8..907a228 100644 --- a/src/interfaces/prescriptionAndes.interface.ts +++ b/src/interfaces/prescriptionAndes.interface.ts @@ -147,6 +147,7 @@ export default interface IPrescriptionAndes extends Document { valor: Number; unidad: String; }; + cuil: String; }; createdAt: Date; createdBy: { @@ -164,4 +165,4 @@ export default interface IPrescriptionAndes extends Document { nombre: String; }; }; -} +};;;;;;;;;;;;;;;;;;;; diff --git a/src/interfaces/user.interface.ts b/src/interfaces/user.interface.ts index 965edb8..18d37fe 100644 --- a/src/interfaces/user.interface.ts +++ b/src/interfaces/user.interface.ts @@ -1,7 +1,7 @@ import { Document } from 'mongoose'; import IRole from './role.interface'; import IProfesionAutorizada from './profesionAutorizada.interface'; -export default interface IUser extends Document{ +export default interface IUser extends Document { username: string; email: string; businessName: string; @@ -16,6 +16,12 @@ export default interface IUser extends Document{ isActive: Boolean; lastLogin?: Date; profesionGrado?: IProfesionAutorizada[]; + organizaciones: [{ + _id: string; + nombre: string; + direccion: string; + }]; isValidPassword(thisUser: IUser, password: string): Promise; idAndes?: string; + // eslint-disable-next-line semi } diff --git a/src/models/patient.model.ts b/src/models/patient.model.ts index 3f0a3f1..f32156b 100644 --- a/src/models/patient.model.ts +++ b/src/models/patient.model.ts @@ -65,6 +65,10 @@ export const patientSchema = new Schema({ idLocalInMPI: { type: Boolean, default: false + }, + cuil: { + type: String, + default: null } }); @@ -130,7 +134,8 @@ const mapAndesPatientToLocal = (andesPatient: any): Partial => { idMPI: andesPatient.id || andesPatient._id, tipoDocumentoExtranjero: andesPatient.tipoIdentificacion || '', nroDocumentoExtranjero: andesPatient.numeroIdentificacion || '', - estado: andesPatient.estado + estado: andesPatient.estado, + cuil: andesPatient.cuil || null }; }; diff --git a/src/models/prescription.model.ts b/src/models/prescription.model.ts index 70e0d63..138fb23 100644 --- a/src/models/prescription.model.ts +++ b/src/models/prescription.model.ts @@ -76,6 +76,11 @@ const prescriptionSchema = new Schema({ type: String, enum: ['publico', 'privado'], default: 'privado' + }, + organizacion: { + _id: { type: Schema.Types.ObjectId }, + nombre: { type: String }, + direccion: { type: String } } }); diff --git a/src/models/prescriptionAndes.model.ts b/src/models/prescriptionAndes.model.ts index aab05af..5d5c52e 100644 --- a/src/models/prescriptionAndes.model.ts +++ b/src/models/prescriptionAndes.model.ts @@ -172,7 +172,8 @@ const prescriptionAndesSchema = new Schema({ edadReal: { valor: Number, unidad: String - } + }, + cuil: String }, createdAt: Date, createdBy: { diff --git a/src/models/user.model.ts b/src/models/user.model.ts index eea0da5..a2e42e6 100644 --- a/src/models/user.model.ts +++ b/src/models/user.model.ts @@ -1,4 +1,5 @@ import { Schema, Model, model } from 'mongoose'; +import mongoose from 'mongoose'; import bcrypt from 'bcryptjs'; import IUser from '../interfaces/user.interface'; import IProfesionAutorizada from '../interfaces/profesionAutorizada.interface'; @@ -84,18 +85,28 @@ export const userSchema = new Schema({ }, profesionGrado: [{ profesion: { - type: String, - required: '{PATH} is required' + type: String, + required: '{PATH} is required' }, codigoProfesion: { - type: String, - required: '{PATH} is required' + type: String, + required: '{PATH} is required' }, numeroMatricula: { - type: String, - required: '{PATH} is required' + type: String, + required: '{PATH} is required' }, - }] + }], + organizaciones: [ + { + _id: { + type: Schema.Types.ObjectId, + default: () => new mongoose.Types.ObjectId() + }, + nombre: String, + direccion: String, + } + ] }); // Model @@ -111,8 +122,6 @@ User.schema.method('isValidPassword', async (thisUser: IUser, password: string): }); // Model Validations -// User.schema.path('email').validate(uniqueEmail, 'This {PATH} address is already registered'); -// User.schema.path('email').validate(validEmail, 'The {PATH} field most be type of email.'); User.schema.path('username').validate(uniqueUsername, 'This {PATH} is already registered'); export default User; diff --git a/src/routes/private.ts b/src/routes/private.ts index 5c2f181..2440af0 100644 --- a/src/routes/private.ts +++ b/src/routes/private.ts @@ -103,6 +103,7 @@ class PrivateRoutes { this.router.get('/users/index', hasPermissionIn('readAny', 'user'), usersController.index); this.router.post('/users/update', hasPermissionIn('updateOwn', 'user'), usersController.update); this.router.get('/users/:id', hasPermissionIn('updateOwn', 'user'), usersController.getUserInfo); + this.router.get('/organizaciones-andes', hasPermissionIn('readOwn', 'user'), usersController.organizacionesAndes); // pharmacy // this.router.get(`/pharmacies/`, hasPermissionIn('readAny','patient'), pharmacyController.index); diff --git a/src/utils/rbac_abac.ts b/src/utils/rbac_abac.ts index ff1e2e6..77855b2 100644 --- a/src/utils/rbac_abac.ts +++ b/src/utils/rbac_abac.ts @@ -1,5 +1,4 @@ import { AccessControl } from 'accesscontrol'; -import Role from '../models/role.model'; class AccessControlLoader {