Files
hsp-gdh/routes/patients.js

284 lines
13 KiB
JavaScript

import express from 'express';
import { error } from '../modules/logManager';
import { pool } from '../modules/databaseManager';
import { verifyToken } from '../modules/tokenManager';
import { verifyPermissions, checkPermissions, checkBanned, checkEmailVerified } from '../modules/permissionManager';
import { respondWithStatus, respondWithStatusJSON } from '../modules/requestHandler';
const router = express.Router();
/**
* Retrieves all patients from the database.
*
* @returns {Promise<Array>} A promise that resolves to an array of patient objects.
*/
router.get('/', verifyToken, checkBanned, checkPermissions('patient', 1), async (req, res) => {
try {
const [rows] = await pool.execute('SELECT * FROM patients WHERE 1');
if (rows.length === 0) return await respondWithStatus(res, 404, 'Patients not found');
return await respondWithStatusJSON(res, 200, rows);
}
catch (err) {
error(err);
return await respondWithStatus(res, 500, 'An error has occured');
}
});
/**
* Inserts a new patient record into the database.
*
* @param {number} user_id - The ID of the user associated with the patient.
* @param {date} date_of_birth - The date of birth of the patient.
* @param {string} gender - The gender of the patient.
* @param {string} address - The address of the patient.
* @param {string} social_security_number - The social security number of the patient.
* @param {string} insurance_number - The insurance number of the patient.
* @returns {Promise} - A promise that resolves with the result of the insertion.
*/
router.post('/', verifyToken, checkBanned, checkPermissions('patient', 2), async (req, res) => {
const { user_id, date_of_birth, gender, address, social_security_number, insurance_number } = req.body;
if ([ user_id, date_of_birth, gender, address, social_security_number, insurance_number ].every(Boolean)) {
try {
const [result] = await pool.execute(
'INSERT INTO patients (user_id, date_of_birth, gender, address, social_security_number, insurance_number) VALUES (?, ?, ?, ?, ?, ?)',
[ user_id, date_of_birth, gender, address, social_security_number, insurance_number ],
);
if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error storing patient');
return await respondWithStatus(res, 200, 'Patient created successfully');
}
catch (err) {
error(err);
return await respondWithStatus(res, 500, 'An error has occured');
}
}
else {
return await respondWithStatus(res, 400, 'Missing fields');
}
});
router.post('/register', verifyToken, checkEmailVerified, checkBanned, async (req, res) => {
const { date_of_birth, gender, address, social_security_number, insurance_number } = req.body;
if ([ date_of_birth, gender, address, social_security_number, insurance_number ].every(Boolean)) {
try {
const [result] = await pool.execute(
'INSERT INTO patients (user_id, date_of_birth, gender, address, social_security_number, insurance_number) VALUES (?, ?, ?, ?, ?, ?)',
[ req.userId, date_of_birth, gender, address, social_security_number, insurance_number ],
);
if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error storing patient');
const [result2] = await pool.execute('INSERT INTO user_roles (user_id, role_id) VALUES (?, (SELECT id FROM roles WHERE name = ? LIMIT 1))', [req.userId, 'Patient']);
if (result2.affectedRows === 0) return await respondWithStatus(res, 500, 'Error adding role to user');
return await respondWithStatus(res, 200, 'Patient created successfully');
}
catch (err) {
error(err);
return await respondWithStatus(res, 500, 'An error has occured');
}
}
else {
return await respondWithStatus(res, 400, 'Missing fields');
}
});
router.get('/:patientId', verifyToken, checkBanned, async (req, res) => {
try {
const patientId = await getPatientId(req.userId);
if (req.params.patientId == '@me') {
if (!patientId) return await respondWithStatus(res, 404, 'Patient not found');
req.params.patientId = patientId;
}
if (patientId != req.params.patientId && !verifyPermissions(req.userId, 'patient', 1)) return await respondWithStatus(res, 403, 'Missing permission');
const [rows] = await pool.execute('SELECT * FROM patients WHERE id = ? LIMIT 1', [req.params.patientId]);
if (rows.length === 0) return await respondWithStatus(res, 404, 'Patient not found');
return await respondWithStatusJSON(res, 200, rows[0]);
}
catch (err) {
error(err);
return await respondWithStatus(res, 500, 'An error has occured');
}
});
router.patch('/:patientId', verifyToken, checkBanned, async (req, res) => {
try {
const { type, value } = req.body;
const patientId = await getPatientId(req.userId);
if (req.params.patientId == '@me') {
if (!patientId) return await respondWithStatus(res, 404, 'Patient not found');
req.params.patientId = patientId;
}
if (patientId != req.params.patientId && !verifyPermissions(req.userId, 'patient', 2)) return await respondWithStatus(res, 403, 'Missing permission');
const [rows] = await pool.execute('SELECT * FROM patients WHERE id = ? LIMIT 1', [req.params.patientId]);
if (rows.length === 0) return await respondWithStatus(res, 404, 'Patient not found');
const excludedKeys = [ 'id', 'user_id' ];
const fields = rows.map(row => Object.keys(row).filter(key => !excludedKeys.includes(key)));
if (fields[0].includes(type)) {
const [result] = await pool.execute(`UPDATE patients SET ${type} = ? WHERE id = ?`, [value, req.params.patientId]);
if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error updating patient');
return await respondWithStatus(res, 200, 'Patient updated successfully');
}
else {
return await respondWithStatus(res, 400, 'Invalid type');
}
}
catch (err) {
error(err);
return await respondWithStatus(res, 500, 'An error has occured');
}
});
router.put('/:patientId', verifyToken, checkBanned, async (req, res) => {
const { user_id, date_of_birth, gender, address, social_security_number, insurance_number } = req.body;
if ([ user_id, date_of_birth, gender, address, social_security_number, insurance_number ].every(Boolean)) {
try {
const patientId = await getPatientId(req.userId);
if (req.params.patientId == '@me') {
if (!patientId) return await respondWithStatus(res, 404, 'Patient not found');
req.params.patientId = patientId;
}
if (patientId != req.params.patientId && !verifyPermissions(req.userId, 'patient', 2)) return await respondWithStatus(res, 403, 'Missing permission');
const [rows] = await pool.execute('SELECT * FROM patients WHERE id = ? LIMIT 1', [req.params.patientId]);
if (rows.length === 0) return await respondWithStatus(res, 404, 'Patient not found');
const [result] = await pool.execute(
'UPDATE patients SET name = ?, date_of_birth = ?, gender = ?, address = ?, social_security_number = ?, insurance_number = ? WHERE id = ?',
[user_id, date_of_birth, gender, address, social_security_number, insurance_number, req.params.patientId],
);
if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error updating patient');
return await respondWithStatus(res, 200, 'Patient updated successfully');
}
catch (err) {
error(err);
return await respondWithStatus(res, 500, 'An error has occured');
}
}
else {
return await respondWithStatus(res, 400, 'Missing fields');
}
});
router.delete('/:patientId', verifyToken, checkBanned, async (req, res) => {
try {
const patientId = await getPatientId(req.userId);
if (req.params.patientId == '@me') {
if (!patientId) return await respondWithStatus(res, 404, 'Patient not found');
req.params.patientId = patientId;
}
if (patientId != req.params.patientId && !verifyPermissions(req.userId, 'patient', 4)) return await respondWithStatus(res, 403, 'Missing permission');
const [rows] = await pool.execute('SELECT * FROM patients WHERE id = ? LIMIT 1', [req.params.patientId]);
if (rows.length === 0) return await respondWithStatus(res, 404, 'Patient not found');
const [result] = await pool.execute('DELETE FROM patients WHERE id = ?', [req.params.patientId]);
if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error removing patient');
return await respondWithStatus(res, 200, 'Patient deleted successfully');
}
catch (err) {
error(err);
return await respondWithStatus(res, 500, 'An error has occured');
}
});
// Appointments endpoints
router.get('/:patientId/appointments', verifyToken, checkBanned, async (req, res) => {
try {
const patientId = await getPatientId(req.userId);
if (req.params.patientId == '@me') {
if (!patientId) return await respondWithStatus(res, 404, 'Patient not found');
req.params.patientId = patientId;
}
if (patientId != req.params.patientId && !verifyPermissions(req.userId, 'appointment', 1)) return await respondWithStatus(res, 403, 'Missing permission');
const [rows] = await pool.execute(
'SELECT a.id, u.first_name, u.last_name, d.email, d.phone, h.name, h.address, a.date, a.time, a.status, s.name FROM appointments a JOIN doctors d ON a.doctor_id = d.id JOIN users u ON d.user_id = u.id JOIN hospitals h ON a.hospital_id = h.id JOIN services s ON a.service_id = s.id WHERE a.patient_id = ?',
[req.params.patientId],
);
if (rows.length === 0) return await respondWithStatus(res, 404, 'Appointments not found');
return await respondWithStatusJSON(res, 200, rows);
}
catch (err) {
error(err);
return await respondWithStatus(res, 500, 'An error has occured');
}
});
router.post('/:patientId/appointments', verifyToken, checkBanned, async (req, res) => {
const { doctor_id, service_id, hospital_id, date, time } = req.body;
if ([ doctor_id, service_id, hospital_id, date, time ].every(Boolean)) {
try {
const patientId = await getPatientId(req.userId);
if (req.params.patientId == '@me') {
if (!patientId) return await respondWithStatus(res, 404, 'Patient not found');
req.params.patientId = patientId;
}
if (patientId != req.params.patientId && !verifyPermissions(req.userId, 'appointment', 2)) return await respondWithStatus(res, 403, 'Missing permission');
const [result] = await pool.execute(
'INSERT INTO appointments (doctor_id, service_id, hospital_id, patient_id, date, time) VALUES (?, ?, ?, ?, ?, ?)',
[ doctor_id, service_id, hospital_id, req.params.patientId, date, time ],
);
if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error storing appointment');
return await respondWithStatus(res, 200, 'Appointment created successfully');
}
catch (err) {
error(err);
return await respondWithStatus(res, 500, 'An error has occured');
}
}
else {
return await respondWithStatus(res, 400, 'Missing fields');
}
});
// GET /:patientId/appointments/:appointmentId
router.get('/:patientId/appointments/:appointmentId', verifyToken, checkBanned, async (req, res) => {
try {
const patientId = await getPatientId(req.userId);
if (req.params.patientId == '@me') {
if (!patientId) return await respondWithStatus(res, 404, 'Patient not found');
req.params.patientId = patientId;
}
if (patientId != req.params.patientId && !verifyPermissions(req.userId, 'appointment', 1)) return await respondWithStatus(res, 403, 'Missing permission');
const [rows] = await pool.execute(
'SELECT a.id, u.first_name, u.last_name, d.email, d.phone, h.name, h.address, a.date, a.time, a.status, s.name FROM appointments a JOIN doctors d ON a.doctor_id = d.id JOIN users u ON d.user_id = u.id JOIN hospitals h ON a.hospital_id = h.id JOIN services s ON a.service_id = s.id WHERE a.id = ? AND a.patient_id = ?',
[req.params.appointmentId, req.params.patientId],
);
if (rows.length === 0) return await respondWithStatus(res, 404, 'Appointment not found');
return await respondWithStatusJSON(res, 200, rows[0]);
}
catch (err) {
error(err);
return await respondWithStatus(res, 500, 'An error has occured');
}
});
// PATCH /:patientId/appointments/:appointmentId
// PUT /:patientId/appointments/:appointmentId
// DELETE /:patientId/appointments/:appointmentId
router.delete('/:patientId/appointments/:appointmentId', verifyToken, checkBanned, async (req, res) => {
try {
const patientId = await getPatientId(req.userId);
if (req.params.patientId == '@me') {
if (!patientId) return await respondWithStatus(res, 404, 'Patient not found');
req.params.patientId = patientId;
}
if (patientId != req.params.patientId && !verifyPermissions(req.userId, 'appointment', 4)) return await respondWithStatus(res, 403, 'Missing permission');
const [rows] = await pool.execute('SELECT * FROM appointments WHERE id = ? AND patient_id = ? LIMIT 1', [req.params.appointmentId, req.params.patientId]);
if (rows.length === 0) return await respondWithStatus(res, 404, 'Appointment not found');
const [result] = await pool.execute('DELETE FROM appointments WHERE id = ?', [req.params.appointmentId]);
if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error removing appointment');
return await respondWithStatus(res, 200, 'Appointment deleted successfully');
}
catch (err) {
error(err);
return await respondWithStatus(res, 500, 'An error has occured');
}
});
export default router;
async function getPatientId(userId) {
const [rows] = await pool.execute('SELECT * FROM patients WHERE user_id = ? LIMIT 1', [userId]);
return rows.length ? rows[0].id : null;
}