diff --git a/controllers/sparepart.controller.js b/controllers/sparepart.controller.js index a1d5fe0..76f1d17 100644 --- a/controllers/sparepart.controller.js +++ b/controllers/sparepart.controller.js @@ -1,43 +1,56 @@ -const SparepartService = require('../services/sparepart.service'); -const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils'); +const SparepartService = require("../services/sparepart.service"); +const { + setResponse, + setResponsePaging, + checkValidate, +} = require("../helpers/utils"); + +const ExcelJS = require("exceljs"); 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 +62,137 @@ 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 ExcelJS = require("exceljs"); + const fs = require("fs"); + const path = require("path"); + + 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/routes/sparepart.route.js b/routes/sparepart.route.js index 27a34ce..e788514 100644 --- a/routes/sparepart.route.js +++ b/routes/sparepart.route.js @@ -1,19 +1,45 @@ -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 + ); + +router.get( + "/export", + verifyToken.verifyAccessToken, + SparepartController.exportExcel +); + +module.exports = router; 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