From 4685cac5631de5b264ec16f4aac88c45a7ca3ba9 Mon Sep 17 00:00:00 2001 From: Tom Butcher Date: Fri, 5 Sep 2025 23:25:14 +0100 Subject: [PATCH] Refactor note and subjob management routes: Enhanced filtering logic and added new route handlers for CRUD operations. Updated services to utilize database functions for improved data handling and error management. Implemented property-based listing for notes and subjobs, ensuring better data retrieval and organization. --- src/routes/management/notetypes.js | 58 +++--- src/routes/misc/notes.js | 51 +++-- src/routes/production/subjobs.js | 36 ++-- src/services/management/notetypes.js | 240 +++++++++++----------- src/services/misc/notes.js | 292 +++++++++++---------------- src/services/production/subjobs.js | 155 ++++++-------- 6 files changed, 378 insertions(+), 454 deletions(-) diff --git a/src/routes/management/notetypes.js b/src/routes/management/notetypes.js index 50fac4c..2bef138 100644 --- a/src/routes/management/notetypes.js +++ b/src/routes/management/notetypes.js @@ -1,42 +1,50 @@ import express from 'express'; import { isAuthenticated } from '../../keycloak.js'; +import { getFilter, convertPropertiesString } from '../../utils.js'; + +const router = express.Router(); import { listNoteTypesRouteHandler, getNoteTypeRouteHandler, editNoteTypeRouteHandler, newNoteTypeRouteHandler, + deleteNoteTypeRouteHandler, + listNoteTypesByPropertiesRouteHandler, } from '../../services/management/notetypes.js'; -import { parseFilter } from '../../utils.js'; -const router = express.Router(); - -// List note types -router.get('/', isAuthenticated, async (req, res) => { +// list of note types +router.get('/', isAuthenticated, (req, res) => { const { page, limit, property, search, sort, order } = req.query; - - const allowedFilters = ['name', 'active', 'color', '_id']; - - var filter = {}; - - for (const [key, value] of Object.entries(req.query)) { - for (var i = 0; i < allowedFilters.length; i++) { - if (key == allowedFilters[i]) { - const parsedFilter = parseFilter(key, value); - filter = { ...filter, ...parsedFilter }; - } - } - } - + const allowedFilters = ['_id', 'name', 'active', 'color']; + const filter = getFilter(req.query, allowedFilters); listNoteTypesRouteHandler(req, res, page, limit, property, filter, search, sort, order); }); -// Get single note type -router.get('/:id', isAuthenticated, getNoteTypeRouteHandler); +router.get('/properties', isAuthenticated, (req, res) => { + let properties = convertPropertiesString(req.query.properties); + const allowedFilters = ['active', 'color']; + const filter = getFilter(req.query, allowedFilters, false); + var masterFilter = {}; + if (req.query.masterFilter) { + masterFilter = JSON.parse(req.query.masterFilter); + } + listNoteTypesByPropertiesRouteHandler(req, res, properties, filter, masterFilter); +}); -// Edit note type -router.put('/:id', isAuthenticated, editNoteTypeRouteHandler); +router.post('/', isAuthenticated, (req, res) => { + newNoteTypeRouteHandler(req, res); +}); -// Create new note type -router.post('/', isAuthenticated, newNoteTypeRouteHandler); +router.get('/:id', isAuthenticated, (req, res) => { + getNoteTypeRouteHandler(req, res); +}); + +router.put('/:id', isAuthenticated, async (req, res) => { + editNoteTypeRouteHandler(req, res); +}); + +router.delete('/:id', isAuthenticated, async (req, res) => { + deleteNoteTypeRouteHandler(req, res); +}); export default router; diff --git a/src/routes/misc/notes.js b/src/routes/misc/notes.js index 0c77892..e9090af 100644 --- a/src/routes/misc/notes.js +++ b/src/routes/misc/notes.js @@ -7,40 +7,39 @@ import { newNoteRouteHandler, deleteNoteRouteHandler, } from '../../services/misc/notes.js'; -import { parseFilter } from '../../utils.js'; +import { getFilter } from '../../utils.js'; const router = express.Router(); -// List notes -router.get('/', isAuthenticated, async (req, res) => { - const { page, limit, property, sort, order } = req.query; - - const allowedFilters = ['parent', 'user._id']; - - var filter = {}; - - for (const [key, value] of Object.entries(req.query)) { - for (var i = 0; i < allowedFilters.length; i++) { - if (key == allowedFilters[i]) { - const filterObject = parseFilter(key, value); - filter = { ...filter, ...filterObject }; - } - } - } - - listNotesRouteHandler(req, res, page, limit, property, filter, '', sort, order); +// list of notes +router.get('/', isAuthenticated, (req, res) => { + const { page, limit, property, search, sort, order } = req.query; + const allowedFilters = ['parent._id']; + const filter = getFilter(req.query, allowedFilters); + listNotesRouteHandler(req, res, page, limit, property, filter, search, sort, order); }); -// Get single note -router.get('/:id', isAuthenticated, getNoteRouteHandler); +router.get('/properties', isAuthenticated, (req, res) => { + let properties = convertPropertiesString(req.query.properties); + const allowedFilters = ['parent']; + const filter = getFilter(req.query, allowedFilters, false); + listNotesByPropertiesRouteHandler(req, res, properties, filter); +}); -// Edit note -router.put('/:id', isAuthenticated, editNoteRouteHandler); +// create new note +router.post('/', isAuthenticated, (req, res) => { + newNoteRouteHandler(req, res); +}); +router.get('/:id', isAuthenticated, (req, res) => { + getNoteRouteHandler(req, res); +}); + +// update note info +router.put('/:id', isAuthenticated, async (req, res) => { + editNoteRouteHandler(req, res); +}); // Delete note router.delete('/:id', isAuthenticated, deleteNoteRouteHandler); -// Create new note -router.post('/', isAuthenticated, newNoteRouteHandler); - export default router; diff --git a/src/routes/production/subjobs.js b/src/routes/production/subjobs.js index 3ad04db..a4a2b5c 100644 --- a/src/routes/production/subjobs.js +++ b/src/routes/production/subjobs.js @@ -2,26 +2,30 @@ import express from 'express'; import { isAuthenticated } from '../../keycloak.js'; const router = express.Router(); -import { listSubJobsRouteHandler } from '../../services/production/subjobs.js'; -import { parseFilter } from '../../utils.js'; +import { + listSubJobsRouteHandler, + listSubJobsByPropertiesRouteHandler, + getSubJobRouteHandler, +} from '../../services/production/subjobs.js'; +import { getFilter } from '../../utils.js'; -// list of print subjobs +// list of sub jobs router.get('/', isAuthenticated, (req, res) => { const { page, limit, property, search, sort, order } = req.query; - const allowedFilters = ['_id', 'job._id']; - - var filter = {}; - - for (const [key, value] of Object.entries(req.query)) { - for (var i = 0; i < allowedFilters.length; i++) { - if (key == allowedFilters[i]) { - const parsedFilter = parseFilter(key, value); - filter = { ...filter, ...parsedFilter }; - } - } - } - + const allowedFilters = ['_id', 'job._id', 'printer._id']; + const filter = getFilter(req.query, allowedFilters); listSubJobsRouteHandler(req, res, page, limit, property, filter, search, sort, order); }); +router.get('/properties', isAuthenticated, (req, res) => { + let properties = convertPropertiesString(req.query.properties); + const allowedFilters = ['job']; + const filter = getFilter(req.query, allowedFilters, false); + listSubJobsByPropertiesRouteHandler(req, res, properties, filter); +}); + +router.get('/:id', isAuthenticated, (req, res) => { + getSubJobRouteHandler(req, res); +}); + export default router; diff --git a/src/services/management/notetypes.js b/src/services/management/notetypes.js index 9a4d707..bcfa900 100644 --- a/src/services/management/notetypes.js +++ b/src/services/management/notetypes.js @@ -2,11 +2,17 @@ import dotenv from 'dotenv'; import { noteTypeModel } from '../../schemas/management/notetype.schema.js'; import log4js from 'log4js'; import mongoose from 'mongoose'; -import { distributeUpdate, newAuditLog, editAuditLog, distributeNew } from '../../utils.js'; - +import { + deleteObject, + listObjects, + getObject, + editObject, + newObject, + listObjectsByProperties, +} from '../../database/database.js'; dotenv.config(); -const logger = log4js.getLogger('NoteTypes'); +const logger = log4js.getLogger('Note Types'); logger.level = process.env.LOG_LEVEL; export const listNoteTypesRouteHandler = async ( @@ -20,135 +26,135 @@ export const listNoteTypesRouteHandler = async ( sort = '', order = 'ascend' ) => { - try { - const skip = (page - 1) * limit; - let noteTypes; - let aggregateCommand = []; + const result = await listObjects({ + model: noteTypeModel, + page, + limit, + property, + filter, + search, + sort, + order, + }); - if (search) { - // Add a text search match stage for name and brand fields - aggregateCommand.push({ - $match: { - $text: { - $search: search, - }, - }, - }); - } - - if (filter != {}) { - // use filtering if present - aggregateCommand.push({ $match: filter }); - } - - if (property != '') { - aggregateCommand.push({ $group: { _id: `$${property}` } }); - aggregateCommand.push({ $project: { _id: 0, [property]: '$_id' } }); - } - - // Add sorting if sort parameter is provided - if (sort) { - const sortOrder = order === 'descend' ? -1 : 1; - aggregateCommand.push({ $sort: { [sort]: sortOrder } }); - } - - aggregateCommand.push({ $skip: skip }); - aggregateCommand.push({ $limit: Number(limit) }); - - console.log(aggregateCommand); - - noteTypes = await noteTypeModel.aggregate(aggregateCommand); - - logger.trace( - `List of note types (Page ${page}, Limit ${limit}, Property ${property}):`, - noteTypes - ); - res.send(noteTypes); - } catch (error) { - logger.error('Error listing note types:', error); - res.status(500).send({ error: error }); + if (result?.error) { + logger.error('Error listing note types.'); + res.status(result.code).send(result); + return; } + + logger.debug(`List of note types (Page ${page}, Limit ${limit}). Count: ${result.length}`); + res.send(result); +}; + +export const listNoteTypesByPropertiesRouteHandler = async ( + req, + res, + properties = '', + filter = {}, + masterFilter = {} +) => { + const result = await listObjectsByProperties({ + model: noteTypeModel, + properties, + filter, + masterFilter, + }); + + if (result?.error) { + logger.error('Error listing note types.'); + res.status(result.code).send(result); + return; + } + + logger.debug(`List of note types. Count: ${result.length}`); + res.send(result); }; export const getNoteTypeRouteHandler = async (req, res) => { - try { - const id = new mongoose.Types.ObjectId(req.params.id); - const noteType = await noteTypeModel.findOne({ - _id: id, - }); - - if (!noteType) { - logger.warn(`Note type not found with supplied id.`); - return res.status(404).send({ error: 'Note type not found.' }); - } - - logger.trace(`Note type with ID: ${id}:`, noteType); - - res.send({ ...noteType._doc }); - } catch (error) { - logger.error('Error fetching note type:', error); - res.status(500).send({ error: error.message }); + const id = req.params.id; + const result = await getObject({ + model: noteTypeModel, + id, + }); + if (result?.error) { + logger.warn(`Note Type not found with supplied id.`); + return res.status(result.code).send(result); } + logger.debug(`Retreived note type with ID: ${id}`); + res.send(result); }; export const editNoteTypeRouteHandler = async (req, res) => { - try { - const id = new mongoose.Types.ObjectId(req.params.id); - const noteType = await noteTypeModel.findOne({ _id: id }); + // Get ID from params + const id = new mongoose.Types.ObjectId(req.params.id); - if (!noteType) { - logger.warn(`Note type not found with supplied id.`); - return res.status(404).send({ error: 'Note type not found.' }); - } + logger.trace(`Note Type with ID: ${id}`); - logger.trace(`Note type with ID: ${id}:`, noteType); + const updateData = { + updatedAt: new Date(), + name: req.body.name, + color: req.body.color, + active: req.body.active, + }; + // Create audit log before updating + const result = await editObject({ + model: noteTypeModel, + id, + updateData, + user: req.user, + }); - try { - const updateData = { - updatedAt: new Date(), - name: req.body.name, - color: req.body.color, - active: req.body.active, - }; - - // Create audit log before updating - await editAuditLog(noteType.toObject(), updateData, id, 'noteType', req.user._id, 'user'); - await distributeUpdate(updateData, id, 'noteType'); - - const result = await noteTypeModel.updateOne({ _id: id }, { $set: updateData }); - if (result.nModified === 0) { - logger.error('No note type updated.'); - res.status(500).send({ error: 'No note types updated.' }); - } - } catch (updateError) { - logger.error('Error updating note type:', updateError); - res.status(500).send({ error: updateError.message }); - } - res.send('OK'); - } catch (fetchError) { - logger.error('Error fetching note type:', fetchError); - res.status(500).send({ error: fetchError.message }); + if (result.error) { + logger.error('Error editing note type:', result.error); + res.status(result).send(result); + return; } + + logger.debug(`Edited note type with ID: ${id}`); + + res.send(result); }; export const newNoteTypeRouteHandler = async (req, res) => { - try { - let { ...newNoteType } = req.body; - newNoteType = { ...newNoteType, createdAt: new Date(), updatedAt: new Date() }; - - const result = await noteTypeModel.create(newNoteType); - if (result.nCreated === 0) { - logger.error('No note type created.'); - res.status(500).send({ error: 'No note type created.' }); - } - - // Create audit log for new note type - await newAuditLog(newNoteType, result._id, 'noteType', req.user); - await distributeNew(result._id, 'filament'); - - res.status(200).send({ status: 'ok' }); - } catch (updateError) { - logger.error('Error creating note type:', updateError); - res.status(500).send({ error: updateError.message }); + const newData = { + updatedAt: new Date(), + name: req.body.name, + color: req.body.color, + active: req.body.active, + }; + const result = await newObject({ + model: noteTypeModel, + newData, + user: req.user, + }); + if (result.error) { + logger.error('No note type created:', result.error); + return res.status(result.code).send(result); } + + logger.debug(`New note type with ID: ${result._id}`); + + res.send(result); +}; + +export const deleteNoteTypeRouteHandler = async (req, res) => { + // Get ID from params + const id = new mongoose.Types.ObjectId(req.params.id); + + logger.trace(`Note Type with ID: ${id}`); + + const result = await deleteObject({ + model: noteTypeModel, + id, + user: req.user, + }); + if (result.error) { + logger.error('No note type deleted:', result.error); + return res.status(result.code).send(result); + } + + logger.debug(`Deleted note type with ID: ${result._id}`); + + res.send(result); }; diff --git a/src/services/misc/notes.js b/src/services/misc/notes.js index a5b11f8..f3c1bbd 100644 --- a/src/services/misc/notes.js +++ b/src/services/misc/notes.js @@ -1,14 +1,16 @@ import dotenv from 'dotenv'; import { noteModel } from '../../schemas/misc/note.schema.js'; import log4js from 'log4js'; -import mongoose from 'mongoose'; import { - deleteAuditLog, - editAuditLog, - expandObjectIds, - flatternObjectIds, - newAuditLog, -} from '../../utils.js'; + deleteObject, + editObject, + getObject, + listObjects, + listObjectsByProperties, + newObject, + recursivelyDeleteChildObjects, +} from '../../database/database.js'; +import mongoose from 'mongoose'; dotenv.config(); @@ -21,197 +23,141 @@ export const listNotesRouteHandler = async ( page = 1, limit = 25, property = '', - filter = {} + filter = {}, + search = '', + sort = '', + order = 'ascend' ) => { - try { - const skip = (page - 1) * limit; - let notes; - let aggregateCommand = []; + const result = await listObjects({ + model: noteModel, + page, + limit, + property, + filter, + search, + sort, + order, + populate: ['noteType', 'user'], + }); - if (Object.keys(filter).length > 0) { - aggregateCommand.push({ $match: filter }); - } - - aggregateCommand.push({ - $lookup: { - from: 'users', // The collection name (usually lowercase plural) - localField: 'user', // The field in your current model - foreignField: '_id', // The field in the users collection - as: 'user', // The output field name - }, - }); - aggregateCommand.push({ $unwind: '$user' }); - aggregateCommand.push({ - $lookup: { - from: 'notetypes', // The collection name (usually lowercase plural) - localField: 'noteType', // The field in your current model - foreignField: '_id', // The field in the users collection - as: 'noteType', // The output field name - }, - }); - aggregateCommand.push({ $unwind: '$noteType' }); - aggregateCommand.push({ - $project: { - name: 1, - _id: 1, - createdAt: 1, - updatedAt: 1, - 'noteType._id': 1, - 'noteType.name': 1, - 'noteType.color': 1, - 'user._id': 1, - 'user.name': 1, - content: 1, - parent: 1, - }, - }); - - aggregateCommand.push({ $skip: skip }); - aggregateCommand.push({ $limit: Number(limit) }); - - notes = await noteModel.aggregate(aggregateCommand); - - logger.trace(`List of notes (Page ${page}, Limit ${limit}, Property ${property}):`, notes); - res.send(notes); - } catch (error) { - logger.error('Error listing notes:', error); - res.status(500).send({ error: error }); + if (result?.error) { + logger.error('Error listing notes.'); + res.status(result.code).send(result); + return; } + + logger.debug(`List of notes (Page ${page}, Limit ${limit}). Count: ${result.length}`); + res.send(result); +}; + +export const listNotesByPropertiesRouteHandler = async (req, res, properties = '', filter = {}) => { + const result = await listObjectsByProperties({ + model: noteModel, + properties, + filter, + populate: ['noteType', 'user'], + }); + + if (result?.error) { + logger.error('Error listing notes.'); + res.status(result.code).send(result); + return; + } + + logger.debug(`List of notes. Count: ${result.length}`); + res.send(result); }; export const getNoteRouteHandler = async (req, res) => { - try { - const id = new mongoose.Types.ObjectId(req.params.id); - const note = await noteModel.findOne({ - _id: id, - }); - - if (!note) { - logger.warn(`Note not found with supplied id.`); - return res.status(404).send({ error: 'Note not found.' }); - } - - logger.trace(`Note with ID: ${id}:`, note); - - res.send({ ...note._doc }); - } catch (error) { - logger.error('Error fetching note:', error); - res.status(500).send({ error: error.message }); + const id = req.params.id; + const result = await getObject({ + model: noteModel, + id, + populate: ['noteType', 'user'], + }); + if (result?.error) { + logger.warn(`Note not found with supplied id.`); + return res.status(result.code).send(result); } + logger.debug(`Retreived note with ID: ${id}`); + res.send(result); }; export const editNoteRouteHandler = async (req, res) => { - try { - const id = new mongoose.Types.ObjectId(req.params.id); - const note = await noteModel.findOne({ _id: id }); + // Get ID from params + const id = new mongoose.Types.ObjectId(req.params.id); - if (!note) { - logger.warn(`Note not found with supplied id.`); - return res.status(404).send({ error: 'Note not found.' }); - } + logger.trace(`Note with ID: ${id}`); - logger.trace(`Note with ID: ${id}:`, note); + const updateData = { + updatedAt: new Date(), + content: req.body.content, + noteType: req.body.noteType, + }; + // Create audit log before updating + const result = await editObject({ + model: noteModel, + id, + updateData, + user: req.user, + }); - try { - const updateData = { - updatedAt: new Date(), - name: req.body.name, - color: req.body.color, - isActive: req.body.isActive, - }; - - const result = await noteModel.updateOne({ _id: id }, { $set: updateData }); - if (result.nModified === 0) { - logger.error('No note updated.'); - res.status(500).send({ error: 'No notes updated.' }); - } - - await editAuditLog(note.toObject(), updateData, id, 'note', req.user); - } catch (updateError) { - logger.error('Error updating note:', updateError); - res.status(500).send({ error: updateError.message }); - } - res.send('OK'); - } catch (fetchError) { - logger.error('Error fetching note:', fetchError); - res.status(500).send({ error: fetchError.message }); + if (result.error) { + logger.error('Error editing note:', result.error); + res.status(result).send(result); + return; } + + logger.debug(`Edited note with ID: ${id}`); + + res.send(result); }; export const newNoteRouteHandler = async (req, res) => { - try { - let { ...newNote } = req.body; - newNote = { ...newNote, createdAt: new Date(), updatedAt: new Date(), user: req.user }; - - const result = await noteModel.create(flatternObjectIds(newNote)); - if (result.nCreated === 0) { - logger.error('No note created.'); - res.status(500).send({ error: 'No note created.' }); - } - - await newAuditLog(expandObjectIds(newNote), result._id, 'note', req.user); - - res.status(200).send({ status: 'ok' }); - } catch (updateError) { - logger.error('Error creating note:', updateError); - res.status(500).send({ error: updateError.message }); + const newData = { + updatedAt: new Date(), + content: req.body.content, + noteType: req.body.noteType, + parent: req.body.parent, + parentType: req.body.parentType, + user: req.user, + }; + const result = await newObject({ + model: noteModel, + newData, + user: req.user, + }); + if (result.error) { + logger.error('No note created:', result.error); + return res.status(result.code).send(result); } + + logger.debug(`New note with ID: ${result._id}`); + + res.send(result); }; export const deleteNoteRouteHandler = async (req, res) => { - try { - const id = new mongoose.Types.ObjectId(req.params.id); - const note = await noteModel.findOne({ _id: id }); + // Get ID from params + const id = req.params.id; - if (!note) { - logger.warn(`Note not found with supplied id.`); - return res.status(404).send({ error: 'Note not found.' }); - } + logger.trace(`Delete note with ID: ${id}`); - // Check if the current user owns this note - if (note.user.toString() !== req.user._id.toString()) { - logger.warn(`User ${req.user._id} attempted to delete note ${id} owned by user ${note.user}`); - return res.status(403).send({ error: 'You can only delete your own notes.' }); - } + // Recursively find and delete all child notes + const result = await recursivelyDeleteChildObjects({ model: noteModel, id, user: req.user }); - logger.trace(`Deleting note with ID: ${id} and all its children`); - - // Recursively find and delete all child notes - const deletedNoteIds = await recursivelyDeleteNotes(id, req.user); - - logger.info(`Successfully deleted note ${id} and ${deletedNoteIds.length - 1} child notes`); - res.send({ - status: 'ok', - deletedNoteIds: deletedNoteIds, - message: `Deleted ${deletedNoteIds.length} notes`, - }); - } catch (error) { - logger.error('Error deleting note:', error); - res.status(500).send({ error: error.message }); - } -}; - -// Helper function to recursively delete notes and their children -const recursivelyDeleteNotes = async (noteId, user) => { - const deletedIds = []; - - // Find all notes that have this note as their parent - const childNotes = await noteModel.find({ parent: noteId }); - - // Recursively delete all children first - for (const childNote of childNotes) { - const childDeletedIds = await recursivelyDeleteNotes(childNote._id, user); - deletedIds.push(...childDeletedIds); + if (result?.length <= 0) { + logger.error('No notes deleted'); + return res.status(404).send(result); } - // Delete the current note + if (result?.error) { + logger.error('No note deleted:', result.error); + return res.status(result.code).send(result); + } - const note = await noteModel.findOne({ _id: noteId }).populate('user').populate('parent'); - - await deleteAuditLog(expandObjectIds(note.toObject()), noteId, 'note', user); - - await noteModel.deleteOne({ _id: noteId }); - deletedIds.push(noteId); - - return deletedIds; + logger.info(`Successfully deleted note ${id} and ${result.length - 1} child notes`); + res.send({ + status: 'ok', + }); }; diff --git a/src/services/production/subjobs.js b/src/services/production/subjobs.js index ce550d4..27c2f54 100644 --- a/src/services/production/subjobs.js +++ b/src/services/production/subjobs.js @@ -1,9 +1,10 @@ import dotenv from 'dotenv'; import { subJobModel } from '../../schemas/production/subjob.schema.js'; import log4js from 'log4js'; +import { getObject, listObjects, listObjectsByProperties } from '../../database/database.js'; dotenv.config(); -const logger = log4js.getLogger('SubJobs'); +const logger = log4js.getLogger('Sub Jobs'); logger.level = process.env.LOG_LEVEL; export const listSubJobsRouteHandler = async ( @@ -17,102 +18,62 @@ export const listSubJobsRouteHandler = async ( sort = '', order = 'ascend' ) => { - try { - // Calculate the skip value based on the page number and limit - const skip = (page - 1) * limit; + const result = await listObjects({ + model: subJobModel, + page, + limit, + property, + filter, + search, + sort, + order, + populate: ['printer'], + }); - let subJobs; - let aggregateCommand = []; - - if (search) { - // Add a text search match stage for name and other searchable fields - aggregateCommand.push({ - $match: { - $text: { - $search: search, - }, - }, - }); - } - // Lookup printer - aggregateCommand.push({ - $lookup: { - from: 'printers', // The name of the Printer collection - localField: 'printer', - foreignField: '_id', - as: 'printer', - }, - }); - - // Lookup job - aggregateCommand.push({ - $lookup: { - from: 'jobs', // The name of the Printer collection - localField: 'job', - foreignField: '_id', - as: 'job', - }, - }); - - aggregateCommand.push({ - $unwind: { - path: '$printer', - preserveNullAndEmptyArrays: true, // Keep documents without a matching filament - }, - }); - - aggregateCommand.push({ - $unwind: { - path: '$job', - preserveNullAndEmptyArrays: true, // Keep documents without a matching filament - }, - }); - - if (filter != {}) { - // use filtering if present - aggregateCommand.push({ $match: filter }); - } - - if (property != '') { - aggregateCommand.push({ $group: { _id: `$${property}` } }); // group all same properties - aggregateCommand.push({ $project: { _id: 0, [property]: '$_id' } }); // rename _id to the property name - } else { - aggregateCommand.push({ - $project: { - state: 1, - _id: 1, - createdAt: 1, - startedAt: 1, - 'printer._id': 1, - 'job._id': 1, - 'printer.name': 1, - }, - }); - } - - // Add sorting if sort parameter is provided - if (sort) { - const sortOrder = order === 'descend' ? -1 : 1; - aggregateCommand.push({ $sort: { [sort]: sortOrder } }); - } else { - // Default sorting by createdAt descending - aggregateCommand.push({ $sort: { createdAt: -1 } }); - } - - aggregateCommand.push({ $skip: skip }); - aggregateCommand.push({ $limit: Number(limit) }); - - console.log(aggregateCommand); - - subJobs = await subJobModel.aggregate(aggregateCommand); - - logger.trace( - `List of print subJobs (Page ${page}, Limit ${limit}, Property ${property}, Sort ${sort}, Order ${order}):`, - subJobs - ); - res.send(subJobs); - } catch (error) { - logger.error('Error listing print subJobs:', error); - res.status(500).send({ error: error }); + if (result?.error) { + logger.error('Error listing sub jobs.'); + res.status(result.code).send(result); + return; } + + logger.debug(`List of sub jobs (Page ${page}, Limit ${limit}). Count: ${result.length}`); + res.send(result); +}; + +export const listSubJobsByPropertiesRouteHandler = async ( + req, + res, + properties = '', + filter = {}, + masterFilter = {} +) => { + const result = await listObjectsByProperties({ + model: subJobModel, + properties, + filter, + masterFilter, + }); + + if (result?.error) { + logger.error('Error listing sub jobs.'); + res.status(result.code).send(result); + return; + } + + logger.debug(`List of sub jobs. Count: ${result.length}`); + res.send(result); +}; + +export const getSubJobRouteHandler = async (req, res) => { + const id = req.params.id; + const result = await getObject({ + model: subJobModel, + id, + }); + if (result?.error) { + logger.warn(`Sub job not found with supplied id.`); + return res.status(result.code).send(result); + } + logger.debug(`Retreived sub job with ID: ${id}`); + res.send(result); };