From 3b9f3474a6708224612b52806e403955ab705a81 Mon Sep 17 00:00:00 2001 From: Muhammad Afif Date: Fri, 24 Oct 2025 16:21:20 +0700 Subject: [PATCH] repair json body user_schedule and validasi user_id tidak boleh sama di satu shift_id --- db/user_schedule.db.js | 67 ++++++++++++++++++++++++++----- services/user_schedule.service.js | 33 +++++++++++++-- validate/user_schedule.schema.js | 2 +- 3 files changed, 86 insertions(+), 16 deletions(-) diff --git a/db/user_schedule.db.js b/db/user_schedule.db.js index 3305ff7..dc7b403 100644 --- a/db/user_schedule.db.js +++ b/db/user_schedule.db.js @@ -21,7 +21,7 @@ const getAllUserScheduleDb = async (searchParams = {}) => { { column: "a.user_id", param: searchParams.user_id, type: "int" }, { column: "a.user_schedule_id", param: searchParams.user_schedule_id, type: "int" }, { column: "a.schedule_id", param: searchParams.schedule_id, type: "int" }, - { column: "a.user_schedule_id", param: searchParams.user_schedule_id, type: "int" }, + { column: "a.shift_id", param: searchParams.shift_id, type: "int" }, ], queryParams ); @@ -30,12 +30,14 @@ const getAllUserScheduleDb = async (searchParams = {}) => { const queryText = ` SELECT COUNT(*) OVER() AS total_data, - a.*, - b.schedule_date, + a.shift_id, c.shift_name, c.start_time, c.end_time, - d.user_fullname + d.user_id, + d.user_fullname, + d.user_name, + d.user_phone FROM user_schedule a LEFT JOIN schedule b ON a.schedule_id = b.schedule_id LEFT JOIN m_shift c ON a.shift_id = c.shift_id @@ -43,19 +45,58 @@ const getAllUserScheduleDb = async (searchParams = {}) => { WHERE a.deleted_at IS NULL ${whereConditions.length > 0 ? ` AND ${whereConditions.join(" AND ")}` : ""} ${whereOrConditions ? ` ${whereOrConditions}` : ""} - ORDER BY a.user_schedule_id ASC + ORDER BY c.shift_id ASC ${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ''} `; const result = await pool.query(queryText, queryParams); - const total = - result?.recordset?.length > 0 - ? parseInt(result.recordset[0].total_data, 10) - : 0; + const records = result.recordset || []; - return { data: result.recordset, total }; + const total = records.length > 0 ? parseInt(records[0].total_data, 10) : 0; + + const groupedData = Object.values( + records.reduce((acc, row) => { + if (!acc[row.shift_id]) { + acc[row.shift_id] = { + shift_id: row.shift_id, + shift_name: row.shift_name, + start_time: row.start_time, + end_time: row.end_time, + users: [], + }; + } + + acc[row.shift_id].users.push({ + user_id: row.user_id, + user_fullname: row.user_fullname, + user_name: row.user_name, + user_phone: row.user_phone, + }); + + return acc; + }, {}) + ); + + return { data: groupedData, total }; }; +const getUserScheduleById = async (userId, shiftId) => { + const queryText = ` + SELECT + a.user_schedule_id, + a.user_id, + a.shift_id + FROM user_schedule a + WHERE a.user_id = $1 + AND a.shift_id = $2 + AND a.deleted_at IS NULL + `; + const result = await pool.query(queryText, [userId, shiftId]); + return result.recordset || []; +}; + + + const getUserScheduleByIdDb = async (id) => { const queryText = ` SELECT @@ -64,7 +105,9 @@ const getUserScheduleByIdDb = async (id) => { c.shift_name, c.start_time, c.end_time, - d.user_fullname + d.user_fullname, + d.user_name, + d.user_phone FROM user_schedule a LEFT JOIN schedule b ON a.schedule_id = b.schedule_id LEFT JOIN m_shift c ON a.shift_id = c.shift_id @@ -107,10 +150,12 @@ const deleteUserScheduleDb = async (id, deletedBy) => { return true; }; + module.exports = { getAllUserScheduleDb, getUserScheduleByIdDb, insertUserScheduleDb, updateUserScheduleDb, deleteUserScheduleDb, + getUserScheduleById, }; diff --git a/services/user_schedule.service.js b/services/user_schedule.service.js index 6c07048..8872ff0 100644 --- a/services/user_schedule.service.js +++ b/services/user_schedule.service.js @@ -1,6 +1,7 @@ const { getAllUserScheduleDb, getUserScheduleByIdDb, + getUserScheduleById, insertUserScheduleDb, updateUserScheduleDb, deleteUserScheduleDb @@ -35,20 +36,30 @@ const { } } - // Create device static async createUserSchedules(data) { try { if (!data || typeof data !== 'object') data = {}; - const result = await insertUserScheduleDb(data); + const exist = await getUserScheduleById( + data.user_id, + data.shift_id + ); + if (exist.length > 0) { + throw new ErrorHandler( + 400, + `User dengan ID ${data.user_id} sudah terdaftar pada shift ${data.shift_id}` + ); + } + + const result = await insertUserScheduleDb(data); return result; } catch (error) { throw new ErrorHandler(error.statusCode, error.message); } } - // Update device + // Update user schedule static async updateUserSchedules(id, data) { try { if (!data || typeof data !== 'object') data = {}; @@ -59,8 +70,22 @@ const { throw new ErrorHandler(404, 'UserSchedules not found'); } - const result = await updateUserScheduleDb(id, data); + // 🧩 VALIDASI SAAT UPDATE + if (data.user_id && data.shift_id) { + const exist = await getUserScheduleById( + data.user_id, + data.shift_id + ); + if (exist.length > 0 && exist[0].id !== Number(id)) { + throw new ErrorHandler( + 400, + `User dengan ID ${data.user_id} sudah terdaftar pada shift ${data.shift_id}` + ); + } + } + + const result = await updateUserScheduleDb(id, data); return result; } catch (error) { throw new ErrorHandler(error.statusCode, error.message); diff --git a/validate/user_schedule.schema.js b/validate/user_schedule.schema.js index 7e8b6af..3d9373a 100644 --- a/validate/user_schedule.schema.js +++ b/validate/user_schedule.schema.js @@ -5,7 +5,7 @@ const Joi = require("joi"); // ======================== const insertUserScheduleSchema = Joi.object({ user_id: Joi.number().integer().required(), - schedule_id: Joi.number().integer().required(), + schedule_id: Joi.number().integer().optional(), shift_id: Joi.number().required(), });