From ed5a1288c39bf9673a9f7a83c27d5baedd2a578b Mon Sep 17 00:00:00 2001 From: "fazri.is" Date: Mon, 4 May 2026 18:30:49 +0700 Subject: [PATCH] update --- .prettierrc | 7 ++ config/default.json | 8 +- src/controllers/user.ts | 180 +++++++++------------------------------- 3 files changed, 48 insertions(+), 147 deletions(-) create mode 100644 .prettierrc diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..43962d8 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "printWidth": 5000, + "semi": true, + "singleQuote": false, + "tabWidth": 4, + "useTabs": true +} diff --git a/config/default.json b/config/default.json index 29f451b..f32aa92 100644 --- a/config/default.json +++ b/config/default.json @@ -22,10 +22,10 @@ "database": { "engine": "postgres", "host": "127.0.0.1", - "port": "15432", - "username": "saude_tl", - "password": "saude_tl_local", - "database": "saude_tl", + "port": "1520", + "username": "saude_stag", + "password": "gM*#o>3W4&5X", + "database": "saude_stag", "synchronize": true, "logging": true }, diff --git a/src/controllers/user.ts b/src/controllers/user.ts index 582a0b1..3fdfa6b 100644 --- a/src/controllers/user.ts +++ b/src/controllers/user.ts @@ -12,8 +12,8 @@ import { Language } from "../langs/lang"; import fs from "fs"; import path from "path"; import fileUpload from "express-fileupload"; -import { v4 as uuidv4 } from 'uuid'; -import config from '../../config/stag.json'; +import { v4 as uuidv4 } from "uuid"; +import config from "../../config/stag.json"; import { profile } from "console"; const log: Logger = new Logger({ @@ -137,20 +137,10 @@ export class UserController { const mapped_data = list_data.map((user) => ({ ...user, profile_picture: user.profile_picture ?? null, - file_profile_picture: user.profile_picture - ? `${config.server.host_swagger}uploads/doctor-profile/${user.profile_picture}` - : null, + file_profile_picture: user.profile_picture ? `${config.server.host_swagger}uploads/doctor-profile/${user.profile_picture}` : null, })); - return ReturnHelper.successResponselist( - res, - 200, - Language.lang.success_view, - count_data, - current_page, - total_count_data, - mapped_data, - ); + return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, mapped_data); } catch (e: unknown) { log.error(e); const err = e as Error; @@ -214,24 +204,14 @@ export class UserController { filter: param.filter, col_any_eq: ["email"], col_any_like: ["User.name", "User.username"], - additional_where: "roles.is_doctor = :is_doctor", + additional_where: "roles.name = :doctor_role_name", }); - whereVal.is_doctor = true; + whereVal.doctor_role_name = "Doctor"; - const res_count = userRepository - .createQueryBuilder("User") - .leftJoin("User.roles", "roles") - .where(whereAttr, whereVal); + const res_count = userRepository.createQueryBuilder("User").leftJoin("User.roles", "roles").where(whereAttr, whereVal); - const subquery = userRepository - .createQueryBuilder("User") - .select("User.id", "id") - .leftJoin("User.roles", "roles") - .where(whereAttr, whereVal) - .orderBy("User." + param.order_field, param.order_direction) - .offset(offset) - .limit(param.limit) - .distinct(true); + const orderExpr = "User." + param.order_field; + const subquery = userRepository.createQueryBuilder("User").select("User.id", "id").addSelect(orderExpr, "_list_doctor_order").leftJoin("User.roles", "roles").where(whereAttr, whereVal).orderBy(orderExpr, param.order_direction).offset(offset).limit(param.limit).distinct(true); const res_list = userRepository .createQueryBuilder("User") @@ -255,20 +235,10 @@ export class UserController { const mapped_data = list_data.map((user) => ({ ...user, profile_picture: user.profile_picture ?? null, - file_profile_picture: user.profile_picture - ? `${config.server.host_swagger}uploads/doctor-profile/${user.profile_picture}` - : null, + file_profile_picture: user.profile_picture ? `${config.server.host_swagger}uploads/doctor-profile/${user.profile_picture}` : null, })); - return ReturnHelper.successResponselist( - res, - 200, - Language.lang.success_view, - count_data, - current_page, - total_count_data, - mapped_data, - ); + return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, mapped_data); } catch (e: unknown) { log.error(e); const err = e as Error; @@ -323,10 +293,7 @@ export class UserController { const filename = "user.xlsx"; - res.setHeader( - "Content-Type", - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - ); + res.setHeader("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); res.setHeader("Content-Disposition", "attachment; filename=" + filename); const workbook = new exceljs.stream.xlsx.WorkbookWriter({ stream: res }); @@ -348,25 +315,7 @@ export class UserController { const fetchAndWrite = async (page: any) => { const offset = (page - 1) * limit; - const data = await userRepository - .createQueryBuilder() - .where(whereAttr, whereVal) - .select([ - "User.id as id", - "User.name as name", - "User.email as email", - "User.username as username", - "User.status as status", - "User.created_at as created_at", - "roles.name as role_name", - "application.id as application", - ]) - .leftJoin("User.roles", "roles") - .leftJoin("roles.application", "application") - .orderBy(param.order_field, param.order_direction) - .offset(offset) - .limit(limit) - .getRawMany(); + const data = await userRepository.createQueryBuilder().where(whereAttr, whereVal).select(["User.id as id", "User.name as name", "User.email as email", "User.username as username", "User.status as status", "User.created_at as created_at", "roles.name as role_name", "application.id as application"]).leftJoin("User.roles", "roles").leftJoin("roles.application", "application").orderBy(param.order_field, param.order_direction).offset(offset).limit(limit).getRawMany(); data.forEach((item: any) => sheet.addRow(item).commit()); @@ -410,11 +359,7 @@ export class UserController { const schema = Joi.object().keys({ email: Joi.string().email().max(64).required().label("Email"), username: Joi.string().max(64).required().label("Username"), - password: Joi.string() - .pattern(new RegExp("^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$")) - .min(8) - .required() - .label("Password"), + password: Joi.string().pattern(new RegExp("^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$")).min(8).required().label("Password"), retype_password: Joi.ref("password"), name: Joi.string().max(64).required().label("Name"), employee_id: Joi.string().uuid().optional().allow("").label("Employee ID"), @@ -431,9 +376,7 @@ export class UserController { data.status = param.status; if (param.employee_id && param.employee_id != "") { - const employee = await OrmHelper.DB.manager - .getRepository(HrmsEmployee) - .findOneByOrFail({ id: param.employee_id }); + const employee = await OrmHelper.DB.manager.getRepository(HrmsEmployee).findOneByOrFail({ id: param.employee_id }); data.employee = employee; } else { data.employee = null; @@ -505,23 +448,11 @@ export class UserController { for (let r of data.roles) { if (r.id == param.id_role) { //already added - return ReturnHelper.errorResponse( - res, - 409, - 401, - Language.lang.failed_insert + ", roles already exists ", - "", - ); + return ReturnHelper.errorResponse(res, 409, 401, Language.lang.failed_insert + ", roles already exists ", ""); } if (r.application.id == new_role?.application.id) { - return ReturnHelper.errorResponse( - res, - 409, - 402, - Language.lang.failed_insert + ", roles in this application already exists ", - "", - ); + return ReturnHelper.errorResponse(res, 409, 402, Language.lang.failed_insert + ", roles in this application already exists ", ""); } } } @@ -604,13 +535,7 @@ export class UserController { return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, data); } else { - return ReturnHelper.errorResponse( - res, - 404, - 401, - Language.lang.failed_not_found + ", role not found", - "", - ); + return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found + ", role not found", ""); } } else { return ReturnHelper.errorResponse(res, 404, 402, Language.lang.failed_not_found, ""); @@ -702,11 +627,7 @@ export class UserController { try { const schema = Joi.object().keys({ id: Joi.string().uuid().required().label("ID"), - password: Joi.string() - .pattern(new RegExp("^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$")) - .min(8) - .required() - .label("Password"), + password: Joi.string().pattern(new RegExp("^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$")).min(8).required().label("Password"), retype_password: Joi.ref("password"), }); @@ -738,11 +659,7 @@ export class UserController { } } - static async uploadFile( - files: fileUpload.FileArray | null | undefined, - fieldName: string, - folderPath: string - ): Promise { + static async uploadFile(files: fileUpload.FileArray | null | undefined, fieldName: string, folderPath: string): Promise { if (!files || !files[fieldName]) return null; const file = files[fieldName] as fileUpload.UploadedFile; @@ -752,13 +669,15 @@ export class UserController { throw { message: `${fieldName}: File size exceeds 1MB limit` }; } - const allowedMimes = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp']; + const allowedMimes = ["image/jpeg", "image/jpg", "image/png", "image/webp"]; if (!allowedMimes.includes(file.mimetype)) { - throw { message: `${fieldName}: Invalid file type. Only JPG, PNG, and WEBP are allowed` }; + throw { + message: `${fieldName}: Invalid file type. Only JPG, PNG, and WEBP are allowed`, + }; } - const ext = file.name.split('.'); - const name = uuidv4() + '.' + ext[ext.length - 1]; + const ext = file.name.split("."); + const name = uuidv4() + "." + ext[ext.length - 1]; const file_path = path.join(folderPath, name); if (!fs.existsSync(folderPath)) { @@ -825,7 +744,7 @@ export class UserController { name: Joi.string().max(64).required().label("Name"), employee_id: Joi.string().uuid().optional().allow("").label("Employee ID"), status: Joi.string().required().label("Status"), - profile_picture: Joi.string().allow('', null).optional().label("Profile Picture"), + profile_picture: Joi.string().allow("", null).optional().label("Profile Picture"), }); req.body.id = req.params["id"]; @@ -837,10 +756,10 @@ export class UserController { const data = await userRepository.findOneBy({ id: param.id }); if (data != null) { - const doctorprofile = await UserController.uploadFile(req.files, 'profile_picture', 'uploads/doctor-profile'); + const doctorprofile = await UserController.uploadFile(req.files, "profile_picture", "uploads/doctor-profile"); if (doctorprofile) { if (data.profile_picture) { - const oldFilePath = path.join('uploads/doctor-profile', data.profile_picture); + const oldFilePath = path.join("uploads/doctor-profile", data.profile_picture); await UserController.deleteFile(oldFilePath); } data.profile_picture = doctorprofile; @@ -884,7 +803,6 @@ export class UserController { return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); } - } static async updateUserSignature(req: Request, res: Response, next: NextFunction): Promise { @@ -920,7 +838,7 @@ export class UserController { try { const schema = Joi.object().keys({ id: Joi.string().uuid().required().label("ID"), - user_signature: Joi.string().allow('', null).optional().label("User Signature"), + user_signature: Joi.string().allow("", null).optional().label("User Signature"), }); req.body.id = req.params["id"]; @@ -932,12 +850,12 @@ export class UserController { const data = await userRepository.findOneBy({ id: param.id }); if (data != null) { - const usersignature = await UserController.uploadFile(req.files, 'user_signature', 'uploads/user-signature'); + const usersignature = await UserController.uploadFile(req.files, "user_signature", "uploads/user-signature"); if (usersignature) { // ← Hapus signature lama jika ada if (data.signature) { - const oldFilePath = path.join('uploads/user-signature', data.signature); + const oldFilePath = path.join("uploads/user-signature", data.signature); await UserController.deleteFile(oldFilePath); } @@ -1009,16 +927,8 @@ export class UserController { const userRepository = OrmHelper.DB.getRepository(User); const userRTRepository = OrmHelper.DB.getRepository(UserRefreshToken); - const affected = ( - !param.hard - ? await userRepository.softDelete({ id: param.id }) - : await userRepository.delete({ id: param.id }) - ).affected ?? 0; - const affected_rt = ( - !param.hard - ? await userRTRepository.softDelete({ id_user: param.id }) - : await userRTRepository.delete({ id_user: param.id }) - ).affected; + const affected = (!param.hard ? await userRepository.softDelete({ id: param.id }) : await userRepository.delete({ id: param.id })).affected ?? 0; + const affected_rt = (!param.hard ? await userRTRepository.softDelete({ id_user: param.id }) : await userRTRepository.delete({ id_user: param.id })).affected; if (affected > 0) { return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); @@ -1056,19 +966,7 @@ export class UserController { const userRepository = OrmHelper.DB.getRepository(User); const detail = await userRepository.findOne({ - relations: [ - "roles", - "roles.application", - "employee", - "employee.department", - "employee.position", - "employee.shift", - "employee.nationality", - "employee.aldeia", - "employee.suco", - "employee.administrativu", - "employee.munisipo", - ], + relations: ["roles", "roles.application", "employee", "employee.department", "employee.position", "employee.shift", "employee.nationality", "employee.aldeia", "employee.suco", "employee.administrativu", "employee.munisipo"], where: { id: param.id }, }); @@ -1076,13 +974,9 @@ export class UserController { const data = { ...detail, signature: detail.signature ?? null, - file_signature: detail.signature - ? `${config.server.host_swagger}uploads/user-signature/${detail.signature}` - : null, + file_signature: detail.signature ? `${config.server.host_swagger}uploads/user-signature/${detail.signature}` : null, profile: detail.profile_picture ?? null, - profile_picture: detail.profile_picture - ? `${config.server.host_swagger}uploads/doctor-profile/${detail.profile_picture}` - : null, + profile_picture: detail.profile_picture ? `${config.server.host_swagger}uploads/doctor-profile/${detail.profile_picture}` : null, }; return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, data);