151 lines
4.4 KiB
JavaScript
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;
|
|
}
|
|
};
|