refactor: rewrite ke codebase lama
This commit is contained in:
+138
@@ -0,0 +1,138 @@
|
||||
const feedbackService = require('../services/feedback.service');
|
||||
const { response, error } = require('../../../helpers/utils/wrapper');
|
||||
const { BadRequestError, InternalServerError } = require('../../../helpers/error');
|
||||
const { SUCCESS, ERROR } = require('../../../helpers/http-status/status_code');
|
||||
const { isValidPayload } = require('../../../helpers/utils/validator');
|
||||
const { createFeedbackModel, updateFeedbackModel, getAllFeedbackModel } = require('../models/feedback.model');
|
||||
const { deleteFileIfExists } = require('../../../helpers/utils/fileHelper');
|
||||
|
||||
class FeedbackController {
|
||||
async addFeedback(req, res) {
|
||||
try {
|
||||
const image_path = req.file;
|
||||
|
||||
const validatePayload = isValidPayload(req.body, createFeedbackModel);
|
||||
|
||||
if (validatePayload.err) {
|
||||
if (image_path?.filename) {
|
||||
await deleteFileIfExists(image_path.filename);
|
||||
}
|
||||
return response(
|
||||
res,
|
||||
'fail',
|
||||
{ err: validatePayload.err, data: null },
|
||||
'Data tidak valid',
|
||||
ERROR.EXPECTATION_FAILED
|
||||
);
|
||||
}
|
||||
|
||||
const result = await feedbackService.createFeedback(validatePayload.data, image_path);
|
||||
|
||||
if (result.err) {
|
||||
return response(res, 'fail', result);
|
||||
}
|
||||
|
||||
return response(res, 'success', result, 'Feedback berhasil dibuat', SUCCESS.CREATED);
|
||||
} catch (err) {
|
||||
if (req.file?.filename) {
|
||||
await deleteFileIfExists(req.file.filename);
|
||||
}
|
||||
return response(res, 'fail', error(new InternalServerError(err.message)), 'Terjadi kesalahan yang tidak terduga', ERROR.INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
async getAllFeedback(req, res) {
|
||||
try {
|
||||
const validatePayload = isValidPayload(req.query, getAllFeedbackModel);
|
||||
|
||||
if (validatePayload.err) {
|
||||
return response(
|
||||
res,
|
||||
'fail',
|
||||
{ err: validatePayload.err, data: null },
|
||||
'Query parameter tidak valid',
|
||||
ERROR.EXPECTATION_FAILED
|
||||
);
|
||||
}
|
||||
|
||||
const result = await feedbackService.getAllFeedback(validatePayload.data);
|
||||
|
||||
if (result.err) {
|
||||
return response(res, 'fail', result);
|
||||
}
|
||||
|
||||
return response(res, 'success', result, 'Berhasil mengambil semua feedback', SUCCESS.OK);
|
||||
} catch (err) {
|
||||
return response(res, 'fail', error(new InternalServerError(err.message)), 'Terjadi kesalahan yang tidak terduga', ERROR.INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
async getFeedbackById(req, res) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
const result = await feedbackService.getFeedbackById(id);
|
||||
|
||||
if (result.err) {
|
||||
return response(res, 'fail', result);
|
||||
}
|
||||
|
||||
return response(res, 'success', result, 'Berhasil mengambil feedback berdasarkan ID', SUCCESS.OK);
|
||||
} catch (err) {
|
||||
return response(res, 'fail', error(new InternalServerError(err.message)), 'Terjadi kesalahan yang tidak terduga', ERROR.INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
async updateFeedback(req, res) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const image_path = req.file;
|
||||
|
||||
const validatePayload = isValidPayload(req.body, updateFeedbackModel);
|
||||
|
||||
if (validatePayload.err) {
|
||||
if (image_path?.filename) {
|
||||
await deleteFileIfExists(image_path.filename);
|
||||
}
|
||||
return response(
|
||||
res,
|
||||
'fail',
|
||||
{ err: validatePayload.err, data: null },
|
||||
'Data tidak valid',
|
||||
ERROR.EXPECTATION_FAILED
|
||||
);
|
||||
}
|
||||
|
||||
const result = await feedbackService.updateFeedback(id, validatePayload.data, image_path);
|
||||
|
||||
if (result.err) {
|
||||
return response(res, 'fail', result);
|
||||
}
|
||||
|
||||
return response(res, 'success', result, 'Feedback berhasil diperbarui', SUCCESS.OK);
|
||||
} catch (err) {
|
||||
if (req.file?.filename) {
|
||||
await deleteFileIfExists(req.file.filename);
|
||||
}
|
||||
return response(res, 'fail', error(new InternalServerError(err.message)), 'Terjadi kesalahan yang tidak terduga', ERROR.INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
async deleteFeedback(req, res) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
const result = await feedbackService.deleteFeedback(id);
|
||||
|
||||
if (result.err) {
|
||||
return response(res, 'fail', result);
|
||||
}
|
||||
|
||||
return response(res, 'success', result, 'Feedback berhasil dihapus', SUCCESS.OK);
|
||||
} catch (err) {
|
||||
return response(res, 'fail', error(new InternalServerError(err.message)), 'Terjadi kesalahan yang tidak terduga', ERROR.INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new FeedbackController();
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
const feedbackController = require('./controllers/feedback.controller');
|
||||
|
||||
module.exports = {
|
||||
feedbackController,
|
||||
};
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
const joi = require('joi');
|
||||
|
||||
const createFeedbackModel = joi.object().keys({
|
||||
nama: joi.string().max(255).required().messages({
|
||||
'string.base': 'Nama harus berupa teks.',
|
||||
'string.empty': 'Nama tidak boleh kosong.',
|
||||
'string.max': 'Nama maksimal {#limit} karakter.',
|
||||
'any.required': 'Nama wajib diisi.',
|
||||
}),
|
||||
|
||||
universitas: joi.string().max(255).required().messages({
|
||||
'string.base': 'Universitas harus berupa teks.',
|
||||
'string.empty': 'Universitas tidak boleh kosong.',
|
||||
'string.max': 'Universitas maksimal {#limit} karakter.',
|
||||
'any.required': 'Universitas wajib diisi.',
|
||||
}),
|
||||
|
||||
pesan: joi.string().required().messages({
|
||||
'string.base': 'Pesan harus berupa teks.',
|
||||
'string.empty': 'Pesan tidak boleh kosong.',
|
||||
'any.required': 'Pesan wajib diisi.',
|
||||
}),
|
||||
|
||||
batch: joi.number().integer().min(1).required().messages({
|
||||
'number.base': 'Batch harus berupa angka.',
|
||||
'number.integer': 'Batch harus berupa bilangan bulat.',
|
||||
'number.min': 'Batch minimal {#limit}.',
|
||||
'any.required': 'Batch wajib diisi.',
|
||||
}),
|
||||
|
||||
posisi: joi.string().max(255).required().messages({
|
||||
'string.base': 'Posisi harus berupa teks.',
|
||||
'string.empty': 'Posisi tidak boleh kosong.',
|
||||
'string.max': 'Posisi maksimal {#limit} karakter.',
|
||||
'any.required': 'Posisi wajib diisi.',
|
||||
}),
|
||||
|
||||
tahun: joi.number().integer().min(2000).max(2100).required().messages({
|
||||
'number.base': 'Tahun harus berupa angka.',
|
||||
'number.integer': 'Tahun harus berupa bilangan bulat.',
|
||||
'number.min': 'Tahun minimal {#limit}.',
|
||||
'number.max': 'Tahun maksimal {#limit}.',
|
||||
'any.required': 'Tahun wajib diisi.',
|
||||
}),
|
||||
|
||||
image_path: joi.string().optional().allow('', null).messages({
|
||||
'string.base': 'Path gambar harus berupa teks.',
|
||||
}),
|
||||
});
|
||||
|
||||
const updateFeedbackModel = joi.object().keys({
|
||||
nama: joi.string().max(255).optional().messages({
|
||||
'string.base': 'Nama harus berupa teks.',
|
||||
'string.max': 'Nama maksimal {#limit} karakter.',
|
||||
}),
|
||||
|
||||
universitas: joi.string().max(255).optional().messages({
|
||||
'string.base': 'Universitas harus berupa teks.',
|
||||
'string.max': 'Universitas maksimal {#limit} karakter.',
|
||||
}),
|
||||
|
||||
pesan: joi.string().optional().messages({
|
||||
'string.base': 'Pesan harus berupa teks.',
|
||||
}),
|
||||
|
||||
batch: joi.number().integer().min(1).optional().messages({
|
||||
'number.base': 'Batch harus berupa angka.',
|
||||
'number.integer': 'Batch harus berupa bilangan bulat.',
|
||||
'number.min': 'Batch minimal {#limit}.',
|
||||
}),
|
||||
|
||||
posisi: joi.string().max(255).optional().messages({
|
||||
'string.base': 'Posisi harus berupa teks.',
|
||||
'string.max': 'Posisi maksimal {#limit} karakter.',
|
||||
}),
|
||||
|
||||
tahun: joi.number().integer().min(2000).max(2100).optional().messages({
|
||||
'number.base': 'Tahun harus berupa angka.',
|
||||
'number.integer': 'Tahun harus berupa bilangan bulat.',
|
||||
'number.min': 'Tahun minimal {#limit}.',
|
||||
'number.max': 'Tahun maksimal {#limit}.',
|
||||
}),
|
||||
|
||||
image_path: joi.string().optional().allow('', null).messages({
|
||||
'string.base': 'Path gambar harus berupa teks.',
|
||||
}),
|
||||
});
|
||||
|
||||
const getAllFeedbackModel = joi.object().keys({
|
||||
batch: joi.number().integer().min(1).optional().messages({
|
||||
'number.base': 'Batch harus berupa angka.',
|
||||
'number.integer': 'Batch harus berupa bilangan bulat.',
|
||||
'number.min': 'Batch minimal {#limit}.',
|
||||
}),
|
||||
|
||||
tahun: joi.number().integer().min(2000).max(2100).optional().messages({
|
||||
'number.base': 'Tahun harus berupa angka.',
|
||||
'number.integer': 'Tahun harus berupa bilangan bulat.',
|
||||
'number.min': 'Tahun minimal {#limit}.',
|
||||
'number.max': 'Tahun maksimal {#limit}.',
|
||||
}),
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
createFeedbackModel,
|
||||
updateFeedbackModel,
|
||||
getAllFeedbackModel,
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
const prisma = require('../../../helpers/db/db_connection');
|
||||
|
||||
class FeedbackRepository {
|
||||
async create(feedbackData) {
|
||||
return prisma.feedback.create({
|
||||
data: {
|
||||
...feedbackData,
|
||||
created_at: new Date(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async findAll() {
|
||||
return prisma.feedback.findMany({
|
||||
orderBy: {
|
||||
created_at: 'desc',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async findAllWithFilters({ batch, tahun }) {
|
||||
const where = {};
|
||||
|
||||
if (batch) {
|
||||
where.batch = parseInt(batch);
|
||||
}
|
||||
|
||||
if (tahun) {
|
||||
where.tahun = parseInt(tahun);
|
||||
}
|
||||
|
||||
return prisma.feedback.findMany({
|
||||
where,
|
||||
orderBy: {
|
||||
created_at: 'desc',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async findById(id) {
|
||||
return prisma.feedback.findUnique({
|
||||
where: { id: parseInt(id) },
|
||||
});
|
||||
}
|
||||
|
||||
async updateById(id, feedbackData) {
|
||||
return prisma.feedback.update({
|
||||
where: { id: parseInt(id) },
|
||||
data: feedbackData,
|
||||
});
|
||||
}
|
||||
|
||||
async deleteById(id) {
|
||||
return prisma.feedback.delete({
|
||||
where: { id: parseInt(id) },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new FeedbackRepository();
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
const path = require('path');
|
||||
const feedbackRepository = require('../repositories/feedback.repository');
|
||||
const imageUploadHelper = require('../../../helpers/utils/imageUpload.helper');
|
||||
const { deleteFileIfExists } = require('../../../helpers/utils/fileHelper');
|
||||
const { data, error } = require('../../../helpers/utils/wrapper');
|
||||
const { NotFoundError } = require('../../../helpers/error');
|
||||
|
||||
class FeedbackService {
|
||||
async createFeedback(feedbackData, imageFile) {
|
||||
try {
|
||||
const imagePath = imageUploadHelper.uploadImage(imageFile);
|
||||
|
||||
const newFeedbackData = {
|
||||
...feedbackData,
|
||||
image_path: imagePath,
|
||||
};
|
||||
|
||||
const result = await feedbackRepository.create(newFeedbackData);
|
||||
return data(result);
|
||||
} catch (err) {
|
||||
if (imageFile?.filename) {
|
||||
try {
|
||||
await deleteFileIfExists(imageFile.filename);
|
||||
} catch (cleanupErr) {
|
||||
console.error('Failed to cleanup file:', cleanupErr);
|
||||
}
|
||||
}
|
||||
return error(err);
|
||||
}
|
||||
}
|
||||
|
||||
async getAllFeedback(query = {}) {
|
||||
try {
|
||||
const feedbackList = await feedbackRepository.findAllWithFilters(query);
|
||||
|
||||
if (feedbackList.length === 0) {
|
||||
return data([]);
|
||||
}
|
||||
|
||||
return data(feedbackList);
|
||||
} catch (err) {
|
||||
return error(err);
|
||||
}
|
||||
}
|
||||
|
||||
async getFeedbackById(id) {
|
||||
try {
|
||||
const feedback = await feedbackRepository.findById(id);
|
||||
|
||||
if (!feedback) {
|
||||
return error(new NotFoundError('Feedback tidak ditemukan'));
|
||||
}
|
||||
|
||||
return data(feedback);
|
||||
} catch (err) {
|
||||
return error(err);
|
||||
}
|
||||
}
|
||||
|
||||
async updateFeedback(id, feedbackData, imageFile) {
|
||||
let oldImagePath = null;
|
||||
let newImageUploaded = false;
|
||||
|
||||
try {
|
||||
const checkResult = await this.getFeedbackById(id);
|
||||
if (checkResult.err) {
|
||||
return checkResult;
|
||||
}
|
||||
|
||||
const existingFeedback = checkResult.data;
|
||||
|
||||
if (imageFile) {
|
||||
oldImagePath = existingFeedback.image_path;
|
||||
|
||||
feedbackData.image_path = imageUploadHelper.uploadImage(imageFile);
|
||||
newImageUploaded = true;
|
||||
|
||||
if (oldImagePath) {
|
||||
const oldFileName = path.basename(oldImagePath);
|
||||
await deleteFileIfExists(oldFileName);
|
||||
}
|
||||
}
|
||||
|
||||
const result = await feedbackRepository.updateById(id, feedbackData);
|
||||
return data(result);
|
||||
} catch (err) {
|
||||
if (newImageUploaded && imageFile?.filename) {
|
||||
try {
|
||||
await deleteFileIfExists(imageFile.filename);
|
||||
} catch (cleanupErr) {
|
||||
console.error('Failed to cleanup new file:', cleanupErr);
|
||||
}
|
||||
}
|
||||
return error(err);
|
||||
}
|
||||
}
|
||||
|
||||
async deleteFeedback(id) {
|
||||
try {
|
||||
const checkResult = await this.getFeedbackById(id);
|
||||
if (checkResult.err) {
|
||||
return checkResult;
|
||||
}
|
||||
|
||||
const feedback = checkResult.data;
|
||||
|
||||
if (feedback.image_path) {
|
||||
const fileName = path.basename(feedback.image_path);
|
||||
await deleteFileIfExists(fileName);
|
||||
}
|
||||
|
||||
const result = await feedbackRepository.deleteById(id);
|
||||
return data(result);
|
||||
} catch (err) {
|
||||
return error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new FeedbackService();
|
||||
Reference in New Issue
Block a user