import usersLogs, { IUserLogs, userLogger } from './users.logs'; import { formatString } from '../../utils/Strings'; import { db } from '../../settings'; import { HttpCodes } from '../../config/Errors'; import { ErrorResponseC, SuccessResponseC } from '../services.response'; import { Response } from 'express'; import { ResultSetHeader, RowDataPacket } from 'mysql2'; import { AuthServices } from '../auth/auth.service'; import { Optimize } from '../../utils/Function'; export class UsersServices { static getStatistics = async (): Promise => { try { const sqlquery = `SELECT (SELECT COUNT(*) FROM teachers) AS teachers, (SELECT COUNT(*) FROM schools) AS schools, (SELECT COUNT(*) FROM inst_designers) AS inst_designers, (SELECT COUNT(*) FROM orders) AS total_orders, (SELECT COUNT(*) FROM courses) AS courses `; const [statistics] = await db.query(sqlquery); const resp: ICode = usersLogs.GET_STATISTICS_SUCCESS; const msg = resp.message; userLogger.info(msg, { type: resp.type }); return new SuccessResponseC( resp.type, statistics[0], msg, HttpCodes.Accepted.code ); } catch (err) { const msg = formatString(usersLogs.GET_STATISTICS_ERROR.message, { error: (err as Error)?.message || '', }); userLogger.error(msg, err as Error); return new ErrorResponseC( usersLogs.GET_STATISTICS_ERROR.type, HttpCodes.InternalServerError.code, msg ); } }; static getUsersBySuperAdmin = async ( res: Response, user_id: number ): Promise => { try { const sqlquery = `SELECT u.user_id, u.email, u.firstName, u.lastName, u.role, u.phone, s.schoolName FROM users u LEFT JOIN schools s ON u.user_id = s.user_id WHERE u.user_id != ?`; const [users] = await db.query(sqlquery, [user_id]); const resp: ICode = usersLogs.GET_USERS_BY_SUPER_ADMIN_SUCCESS; const msg = formatString(resp.message, { count: users.length }); userLogger.info(msg, { type: resp.type }); return new SuccessResponseC( resp.type, users, msg, HttpCodes.Accepted.code ); } catch (err) { const msg = formatString( usersLogs.GET_USERS_BY_SUPER_ADMIN_ERROR.message, { error: (err as Error)?.message || '', } ); userLogger.error(msg, err as Error); return new ErrorResponseC( usersLogs.GET_USERS_BY_SUPER_ADMIN_ERROR.type, HttpCodes.InternalServerError.code, msg ); } }; static getUsersByAdmin = async ( res: Response, user_id: number ): Promise => { try { const sqlquery = `SELECT u.user_id, u.email, u.firstName, u.lastName, u.role, u.phone, s.schoolName FROM users u LEFT JOIN schools s ON u.user_id = s.user_id WHERE u.user_id != ? AND u.role != "super_admin" AND u.role != "admin" AND u.role != "inst_admin"`; const [users] = await db.query(sqlquery, [user_id]); const resp: ICode = usersLogs.GET_USERS_BY_ADMIN_SUCCESS; const msg = formatString(resp.message, { count: users.length }); userLogger.info(msg, { type: resp.type }); return new SuccessResponseC( resp.type, users, msg, HttpCodes.Accepted.code ); } catch (err) { const msg = formatString(usersLogs.GET_USERS_BY_ADMIN_ERROR.message, { error: (err as Error)?.message || '', }); userLogger.error(msg, err as Error); return new ErrorResponseC( usersLogs.GET_USERS_BY_ADMIN_ERROR.type, HttpCodes.InternalServerError.code, msg ); } }; static getUserById = async ( res: Response, userId: number ): Promise => { try { const sqlquery = 'SELECT * FROM users WHERE user_id = ?'; const [[user]] = await db.query(sqlquery, [userId]); if (!user) { const msg = formatString(usersLogs.GET_USER_BY_ID_ERROR.message, { userId, }); userLogger.error(msg); return new ErrorResponseC( usersLogs.GET_USER_BY_ID_ERROR.type, HttpCodes.NotFound.code, msg ); } // get additional info base on role const additionalInfo = await AuthServices.getAdditionalInfo( user.role, user.user_id ); if (additionalInfo.isErr) { const msg = formatString(usersLogs.GET_USER_BY_ID_ERROR.message, { error: (additionalInfo.err as Error)?.message || '', }); userLogger.error(msg, additionalInfo.err as Error); return new ErrorResponseC( usersLogs.GET_USER_BY_ID_ERROR.type, HttpCodes.InternalServerError.code, msg ); } const resp: ICode = usersLogs.GET_USER_BY_ID_SUCCESS; const msg = formatString(resp.message, { userId: user.user_id, email: user.email, }); userLogger.info(msg, { type: resp.type }); return new SuccessResponseC( resp.type, { ...Optimize(user), ...additionalInfo.data }, msg, HttpCodes.Accepted.code ); } catch (err) { const msg = formatString(usersLogs.GET_USER_BY_ID_ERROR.message, { error: (err as Error)?.message || '', }); userLogger.error(msg, err as Error); return new ErrorResponseC( usersLogs.GET_USER_BY_ID_ERROR.type, HttpCodes.InternalServerError.code, msg ); } }; static updateUserById = async ( res: Response, userId: number, data: { email: string; firstName: string; lastName: string; role: string; phone: string | null; additionalInfo: any; } ): Promise => { try { const sqlquery = 'SELECT * FROM users WHERE user_id = ?'; const [[user]] = await db.query(sqlquery, [userId]); if (!user) { const msg = formatString(usersLogs.UPDATE_USER_BY_ID_ERROR.message, { userId, }); userLogger.error(msg); return new ErrorResponseC( usersLogs.UPDATE_USER_BY_ID_ERROR.type, HttpCodes.NotFound.code, msg ); } const sqlUpdateQuery = 'UPDATE users SET email = ?, firstName = ?, lastName = ?, role = ?, phone = ? WHERE user_id = ?'; const result = await db.query(sqlUpdateQuery, [ data.email, data.firstName, data.lastName, data.role, data.phone, userId, ]); // if (data.password) { // const hashedPassword = bcrypt.hashSync(data.password, 10); // const sqlUpdatePasswordQuery = // 'UPDATE users SET password = ? WHERE user_id = ?'; // await db.query(sqlUpdatePasswordQuery, [ // hashedPassword, // userId, // ]); // } // update additional info base on role if ( user.role !== 'admin' && user.role !== 'super_admin' && user.role !== 'inst_admin' ) { const updateAdditionalInfo = await this.updateAdditionalInfo( user.role, user.user_id, data.additionalInfo ); if (updateAdditionalInfo.isErr) { const msg = formatString(usersLogs.UPDATE_USER_BY_ID_ERROR.message, { error: (updateAdditionalInfo.err as Error)?.message || '', }); userLogger.error(msg, updateAdditionalInfo.err as Error); return new ErrorResponseC( usersLogs.UPDATE_USER_BY_ID_ERROR.type, HttpCodes.InternalServerError.code, msg ); } } const resp: ICode = usersLogs.UPDATE_USER_BY_ID_SUCCESS; const msg = formatString(resp.message, { userId, }); userLogger.info(msg, { type: resp.type }); return new SuccessResponseC( resp.type, { ...Optimize(user), ...data }, msg, HttpCodes.Accepted.code ); } catch (err) { const msg = formatString(usersLogs.UPDATE_USER_BY_ID_ERROR.message, { error: (err as Error)?.message || '', }); userLogger.error(msg, err as Error); return new ErrorResponseC( usersLogs.UPDATE_USER_BY_ID_ERROR.type, HttpCodes.InternalServerError.code, msg ); } }; static updateTeacherById = async ( res: Response, teacherId: number, data: { email: string; firstName: string; lastName: string; role: string; phone: string | null; additionalInfo: any; } ): Promise => { try { const sqlquery = 'SELECT * FROM teachers WHERE teacher_id = ?'; const [[teacher]] = await db.query(sqlquery, [teacherId]); if (!teacher) { const msg = formatString(usersLogs.UPDATE_USER_BY_ID_ERROR.message, { teacherId, }); userLogger.error(msg); return new ErrorResponseC( usersLogs.UPDATE_USER_BY_ID_ERROR.type, HttpCodes.NotFound.code, msg ); } const sqlUpdateQuery = 'UPDATE users SET email = ?, firstName = ?, lastName = ?, role = ?, phone = ? WHERE user_id = ?'; const result = await db.query(sqlUpdateQuery, [ data.email, data.firstName, data.lastName, data.role, data.phone, teacher.user_id, ]); // update additional info base on role const updateAdditionalInfo = await this.updateAdditionalInfo( 'teacher', teacher.user_id, data.additionalInfo ); if (updateAdditionalInfo.isErr) { const msg = formatString(usersLogs.UPDATE_USER_BY_ID_ERROR.message, { error: (updateAdditionalInfo.err as Error)?.message || '', }); userLogger.error(msg, updateAdditionalInfo.err as Error); return new ErrorResponseC( usersLogs.UPDATE_USER_BY_ID_ERROR.type, HttpCodes.InternalServerError.code, msg ); } const resp: ICode = usersLogs.UPDATE_USER_BY_ID_SUCCESS; const msg = formatString(resp.message, { teacherId, }); userLogger.info(msg, { type: resp.type }); return new SuccessResponseC( resp.type, { ...Optimize(teacher), ...data }, msg, HttpCodes.Accepted.code ); } catch (err) { const msg = formatString(usersLogs.UPDATE_USER_BY_ID_ERROR.message, { error: (err as Error)?.message || '', }); userLogger.error(msg, err as Error); return new ErrorResponseC( usersLogs.UPDATE_USER_BY_ID_ERROR.type, HttpCodes.InternalServerError.code, msg ); } }; static updateAdditionalInfo = async ( role: string, user_id: number, additionalInfo: any ): Promise<{ isErr: boolean; err: any; }> => { const tableName = role === 'teacher' ? 'teachers' : role === 'school' ? 'schools' : 'inst_designers'; if (!additionalInfo) return { isErr: false, err: null }; const additionalInfoKeys = Object.keys(additionalInfo); const additionalInfoValues = Object.values(additionalInfo); const additionalInfoColumns = additionalInfoKeys.join(' = ?, '); additionalInfoValues.push(user_id); try { const sqlquery = `UPDATE ${tableName} SET ${additionalInfoColumns} = ? WHERE user_id = ?`; await db.query(sqlquery, additionalInfoValues); return { isErr: false, err: null }; } catch (err) { return { isErr: true, err }; } }; static deleteUserById = async ( res: Response, userId: number ): Promise => { try { const sqlquery = 'SELECT * FROM users WHERE user_id = ?'; const [[user]] = await db.query(sqlquery, [userId]); if (!user) { const msg = formatString(usersLogs.DELETE_USER_BY_ID_ERROR.message, { userId, }); userLogger.error(msg); return new ErrorResponseC( usersLogs.DELETE_USER_BY_ID_ERROR.type, HttpCodes.NotFound.code, msg ); } const sqlDeleteQuery = 'DELETE FROM users WHERE user_id = ?'; await db.query(sqlDeleteQuery, [userId]); // delete additional info base on role if ( user.role !== 'admin' && user.role !== 'super_admin' && user.role !== 'inst_admin' ) { const tableName = user.role === 'teacher' ? 'teachers' : user.role === 'school' ? 'schools' : 'inst_designers'; const sqlDeleteAdditionalInfoQuery = `DELETE FROM ${tableName} WHERE user_id = ?`; await db.query(sqlDeleteAdditionalInfoQuery, [userId]); } const resp: ICode = usersLogs.DELETE_USER_BY_ID_SUCCESS; const msg = formatString(resp.message, { userId, }); userLogger.info(msg, { type: resp.type }); return new SuccessResponseC( resp.type, { ...Optimize(user) }, msg, HttpCodes.Accepted.code ); } catch (err) { const msg = formatString(usersLogs.DELETE_USER_BY_ID_ERROR.message, { error: (err as Error)?.message || '', }); userLogger.error(msg, err as Error); return new ErrorResponseC( usersLogs.DELETE_USER_BY_ID_ERROR.type, HttpCodes.InternalServerError.code, msg ); } }; static deleteTeacherById = async ( res: Response, teacherId: number ): Promise => { try { const sqlquery = 'SELECT * FROM teachers WHERE teacher_id = ?'; const [[teacher]] = await db.query(sqlquery, [teacherId]); if (!teacher) { const msg = formatString(usersLogs.DELETE_USER_BY_ID_ERROR.message, { teacherId, }); userLogger.error(msg); return new ErrorResponseC( usersLogs.DELETE_USER_BY_ID_ERROR.type, HttpCodes.NotFound.code, msg ); } const sqlDeleteQuery = 'DELETE FROM users WHERE user_id = ?'; await db.query(sqlDeleteQuery, [teacher.user_id]); const resp: ICode = usersLogs.DELETE_USER_BY_ID_SUCCESS; const msg = formatString(resp.message, { teacherId, }); userLogger.info(msg, { type: resp.type }); return new SuccessResponseC( resp.type, { ...Optimize(teacher) }, msg, HttpCodes.Accepted.code ); } catch (err) { const msg = formatString(usersLogs.DELETE_USER_BY_ID_ERROR.message, { error: (err as Error)?.message || '', }); userLogger.error(msg, err as Error); return new ErrorResponseC( usersLogs.DELETE_USER_BY_ID_ERROR.type, HttpCodes.InternalServerError.code, msg ); } }; static bulkDeleteUsers = async ( res: Response, userIds: number[] ): Promise => { try { // const sqlDeleteQuery = 'DELETE FROM users WHERE user_id IN (?)'; // await db.query(sqlDeleteQuery, [userIds]); for (const userId of userIds) { const sqlDeleteQuery = 'DELETE FROM users WHERE user_id = ?'; await db.query(sqlDeleteQuery, [userId]); } const resp: ICode = usersLogs.DELETE_USER_BY_ID_SUCCESS; const msg = formatString(resp.message, { userIds: userIds.join(', '), }); userLogger.info(msg, { type: resp.type }); return new SuccessResponseC(resp.type, {}, msg, HttpCodes.Accepted.code); } catch (err) { const msg = formatString(usersLogs.DELETE_USER_BY_ID_ERROR.message, { error: (err as Error)?.message || '', }); userLogger.error(msg, err as Error); return new ErrorResponseC( usersLogs.DELETE_USER_BY_ID_ERROR.type, HttpCodes.InternalServerError.code, msg ); } }; static bulkDeleteTeachers = async ( res: Response, teacherIds: number[] ): Promise => { try { for (const teacherId of teacherIds) { const sqlquery = 'SELECT * FROM teachers WHERE teacher_id = ?'; const [[teacher]] = await db.query(sqlquery, [teacherId]); if (!teacher) { const msg = formatString(usersLogs.DELETE_USER_BY_ID_ERROR.message, { teacherId, }); userLogger.error(msg); return new ErrorResponseC( usersLogs.DELETE_USER_BY_ID_ERROR.type, HttpCodes.NotFound.code, msg ); } const sqlDeleteQuery = 'DELETE FROM users WHERE user_id = ?'; await db.query(sqlDeleteQuery, [teacher.user_id]); } const resp: ICode = usersLogs.DELETE_USER_BY_ID_SUCCESS; const msg = formatString(resp.message, { teacherIds: teacherIds.join(', '), }); userLogger.info(msg, { type: resp.type }); return new SuccessResponseC(resp.type, {}, msg, HttpCodes.Accepted.code); } catch (err) { const msg = formatString(usersLogs.DELETE_USER_BY_ID_ERROR.message, { error: (err as Error)?.message || '', }); userLogger.error(msg, err as Error); return new ErrorResponseC( usersLogs.DELETE_USER_BY_ID_ERROR.type, HttpCodes.InternalServerError.code, msg ); } }; static getTeachersBySchool = async ( res: Response, schoolId: number ): Promise => { try { const sqlquery = 'SELECT t.*, u.firstName, u.lastName, u.user_id, u.email, u.phone FROM teachers t JOIN users u ON t.user_id = u.user_id WHERE t.school_id = ?'; const [teachers] = await db.query(sqlquery, [schoolId]); const resp: ICode = usersLogs.GET_TEACHERS_BY_SCHOOL_SUCCESS; const msg = formatString(resp.message, { count: teachers.length }); userLogger.info(msg, { type: resp.type }); return new SuccessResponseC( resp.type, teachers, msg, HttpCodes.Accepted.code ); } catch (err) { const msg = formatString(usersLogs.GET_TEACHERS_BY_SCHOOL_ERROR.message, { error: (err as Error)?.message || '', }); userLogger.error(msg, err as Error); return new ErrorResponseC( usersLogs.GET_TEACHERS_BY_SCHOOL_ERROR.type, HttpCodes.InternalServerError.code, msg ); } }; static getTeacherById = async ( res: Response, teacherId: number ): Promise => { try { const sqlquery = 'SELECT t.*, u.firstName, u.lastName, u.user_id, u.email, u.phone FROM teachers t JOIN users u ON t.user_id = u.user_id WHERE t.teacher_id = ?'; const [[teacher]] = await db.query(sqlquery, [teacherId]); if (!teacher) { const msg = formatString(usersLogs.GET_TEACHER_BY_ID_ERROR.message, { teacherId, }); userLogger.error(msg); return new ErrorResponseC( usersLogs.GET_TEACHER_BY_ID_ERROR.type, HttpCodes.NotFound.code, msg ); } const resp: ICode = usersLogs.GET_TEACHER_BY_ID_SUCCESS; const msg = formatString(resp.message, { teacherId, }); userLogger.info(msg, { type: resp.type }); return new SuccessResponseC( resp.type, teacher, msg, HttpCodes.Accepted.code ); } catch (err) { const msg = formatString(usersLogs.GET_TEACHER_BY_ID_ERROR.message, { error: (err as Error)?.message || '', }); userLogger.error(msg, err as Error); return new ErrorResponseC( usersLogs.GET_TEACHER_BY_ID_ERROR.type, HttpCodes.InternalServerError.code, msg ); } }; static getSchools = async (res: Response): Promise => { try { const sqlquery = 'SELECT * FROM schools'; const [schools] = await db.query(sqlquery); const resp: ICode = usersLogs.GET_SCHOOLS_SUCCESS; const msg = resp.message; userLogger.info(msg, { type: resp.type }); return new SuccessResponseC( resp.type, schools, msg, HttpCodes.Accepted.code ); } catch (err) { const msg = formatString(usersLogs.GET_SCHOOLS_ERROR.message, { error: (err as Error)?.message || '', }); userLogger.error(msg, err as Error); return new ErrorResponseC( usersLogs.GET_SCHOOLS_ERROR.type, HttpCodes.InternalServerError.code, msg ); } }; static getTeachers = async (res: Response): Promise => { try { const sqlquery = 'SELECT t.*, u.email FROM teachers t JOIN users u ON t.user_id = u.user_id'; const [teachers] = await db.query(sqlquery); const resp: ICode = usersLogs.GET_TEACHERS_SUCCESS; const msg = resp.message; userLogger.info(msg, { type: resp.type }); return new SuccessResponseC( resp.type, teachers, msg, HttpCodes.Accepted.code ); } catch (err) { const msg = formatString(usersLogs.GET_TEACHERS_ERROR.message, { error: (err as Error)?.message || '', }); userLogger.error(msg, err as Error); return new ErrorResponseC( usersLogs.GET_TEACHERS_ERROR.type, HttpCodes.InternalServerError.code, msg ); } }; static getInstDesigners = async (res: Response): Promise => { try { const sqlquery = 'SELECT * FROM inst_designers'; const [instDesigners] = await db.query(sqlquery); const resp: ICode = usersLogs.GET_INST_DESIGNERS_SUCCESS; const msg = resp.message; userLogger.info(msg, { type: resp.type }); return new SuccessResponseC( resp.type, instDesigners, msg, HttpCodes.Accepted.code ); } catch (err) { const msg = formatString(usersLogs.GET_INST_DESIGNERS_ERROR.message, { error: (err as Error)?.message || '', }); userLogger.error(msg, err as Error); return new ErrorResponseC( usersLogs.GET_INST_DESIGNERS_ERROR.type, HttpCodes.InternalServerError.code, msg ); } }; }