194 lines
5.6 KiB
JavaScript
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 });
|
|
}
|
|
};
|
|
|