import dotenv from 'dotenv'; import { printerModel } from '../../schemas/production/printer.schema.js'; import log4js from 'log4js'; import { newAuditLog, getAuditLogs } from '../../utils.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 getAuditLogs(id); 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 }); } };