import dotenv from "dotenv"; import { printerModel } from "../../schemas/printer.schema.js"; import log4js from "log4js"; import { newAuditLog } from "../../util/index.js"; import mongoose from "mongoose"; import { auditLogModel } from "../../schemas/auditlog.schema.js"; dotenv.config(); const logger = log4js.getLogger("Printers"); logger.level = process.env.LOG_LEVEL; export const listPrintersRouteHandler = async ( req, res, page = 1, limit = 25, ) => { try { // Calculate the skip value based on the page number and limit const skip = (page - 1) * limit; // Fetch users with pagination const printers = await printerModel.find().skip(skip).limit(limit); logger.trace(`List of printers (Page ${page}, Limit ${limit}):`); res.send(printers); } catch (error) { logger.error("Error listing users:", error); res.status(500).send({ error: error }); } }; export const getPrinterRouteHandler = async (req, res) => { const id = req.params.id; try { // Fetch the printer with the given remote address const printer = await printerModel .findOne({ _id: id }) .populate("subJobs") .populate("currentJob") .populate({ path: "currentJob", populate: { path: "gcodeFile", }, }) .populate("currentSubJob") .populate({ path: "subJobs", populate: { path: "job", }, }) .populate("vendor") .populate({ path: "currentFilamentStock", populate: { path: "filament", },}) if (!printer) { logger.warn(`Printer with id ${id} not found.`); return res.status(404).send({ error: "Printer not found" }); } logger.trace(`Printer with id ${id}:`, printer); const auditLogs = await auditLogModel.find({ target: new mongoose.Types.ObjectId(id) }).populate('owner'); res.send({...printer._doc, auditLogs: auditLogs}); } catch (error) { logger.error("Error fetching printer:", error); res.status(500).send({ error: error.message }); } }; export const editPrinterRouteHandler = async (req, res) => { const id = req.params.id; try { // Fetch the printer first to get the old state const printer = await printerModel.findOne({ _id: id }); if (!printer) { logger.warn(`Printer not found with supplied id.`); return res.status(404).send({ error: "Printer not found." }); } try { const updateData = { updatedAt: new Date(), moonraker: req.body.moonraker, tags: req.body.tags, name: req.body.name, vendor: req.body.vendor.id, }; // Create audit log before updating await newAuditLog( printer.toObject(), updateData, id, 'Printer', req.user._id, 'User' ); const result = await printerModel.updateOne( { _id: id }, { $set: updateData }, ); if (result.nModified === 0) { logger.error("No printers updated."); res.status(500).send({ error: "No printers updated." }); } } catch (updateError) { logger.error("Error updating printer:", updateError); res.status(500).send({ error: updateError.message }); } res.send("OK"); } catch (fetchError) { logger.error("Error fetching printer:", fetchError); res.status(500).send({ error: fetchError.message }); } }; export const createPrinterRouteHandler = async (req, res) => { try { const { name, moonraker, tags = [], firmware = "n/a" } = req.body; // Validate required fields if (!name || !moonraker) { logger.warn("Missing required fields in printer creation request"); return res.status(400).send({ error: "Missing required fields. name and moonraker configuration are required.", }); } // Validate moonraker configuration if (!moonraker.host || !moonraker.port || !moonraker.protocol) { logger.warn( "Invalid moonraker configuration in printer creation request", ); return res.status(400).send({ error: "Invalid moonraker configuration. host, port, protocol are required.", }); } // Create new printer instance const newPrinter = new printerModel({ name, moonraker, tags, firmware, online: false, state: { type: "offline", }, }); // Save the printer const savedPrinter = await newPrinter.save(); // Create audit log for new printer await newAuditLog( {}, newPrinter.toObject(), savedPrinter._id, 'Printer', req.user._id, 'User' ); logger.info(`Created new printer: ${name}`); res.status(201).send(savedPrinter); } catch (error) { logger.error("Error creating printer:", error); res.status(500).send({ error: error.message }); } }; export const getPrinterStatsRouteHandler = async (req, res) => { try { const stats = await printerModel.aggregate([ { $group: { _id: "$state.type", count: { $sum: 1 } } } ]); // Transform the results into a more readable format const formattedStats = stats.reduce((acc, curr) => { acc[curr._id] = curr.count; return acc; }, {}); logger.trace("Printer stats by state:", formattedStats); res.send(formattedStats); } catch (error) { logger.error("Error fetching printer stats:", error); res.status(500).send({ error: error.message }); } };