update
This commit is contained in:
7
.prettierrc
Normal file
7
.prettierrc
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 5000,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": false,
|
||||||
|
"tabWidth": 4,
|
||||||
|
"useTabs": true
|
||||||
|
}
|
||||||
@ -22,10 +22,10 @@
|
|||||||
"database": {
|
"database": {
|
||||||
"engine": "postgres",
|
"engine": "postgres",
|
||||||
"host": "127.0.0.1",
|
"host": "127.0.0.1",
|
||||||
"port": "15432",
|
"port": "1520",
|
||||||
"username": "saude_tl",
|
"username": "saude_stag",
|
||||||
"password": "saude_tl_local",
|
"password": "gM*#o>3W4&5X",
|
||||||
"database": "saude_tl",
|
"database": "saude_stag",
|
||||||
"synchronize": true,
|
"synchronize": true,
|
||||||
"logging": true
|
"logging": true
|
||||||
},
|
},
|
||||||
|
|||||||
@ -12,8 +12,8 @@ import { Language } from "../langs/lang";
|
|||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import fileUpload from "express-fileupload";
|
import fileUpload from "express-fileupload";
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from "uuid";
|
||||||
import config from '../../config/stag.json';
|
import config from "../../config/stag.json";
|
||||||
import { profile } from "console";
|
import { profile } from "console";
|
||||||
|
|
||||||
const log: Logger<ILogObj> = new Logger({
|
const log: Logger<ILogObj> = new Logger({
|
||||||
@ -137,20 +137,10 @@ export class UserController {
|
|||||||
const mapped_data = list_data.map((user) => ({
|
const mapped_data = list_data.map((user) => ({
|
||||||
...user,
|
...user,
|
||||||
profile_picture: user.profile_picture ?? null,
|
profile_picture: user.profile_picture ?? null,
|
||||||
file_profile_picture: user.profile_picture
|
file_profile_picture: user.profile_picture ? `${config.server.host_swagger}uploads/doctor-profile/${user.profile_picture}` : null,
|
||||||
? `${config.server.host_swagger}uploads/doctor-profile/${user.profile_picture}`
|
|
||||||
: null,
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return ReturnHelper.successResponselist(
|
return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, mapped_data);
|
||||||
res,
|
|
||||||
200,
|
|
||||||
Language.lang.success_view,
|
|
||||||
count_data,
|
|
||||||
current_page,
|
|
||||||
total_count_data,
|
|
||||||
mapped_data,
|
|
||||||
);
|
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
log.error(e);
|
log.error(e);
|
||||||
const err = e as Error;
|
const err = e as Error;
|
||||||
@ -214,24 +204,14 @@ export class UserController {
|
|||||||
filter: param.filter,
|
filter: param.filter,
|
||||||
col_any_eq: ["email"],
|
col_any_eq: ["email"],
|
||||||
col_any_like: ["User.name", "User.username"],
|
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
|
const res_count = userRepository.createQueryBuilder("User").leftJoin("User.roles", "roles").where(whereAttr, whereVal);
|
||||||
.createQueryBuilder("User")
|
|
||||||
.leftJoin("User.roles", "roles")
|
|
||||||
.where(whereAttr, whereVal);
|
|
||||||
|
|
||||||
const subquery = userRepository
|
const orderExpr = "User." + param.order_field;
|
||||||
.createQueryBuilder("User")
|
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);
|
||||||
.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 res_list = userRepository
|
const res_list = userRepository
|
||||||
.createQueryBuilder("User")
|
.createQueryBuilder("User")
|
||||||
@ -255,20 +235,10 @@ export class UserController {
|
|||||||
const mapped_data = list_data.map((user) => ({
|
const mapped_data = list_data.map((user) => ({
|
||||||
...user,
|
...user,
|
||||||
profile_picture: user.profile_picture ?? null,
|
profile_picture: user.profile_picture ?? null,
|
||||||
file_profile_picture: user.profile_picture
|
file_profile_picture: user.profile_picture ? `${config.server.host_swagger}uploads/doctor-profile/${user.profile_picture}` : null,
|
||||||
? `${config.server.host_swagger}uploads/doctor-profile/${user.profile_picture}`
|
|
||||||
: null,
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return ReturnHelper.successResponselist(
|
return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, mapped_data);
|
||||||
res,
|
|
||||||
200,
|
|
||||||
Language.lang.success_view,
|
|
||||||
count_data,
|
|
||||||
current_page,
|
|
||||||
total_count_data,
|
|
||||||
mapped_data,
|
|
||||||
);
|
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
log.error(e);
|
log.error(e);
|
||||||
const err = e as Error;
|
const err = e as Error;
|
||||||
@ -323,10 +293,7 @@ export class UserController {
|
|||||||
|
|
||||||
const filename = "user.xlsx";
|
const filename = "user.xlsx";
|
||||||
|
|
||||||
res.setHeader(
|
res.setHeader("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||||
"Content-Type",
|
|
||||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
||||||
);
|
|
||||||
res.setHeader("Content-Disposition", "attachment; filename=" + filename);
|
res.setHeader("Content-Disposition", "attachment; filename=" + filename);
|
||||||
|
|
||||||
const workbook = new exceljs.stream.xlsx.WorkbookWriter({ stream: res });
|
const workbook = new exceljs.stream.xlsx.WorkbookWriter({ stream: res });
|
||||||
@ -348,25 +315,7 @@ export class UserController {
|
|||||||
const fetchAndWrite = async (page: any) => {
|
const fetchAndWrite = async (page: any) => {
|
||||||
const offset = (page - 1) * limit;
|
const offset = (page - 1) * limit;
|
||||||
|
|
||||||
const data = await userRepository
|
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();
|
||||||
.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());
|
data.forEach((item: any) => sheet.addRow(item).commit());
|
||||||
|
|
||||||
@ -410,11 +359,7 @@ export class UserController {
|
|||||||
const schema = Joi.object().keys({
|
const schema = Joi.object().keys({
|
||||||
email: Joi.string().email().max(64).required().label("Email"),
|
email: Joi.string().email().max(64).required().label("Email"),
|
||||||
username: Joi.string().max(64).required().label("Username"),
|
username: Joi.string().max(64).required().label("Username"),
|
||||||
password: Joi.string()
|
password: Joi.string().pattern(new RegExp("^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$")).min(8).required().label("Password"),
|
||||||
.pattern(new RegExp("^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$"))
|
|
||||||
.min(8)
|
|
||||||
.required()
|
|
||||||
.label("Password"),
|
|
||||||
retype_password: Joi.ref("password"),
|
retype_password: Joi.ref("password"),
|
||||||
name: Joi.string().max(64).required().label("Name"),
|
name: Joi.string().max(64).required().label("Name"),
|
||||||
employee_id: Joi.string().uuid().optional().allow("").label("Employee ID"),
|
employee_id: Joi.string().uuid().optional().allow("").label("Employee ID"),
|
||||||
@ -431,9 +376,7 @@ export class UserController {
|
|||||||
data.status = param.status;
|
data.status = param.status;
|
||||||
|
|
||||||
if (param.employee_id && param.employee_id != "") {
|
if (param.employee_id && param.employee_id != "") {
|
||||||
const employee = await OrmHelper.DB.manager
|
const employee = await OrmHelper.DB.manager.getRepository(HrmsEmployee).findOneByOrFail({ id: param.employee_id });
|
||||||
.getRepository(HrmsEmployee)
|
|
||||||
.findOneByOrFail({ id: param.employee_id });
|
|
||||||
data.employee = employee;
|
data.employee = employee;
|
||||||
} else {
|
} else {
|
||||||
data.employee = null;
|
data.employee = null;
|
||||||
@ -505,23 +448,11 @@ export class UserController {
|
|||||||
for (let r of data.roles) {
|
for (let r of data.roles) {
|
||||||
if (r.id == param.id_role) {
|
if (r.id == param.id_role) {
|
||||||
//already added
|
//already added
|
||||||
return ReturnHelper.errorResponse(
|
return ReturnHelper.errorResponse(res, 409, 401, Language.lang.failed_insert + ", roles already exists ", "");
|
||||||
res,
|
|
||||||
409,
|
|
||||||
401,
|
|
||||||
Language.lang.failed_insert + ", roles already exists ",
|
|
||||||
"",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r.application.id == new_role?.application.id) {
|
if (r.application.id == new_role?.application.id) {
|
||||||
return ReturnHelper.errorResponse(
|
return ReturnHelper.errorResponse(res, 409, 402, Language.lang.failed_insert + ", roles in this application already exists ", "");
|
||||||
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);
|
return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, data);
|
||||||
} else {
|
} else {
|
||||||
return ReturnHelper.errorResponse(
|
return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found + ", role not found", "");
|
||||||
res,
|
|
||||||
404,
|
|
||||||
401,
|
|
||||||
Language.lang.failed_not_found + ", role not found",
|
|
||||||
"",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return ReturnHelper.errorResponse(res, 404, 402, Language.lang.failed_not_found, "");
|
return ReturnHelper.errorResponse(res, 404, 402, Language.lang.failed_not_found, "");
|
||||||
@ -702,11 +627,7 @@ export class UserController {
|
|||||||
try {
|
try {
|
||||||
const schema = Joi.object().keys({
|
const schema = Joi.object().keys({
|
||||||
id: Joi.string().uuid().required().label("ID"),
|
id: Joi.string().uuid().required().label("ID"),
|
||||||
password: Joi.string()
|
password: Joi.string().pattern(new RegExp("^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$")).min(8).required().label("Password"),
|
||||||
.pattern(new RegExp("^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$"))
|
|
||||||
.min(8)
|
|
||||||
.required()
|
|
||||||
.label("Password"),
|
|
||||||
retype_password: Joi.ref("password"),
|
retype_password: Joi.ref("password"),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -738,11 +659,7 @@ export class UserController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async uploadFile(
|
static async uploadFile(files: fileUpload.FileArray | null | undefined, fieldName: string, folderPath: string): Promise<string | null> {
|
||||||
files: fileUpload.FileArray | null | undefined,
|
|
||||||
fieldName: string,
|
|
||||||
folderPath: string
|
|
||||||
): Promise<string | null> {
|
|
||||||
if (!files || !files[fieldName]) return null;
|
if (!files || !files[fieldName]) return null;
|
||||||
|
|
||||||
const file = files[fieldName] as fileUpload.UploadedFile;
|
const file = files[fieldName] as fileUpload.UploadedFile;
|
||||||
@ -752,13 +669,15 @@ export class UserController {
|
|||||||
throw { message: `${fieldName}: File size exceeds 1MB limit` };
|
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)) {
|
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 ext = file.name.split(".");
|
||||||
const name = uuidv4() + '.' + ext[ext.length - 1];
|
const name = uuidv4() + "." + ext[ext.length - 1];
|
||||||
const file_path = path.join(folderPath, name);
|
const file_path = path.join(folderPath, name);
|
||||||
|
|
||||||
if (!fs.existsSync(folderPath)) {
|
if (!fs.existsSync(folderPath)) {
|
||||||
@ -825,7 +744,7 @@ export class UserController {
|
|||||||
name: Joi.string().max(64).required().label("Name"),
|
name: Joi.string().max(64).required().label("Name"),
|
||||||
employee_id: Joi.string().uuid().optional().allow("").label("Employee ID"),
|
employee_id: Joi.string().uuid().optional().allow("").label("Employee ID"),
|
||||||
status: Joi.string().required().label("Status"),
|
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"];
|
req.body.id = req.params["id"];
|
||||||
@ -837,10 +756,10 @@ export class UserController {
|
|||||||
const data = await userRepository.findOneBy({ id: param.id });
|
const data = await userRepository.findOneBy({ id: param.id });
|
||||||
|
|
||||||
if (data != null) {
|
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 (doctorprofile) {
|
||||||
if (data.profile_picture) {
|
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);
|
await UserController.deleteFile(oldFilePath);
|
||||||
}
|
}
|
||||||
data.profile_picture = doctorprofile;
|
data.profile_picture = doctorprofile;
|
||||||
@ -884,7 +803,6 @@ export class UserController {
|
|||||||
|
|
||||||
return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message);
|
return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async updateUserSignature(req: Request, res: Response, next: NextFunction): Promise<Response> {
|
static async updateUserSignature(req: Request, res: Response, next: NextFunction): Promise<Response> {
|
||||||
@ -920,7 +838,7 @@ export class UserController {
|
|||||||
try {
|
try {
|
||||||
const schema = Joi.object().keys({
|
const schema = Joi.object().keys({
|
||||||
id: Joi.string().uuid().required().label("ID"),
|
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"];
|
req.body.id = req.params["id"];
|
||||||
@ -932,12 +850,12 @@ export class UserController {
|
|||||||
const data = await userRepository.findOneBy({ id: param.id });
|
const data = await userRepository.findOneBy({ id: param.id });
|
||||||
|
|
||||||
if (data != null) {
|
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) {
|
if (usersignature) {
|
||||||
// ← Hapus signature lama jika ada
|
// ← Hapus signature lama jika ada
|
||||||
if (data.signature) {
|
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);
|
await UserController.deleteFile(oldFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1009,16 +927,8 @@ export class UserController {
|
|||||||
const userRepository = OrmHelper.DB.getRepository(User);
|
const userRepository = OrmHelper.DB.getRepository(User);
|
||||||
const userRTRepository = OrmHelper.DB.getRepository(UserRefreshToken);
|
const userRTRepository = OrmHelper.DB.getRepository(UserRefreshToken);
|
||||||
|
|
||||||
const affected = (
|
const affected = (!param.hard ? await userRepository.softDelete({ id: param.id }) : await userRepository.delete({ id: param.id })).affected ?? 0;
|
||||||
!param.hard
|
const affected_rt = (!param.hard ? await userRTRepository.softDelete({ id_user: param.id }) : await userRTRepository.delete({ id_user: param.id })).affected;
|
||||||
? 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) {
|
if (affected > 0) {
|
||||||
return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {});
|
return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {});
|
||||||
@ -1056,19 +966,7 @@ export class UserController {
|
|||||||
const userRepository = OrmHelper.DB.getRepository(User);
|
const userRepository = OrmHelper.DB.getRepository(User);
|
||||||
|
|
||||||
const detail = await userRepository.findOne({
|
const detail = await userRepository.findOne({
|
||||||
relations: [
|
relations: ["roles", "roles.application", "employee", "employee.department", "employee.position", "employee.shift", "employee.nationality", "employee.aldeia", "employee.suco", "employee.administrativu", "employee.munisipo"],
|
||||||
"roles",
|
|
||||||
"roles.application",
|
|
||||||
"employee",
|
|
||||||
"employee.department",
|
|
||||||
"employee.position",
|
|
||||||
"employee.shift",
|
|
||||||
"employee.nationality",
|
|
||||||
"employee.aldeia",
|
|
||||||
"employee.suco",
|
|
||||||
"employee.administrativu",
|
|
||||||
"employee.munisipo",
|
|
||||||
],
|
|
||||||
where: { id: param.id },
|
where: { id: param.id },
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1076,13 +974,9 @@ export class UserController {
|
|||||||
const data = {
|
const data = {
|
||||||
...detail,
|
...detail,
|
||||||
signature: detail.signature ?? null,
|
signature: detail.signature ?? null,
|
||||||
file_signature: detail.signature
|
file_signature: detail.signature ? `${config.server.host_swagger}uploads/user-signature/${detail.signature}` : null,
|
||||||
? `${config.server.host_swagger}uploads/user-signature/${detail.signature}`
|
|
||||||
: null,
|
|
||||||
profile: detail.profile_picture ?? null,
|
profile: detail.profile_picture ?? null,
|
||||||
profile_picture: detail.profile_picture
|
profile_picture: detail.profile_picture ? `${config.server.host_swagger}uploads/doctor-profile/${detail.profile_picture}` : null,
|
||||||
? `${config.server.host_swagger}uploads/doctor-profile/${detail.profile_picture}`
|
|
||||||
: null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, data);
|
return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, data);
|
||||||
|
|||||||
Reference in New Issue
Block a user