import Product from "../models/Product.model.js"; import Order from "../models/Order.model.js"; import Store from "../models/Store.model.js"; import mongoose from "mongoose"; import logger from "../utils/logger.js"; /** * Updates a product's stock quantity */ export const updateStock = async (req, res) => { try { const { productId } = req.params; const { currentStock, stockTracking, lowStockThreshold } = req.body; if (currentStock === undefined) { return res.status(400).json({ message: "Stock quantity is required" }); } // Validate product exists and belongs to the vendor's store const product = await Product.findOne({ _id: productId, storeId: req.user.storeId }); if (!product) { return res.status(404).json({ message: "Product not found" }); } // Update stock values let stockStatus = "in_stock"; if (currentStock <= 0) { stockStatus = "out_of_stock"; } else if (currentStock <= (lowStockThreshold || product.lowStockThreshold)) { stockStatus = "low_stock"; } const updatedProduct = await Product.findByIdAndUpdate( productId, { currentStock: currentStock, stockTracking: stockTracking !== undefined ? stockTracking : product.stockTracking, lowStockThreshold: lowStockThreshold !== undefined ? lowStockThreshold : product.lowStockThreshold, stockStatus: stockStatus }, { new: true } ); return res.status(200).json(updatedProduct); } catch (error) { logger.error("Error updating stock", { error }); return res.status(500).json({ message: "Failed to update stock", error: error.message }); } }; /** * Gets stock information for all products in a store */ export const getStoreStock = async (req, res) => { try { const products = await Product.find({ storeId: req.user.storeId }) .select('_id name currentStock stockTracking stockStatus lowStockThreshold') .sort({ stockStatus: 1, name: 1 }); return res.status(200).json(products); } catch (error) { logger.error("Error fetching store stock", { error }); return res.status(500).json({ message: "Failed to fetch stock information", error: error.message }); } }; /** * Updates stock levels when an order is placed * This should be called from the order creation logic */ export const decreaseStockOnOrder = async (order) => { try { // Process each ordered product for (const item of order.products) { const product = await Product.findById(item.productId); // Skip if product doesn't exist or stock tracking is disabled if (!product || !product.stockTracking) continue; // Calculate new stock level let newStock = Math.max(0, product.currentStock - item.quantity); let stockStatus = "in_stock"; if (newStock <= 0) { stockStatus = "out_of_stock"; } else if (newStock <= product.lowStockThreshold) { stockStatus = "low_stock"; } // Update the product stock await Product.findByIdAndUpdate( item.productId, { currentStock: newStock, stockStatus: stockStatus }, { new: true } ); } return true; } catch (error) { logger.error("Error decreasing stock on order", { orderId: order._id, error }); return false; } }; /** * Restores stock when an order is cancelled */ export const restoreStockOnCancel = async (order) => { try { // Process each ordered product for (const item of order.products) { const product = await Product.findById(item.productId); // Skip if product doesn't exist or stock tracking is disabled if (!product || !product.stockTracking) continue; // Calculate new stock level let newStock = product.currentStock + item.quantity; let stockStatus = "in_stock"; if (newStock <= 0) { stockStatus = "out_of_stock"; } else if (newStock <= product.lowStockThreshold) { stockStatus = "low_stock"; } // Update the product stock await Product.findByIdAndUpdate( item.productId, { currentStock: newStock, stockStatus: stockStatus }, { new: true } ); } return true; } catch (error) { logger.error("Error restoring stock on cancel", { orderId: order._id, error }); return false; } };