diff --git a/controllers/notification_error_log.controller.js b/controllers/notification_error_log.controller.js new file mode 100644 index 0000000..64b6670 --- /dev/null +++ b/controllers/notification_error_log.controller.js @@ -0,0 +1,71 @@ +const NotificationErrorLogService = require('../services/notification_error_log.service'); +const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils'); +const { insertNotificationErrorLogSchema } = require('../validate/notification_error_log.schema'); + +class NotificationErrorLogController { + // Get all notification error logs + static async getAll(req, res) { + try { + const results = await NotificationErrorLogService.getAllNotificationErrorLog(); + const response = await setResponse(results, 'Notification Error Logs found') + + res.status(response.statusCode).json(response); + } catch (error) { + const response = await setResponse(error, error.message, error.statusCode || 500); + res.status(response.statusCode).json(response); + } + } + + // Get notification error log by ID + static async getById(req, res) { + try { + const { id } = req.params; + + const results = await NotificationErrorLogService.getNotificationErrorLogById(id); + const response = await setResponse(results, 'Notification Error Log found') + + res.status(response.statusCode).json(response); + } catch (error) { + const response = await setResponse(error, error.message, error.statusCode || 500); + res.status(response.statusCode).json(response); + } + } + + // Get notification error logs by notification_error_id + static async getByNotificationErrorId(req, res) { + try { + const { id } = req.params; + + const results = await NotificationErrorLogService.getNotificationErrorLogByNotificationErrorId(id); + const response = await setResponse(results, 'Notification Error Logs found') + + res.status(response.statusCode).json(response); + } catch (error) { + const response = await setResponse(error, error.message, error.statusCode || 500); + res.status(response.statusCode).json(response); + } + } + + // Create notification error log + static async create(req, res) { + try { + const { error, value } = await checkValidate(insertNotificationErrorLogSchema, req) + + if (error) { + return res.status(400).json(setResponse(error, 'Validation failed', 400)); + } + + value.created_by = req.user.user_id; + + const results = await NotificationErrorLogService.createNotificationErrorLog(value); + const response = await setResponse(results, 'Notification Error Log created successfully') + + return res.status(response.statusCode).json(response); + } catch (error) { + const response = await setResponse(error, error.message, error.statusCode || 500); + return res.status(response.statusCode).json(response); + } + } +} + +module.exports = NotificationErrorLogController; \ No newline at end of file diff --git a/controllers/sparepart.controller.js b/controllers/sparepart.controller.js index a1d5fe0..e0cf690 100644 --- a/controllers/sparepart.controller.js +++ b/controllers/sparepart.controller.js @@ -1,43 +1,58 @@ -const SparepartService = require('../services/sparepart.service'); -const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils'); +const ExcelJS = require("exceljs"); +const fs = require("fs"); +const path = require("path"); + +const SparepartService = require("../services/sparepart.service"); +const { + setResponse, + setResponsePaging, + checkValidate, +} = require("../helpers/utils"); const { insertSparepartSchema, updateSparepartSchema, -} = require('../validate/sparepart.schema'); +} = require("../validate/sparepart.schema"); class SparepartController { static async getAll(req, res) { const queryParams = req.query; const results = await SparepartService.getAllSparepart(queryParams); - const response = await setResponsePaging(queryParams, results, 'Sparepart found'); + const response = await setResponsePaging( + queryParams, + results, + "Sparepart found" + ); res.status(response.statusCode).json(response); } static async getById(req, res) { const { id } = req.params; const results = await SparepartService.getSparepartById(id); - const response = await setResponse(results, 'Sparepart found'); + const response = await setResponse(results, "Sparepart found"); res.status(response.statusCode).json(response); } - + static async create(req, res) { const { error, value } = await checkValidate(insertSparepartSchema, req); if (error) { - return res.status(400).json(setResponse(error, 'Validation failed', 400)); + return res.status(400).json(setResponse(error, "Validation failed", 400)); } try { if (req.file) { const file = req.file; - const ext = require('path').extname(file.originalname).toLowerCase(); + const ext = require("path").extname(file.originalname).toLowerCase(); const typeDoc = ext === ".pdf" ? "PDF" : "IMAGE"; const folder = typeDoc === "PDF" ? "pdf" : "images"; const pathDocument = `${folder}/${file.filename}`; value.sparepart_foto = pathDocument; } - value.userId = req.user.user_id + value.userId = req.user.user_id; const results = await SparepartService.createSparepart(value); - const response = await setResponse(results, 'Sparepart created successfully'); + const response = await setResponse( + results, + "Sparepart created successfully" + ); return res.status(response.statusCode).json(response); } catch (err) { const response = setResponse([], err.message, err.statusCode || 500); @@ -49,32 +64,133 @@ class SparepartController { const { id } = req.params; const { error, value } = await checkValidate(updateSparepartSchema, req); if (error) { - return res.status(400).json(setResponse(error, 'Validation failed', 400)); + return res.status(400).json(setResponse(error, "Validation failed", 400)); } try { if (req.file) { const file = req.file; - const ext = require('path').extname(file.originalname).toLowerCase(); + const ext = require("path").extname(file.originalname).toLowerCase(); const typeDoc = ext === ".pdf" ? "PDF" : "IMAGE"; const folder = typeDoc === "PDF" ? "pdf" : "images"; const pathDocument = `${folder}/${file.filename}`; value.sparepart_foto = pathDocument; } - value.userId = req.user.user_id + value.userId = req.user.user_id; const results = await SparepartService.updateSparepart(id, value); - const response = await setResponse(results, 'Sparepart updated successfully'); + const response = await setResponse( + results, + "Sparepart updated successfully" + ); res.status(response.statusCode).json(response); } catch (err) { const response = setResponse([], err.message, err.statusCode || 500); res.status(response.statusCode).json(response); } } - + + static async exportExcel(req, res) { + try { + const queryParams = req.query || {}; + queryParams.limit = null; + + const results = await SparepartService.getAllSparepart(queryParams); + + const workbook = new ExcelJS.Workbook(); + const worksheet = workbook.addWorksheet("Sparepart Data"); + + worksheet.columns = [ + { header: "Name Sparepart", key: "sparepart_name", width: 30 }, + { header: "Code Sparepart", key: "sparepart_code", width: 20 }, + { header: "QTY Sparepart", key: "sparepart_qty", width: 15 }, + { header: "Merk", key: "sparepart_merk", width: 20 }, + { header: "Model", key: "sparepart_model", width: 20 }, + { header: "Unit", key: "sparepart_unit", width: 10 }, + { header: "Stock", key: "sparepart_stok", width: 10 }, + { header: "Foto", key: "sparepart_foto", width: 25 }, + { header: "Item Type", key: "sparepart_item_type", width: 25 }, + { header: "Dibuat Pada", key: "created_at", width: 20 }, + ]; + + worksheet.addRows( + results.data.map((item) => ({ + sparepart_name: item.sparepart_name, + sparepart_code: item.sparepart_code, + sparepart_qty: item.sparepart_qty, + sparepart_merk: item.sparepart_merk, + sparepart_model: item.sparepart_model, + sparepart_unit: item.sparepart_unit, + sparepart_stok: item.sparepart_stok, + sparepart_foto: "", + sparepart_item_type: item.sparepart_item_type, + created_at: item.created_at, + })) + ); + + for (let i = 0; i < results.data.length; i++) { + const item = results.data[i]; + const rowNumber = i + 2; + + if (!item.sparepart_foto) continue; + + let foto = item.sparepart_foto.trim(); + + foto = foto.replace(/^images\//, ""); + + const fullPath = path.resolve(process.cwd(), "uploads", "images", foto); + + if (fs.existsSync(fullPath)) { + const ext = fullPath.split(".").pop().toLowerCase(); + + const imageId = workbook.addImage({ + filename: fullPath, + extension: ext, + }); + + worksheet.addImage(imageId, { + tl: { col: 7, row: rowNumber - 1 }, + ext: { width: 80, height: 80 }, + }); + + worksheet.getRow(rowNumber).height = 70; + } + } + + worksheet.getRow(1).eachCell((cell) => { + cell.font = { bold: true }; + cell.alignment = { horizontal: "center" }; + }); + + const buffer = await workbook.xlsx.writeBuffer(); + + res.setHeader( + "Content-Type", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + ); + res.setHeader( + "Content-Disposition", + "attachment; filename=sparepart_data.xlsx" + ); + + return res.send(buffer); + } catch (error) { + console.log("Export Excel Error:", error); + return res.status(500).json({ + message: error.message, + }); + } + } + static async delete(req, res) { const { id } = req.params; - const results = await SparepartService.deleteSparepart(id, req.user.user_id); - const response = await setResponse(results, 'Sparepart deleted successfully'); + const results = await SparepartService.deleteSparepart( + id, + req.user.user_id + ); + const response = await setResponse( + results, + "Sparepart deleted successfully" + ); res.status(response.statusCode).json(response); } } -module.exports = SparepartController; \ No newline at end of file +module.exports = SparepartController; diff --git a/db/brand_sparepart.db.js b/db/brand_sparepart.db.js new file mode 100644 index 0000000..850879d --- /dev/null +++ b/db/brand_sparepart.db.js @@ -0,0 +1,130 @@ +const pool = require("../config"); + +// Get spareparts by brand_id +const getSparepartsByBrandIdDb = async (brandId) => { + const queryText = ` + SELECT + s.sparepart_id, + s.sparepart_name, + s.sparepart_code, + s.sparepart_description, + s.sparepart_model, + s.sparepart_foto, + s.sparepart_item_type, + s.sparepart_qty, + s.sparepart_unit, + s.sparepart_merk, + s.sparepart_stok, + s.created_at, + s.updated_at + FROM brand_spareparts bs + JOIN m_sparepart s ON bs.sparepart_id = s.sparepart_id + WHERE bs.brand_id = $1 + AND s.deleted_at IS NULL + ORDER BY s.sparepart_name + `; + const result = await pool.query(queryText, [brandId]); + return result.recordset; +}; + +// Get brands by sparepart_id +const getBrandsBySparepartIdDb = async (sparepartId) => { + const queryText = ` + SELECT + b.brand_id, + b.brand_name, + b.brand_type, + b.brand_manufacture, + b.brand_model, + b.brand_code, + b.is_active, + b.created_at, + b.updated_at + FROM brand_spareparts bs + JOIN m_brands b ON bs.brand_id = b.brand_id + WHERE bs.sparepart_id = $1 + AND b.deleted_at IS NULL + ORDER BY b.brand_name + `; + const result = await pool.query(queryText, [sparepartId]); + return result.recordset; +}; + +// Insert brand-spareparts relationship +const insertBrandSparepartDb = async (brandId, sparepartId, createdBy) => { + const queryText = ` + INSERT INTO brand_spareparts (brand_id, sparepart_id, created_by, created_at) + VALUES ($1, $2, $3, CURRENT_TIMESTAMP) + `; + const result = await pool.query(queryText, [brandId, sparepartId, createdBy]); + return result.recordset; +}; + +// Insert multiple brand-spareparts relationships +const insertMultipleBrandSparepartsDb = async (brandId, sparepartIds, createdBy) => { + if (!sparepartIds || sparepartIds.length === 0) return []; + + const values = sparepartIds.map((_, index) => `($1, $${index + 2}, $${sparepartIds.length + 2}, CURRENT_TIMESTAMP)`).join(', '); + const queryText = ` + INSERT INTO brand_spareparts (brand_id, sparepart_id, created_by, created_at) + VALUES ${values} + `; + const params = [brandId, ...sparepartIds, createdBy]; + const result = await pool.query(queryText, params); + return result.recordset; +}; + +// Delete specific brand-sparepart relationship +const deleteBrandSparepartDb = async (brandId, sparepartId) => { + const queryText = ` + DELETE FROM brand_spareparts + WHERE brand_id = $1 AND sparepart_id = $2 + `; + const result = await pool.query(queryText, [brandId, sparepartId]); + return result.rowsAffected > 0; +}; + +// Delete all spareparts for a brand +const deleteAllBrandSparepartsDb = async (brandId) => { + const queryText = ` + DELETE FROM brand_spareparts + WHERE brand_id = $1 + `; + const result = await pool.query(queryText, [brandId]); + return result.rowsAffected > 0; +}; + +// Update brand-spareparts (replace all) +const updateBrandSparepartsDb = async (brandId, sparepartIds, updatedBy) => { + // Delete existing relationships + await deleteAllBrandSparepartsDb(brandId); + + // Insert new relationships + if (sparepartIds && sparepartIds.length > 0) { + return await insertMultipleBrandSparepartsDb(brandId, sparepartIds, updatedBy); + } + + return true; +}; + +// Check if brand-sparepart relationship exists +const checkBrandSparepartExistsDb = async (brandId, sparepartId) => { + const queryText = ` + SELECT 1 + FROM brand_spareparts + WHERE brand_id = $1 AND sparepart_id = $2 + `; + const result = await pool.query(queryText, [brandId, sparepartId]); + return result.recordset.length > 0; +}; + +module.exports = { + getSparepartsByBrandIdDb, + getBrandsBySparepartIdDb, + insertBrandSparepartDb, + insertMultipleBrandSparepartsDb, + deleteBrandSparepartDb, + deleteAllBrandSparepartsDb, + updateBrandSparepartsDb, + checkBrandSparepartExistsDb, +}; \ No newline at end of file diff --git a/db/notification_error_log.db.js b/db/notification_error_log.db.js index 55a4a45..1a8a0cf 100644 --- a/db/notification_error_log.db.js +++ b/db/notification_error_log.db.js @@ -1,23 +1,13 @@ const pool = require("../config"); -const createNotificationErrorLogDb = async (data) => { - const store = { - notification_error_id: data.notification_error_id, - contact_id: data.contact_id, - notification_error_log_description: data.notification_error_log_description, - created_by: data.created_by - }; - - const { query: queryText, values } = pool.buildDynamicInsert("notification_error_log", store); - const result = await pool.query(queryText, values); - return result.recordset[0]; -}; - const getAllNotificationErrorLogDb = async () => { const queryText = ` SELECT - a.* + a.*, + b.contact_name, + b.contact_type FROM notification_error_log a + LEFT JOIN contact b ON a.contact_id = b.contact_id WHERE a.deleted_at IS NULL ORDER BY a.notification_error_log_id DESC `; @@ -28,23 +18,37 @@ const getAllNotificationErrorLogDb = async () => { const getNotificationErrorLogByIdDb = async (id) => { const queryText = ` SELECT - a.* + a.*, + b.contact_name, + b.contact_type FROM notification_error_log a + LEFT JOIN contact b ON a.contact_id = b.contact_id WHERE a.notification_error_log_id = $1 AND a.deleted_at IS NULL `; const result = await pool.query(queryText, [id]); return result.recordset[0]; }; -const updateNotificationErrorLogDb = async (id, data) => { - const store = { ...data }; - const whereData = { - notification_error_log_id: id - }; +const getNotificationErrorLogByNotificationErrorIdDb = async (notificationErrorId) => { + const queryText = ` + SELECT + a.*, + b.contact_name, + b.contact_type + FROM notification_error_log a + LEFT JOIN contact b ON a.contact_id = b.contact_id + WHERE a.notification_error_id = $1 AND a.deleted_at IS NULL + ORDER BY a.created_at DESC + `; + const result = await pool.query(queryText, [notificationErrorId]); + return result.recordset; +}; - const { query: queryText, values } = pool.buildDynamicUpdate("notification_error_log", store, whereData); - await pool.query(`${queryText} AND deleted_at IS NULL`, values); - return true; +const createNotificationErrorLogDb = async (store) => { + const { query: queryText, values } = pool.buildDynamicInsert("notification_error_log", store); + const result = await pool.query(queryText, values); + const insertedId = result.recordset[0]?.inserted_id; + return insertedId ? await getNotificationErrorLogByIdDb(insertedId) : null; }; const deleteNotificationErrorLogDb = async (id, deletedBy) => { @@ -58,9 +62,9 @@ const deleteNotificationErrorLogDb = async (id, deletedBy) => { }; module.exports = { - createNotificationErrorLogDb, getAllNotificationErrorLogDb, getNotificationErrorLogByIdDb, - updateNotificationErrorLogDb, + getNotificationErrorLogByNotificationErrorIdDb, + createNotificationErrorLogDb, deleteNotificationErrorLogDb, }; \ No newline at end of file diff --git a/package.json b/package.json index 0f41f3d..ee2d46c 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "crypto": "^1.0.1", "crypto-js": "^4.2.0", "dotenv": "^8.2.0", + "exceljs": "^4.4.0", "express": "^4.18.2", "express-async-errors": "^3.1.1", "google-auth-library": "^8.7.0", diff --git a/routes/index.js b/routes/index.js index 1520898..ee0e37e 100644 --- a/routes/index.js +++ b/routes/index.js @@ -17,6 +17,7 @@ const contact = require("./contact.route") const notificationError = require("./notification_error.route") const notificationErrorSparepart = require("./notification_error_sparepart.route") const sparepart = require("./sparepart.route") +const notificationErrorLog = require("./notification_error_log.route") router.use("/auth", auth); router.use("/user", users); @@ -36,5 +37,6 @@ router.use("/contact", contact) router.use("/notification", notificationError) router.use("/notification-sparepart", notificationErrorSparepart) router.use("/sparepart", sparepart) +router.use("/notification-log", notificationErrorLog) module.exports = router; diff --git a/routes/notification_error_log.route.js b/routes/notification_error_log.route.js new file mode 100644 index 0000000..ce5e0f1 --- /dev/null +++ b/routes/notification_error_log.route.js @@ -0,0 +1,18 @@ +const express = require('express'); +const NotificationErrorLogController = require('../controllers/notification_error_log.controller'); +const verifyToken = require("../middleware/verifyToken") +const verifyAccess = require("../middleware/verifyAccess") + +const router = express.Router(); + +router.route("/") + .get(verifyToken.verifyAccessToken, NotificationErrorLogController.getAll) + .post(verifyToken.verifyAccessToken, verifyAccess(), NotificationErrorLogController.create); + +router.route("/:id") + .get(verifyToken.verifyAccessToken, NotificationErrorLogController.getById); + +router.route("/notification_error/:id") + .get(verifyToken.verifyAccessToken, NotificationErrorLogController.getByNotificationErrorId); + +module.exports = router; \ No newline at end of file diff --git a/routes/sparepart.route.js b/routes/sparepart.route.js index 27a34ce..c151538 100644 --- a/routes/sparepart.route.js +++ b/routes/sparepart.route.js @@ -1,19 +1,39 @@ -const express = require('express'); -const SparepartController = require('../controllers/sparepart.controller'); -const verifyToken = require('../middleware/verifyToken'); -const verifyAccess = require('../middleware/verifyAccess'); -const upload = require('../middleware/uploads'); +const express = require("express"); +const SparepartController = require("../controllers/sparepart.controller"); +const verifyToken = require("../middleware/verifyToken"); +const verifyAccess = require("../middleware/verifyAccess"); +const upload = require("../middleware/uploads"); const router = express.Router(); -router.route('/') - .get(verifyToken.verifyAccessToken, SparepartController.getAll) - .post(verifyToken.verifyAccessToken, verifyAccess(), upload.single('sparepart_foto') -, SparepartController.create); +router.get( + "/export", + verifyToken.verifyAccessToken, + SparepartController.exportExcel +); -router.route('/:id') +router + .route("/") + .get(verifyToken.verifyAccessToken, SparepartController.getAll) + .post( + verifyToken.verifyAccessToken, + verifyAccess(), + upload.single("sparepart_foto"), + SparepartController.create + ); + +router + .route("/:id") .get(verifyToken.verifyAccessToken, SparepartController.getById) - .put(verifyToken.verifyAccessToken, verifyAccess(), upload.single('sparepart_foto') -, SparepartController.update) - .delete(verifyToken.verifyAccessToken, verifyAccess(), SparepartController.delete); - -module.exports = router; \ No newline at end of file + .put( + verifyToken.verifyAccessToken, + verifyAccess(), + upload.single("sparepart_foto"), + SparepartController.update + ) + .delete( + verifyToken.verifyAccessToken, + verifyAccess(), + SparepartController.delete + ); + +module.exports = router; diff --git a/services/brand.service.js b/services/brand.service.js index 9bf28b2..883a62d 100644 --- a/services/brand.service.js +++ b/services/brand.service.js @@ -9,6 +9,13 @@ const { checkBrandNameExistsDb, } = require("../db/brand.db"); +const { + insertMultipleBrandSparepartsDb, + updateBrandSparepartsDb, + deleteAllBrandSparepartsDb, + getSparepartsByBrandIdDb, +} = require("../db/brand_sparepart.db"); + // Error code operations const { getErrorCodesByBrandIdDb, @@ -33,9 +40,21 @@ class BrandService { try { const results = await getAllBrandsDb(param); - results.data.map((element) => {}); + // Add spareparts data for each brand + const brandsWithSpareparts = await Promise.all( + results.data.map(async (brand) => { + const spareparts = await getSparepartsByBrandIdDb(brand.brand_id); + return { + ...brand, + spareparts: spareparts + }; + }) + ); - return results; + return { + ...results, + data: brandsWithSpareparts + }; } catch (error) { throw new ErrorHandler(error.statusCode, error.message); } @@ -47,6 +66,9 @@ class BrandService { const brand = await getBrandByIdDb(id); if (!brand) throw new ErrorHandler(404, "Brand not found"); + // Get spareparts for this brand + const spareparts = await getSparepartsByBrandIdDb(brand.brand_id); + const errorCodes = await getErrorCodesByBrandIdDb(brand.brand_id); const errorCodesWithSolutions = await Promise.all( @@ -95,6 +117,7 @@ class BrandService { return { ...brand, + spareparts: spareparts, error_code: errorCodesWithSolutions, }; } catch (error) { @@ -102,6 +125,7 @@ class BrandService { } } + // Create brand static async createBrandWithFullData(data) { try { @@ -154,6 +178,10 @@ class BrandService { const brandId = createdBrand.brand_id; + if (data.spareparts && Array.isArray(data.spareparts) && data.spareparts.length > 0) { + await insertMultipleBrandSparepartsDb(brandId, data.spareparts, data.created_by); + } + for (const errorCodeData of data.error_code) { const errorId = await createErrorCodeDb(brandId, { error_code: errorCodeData.error_code, @@ -184,7 +212,8 @@ class BrandService { } } - return await this.getBrandById(brandId); + const createdBrandWithSpareparts = await this.getBrandById(brandId); + return createdBrandWithSpareparts; } catch (error) { throw new ErrorHandler(500, `Bulk insert failed: ${error.message}`); } @@ -231,6 +260,10 @@ class BrandService { await updateBrandDb(existingBrand.brand_name, brandData); + if (data.spareparts !== undefined) { + await updateBrandSparepartsDb(existingBrand.brand_id, data.spareparts || [], data.updated_by); + } + if (data.error_code && Array.isArray(data.error_code)) { const existingErrorCodes = await getErrorCodesByBrandIdDb(id); const incomingErrorCodes = data.error_code.map((ec) => ec.error_code); @@ -350,7 +383,8 @@ class BrandService { } } - return await this.getBrandById(id); + const updatedBrandWithSpareparts = await this.getBrandById(id); + return updatedBrandWithSpareparts; } catch (error) { throw new ErrorHandler(500, `Update failed: ${error.message}`); } diff --git a/services/notification_error.service.js b/services/notification_error.service.js index 7d96f76..8ca77d5 100644 --- a/services/notification_error.service.js +++ b/services/notification_error.service.js @@ -11,12 +11,10 @@ const { getSolutionsByErrorCodeIdDb, } = require('../db/brand_code_solution.db'); -const { - getSparePartnsByErrorCodeIdDb, -} = require('../db/sparepart.db'); const { getAllNotificationErrorLogDb, + getNotificationErrorLogByNotificationErrorIdDb, } = require('../db/notification_error_log.db'); const { getFileUploadByPathDb } = require('../db/file_uploads.db'); @@ -73,20 +71,15 @@ class NotificationService { }) ); - // Get spareparts for this error code - const spareparts = (await getSparePartnsByErrorCodeIdDb(errorCode.error_code_id)) || []; - notification.error_code = { ...errorCode, - solution: solutionsWithDetails, - sparepart: spareparts + solution: solutionsWithDetails }; } } // Get activity logs for this notification - const activityLogs = (await getAllNotificationErrorLogDb()) || []; - const notificationLogs = activityLogs.filter(log => log.notification_error_id === parseInt(id)); + const notificationLogs = (await getNotificationErrorLogByNotificationErrorIdDb(id)) || []; notification.activity_logs = notificationLogs; diff --git a/services/notification_error_log.service.js b/services/notification_error_log.service.js new file mode 100644 index 0000000..45d9f58 --- /dev/null +++ b/services/notification_error_log.service.js @@ -0,0 +1,91 @@ +const { + getAllNotificationErrorLogDb, + getNotificationErrorLogByIdDb, + getNotificationErrorLogByNotificationErrorIdDb, + createNotificationErrorLogDb, + updateNotificationErrorLogDb, + deleteNotificationErrorLogDb +} = require('../db/notification_error_log.db'); + +const { ErrorHandler } = require('../helpers/error'); + +class NotificationErrorLogService { + // Get all Notification Error Logs + static async getAllNotificationErrorLog() { + try { + const results = await getAllNotificationErrorLogDb(); + + results.data.map(element => { + }); + + return results; + } catch (error) { + throw new ErrorHandler(error.statusCode, error.message); + } + } + + // Get Notification Error Log by ID + static async getNotificationErrorLogById(id) { + try { + const result = await getNotificationErrorLogByIdDb(id); + + if (!result) { + throw new ErrorHandler(404, 'Notification Error Log not found'); + } + + return result; + } catch (error) { + throw new ErrorHandler(error.statusCode, error.message); + } + } + + // Create Notification Error Log + static async createNotificationErrorLog(data) { + try { + if (!data || typeof data !== 'object') data = {}; + + const store = { + notification_error_id: data.notification_error_id, + contact_id: data.contact_id, + notification_error_log_description: data.notification_error_log_description, + created_by: data.created_by + }; + + const result = await createNotificationErrorLogDb(store); + + return result; + } catch (error) { + throw new ErrorHandler(error.statusCode, error.message); + } + } + + // Get Notification Error Log by notification_error_id + static async getNotificationErrorLogByNotificationErrorId(notificationErrorId) { + try { + const results = await getNotificationErrorLogByNotificationErrorIdDb(notificationErrorId); + + return results; + } catch (error) { + throw new ErrorHandler(error.statusCode, error.message); + } + } + + // Soft delete Notification Error Log + static async deleteNotificationErrorLog(id, userId) { + try { + const dataExist = await getNotificationErrorLogByIdDb(id); + + if (!dataExist) { + throw new ErrorHandler(404, 'Notification Error Log not found'); + } + + const result = await deleteNotificationErrorLogDb(id, userId); + + return result; + } catch (error) { + throw new ErrorHandler(error.statusCode, error.message); + } + } +} + +module.exports = NotificationErrorLogService; \ No newline at end of file diff --git a/uploads/images/img-e102e31c-2025-11-25_09-19-36.jpg b/uploads/images/img-e102e31c-2025-11-25_09-19-36.jpg deleted file mode 100644 index 320a119..0000000 Binary files a/uploads/images/img-e102e31c-2025-11-25_09-19-36.jpg and /dev/null differ diff --git a/uploads/images/img-e37c76ce-2025-11-25_09-20-26.jpg b/uploads/images/img-e37c76ce-2025-11-25_09-20-26.jpg deleted file mode 100644 index 320a119..0000000 Binary files a/uploads/images/img-e37c76ce-2025-11-25_09-20-26.jpg and /dev/null differ diff --git a/uploads/images/img-83d4f845-2025-11-24_16-42-41.jpg b/uploads/images/tesimage.jpg similarity index 100% rename from uploads/images/img-83d4f845-2025-11-24_16-42-41.jpg rename to uploads/images/tesimage.jpg diff --git a/validate/brand.schema.js b/validate/brand.schema.js index 3f5d99a..5d9d30f 100644 --- a/validate/brand.schema.js +++ b/validate/brand.schema.js @@ -10,6 +10,7 @@ const insertBrandSchema = Joi.object({ brand_model: Joi.string().max(100).optional().allow(""), is_active: Joi.boolean().required(), description: Joi.string().max(255).optional().allow(""), + spareparts: Joi.array().items(Joi.number().integer()).optional(), // Array of sparepart_id error_code: Joi.array() .items( Joi.object({ @@ -56,6 +57,7 @@ const updateBrandSchema = Joi.object({ brand_model: Joi.string().max(100).optional().allow(""), is_active: Joi.boolean().required(), description: Joi.string().max(255).optional().allow(""), + spareparts: Joi.array().items(Joi.number().integer()).optional(), // Array of sparepart_id error_code: Joi.array() .items( Joi.object({ diff --git a/validate/notification_error_log.schema.js b/validate/notification_error_log.schema.js new file mode 100644 index 0000000..ed740b4 --- /dev/null +++ b/validate/notification_error_log.schema.js @@ -0,0 +1,11 @@ +const Joi = require("joi"); + +const insertNotificationErrorLogSchema = Joi.object({ + notification_error_id: Joi.number().integer().required(), + contact_id: Joi.number().integer().required(), + notification_error_log_description: Joi.string().required() +}); + +module.exports = { + insertNotificationErrorLogSchema, +}; \ No newline at end of file diff --git a/validate/sparepart.schema.js b/validate/sparepart.schema.js index 8c7c617..be204c1 100644 --- a/validate/sparepart.schema.js +++ b/validate/sparepart.schema.js @@ -4,14 +4,14 @@ const Joi = require("joi"); // ======================== const insertSparepartSchema = Joi.object({ sparepart_name: Joi.string().max(255).required(), - sparepart_description: Joi.string().max(255).required(), - sparepart_model: Joi.string().max(255).required(), + sparepart_description: Joi.string().max(255).optional(), + sparepart_model: Joi.string().max(255).optional(), sparepart_foto: Joi.string().max(255).optional().allow(""), - sparepart_item_type: Joi.string().max(255).required(), + sparepart_item_type: Joi.string().max(255).optional(), sparepart_qty: Joi.number().integer().min(1), - sparepart_unit: Joi.string().max(255).required(), - sparepart_merk: Joi.string().max(255).required(), - sparepart_stok: Joi.string().max(255).required(), + sparepart_unit: Joi.string().max(255).optional(), + sparepart_merk: Joi.string().max(255).optional(), + sparepart_stok: Joi.string().max(255).optional(), }); // Update Validation @@ -22,9 +22,9 @@ const updateSparepartSchema = Joi.object({ sparepart_foto: Joi.string().max(255).optional().allow(''), sparepart_item_type: Joi.string().max(255).optional(), sparepart_qty: Joi.number().integer().min(1), - sparepart_unit: Joi.string().max(255).required(), - sparepart_merk: Joi.string().max(255).required(), - sparepart_stok: Joi.string().max(255).required(), + sparepart_unit: Joi.string().max(255).optional(), + sparepart_merk: Joi.string().max(255).optional(), + sparepart_stok: Joi.string().max(255).optional(), }); module.exports = { insertSparepartSchema,