import dotenv from 'dotenv'; import { filamentStockModel } from '../../schemas/inventory/filamentstock.schema.js'; import { filamentModel } from '../../schemas/management/filament.schema.js'; import { stockEventModel } from '../../schemas/inventory/stockevent.schema.js'; import log4js from 'log4js'; import mongoose from 'mongoose'; import { distributeNew, flatternObjectIds, getAuditLogs, newAuditLog } from '../../utils.js'; dotenv.config(); const logger = log4js.getLogger('Filament Stocks'); logger.level = process.env.LOG_LEVEL; export const listFilamentStocksRouteHandler = async ( req, res, page = 1, limit = 25, property = '', filter = {}, sort = '', order = 'ascend' ) => { try { // Calculate the skip value based on the page number and limit const skip = (page - 1) * limit; let filamentStock; let aggregateCommand = []; aggregateCommand.push({ $lookup: { from: 'filaments', // The collection name (usually lowercase plural) localField: 'filament', // The field in your current model foreignField: '_id', // The field in the products collection as: 'filament', // The output field name }, }); aggregateCommand.push({ $unwind: '$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: { image: 0, url: 0 } }); } // 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); filamentStock = await filamentStockModel.aggregate(aggregateCommand); logger.trace( `List of filamentStocks (Page ${page}, Limit ${limit}, Property ${property}):`, filamentStock ); res.send(filamentStock); } catch (error) { logger.error('Error listing filament stocks:', error); res.status(500).send({ error: error }); } }; export const getFilamentStockRouteHandler = async (req, res) => { try { // Get ID from params const id = new mongoose.Types.ObjectId(req.params.id); // Fetch the filamentStock with the given remote address const filamentStock = await filamentStockModel .findOne({ _id: id, }) .populate('filament'); if (!filamentStock) { logger.warn(`Filament stock not found with supplied id.`); return res.status(404).send({ error: 'Print job not found.' }); } logger.trace(`Filament stock with ID: ${id}:`, filamentStock); const auditLogs = await getAuditLogs(id); res.send({ ...filamentStock._doc, auditLogs: auditLogs }); } catch (error) { logger.error('Error fetching filament stock:', error); res.status(500).send({ error: error.message }); } }; export const newFilamentStockRouteHandler = async (req, res) => { var filament = null; try { // Get ID from params const id = new mongoose.Types.ObjectId(req.body.filament._id); // Fetch the filament with the given remote address filament = await filamentModel.findOne({ _id: id, }); if (!filament) { logger.warn(`Filament not found with supplied id.`); return res.status(404).send({ error: 'Filament not found.' }); } logger.trace(`Filament with ID: ${id}:`, filament); } catch (error) { logger.error('Error fetching filament:', error); return res.status(500).send({ error: error.message }); } try { logger.warn(req.body); const startingWeight = req.body.startingWeight; // { net, gross } if (!startingWeight || typeof startingWeight.gross !== 'number') { return res.status(400).send({ error: 'startingWeight.gross is required' }); } // Calculate net if not provided const net = typeof startingWeight.net === 'number' ? startingWeight.net : startingWeight.gross - filament.emptySpoolWeight; const starting = { gross: startingWeight.gross, net: net, }; const newFilamentStock = { startingWeight: starting, currentWeight: { ...starting }, filament: req.body.filament, state: { type: 'unconsumed', percent: '0', // schema requires string }, }; const result = await filamentStockModel.create(flatternObjectIds(newFilamentStock)); if (!result) { logger.error('No filament stock created.'); return res.status(500).send({ error: 'No filament stock created.' }); } await newAuditLog(newFilamentStock, result._id, 'filamentStock', req.user); await distributeNew(result._id, 'filamentStock'); console.log(result); // Create initial stock event (optional, but keep logic if needed) const stockEvent = { value: starting.net, current: starting.net, unit: 'g', parent: result, parentType: 'filamentStock', owner: req.user, ownerType: 'user', createdAt: new Date(), updatedAt: new Date(), }; const eventResult = await stockEventModel.create(flatternObjectIds(stockEvent)); if (!eventResult) { logger.error('Failed to create initial stock event.'); return res.status(500).send({ error: 'Failed to create initial stock event.' }); } await newAuditLog(stockEvent, eventResult._id, 'stockEvent', req.user); return res.send({ status: 'ok' }); } catch (updateError) { logger.error('Error adding filament stock:', updateError); return res.status(500).send({ error: updateError.message }); } };