diff --git a/controllers/schedule.controller.js b/controllers/schedule.controller.js new file mode 100644 index 0000000..e69de29 diff --git a/controllers/shift.controller.js b/controllers/shift.controller.js new file mode 100644 index 0000000..e69de29 diff --git a/db/roles.db.js b/db/roles.db.js index 82215e8..f6bd051 100644 --- a/db/roles.db.js +++ b/db/roles.db.js @@ -14,7 +14,11 @@ const getAllRolesDb = async (searchParams = {}) => { const { whereConditions, whereParamAnd } = pool.buildFilterQuery( [ { column: "r.role_name", param: searchParams.role_name, type: "string" }, - { column: "r.role_level", param: searchParams.role_level, type: "number" }, + { + column: "r.role_level", + param: searchParams.role_level, + type: "number", + }, ], queryParams ); @@ -38,14 +42,15 @@ const getAllRolesDb = async (searchParams = {}) => { WHERE r.deleted_at IS NULL ${whereConditions.length > 0 ? `AND ${whereConditions.join(" AND ")}` : ""} ORDER BY r.role_id ASC - ${searchParams.limit ? `OFFSET $2 ROWS FETCH NEXT $1 ROWS ONLY` : ''}; + ${searchParams.limit ? `OFFSET $2 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 total = + result?.recordset.length > 0 + ? parseInt(result.recordset[0].total_data, 10) + : 0; return { data: result.recordset, total }; }; @@ -75,7 +80,10 @@ const getRolesByIdDb = async (id) => { const createRolesDB = async (data) => { const store = { ...data }; - const { query: queryText, values } = pool.buildDynamicInsert("m_roles", store); + const { query: queryText, values } = pool.buildDynamicInsert( + "m_roles", + store + ); const result = await pool.query(queryText, values); const insertedId = result.recordset[0]?.inserted_id; @@ -87,7 +95,11 @@ const updateRolesDb = async (id, data) => { const store = { ...data }; const whereData = { role_id: id }; - const { query: queryText, values } = pool.buildDynamicUpdate("m_roles", store, whereData); + const { query: queryText, values } = pool.buildDynamicUpdate( + "m_roles", + store, + whereData + ); await pool.query(`${queryText} AND deleted_at IS NULL`, values); return getRolesByIdDb(id); diff --git a/db/schedule.db.js b/db/schedule.db.js new file mode 100644 index 0000000..7d6e2bc --- /dev/null +++ b/db/schedule.db.js @@ -0,0 +1,117 @@ +const pool = require("../config"); +const formattedDate = require("../utils/date"); + +// Get all schedules +const getAllScheduleDb = async (searchParams = {}) => { + let queryParams = []; + + if (searchParams.limit) { + const page = Number(searchParams.page ?? 1) - 1; + queryParams = [Number(searchParams.limit ?? 10), page]; + } + + const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike( + ["a.schedule_date"], + searchParams.criteria, + queryParams + ); + if (whereParamOr) queryParams = whereParamOr; + + const { whereConditions, whereParamAnd } = pool.buildFilterQuery( + [{ column: "a.schedule_date", param: searchParams.name, type: "date" }], + queryParams + ); + if (whereParamAnd) queryParams = whereParamAnd; + + const queryText = ` + SELECT + COUNT(*) OVER() AS total_data, + a.*, + b.user_id, + c.shift_id + FROM schedule a + LEFT JOIN m_shift b ON a.shift_id = b.shift_id + LEFT JOIN user_schedule c ON a.user_schedule_id = c.user_schedule_id + WHERE a.deleted_at IS NULL + ${whereConditions.length > 0 ? ` AND ${whereConditions.join(" AND ")}` : ""} + ${whereOrConditions ? ` ${whereOrConditions}` : ""} + ORDER BY a.schedule_id ASC + ${searchParams.limit ? `OFFSET $2 ROWS FETCH NEXT $1 ROWS ONLY` : ""} + `; + + const result = await pool.query(queryText, queryParams); + + const data = result.recordset.map((item) => ({ + ...item, + schedule_date: item.schedule_date + ? formattedDate(item.schedule_date) + : null, + })); + + const total = + result?.recordset?.length > 0 + ? parseInt(result.recordset[0].total_data, 10) + : 0; + + return { data, total }; +}; + +const getScheduleByIdDb = async (id) => { + const queryText = ` + SELECT + COUNT(*) OVER() AS total_data, + a.*, + b.shift_id, + b.shift_name, + b.start_time, + b.end_time, + c.user_schedule_id, + c.user_id + FROM schedule a + LEFT JOIN m_shift b ON a.shift_id = b.shift_id + LEFT JOIN user_schedule c ON a.user_schedule_id = c.user_schedule_id + WHERE a.schedule_id = $1 AND a.deleted_at IS NULL + `; + const result = await pool.query(queryText, [id]); + + const data = result.recordset.map((item) => ({ + ...item, + schedule_date: item.schedule_date + ? formattedDate(item.schedule_date) + : null, + })); + + return data; +}; + +const updateScheduleDb = async (id, data) => { + const store = { ...data }; + const whereData = { schedule_id: id }; + + const { query: queryText, values } = pool.buildDynamicUpdate( + "schedule", + store, + whereData + ); + + await pool.query(`${queryText} AND deleted_at IS NULL`, values); + return getScheduleByIdDb(id); +}; + +// Soft delete schedule +const deleteScheduleDb = async (id, deletedBy) => { + const queryText = ` + UPDATE schedule + SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1 + WHERE schedule_id = $2 AND deleted_at IS NULL + `; + await pool.query(queryText, [deletedBy, id]); + return true; +}; + +module.exports = { + getAllScheduleDb, + getScheduleByIdDb, + updateScheduleDb, + deleteScheduleDb, +}; diff --git a/db/shift.db.js b/db/shift.db.js new file mode 100644 index 0000000..e69de29 diff --git a/routes/schedule.route.js b/routes/schedule.route.js new file mode 100644 index 0000000..e69de29 diff --git a/routes/shift.route.js b/routes/shift.route.js new file mode 100644 index 0000000..e69de29 diff --git a/services/schedule.service.js b/services/schedule.service.js new file mode 100644 index 0000000..e69de29 diff --git a/services/shift.service.js b/services/shift.service.js new file mode 100644 index 0000000..e69de29 diff --git a/utils/date.js b/utils/date.js new file mode 100644 index 0000000..400d9ce --- /dev/null +++ b/utils/date.js @@ -0,0 +1,8 @@ +module.exports = { + formattedDate: (timestamp) => { + let date = new Date(timestamp); + let options = { day: "numeric", month: "long", year: "numeric" }; + let formattedDate = date.toISOString("id-ID", options); + return formattedDate; + }, + }; \ No newline at end of file diff --git a/validate/schedule.schema.js b/validate/schedule.schema.js new file mode 100644 index 0000000..e69de29 diff --git a/validate/shift.schema.js b/validate/shift.schema.js new file mode 100644 index 0000000..e69de29