Files
ember-market-frontend/backend/controllers/stock.controller.js
2025-03-10 17:39:37 +00:00

151 lines
4.4 KiB
JavaScript

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;
}
};