crud: notification
This commit is contained in:
83
controllers/notification.controller.js
Normal file
83
controllers/notification.controller.js
Normal file
@@ -0,0 +1,83 @@
|
||||
const NotificationService = require('../services/notification.service');
|
||||
const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils');
|
||||
const { insertNotificationSchema, updateNotificationSchema } = require('../validate/notification.schema');
|
||||
|
||||
class NotificationController {
|
||||
static async getAll(req, res) {
|
||||
try {
|
||||
const queryParams = req.query;
|
||||
const results = await NotificationService.getAllNotification(queryParams);
|
||||
const response = await setResponsePaging(queryParams, results, 'Notification list retrieved successfully');
|
||||
return res.status(response.statusCode).json(response);
|
||||
} catch (err) {
|
||||
console.error("❌ [getAll] Notification Error:", err.message);
|
||||
return res.status(500).json(setResponse(err, 'Failed to fetch notifications', 500));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static async getById(req, res) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const results = await NotificationService.getNotificationById(id);
|
||||
const response = await setResponse(results, 'Notification retrieved successfully');
|
||||
return res.status(response.statusCode).json(response);
|
||||
} catch (err) {
|
||||
console.error("❌ [getById] Notification Error:", err.message);
|
||||
return res.status(500).json(setResponse(err, 'Failed to fetch notification', 500));
|
||||
}
|
||||
}
|
||||
|
||||
static async create(req, res) {
|
||||
try {
|
||||
const { error, value } = await checkValidate(insertNotificationSchema, req);
|
||||
|
||||
if (error) {
|
||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
||||
}
|
||||
|
||||
value.created_by = req.user?.user_id || 'system';
|
||||
|
||||
const results = await NotificationService.createNotification(value);
|
||||
const response = await setResponse(results, 'Notification created successfully');
|
||||
return res.status(response.statusCode).json(response);
|
||||
} catch (err) {
|
||||
console.error("❌ [create] Notification Error:", err.message);
|
||||
return res.status(500).json(setResponse(err, 'Failed to create notification', 500));
|
||||
}
|
||||
}
|
||||
|
||||
static async update(req, res) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const { error, value } = await checkValidate(updateNotificationSchema, req);
|
||||
|
||||
if (error) {
|
||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
||||
}
|
||||
|
||||
value.updated_by = req.user?.user_id || 'system';
|
||||
|
||||
const results = await NotificationService.updateNotification(id, value);
|
||||
const response = await setResponse(results, 'Notification updated successfully');
|
||||
return res.status(response.statusCode).json(response);
|
||||
} catch (err) {
|
||||
console.error("❌ [update] Notification Error:", err.message);
|
||||
return res.status(500).json(setResponse(err, 'Failed to update notification', 500));
|
||||
}
|
||||
}
|
||||
|
||||
static async delete(req, res) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const results = await NotificationService.deleteNotification(id, req.user?.user_id || 'system');
|
||||
const response = await setResponse(results, 'Notification deleted successfully');
|
||||
return res.status(response.statusCode).json(response);
|
||||
} catch (err) {
|
||||
console.error("❌ [delete] Notification Error:", err.message);
|
||||
return res.status(500).json(setResponse(err, 'Failed to delete notification', 500));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = NotificationController;
|
||||
107
db/notification.db.js
Normal file
107
db/notification.db.js
Normal file
@@ -0,0 +1,107 @@
|
||||
const pool = require("../config");
|
||||
|
||||
const getAllNotificationDb = 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.is_send", "a.is_delivered", "a.is_read", "a.is_active"],
|
||||
searchParams.criteria,
|
||||
queryParams
|
||||
);
|
||||
if (whereParamOr) queryParams = whereParamOr;
|
||||
|
||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
||||
[
|
||||
{ column: "a.is_delivered", param: searchParams.is_delivered, type: "int" },
|
||||
{ column: "a.is_send", param: searchParams.is_send, type: "int" },
|
||||
{ column: "a.is_read", param: searchParams.is_read, type: "int" },
|
||||
{ column: "a.is_active", param: searchParams.is_active, type: "int" },
|
||||
],
|
||||
queryParams
|
||||
);
|
||||
if (whereParamAnd) queryParams = whereParamAnd;
|
||||
|
||||
const queryText = `
|
||||
SELECT
|
||||
COUNT(*) OVER() AS total_data,
|
||||
a.*,
|
||||
b.error_code,
|
||||
b.error_code_name,
|
||||
b.error_code_description,
|
||||
c.solution_name,
|
||||
c.type_solution,
|
||||
c.path_solution
|
||||
FROM notification_error a
|
||||
LEFT JOIN brand_code b ON a.error_code_id = b.error_code_id AND b.deleted_at IS NULL
|
||||
LEFT JOIN brand_code_solution c ON a.error_code_id = c.error_code_id AND c.deleted_at IS NULL
|
||||
WHERE a.deleted_at IS NULL
|
||||
${whereConditions.length > 0 ? ` AND ${whereConditions.join(" AND ")}` : ""}
|
||||
${whereOrConditions ? ` ${whereOrConditions}` : ""}
|
||||
ORDER BY a.notification_error_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;
|
||||
|
||||
return { data: result.recordset, total };
|
||||
};
|
||||
|
||||
const getNotificationByIdDb = async (id) => {
|
||||
const queryText = `
|
||||
SELECT a.*,
|
||||
b.error_code,
|
||||
b.error_code_name,
|
||||
b.error_code_description,
|
||||
c.solution_name,
|
||||
c.type_solution,
|
||||
c.path_solution
|
||||
FROM notification_error a
|
||||
LEFT JOIN brand_code b ON a.error_code_id = b.error_code_id AND b.deleted_at IS NULL
|
||||
LEFT JOIN brand_code_solution c ON a.error_code_id = c.error_code_id AND c.deleted_at IS NULL
|
||||
WHERE a.notification_error_id = $1 AND a.deleted_at IS NULL
|
||||
`;
|
||||
const result = await pool.query(queryText, [id]);
|
||||
return result.recordset?.[0] || null;
|
||||
};
|
||||
|
||||
const insertNotificationDb = async (store) => {
|
||||
const { query: queryText, values } = pool.buildDynamicInsert("notification_error", store);
|
||||
const result = await pool.query(queryText, values);
|
||||
const insertedId = result.recordset?.[0]?.inserted_id;
|
||||
return insertedId ? await getNotificationByIdDb(insertedId) : null;
|
||||
};
|
||||
|
||||
const updateNotificationDb = async (id, data) => {
|
||||
const store = { ...data };
|
||||
const whereData = { notification_error_id: id };
|
||||
const { query: queryText, values } = pool.buildDynamicUpdate("notification_error", store, whereData);
|
||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
||||
return getNotificationByIdDb(id);
|
||||
};
|
||||
|
||||
const deleteNotificationDb = async (id, deletedBy) => {
|
||||
const queryText = `
|
||||
UPDATE notification_error
|
||||
SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1
|
||||
WHERE notification_error_id = $2 AND deleted_at IS NULL
|
||||
`;
|
||||
await pool.query(queryText, [deletedBy, id]);
|
||||
return true;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getAllNotificationDb,
|
||||
getNotificationByIdDb,
|
||||
insertNotificationDb,
|
||||
updateNotificationDb,
|
||||
deleteNotificationDb,
|
||||
};
|
||||
23
routes/notification.route.js
Normal file
23
routes/notification.route.js
Normal file
@@ -0,0 +1,23 @@
|
||||
const express = require('express');
|
||||
const NotificationController = require('../controllers/notification.controller');
|
||||
const verifyToken = require('../middleware/verifyToken');
|
||||
const verifyAccess = require('../middleware/verifyAccess');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// ===========================
|
||||
// Notification Routes
|
||||
// ===========================
|
||||
|
||||
router
|
||||
.route('/')
|
||||
.get(verifyToken.verifyAccessToken, NotificationController.getAll)
|
||||
.post(verifyToken.verifyAccessToken, verifyAccess(), NotificationController.create);
|
||||
|
||||
router
|
||||
.route('/:id')
|
||||
.get(verifyToken.verifyAccessToken, NotificationController.getById)
|
||||
.put(verifyToken.verifyAccessToken, verifyAccess(), NotificationController.update)
|
||||
.delete(verifyToken.verifyAccessToken, verifyAccess(), NotificationController.delete);
|
||||
|
||||
module.exports = router;
|
||||
86
services/notification.service.js
Normal file
86
services/notification.service.js
Normal file
@@ -0,0 +1,86 @@
|
||||
const {
|
||||
getAllNotificationDb,
|
||||
getNotificationByIdDb,
|
||||
insertNotificationDb,
|
||||
updateNotificationDb,
|
||||
deleteNotificationDb,
|
||||
handleBrandCodeError // 🧩 tambahkan ini
|
||||
} = require('../db/notification.db');
|
||||
|
||||
const { ErrorHandler } = require('../helpers/error');
|
||||
|
||||
class NotificationService {
|
||||
// Get all Notifications
|
||||
static async getAllNotification(param) {
|
||||
try {
|
||||
const results = await getAllNotificationDb(param);
|
||||
|
||||
results.data.map(element => {
|
||||
});
|
||||
|
||||
return results;
|
||||
} catch (error) {
|
||||
throw new ErrorHandler(error.statusCode, error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Get notification by ID
|
||||
static async getNotificationById(id) {
|
||||
try {
|
||||
const result = await getNotificationByIdDb(id);
|
||||
|
||||
if (!result || (Array.isArray(result) && result.length < 1)) {
|
||||
throw new ErrorHandler(404, 'Notification not found');
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
throw new ErrorHandler(error.statusCode, error.message);
|
||||
}
|
||||
}
|
||||
|
||||
static async createNotification(data) {
|
||||
try {
|
||||
if (!data || typeof data !== 'object') data = {};
|
||||
|
||||
const result = await insertNotificationDb(data);
|
||||
return result;
|
||||
} catch (error) {
|
||||
throw new ErrorHandler(error.statusCode, error.message);
|
||||
}
|
||||
}
|
||||
|
||||
static async updateNotification(id, data) {
|
||||
try {
|
||||
if (!data || typeof data !== 'object') data = {};
|
||||
|
||||
const dataExist = await getNotificationByIdDb(id);
|
||||
|
||||
if (!dataExist || (Array.isArray(dataExist) && dataExist.length < 1)) {
|
||||
throw new ErrorHandler(404, 'Notification not found');
|
||||
}
|
||||
|
||||
const result = await updateNotificationDb(id, data);
|
||||
return result;
|
||||
} catch (error) {
|
||||
throw new ErrorHandler(error.statusCode, error.message);
|
||||
}
|
||||
}
|
||||
|
||||
static async deleteNotification(id, userId) {
|
||||
try {
|
||||
const dataExist = await getNotificationByIdDb(id);
|
||||
|
||||
if (!dataExist || (Array.isArray(dataExist) && dataExist.length < 1)) {
|
||||
throw new ErrorHandler(404, 'Notification not found');
|
||||
}
|
||||
|
||||
const result = await deleteNotificationDb(id, userId);
|
||||
return result;
|
||||
} catch (error) {
|
||||
throw new ErrorHandler(error.statusCode, error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = NotificationService;
|
||||
65
validate/notification.schema.js
Normal file
65
validate/notification.schema.js
Normal file
@@ -0,0 +1,65 @@
|
||||
// ========================
|
||||
// Notification Validation
|
||||
// ========================
|
||||
|
||||
const Joi = require("joi");
|
||||
|
||||
// ========================
|
||||
// Insert Notification Schema
|
||||
// ========================
|
||||
const insertNotificationSchema = Joi.object({
|
||||
error_code_id: Joi.number().required().messages({
|
||||
"any.required": "error_code_id is required",
|
||||
"number.base": "error_code_id must be a number",
|
||||
}),
|
||||
|
||||
is_send: Joi.boolean().required().messages({
|
||||
"any.required": "is_send is required",
|
||||
"boolean.base": "is_send must be a boolean",
|
||||
}),
|
||||
|
||||
is_delivered: Joi.boolean().required().messages({
|
||||
"any.required": "is_delivered is required",
|
||||
"boolean.base": "is_delivered must be a boolean",
|
||||
}),
|
||||
|
||||
is_read: Joi.boolean().required().messages({
|
||||
"any.required": "is_read is required",
|
||||
"boolean.base": "is_read must be a boolean",
|
||||
}),
|
||||
|
||||
is_active: Joi.boolean().required().messages({
|
||||
"any.required": "is_active is required",
|
||||
"boolean.base": "is_active must be a boolean",
|
||||
}),
|
||||
});
|
||||
|
||||
// ========================
|
||||
// Update Notification Schema
|
||||
// ========================
|
||||
const updateNotificationSchema = Joi.object({
|
||||
error_code_id: Joi.number().optional().messages({
|
||||
"number.base": "error_code_id must be a number",
|
||||
}),
|
||||
|
||||
is_send: Joi.boolean().optional().messages({
|
||||
"boolean.base": "is_send must be a boolean",
|
||||
}),
|
||||
|
||||
is_delivered: Joi.boolean().optional().messages({
|
||||
"boolean.base": "is_delivered must be a boolean",
|
||||
}),
|
||||
|
||||
is_read: Joi.boolean().optional().messages({
|
||||
"boolean.base": "is_read must be a boolean",
|
||||
}),
|
||||
|
||||
is_active: Joi.boolean().optional().messages({
|
||||
"boolean.base": "is_active must be a boolean",
|
||||
}),
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
insertNotificationSchema,
|
||||
updateNotificationSchema,
|
||||
};
|
||||
Reference in New Issue
Block a user