import config from '../../config.js'; import { stockAuditModel } from '../../database/schemas/inventory/stockaudit.schema.js'; import log4js from 'log4js'; import mongoose from 'mongoose'; import { getAuditLogs } from '../../utils.js'; import { getModelStats, getModelHistory, searchObjects } from '../../database/database.js'; const logger = log4js.getLogger('Stock Audits'); logger.level = config.server.logLevel; export const listStockAuditsRouteHandler = async ( req, res, page = 1, limit = 25, property = '', filter = {} ) => { try { const skip = (page - 1) * limit; let stockAudits; let aggregateCommand = []; // Lookup createdBy user aggregateCommand.push({ $lookup: { from: 'users', localField: 'createdBy', foreignField: '_id', as: 'createdBy', }, }); aggregateCommand.push({ $unwind: '$createdBy' }); if (filter != {}) { aggregateCommand.push({ $match: filter }); } if (property != '') { aggregateCommand.push({ $group: { _id: `$${property}` } }); aggregateCommand.push({ $project: { _id: 0, [property]: '$_id' } }); } aggregateCommand.push({ $skip: skip }); aggregateCommand.push({ $limit: Number(limit) }); stockAudits = await stockAuditModel.aggregate(aggregateCommand); logger.trace( `List of stock audits (Page ${page}, Limit ${limit}, Property ${property}):`, stockAudits ); res.send(stockAudits); } catch (error) { logger.error('Error listing stock audits:', error); res.status(500).send({ error: error }); } }; export const searchStockAuditsRouteHandler = async (req, res, search) => { const result = await searchObjects({ model: stockAuditModel, search, }); res.send(result); }; export const getStockAuditRouteHandler = async (req, res) => { try { const id = new mongoose.Types.ObjectId(req.params.id); const stockAudit = await stockAuditModel .findOne({ _id: id, }) .populate('createdBy') .populate('items.filamentStock') .populate('items.partStock'); if (!stockAudit) { logger.warn(`Stock audit not found with supplied id.`); return res.status(404).send({ error: 'Stock audit not found.' }); } logger.trace(`Stock audit with ID: ${id}:`, stockAudit); const auditLogs = await getAuditLogs(id); res.send({ ...stockAudit._doc, auditLogs: auditLogs }); } catch (error) { logger.error('Error fetching stock audit:', error); res.status(500).send({ error: error.message }); } }; export const newStockAuditRouteHandler = async (req, res) => { try { const newStockAudit = { type: req.body.type, status: req.body.status || 'pending', notes: req.body.notes, items: req.body.items.map((item) => ({ type: item.type, stock: item.type === 'filament' ? new mongoose.Types.ObjectId(item.filamentStock) : new mongoose.Types.ObjectId(item.partStock), expectedQuantity: item.expectedQuantity, actualQuantity: item.actualQuantity, notes: item.notes, })), createdBy: new mongoose.Types.ObjectId(req.body.createdBy), completedAt: req.body.status === 'completed' ? new Date() : null, }; const result = await stockAuditModel.create(newStockAudit); if (!result) { logger.error('No stock audit created.'); return res.status(500).send({ error: 'No stock audit created.' }); } return res.send({ status: 'ok', id: result._id }); } catch (error) { logger.error('Error adding stock audit:', error); return res.status(500).send({ error: error.message }); } }; export const updateStockAuditRouteHandler = async (req, res) => { try { const id = new mongoose.Types.ObjectId(req.params.id); const updateData = { ...req.body, items: req.body.items?.map((item) => ({ type: item.type, stock: item.type === 'filament' ? new mongoose.Types.ObjectId(item.filamentStock) : new mongoose.Types.ObjectId(item.partStock), expectedQuantity: item.expectedQuantity, actualQuantity: item.actualQuantity, notes: item.notes, })), completedAt: req.body.status === 'completed' ? new Date() : null, }; const result = await stockAuditModel.findByIdAndUpdate(id, { $set: updateData }, { new: true }); if (!result) { logger.warn(`Stock audit not found with supplied id.`); return res.status(404).send({ error: 'Stock audit not found.' }); } logger.trace(`Updated stock audit with ID: ${id}:`, result); res.send(result); } catch (error) { logger.error('Error updating stock audit:', error); res.status(500).send({ error: error.message }); } }; export const deleteStockAuditRouteHandler = async (req, res) => { try { const id = new mongoose.Types.ObjectId(req.params.id); const result = await stockAuditModel.findByIdAndDelete(id); if (!result) { logger.warn(`Stock audit not found with supplied id.`); return res.status(404).send({ error: 'Stock audit not found.' }); } logger.trace(`Deleted stock audit with ID: ${id}`); res.send({ status: 'ok' }); } catch (error) { logger.error('Error deleting stock audit:', error); res.status(500).send({ error: error.message }); } }; export const getStockAuditStatsRouteHandler = async (req, res) => { const result = await getModelStats({ model: stockAuditModel }); if (result?.error) { logger.error('Error fetching stock audit stats:', result.error); return res.status(result.code).send(result); } logger.trace('Stock audit stats:', result); res.send(result); }; export const getStockAuditHistoryRouteHandler = async (req, res) => { const from = req.query.from; const to = req.query.to; const result = await getModelHistory({ model: stockAuditModel, from, to }); if (result?.error) { logger.error('Error fetching stock audit history:', result.error); return res.status(result.code).send(result); } logger.trace('Stock audit history:', result); res.send(result); };