194 lines
5.6 KiB
JavaScript

import dotenv from "dotenv";
import mongoose from "mongoose";
import { jobModel } from "../../schemas/production/job.schema.js";
import { subJobModel } from "../../schemas/production/subjob.schema.js";
import { noteModel } from "../../schemas/misc/note.schema.js";
import jwt from "jsonwebtoken";
import log4js from "log4js";
import { auditLogModel } from "../../schemas/management/auditlog.schema.js";
dotenv.config();
const logger = log4js.getLogger("Jobs");
logger.level = process.env.LOG_LEVEL;
export const listJobsRouteHandler = 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 jobs = await jobModel
.find()
.sort({ createdAt: -1 })
.skip(skip)
.limit(limit)
.populate("subJobs", "state")
.populate("gcodeFile", "name");
logger.trace(`List of print jobs (Page ${page}, Limit ${limit}):`);
res.send(jobs);
} catch (error) {
logger.error("Error listing print jobs:", error);
res.status(500).send({ error: error });
}
};
export const getJobRouteHandler = async (req, res) => {
try {
// Get ID from params
const id = new mongoose.Types.ObjectId(req.params.id);
// Fetch the job with the given remote address
const job = await jobModel
.findOne({
_id: id,
})
.populate("printers", "name state")
.populate("gcodeFile")
.populate("subJobs")
.populate("notes");
if (!job) {
logger.warn(`Job not found with supplied id.`);
return res.status(404).send({ error: "Print job not found." });
}
logger.trace(`Job with ID: ${id}:`, job);
const targetIds = [id, ...job.subJobs.map(subJob => subJob._id)];
const auditLogs = await auditLogModel.find({
target: { $in: targetIds.map(id => new mongoose.Types.ObjectId(id)) }
}).populate('owner');
res.send({...job._doc, auditLogs: auditLogs});
} catch (error) {
logger.error("Error fetching job:", error);
res.status(500).send({ error: error.message });
}
};
export const editJobRouteHandler = async (req, res) => {
try {
// Get ID from params
const id = new mongoose.Types.ObjectId(req.params.id);
// Fetch the job with the given remote address
const job = await jobModel.findOne({ _id: id });
if (!job) {
logger.warn(`Job not found with supplied id.`);
return res.status(404).send({ error: "Print job not found." });
}
logger.trace(`Job with ID: ${id}:`, job);
const { createdAt, updatedAt, started_at, status, ...updateData } =
req.body;
const result = await jobModel.updateOne(
{ _id: id },
{ $set: updateData },
);
if (result.nModified === 0) {
logger.warn("No jobs updated.");
return res.status(400).send({ error: "No jobs updated." });
}
res.send({ message: "Print job updated successfully" });
} catch (error) {
logger.error("Error updating job:", error);
res.status(500).send({ error: error.message });
}
};
export const createJobRouteHandler = async (req, res) => {
try {
const { gcodeFile, printers, quantity = 1 } = req.body;
if (!printers || printers.length === 0) {
return res
.status(400)
.send({ error: "At least one printer must be specified" });
}
// Convert printer IDs to ObjectIds
const printerIds = printers.map((id) => new mongoose.Types.ObjectId(id));
// Create new print job
const newJob = new jobModel({
state: { type: "draft" },
printers: printerIds,
gcodeFile: gcodeFile ? new mongoose.Types.ObjectId(gcodeFile) : null,
quantity,
subJobs: [], // Initialize empty array for subjob references
createdAt: new Date(),
updatedAt: new Date(),
startedAt: null
});
// Save the print job first to get its ID
const savedJob = await newJob.save();
// Create subjobs array with sequential numbers based on quantity
const subJobs = await Promise.all(
Array.from({ length: quantity }, (_, index) => {
const subJob = new subJobModel({
printer: printerIds[index % printerIds.length], // Distribute across available printers
job: savedJob._id,
gcodeFile: gcodeFile ? new mongoose.Types.ObjectId(gcodeFile) : null,
subJobId: `subjob-${index + 1}`,
state: { type: "draft" },
number: index + 1,
createdAt: new Date(),
updatedAt: new Date(),
});
return subJob.save();
}),
);
// Update the print job with the subjob references
savedJob.subJobs = subJobs.map((subJob) => subJob._id);
await savedJob.save();
logger.trace(
`Created new print job with ID: ${savedJob._id} and ${subJobs.length} subjobs`,
);
res.status(201).send({ job: savedJob, subJobs });
} catch (error) {
logger.error("Error creating print job:", error);
res.status(500).send({ error: error.message });
}
};
export const getJobStatsRouteHandler = async (req, res) => {
try {
const stats = await jobModel.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("Print job stats by state:", formattedStats);
res.send(formattedStats);
} catch (error) {
logger.error("Error fetching print job stats:", error);
res.status(500).send({ error: error.message });
}
};