221 lines
6.1 KiB
JavaScript
221 lines
6.1 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 {
|
|
editAuditLog,
|
|
flatternObjectIds,
|
|
distributeUpdate,
|
|
newAuditLog,
|
|
distributeNew,
|
|
} from '../../utils.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({
|
|
$lookup: {
|
|
from: 'vendors', // The name of the Filament collection
|
|
localField: 'vendor',
|
|
foreignField: '_id',
|
|
as: 'vendor',
|
|
},
|
|
});
|
|
|
|
aggregateCommand.push({
|
|
$unwind: {
|
|
path: '$vendor',
|
|
preserveNullAndEmptyArrays: true, // Keep documents without a matching vendor
|
|
},
|
|
});
|
|
|
|
aggregateCommand.push({
|
|
$addFields: {
|
|
vendor: '$vendor',
|
|
},
|
|
});
|
|
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');
|
|
|
|
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);
|
|
|
|
res.send({ ...product._doc });
|
|
} 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,
|
|
amount: req.body.amount,
|
|
priceMode: req.body.priceMode,
|
|
};
|
|
|
|
// Create audit log before updating
|
|
await editAuditLog(product.toObject(), updateData, id, 'product', req.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.' });
|
|
}
|
|
|
|
await distributeUpdate(updateData, id, 'product');
|
|
} 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,
|
|
parts: partIds,
|
|
margin: req.body.margin,
|
|
amount: req.body.amount,
|
|
priceMode: req.body.priceMode,
|
|
};
|
|
|
|
const newProductResult = await productModel.create(flatternObjectIds(newProduct));
|
|
|
|
if (newProductResult.nCreated === 0) {
|
|
logger.error('No product created.');
|
|
res.status(500).send({ error: 'No product created.' });
|
|
}
|
|
|
|
const parts = req.body.parts || [];
|
|
|
|
var partIds = [];
|
|
|
|
for (const part of parts) {
|
|
const newPart = {
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
name: part.name,
|
|
product: { _id: newProductResult._id },
|
|
};
|
|
|
|
const newPartResult = await partModel.create(flatternObjectIds(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);
|
|
}
|
|
|
|
// Create audit log for new product
|
|
await newAuditLog(newProduct, newProductResult._id, 'product', req.user);
|
|
await distributeNew(newProductResult._id, 'product');
|
|
|
|
res.status(200).send({ ...newProductResult });
|
|
} catch (updateError) {
|
|
logger.error('Error updating product:', updateError);
|
|
res.status(500).send({ error: updateError.message });
|
|
}
|
|
};
|