|
|
|
const User = require("../models/User.js");
|
|
|
|
const Product = require("../models/Product.js");
|
|
|
|
const Order = require("../models/Order.js");
|
|
|
|
const auth = require("../auth.js");
|
|
|
|
const {verify, verifyAdmin} = auth;
|
|
|
|
|
|
|
|
|
|
|
|
// Controllers
|
|
|
|
|
|
|
|
// create product controller
|
|
|
|
module.exports.createProduct = async (req, res) => {
|
|
|
|
try {
|
|
|
|
const { name, price, description, inventory } = req.body;
|
|
|
|
|
|
|
|
// Create a new product instance
|
|
|
|
const product = new Product({
|
|
|
|
name,
|
|
|
|
price,
|
|
|
|
description,
|
|
|
|
inventory
|
|
|
|
});
|
|
|
|
|
|
|
|
// Save the product to the database
|
|
|
|
await product.save();
|
|
|
|
|
|
|
|
res.status(201).json(true);
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
res.status(500).json(false);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports.isProductExisting = async (req, res) => {
|
|
|
|
try {
|
|
|
|
const { productName } = req.body;
|
|
|
|
|
|
|
|
|
|
|
|
const existingProduct = await Product.findOne({ name: productName });
|
|
|
|
|
|
|
|
const productExists = !!existingProduct;
|
|
|
|
|
|
|
|
if (productExists == true) {
|
|
|
|
res.json(true);
|
|
|
|
} else {
|
|
|
|
res.json(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
res.status(500).json(false);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// retrieve all products controller
|
|
|
|
module.exports.getAllProducts = async (req, res) => {
|
|
|
|
try {
|
|
|
|
// Fetch all products from the database
|
|
|
|
const products = await Product.find();
|
|
|
|
|
|
|
|
res.json(products);
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
res.status(500).json({ message: 'Error retrieving products' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// retrieve all active products controller
|
|
|
|
exports.getAllActiveProducts = async (req, res) => {
|
|
|
|
try {
|
|
|
|
const products = await Product.find({ isActive: true });
|
|
|
|
|
|
|
|
res.json(products);
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
res.status(500).json({ message: 'Error retrieving active products' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// search products controller
|
|
|
|
exports.searchProducts = async (req, res) => {
|
|
|
|
try {
|
|
|
|
const { query } = req.body;
|
|
|
|
|
|
|
|
// Build the search query using case-insensitive regex
|
|
|
|
const regex = new RegExp(escapeRegex(query), 'i');
|
|
|
|
|
|
|
|
const products = await Product.find({
|
|
|
|
$or: [
|
|
|
|
{ name: regex },
|
|
|
|
// Add more fields to search if needed
|
|
|
|
],
|
|
|
|
});
|
|
|
|
|
|
|
|
res.json(products);
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
res.status(500).json({ message: 'Error searching products' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Helper function to escape special characters in the search query
|
|
|
|
function escapeRegex(text) {
|
|
|
|
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// update product controller
|
|
|
|
exports.updateProduct = async (req, res) => {
|
|
|
|
try {
|
|
|
|
const { productId } = req.params;
|
|
|
|
const { name, price, description, inventory } = req.body;
|
|
|
|
|
|
|
|
// Find the product to update
|
|
|
|
const product = await Product.findByIdAndUpdate(productId, {
|
|
|
|
name,
|
|
|
|
price,
|
|
|
|
description,
|
|
|
|
inventory,
|
|
|
|
}, { new: true });
|
|
|
|
|
|
|
|
if (!product) {
|
|
|
|
return res.status(404).json(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
res.json(true);
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
res.status(500).json(false);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// archive product controller
|
|
|
|
exports.archiveProduct = async (req, res) => {
|
|
|
|
try {
|
|
|
|
const { productId } = req.params;
|
|
|
|
|
|
|
|
// Find the product to archive
|
|
|
|
const product = await Product.findById(productId);
|
|
|
|
|
|
|
|
if (!product) {
|
|
|
|
return res.status(404).json({ message: 'Product not found' });
|
|
|
|
}else if (product.isActive === false){
|
|
|
|
return res.status(404).json({ message: 'Product already archived' });
|
|
|
|
}
|
|
|
|
|
|
|
|
product.isActive = false;
|
|
|
|
|
|
|
|
await product.save();
|
|
|
|
|
|
|
|
res.json({ message: 'Product archived successfully' });
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
res.status(500).json({ message: 'Error archiving product' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// activate product controller
|
|
|
|
exports.activateProduct = async (req, res) => {
|
|
|
|
try {
|
|
|
|
const { productId } = req.params;
|
|
|
|
|
|
|
|
// Find the product to archive
|
|
|
|
const product = await Product.findById(productId);
|
|
|
|
|
|
|
|
if (!product) {
|
|
|
|
return res.status(404).json({ message: 'Product not found' });
|
|
|
|
}else if (product.isActive === true){
|
|
|
|
return res.status(404).json({ message: 'Product already active' });
|
|
|
|
}
|
|
|
|
|
|
|
|
product.isActive = true;
|
|
|
|
|
|
|
|
await product.save();
|
|
|
|
|
|
|
|
res.json({ message: 'Product activated successfully' });
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
res.status(500).json({ message: 'Error activating product' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Controller to create an order || check-out
|
|
|
|
exports.createOrder = async (req, res, next) => {
|
|
|
|
try {
|
|
|
|
let cartItems = req.body.orderedItems;
|
|
|
|
|
|
|
|
// Fetch product prices from the database
|
|
|
|
await Product.find({ _id: { $in: cartItems.map(item => item.productId) } }).then( result => {
|
|
|
|
for (i = 0 ; i < result.length; i++) {
|
|
|
|
cartItems[i].price = result[i].price;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Create the order with retrieved prices
|
|
|
|
const newOrder = new Order({
|
|
|
|
userId: req.user.id,
|
|
|
|
products: cartItems,
|
|
|
|
totalAmount: calculateTotalPrice(cartItems)
|
|
|
|
});
|
|
|
|
|
|
|
|
// Save the order and update inventory
|
|
|
|
await newOrder.save();
|
|
|
|
await updateProductInventory(cartItems);
|
|
|
|
|
|
|
|
|
|
|
|
// Update User orders
|
|
|
|
await User.findById(req.user.id).then( result => {
|
|
|
|
|
|
|
|
const newOrderUserUpdate = {
|
|
|
|
products: cartItems,
|
|
|
|
totalAmount: calculateTotalPrice(cartItems),
|
|
|
|
purchasedOn : new Date()
|
|
|
|
}
|
|
|
|
|
|
|
|
result.orders.push(newOrderUserUpdate);
|
|
|
|
|
|
|
|
result.save();
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
res.status(201).json({ message: 'Order created successfully', newOrder });
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
res.status(500).json({ message: 'Error creating order' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Helper functions for calculating total price and updating inventory
|
|
|
|
function calculateTotalPrice(cartItems) {
|
|
|
|
return cartItems.reduce((total, item) => {
|
|
|
|
const itemPrice = Number(item.price); // Ensure price is a number
|
|
|
|
const itemQuantity = Number(item.quantity); // Ensure quantity is a number
|
|
|
|
return total + (itemPrice * itemQuantity);
|
|
|
|
}, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function updateProductInventory(cartItems) {
|
|
|
|
try {
|
|
|
|
await Promise.all(
|
|
|
|
cartItems.map(async item => {
|
|
|
|
const product = await Product.findById(item.productId);
|
|
|
|
|
|
|
|
if (!product) {
|
|
|
|
throw new Error(`Product not found: ${item.productId}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure quantity doesn't go below zero
|
|
|
|
const newQuantity = Math.max(0, product.inventory - item.quantity);
|
|
|
|
|
|
|
|
product.inventory = newQuantity;
|
|
|
|
await product.save();
|
|
|
|
})
|
|
|
|
);
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error updating product quantities:', error);
|
|
|
|
// Handle the error appropriately (e.g., rollback order creation)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// My Cart
|
|
|
|
|
|
|
|
exports.addProductToCart = async (req, res) => {
|
|
|
|
try {
|
|
|
|
const { productId, quantity } = req.body;
|
|
|
|
|
|
|
|
// Find the user
|
|
|
|
const user = await User.findById(req.user.id);
|
|
|
|
|
|
|
|
// Check if the cart array exists
|
|
|
|
if (!user.myCart) {
|
|
|
|
user.myCart = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
const existingItemIndex = user.myCart.findIndex(item => item.productId === productId);
|
|
|
|
|
|
|
|
if (existingItemIndex !== -1) {
|
|
|
|
// Update quantity of existing item
|
|
|
|
user.myCart[existingItemIndex].quantity += quantity;
|
|
|
|
} else {
|
|
|
|
if (quantity <= 0) {
|
|
|
|
return res.json({ message: 'Provide valid quantity' });
|
|
|
|
}
|
|
|
|
// Add new item to cart
|
|
|
|
const product = await Product.findById(productId);
|
|
|
|
user.myCart.push({
|
|
|
|
productId,
|
|
|
|
name: product.name,
|
|
|
|
quantity
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
await user.save(); // Save the updated user with cart items
|
|
|
|
|
|
|
|
res.json({ message: 'Product added to cart successfully' });
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
res.status(500).json({ message: 'Error adding product to cart' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.updateProductQuantity = async (req, res) => {
|
|
|
|
try {
|
|
|
|
const { productId, quantity } = req.body;
|
|
|
|
|
|
|
|
// Find the user
|
|
|
|
const user = await User.findById(req.user.id);
|
|
|
|
|
|
|
|
if (!user.myCart) {
|
|
|
|
return res.status(400).json({ message: 'Cart is empty' });
|
|
|
|
}
|
|
|
|
|
|
|
|
const itemIndex = user.myCart.findIndex(item => item.productId === productId);
|
|
|
|
|
|
|
|
if (itemIndex === -1) {
|
|
|
|
return res.status(404).json({ message: 'Product not found in cart' });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Validate quantity (e.g., must be positive, not exceed available inventory)
|
|
|
|
if (quantity <= 0) {
|
|
|
|
return res.status(400).json({ message: 'Quantity must be greater than zero' });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update quantity in the cart
|
|
|
|
user.myCart[itemIndex].quantity = quantity;
|
|
|
|
|
|
|
|
await user.save(); // Save the updated cart
|
|
|
|
|
|
|
|
res.json({ message: 'Product quantity updated successfully' });
|
|
|
|
console.log(user.myCart);
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
res.status(500).json({ message: 'Error updating product quantity' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.removeProductFromCart = async (req, res) => {
|
|
|
|
try {
|
|
|
|
const productId = req.params.productId;
|
|
|
|
const user = await User.findById(req.user.id);
|
|
|
|
const existingItemIndex = user.myCart.findIndex(item => item.productId === productId);
|
|
|
|
|
|
|
|
let x = await User.findByIdAndUpdate(
|
|
|
|
req.user.id,
|
|
|
|
{
|
|
|
|
$pull: { myCart: { productId } }
|
|
|
|
},
|
|
|
|
{ new: true } // Return the updated user document
|
|
|
|
).exec();
|
|
|
|
|
|
|
|
if (existingItemIndex <= 0) {
|
|
|
|
res.json({ message: 'Product not in cart' });
|
|
|
|
}else{
|
|
|
|
res.json({ message: 'Product removed from cart successfully' });
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
res.status(500).json({ message: 'Error removing product from cart' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.getCartDetails = async (req, res) => {
|
|
|
|
try {
|
|
|
|
const user = await User.findById(req.user.id);
|
|
|
|
|
|
|
|
if (!user || !user.myCart || user.myCart.length < 0) {
|
|
|
|
return res.json({ cartItems: [], totalPrice: 0 }); // Handle empty cart
|
|
|
|
}
|
|
|
|
|
|
|
|
const cartItems = user.myCart;
|
|
|
|
let totalPrice = 0;
|
|
|
|
|
|
|
|
for (const item of cartItems) {
|
|
|
|
const findItemPrice = await Product.findById(item.productId);
|
|
|
|
const subtotal = findItemPrice.price * item.quantity;
|
|
|
|
totalPrice += subtotal;
|
|
|
|
item.price = findItemPrice.price;
|
|
|
|
|
|
|
|
// Add subtotal to the item object for clarity in response
|
|
|
|
item.subtotal = subtotal;
|
|
|
|
}
|
|
|
|
|
|
|
|
res.json({ cartItems, totalPrice });
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
res.status(500).json({ message: 'Error fetching cart details' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports.getProduct = (request, response) => {
|
|
|
|
let reqParams = request.params.productId;
|
|
|
|
|
|
|
|
Product.findById(reqParams).then(result => response.send(result))
|
|
|
|
.catch(error => response.send(error));
|
|
|
|
|
|
|
|
}
|