210 lines
6.0 KiB
JavaScript

import dotenv from 'dotenv';
import { productModel } from '../../schemas/management/product.schema.js';
import { partModel } from '../../schemas/management/part.schema.js';
import log4js from 'log4js';
import mongoose from 'mongoose';
import { newAuditLog } from '../../utils.js';
import { auditLogModel } from '../../schemas/management/auditlog.schema.js';
dotenv.config();
const logger = log4js.getLogger('Products');
logger.level = process.env.LOG_LEVEL;
export const listProductsRouteHandler = async (
req,
res,
page = 1,
limit = 25,
property = '',
filter = {}
) => {
try {
// Calculate the skip value based on the page number and limit
const skip = (page - 1) * limit;
let product;
let aggregateCommand = [];
if (filter != {}) {
// use filtering if present
aggregateCommand.push({ $match: filter });
}
if (property != '') {
// Match documents where the specified property is either null, undefined, empty string, empty array or empty object
aggregateCommand.push({
$match: {
$or: [
{ [property]: null },
{ [property]: '' },
{ [property]: [] },
{ [property]: {} },
{ [property]: { $exists: false } },
],
},
});
aggregateCommand.push({ $project: { _id: 1, [property]: 1 } });
} else {
aggregateCommand.push({ $project: { image: 0, url: 0 } });
}
aggregateCommand.push({ $skip: skip });
aggregateCommand.push({ $limit: Number(limit) });
console.log(aggregateCommand);
product = await productModel.aggregate(aggregateCommand);
logger.trace(`List of products (Page ${page}, Limit ${limit}, Property ${property}):`, product);
res.send(product);
} catch (error) {
logger.error('Error listing products:', error);
res.status(500).send({ error: error });
}
};
export const getProductRouteHandler = async (req, res) => {
try {
// Get ID from params
const id = new mongoose.Types.ObjectId(req.params.id);
// Fetch the product with the given remote address
const product = await productModel
.findOne({
_id: id,
})
.populate('vendor')
.populate('parts');
if (!product) {
logger.warn(`Product not found with supplied id.`);
return res.status(404).send({ error: 'Print job not found.' });
}
logger.trace(`Product with ID: ${id}:`, product);
const auditLogs = await auditLogModel
.find({
target: id,
})
.populate('owner');
res.send({ ...product._doc, auditLogs: auditLogs });
} catch (error) {
logger.error('Error fetching Product:', error);
res.status(500).send({ error: error.message });
}
};
export const editProductRouteHandler = async (req, res) => {
// Get ID from params
const id = new mongoose.Types.ObjectId(req.params.id);
var product = null;
try {
// Fetch the product with the given remote address
product = await productModel.findOne({ _id: id });
if (!product) {
// Error handling
logger.warn(`Product not found with supplied id.`);
return res.status(404).send({ error: 'Print job not found.' });
}
logger.trace(`Product with ID: ${id}:`, product);
} catch (fetchError) {
logger.error('Error fetching product:', fetchError);
res.status(500).send({ error: fetchError.message });
}
try {
const updateData = {
updatedAt: new Date(),
name: req.body?.name,
vendor: req.body?.vendor?.id,
tags: req.body?.tags,
version: req.body?.version,
parts: req.body?.parts,
margin: req.body.margin,
price: req.body.price,
marginOrPrice: req.body.marginOrPrice,
};
// Create audit log before updating
await newAuditLog(product.toObject(), updateData, id, 'Product', req.user._id, 'User');
const result = await productModel.updateOne({ _id: id }, { $set: updateData });
if (result.nModified === 0) {
logger.error('No Product updated.');
res.status(500).send({ error: 'No products updated.' });
}
} catch (updateError) {
logger.error('Error updating product:', updateError);
res.status(500).send({ error: updateError.message });
}
res.send('OK');
};
export const newProductRouteHandler = async (req, res) => {
try {
const newProduct = {
createdAt: new Date(),
updatedAt: new Date(),
name: req.body.name,
vendor: req.body.vendor.id,
parts: partIds,
margin: req.body.margin,
price: req.body.price,
marginOrPrice: req.body.marginOrPrice,
};
const newProductResult = await productModel.create(newProduct);
if (newProductResult.nCreated === 0) {
logger.error('No product created.');
res.status(500).send({ error: 'No product created.' });
}
// Create audit log for new product
await newAuditLog({}, newProduct, newProductResult._id, 'Product', req.user._id, 'User');
const parts = req.body.parts || [];
const productId = newProductResult._id;
var partIds = [];
for (const part of parts) {
const newPart = {
createdAt: new Date(),
updatedAt: new Date(),
name: part.name,
product: productId,
};
const newPartResult = await partModel.create(newPart);
if (newPartResult.nCreated === 0) {
logger.error('No parts created.');
res.status(500).send({ error: 'No parts created.' });
}
partIds.push(newPartResult._id);
// Create audit log for each new part
await newAuditLog({}, newPart, newPartResult._id, 'Part', req.user._id, 'User');
}
const editProductResult = await productModel.updateOne(
{ _id: productId },
{ $set: { parts: partIds } }
);
if (editProductResult.nModified === 0) {
logger.error('No product updated.');
res.status(500).send({ error: 'No products updated.' });
}
res.status(200).send({ ...newProductResult, parts: partIds });
} catch (updateError) {
logger.error('Error updating product:', updateError);
res.status(500).send({ error: updateError.message });
}
};