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