From 69dc2cb1b4e087fdc1ad778b906d1e0007a35034 Mon Sep 17 00:00:00 2001 From: Sibunnayak Date: Thu, 22 Aug 2024 16:40:00 +0530 Subject: [PATCH] category and product updated and brand created --- app.js | 3 + public/temp/tmp-1-1724319327212 | Bin 0 -> 11458 bytes resources/Brands/BrandsController.js | 111 +++++ resources/Brands/BrandsModel.js | 18 + resources/Brands/BrandsRoutes.js | 26 ++ resources/Category/CategoryModel.js | 1 - resources/Category/categoryController.js | 170 +++----- resources/Category/categoryRoutes.js | 6 +- resources/Inventory/InventoryController.js | 41 +- resources/Products/ProductController.js | 456 +++++++++++++++++---- resources/Products/ProductModel.js | 17 +- 11 files changed, 631 insertions(+), 218 deletions(-) create mode 100644 public/temp/tmp-1-1724319327212 create mode 100644 resources/Brands/BrandsController.js create mode 100644 resources/Brands/BrandsModel.js create mode 100644 resources/Brands/BrandsRoutes.js diff --git a/app.js b/app.js index 77f5d9e..2a5385c 100644 --- a/app.js +++ b/app.js @@ -151,6 +151,7 @@ import SalesCoOrdinatorRoute from "./resources/SalesCoOrdinators/SalesCoOrdinato import TerritoryManagerRoute from "./resources/TerritoryManagers/TerritoryManagerRoute.js"; // category Route import categoryRoute from "./resources/Category/categoryRoutes.js"; +import brandroute from "./resources/Brands/BrandsRoutes.js"; import RegistrationImageRoute from "./resources/RegistrationImage/RegistrationImageRoute.js"; import loginImageRoute from "./resources/LoginImage/LoginImageRoute.js"; import shopImageRoute from "./resources/ShopPageImage/ShopPageImageRoute.js"; @@ -199,6 +200,8 @@ app.use("/api", ProductRouter); // Category app.use("/api/category", categoryRoute); +//Brand +app.use("/api/brand", brandroute); // registration image app.use("/api/registerImage", RegistrationImageRoute); app.use("/api/loginImage", loginImageRoute); diff --git a/public/temp/tmp-1-1724319327212 b/public/temp/tmp-1-1724319327212 new file mode 100644 index 0000000000000000000000000000000000000000..570d4e2083c3d2e6ebc71ccd67006847e7a88131 GIT binary patch literal 11458 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 literal 0 HcmV?d00001 diff --git a/resources/Brands/BrandsController.js b/resources/Brands/BrandsController.js new file mode 100644 index 0000000..554b066 --- /dev/null +++ b/resources/Brands/BrandsController.js @@ -0,0 +1,111 @@ +import mongoose from "mongoose"; +import { BrandModel } from "./BrandsModel.js"; + +// Add new Brand +export const addBrand = async (req, res) => { + const { brandName } = req.body; + + if (!req?.user) { + return res.status(400).json({ message: "Please login!" }); + } + + try { + if (!mongoose.Types.ObjectId.isValid(req.user._id)) { + return res.status(400).json({ message: "Please login again." }); + } + + if (!brandName) { + return res.status(400).json({ message: "Please provide a brand name" }); + } + + const brand = await BrandModel.create({ + brandName, + addedBy: req.user._id, + }); + + return res.status(201).json({ success: true, brand, message: "Brand added successfully" }); + } catch (error) { + res.status(500).json({ + success: false, + message: error.message || "Something went wrong", + }); + } +}; + +// Get all Brands +export const getBrands = async (req, res) => { + try { + const brands = await BrandModel.find().sort({ createdAt: -1 }); + if (!brands.length) { + return res.status(404).json({ message: "No brands found" }); + } + + res.status(200).json({ success: true, brands }); + } catch (error) { + res.status(500).json({ + success: false, + message: error.message || "Something went wrong", + }); + } +}; + +// Update Brand +export const updateBrand = async (req, res) => { + const { _id } = req.params; + const { brandName } = req.body; + + if (!req?.user) { + return res.status(400).json({ message: "Please login!" }); + } + + if (!mongoose.Types.ObjectId.isValid(_id)) { + return res.status(404).json({ message: "Invalid brand ID" }); + } + + try { + const updatedBrand = await BrandModel.findByIdAndUpdate( + _id, + { brandName }, + { new: true, runValidators: true } + ); + + if (!updatedBrand) { + return res.status(404).json({ message: "Brand not found" }); + } + + res.status(200).json({ success: true, updatedBrand, message: "Brand updated successfully" }); + } catch (error) { + res.status(500).json({ + success: false, + message: error.message || "Something went wrong", + }); + } +}; + +// Delete Brand +export const deleteBrand = async (req, res) => { + const { _id } = req.params; + + if (!req?.user) { + return res.status(400).json({ message: "Please login!" }); + } + + if (!mongoose.Types.ObjectId.isValid(_id)) { + return res.status(404).json({ message: "Invalid brand ID" }); + } + + try { + const deletedBrand = await BrandModel.findByIdAndDelete(_id); + + if (!deletedBrand) { + return res.status(404).json({ message: "Brand not found" }); + } + + res.status(200).json({ success: true, deletedBrand, message: "Brand deleted successfully" }); + } catch (error) { + res.status(500).json({ + success: false, + message: error.message || "Something went wrong", + }); + } +}; diff --git a/resources/Brands/BrandsModel.js b/resources/Brands/BrandsModel.js new file mode 100644 index 0000000..c1343b7 --- /dev/null +++ b/resources/Brands/BrandsModel.js @@ -0,0 +1,18 @@ +import mongoose from "mongoose"; + +const BrandSchema = new mongoose.Schema( + { + brandName: { + type: String, + required: [true, "Name of brand required"], + }, + addedBy: { + type: mongoose.Schema.ObjectId, + ref: "User", + required: true, + }, + }, + { timestamps: true } +); + +export const BrandModel = mongoose.model("BrandModel", BrandSchema); diff --git a/resources/Brands/BrandsRoutes.js b/resources/Brands/BrandsRoutes.js new file mode 100644 index 0000000..6a0f869 --- /dev/null +++ b/resources/Brands/BrandsRoutes.js @@ -0,0 +1,26 @@ +import express from "express"; +import { isAuthenticatedUser, authorizeRoles } from "../../middlewares/auth.js"; +import { + addBrand, + deleteBrand, + getBrands, + updateBrand, +} from "./BrandsController.js"; + +const router = express.Router(); + +router + .route("/add") + .post(isAuthenticatedUser, authorizeRoles("admin"), addBrand); + +router.route("/getBrands").get(getBrands); + +router + .route("/update/:_id") + .patch(isAuthenticatedUser, authorizeRoles("admin"), updateBrand); + +router + .route("/delete/:_id") + .delete(isAuthenticatedUser, authorizeRoles("admin"), deleteBrand); + +export default router; diff --git a/resources/Category/CategoryModel.js b/resources/Category/CategoryModel.js index c05dae5..1f1aac9 100644 --- a/resources/Category/CategoryModel.js +++ b/resources/Category/CategoryModel.js @@ -6,7 +6,6 @@ const CategorySchema = new mongoose.Schema( type: String, required: [true, "Name of category required "], }, - categoryImage: {}, addedBy: { type: mongoose.Schema.ObjectId, ref: "User", diff --git a/resources/Category/categoryController.js b/resources/Category/categoryController.js index 0bc68e6..e3eaebd 100644 --- a/resources/Category/categoryController.js +++ b/resources/Category/categoryController.js @@ -1,53 +1,43 @@ import mongoose from "mongoose"; import { CategoryModel } from "./CategoryModel.js"; -import cloudinary from "../../Utils/cloudinary.js"; // Add new Category export const addCategory = async (req, res) => { const { categoryName } = req.body; - const { categoryImage } = req.files; - // console.log(categoryName, categoryImage); - if (!req?.user) return res.status(400).json({ message: "please login !" }); + if (!req?.user) { + return res.status(400).json({ message: "Please login!" }); + } + try { if (!mongoose.Types.ObjectId.isValid(req.user._id)) { - return res.status(400).json({ message: "please login again " }); + return res.status(400).json({ message: "Please login again." }); } - const result = await cloudinary.v2.uploader.upload( - categoryImage.tempFilePath, - { - folder: "GetSygnal/category", - } - ); - if (result) { - const category = await CategoryModel.create({ - categoryName, - categoryImage: result, - addedBy: req.user._id, - }); - if (category) { - return res - .status(201) - .json({ success: true, category, message: "category Added" }); - } + if (!categoryName) { + return res.status(400).json({ message: "Please provide a category name" }); } + + const category = await CategoryModel.create({ + categoryName, + addedBy: req.user._id, + }); + + return res.status(201).json({ success: true, category, message: "Category added successfully" }); } catch (error) { res.status(500).json({ success: false, - message: error.message ? error.message : "Something went Wrong", + message: error.message || "Something went wrong", }); } }; +// Get all Categories export const getCategories = async (req, res) => { try { - // if (!req?.user) return res.status(400).json({ message: "please login !" }); - const categories = await CategoryModel.find().sort({ - createdAt: -1, - }); + const categories = await CategoryModel.find().sort({ createdAt: -1 }); - if (!categories) { + if (!categories.length) { return res.status(404).json({ message: "No categories found" }); } @@ -55,96 +45,68 @@ export const getCategories = async (req, res) => { } catch (error) { res.status(500).json({ success: false, - message: error.message ? error.message : "Something went wrong", + message: error.message || "Something went wrong", }); } }; +// Update Category export const updateCategory = async (req, res) => { - try { - if (!req?.user) return res.status(400).json({ message: "please login !" }); - const { _id } = req.params; - const { categoryName } = req.body; - const olderImage = req.body?.olderImage; - const categoryImag = req.files?.categoryImage; + const { _id } = req.params; + const { categoryName } = req.body; - if (!mongoose.Types.ObjectId.isValid(_id)) { - return res.status(404).json({ error: "Can not find the document " }); - } - - // find the document with the id to delete the image from cloudinary - if (JSON.parse(olderImage).length == 0) { - const deletefromCloudinary = await CategoryModel.findOne({ _id: _id }); - - const deleteresponse = await cloudinary.v2.uploader.destroy( - deletefromCloudinary.categoryImage.public_id - ); - if (deleteresponse) { - const result = await cloudinary.v2.uploader.upload( - categoryImag.tempFilePath, - { - folder: "GetSygnal/category", - } - ); - const update = await CategoryModel.findOneAndUpdate( - { _id: _id }, - { categoryName: categoryName, categoryImage: result }, // Provide the updated categoryName - { new: true } // To return the updated document - ); - if (!update) { - return res - .status(404) - .json({ message: "Can not update document, something went wrong" }); - } else { - return res.status(200).json({ success: true, update }); - } - } - } else { - const update = await CategoryModel.findOneAndUpdate( - { _id: _id }, - { categoryName: categoryName, categoryImage: JSON.parse(olderImage) }, // Provide the updated categoryName - { new: true } // To return the updated document - ); - if (update) { - return res.status(200).json({ success: true, update }); - } - } - } catch (error) { - res.status(500).json({ - success: false, - message: error.message ? error.message : "Something went wrong", - }); + if (!req?.user) { + return res.status(400).json({ message: "Please login!" }); + } + + if (!mongoose.Types.ObjectId.isValid(_id)) { + return res.status(404).json({ message: "Invalid category ID" }); } -}; -export const deleteCategory = async (req, res) => { try { - if (!req?.user) return res.status(400).json({ message: "please login !" }); - const { _id } = req.params; - if (!mongoose.Types.ObjectId.isValid(_id)) { - return res.status(404).json({ error: "Can not find the document " }); - } - - const deletefromCloudinary = await CategoryModel.findOne({ _id: _id }); - - const deleteresponse = await cloudinary.v2.uploader.destroy( - deletefromCloudinary.categoryImage.public_id + const updatedCategory = await CategoryModel.findByIdAndUpdate( + _id, + { categoryName }, + { new: true, runValidators: true } ); - if (deleteresponse) { - const deleteCategory = await CategoryModel.findOneAndDelete({ _id: _id }); - if (!deleteCategory) { - return res.status(404).json({ - error: "Can not find the document with the provided id to delete ", - }); - } - res.status(200).json({ success: true, deleteCategory }); - } else { - return res.status(404).json({ error: "can not delete the category " }); + + if (!updatedCategory) { + return res.status(404).json({ message: "Category not found" }); } + + res.status(200).json({ success: true, updatedCategory, message: "Category updated successfully" }); } catch (error) { res.status(500).json({ success: false, - message: error.message ? error.message : "Something went wrong", + message: error.message || "Something went wrong", + }); + } +}; + +// Delete Category +export const deleteCategory = async (req, res) => { + const { _id } = req.params; + + if (!req?.user) { + return res.status(400).json({ message: "Please login!" }); + } + + if (!mongoose.Types.ObjectId.isValid(_id)) { + return res.status(404).json({ message: "Invalid category ID" }); + } + + try { + const deletedCategory = await CategoryModel.findByIdAndDelete(_id); + + if (!deletedCategory) { + return res.status(404).json({ message: "Category not found" }); + } + + res.status(200).json({ success: true, deletedCategory, message: "Category deleted successfully" }); + } catch (error) { + res.status(500).json({ + success: false, + message: error.message || "Something went wrong", }); } }; diff --git a/resources/Category/categoryRoutes.js b/resources/Category/categoryRoutes.js index 66c8cc5..0875a6a 100644 --- a/resources/Category/categoryRoutes.js +++ b/resources/Category/categoryRoutes.js @@ -10,20 +10,20 @@ const router = express.Router(); router .route("/add") - .post(isAuthenticatedUser, authorizeRoles("admin", "Employee"), addCategory); + .post(isAuthenticatedUser, authorizeRoles("admin"), addCategory); router.route("/getCategories").get(getCategories); router .route("/update/:_id") .patch( isAuthenticatedUser, - authorizeRoles("admin", "Employee"), + authorizeRoles("admin"), updateCategory ); router .route("/delete/:_id") .delete( isAuthenticatedUser, - authorizeRoles("admin", "Employee"), + authorizeRoles("admin"), deleteCategory ); diff --git a/resources/Inventory/InventoryController.js b/resources/Inventory/InventoryController.js index 19af1d1..bc13496 100644 --- a/resources/Inventory/InventoryController.js +++ b/resources/Inventory/InventoryController.js @@ -79,8 +79,6 @@ export const getDistributors = async (req, res) => { export const getAllInventories = async (req, res) => { try { const { page = 1, show = 10, startDate, endDate, name } = req.query; - - // Build query for date filtering const query = {}; if (startDate && endDate) { @@ -98,18 +96,17 @@ export const getAllInventories = async (req, res) => { $lte: new Date(end).setDate(end.getDate() + 1), }; } - } else if (startDate) { + } else if (startDate && endDate==='') { query.createdAt = { $gte: new Date(startDate), $lte: new Date(), }; - } else if (endDate) { + } else if (endDate && startDate==='') { query.createdAt = { $lte: new Date(endDate), }; } - // Fetch all matching documents (without pagination) to calculate total data const allInventories = await Inventory.find(query).sort({ createdAt: -1 }); // Populate additional details @@ -127,14 +124,17 @@ export const getAllInventories = async (req, res) => { if (inventory.addedFor === "PrincipalDistributor") { addedForData = await User.findById(inventory.addedForId); - const shippingAddress = await ShippingAddress.findOne({ - user: addedForData._id, - }); - addedForData = { - ...addedForData.toObject(), - shippingAddress, - }; - tradeName = addedForData.shippingAddress?.tradeName?.toLowerCase() || ""; + if (addedForData) { + const shippingAddress = await ShippingAddress.findOne({ + user: addedForData._id, + }); + addedForData = { + ...addedForData.toObject(), + shippingAddress, + }; + tradeName = + addedForData.shippingAddress?.tradeName?.toLowerCase() || ""; + } } else if (inventory.addedFor === "RetailDistributor") { addedForData = await KYC.findById(inventory.addedForId); tradeName = addedForData?.trade_name?.toLowerCase() || ""; @@ -149,11 +149,13 @@ export const getAllInventories = async (req, res) => { }) ); - // Apply name filter + // Apply name filter if the name parameter is provided let filteredInventories = populatedInventories; if (name) { filteredInventories = filteredInventories.filter( - (inventory) => inventory.tradeName && inventory.tradeName.includes(name.toLowerCase()) + (inventory) => + inventory.tradeName && + inventory.tradeName.includes(name.toLowerCase()) ); } @@ -161,8 +163,10 @@ export const getAllInventories = async (req, res) => { const total_data = filteredInventories.length; // Apply pagination after filtering - const paginatedInventories = filteredInventories - .slice((page - 1) * show, page * show); + const paginatedInventories = filteredInventories.slice( + (page - 1) * show, + page * show + ); // Calculate total pages const total_pages = Math.ceil(total_data / show); @@ -171,10 +175,11 @@ export const getAllInventories = async (req, res) => { res.status(200).json({ total_data, total_pages, - current_page: page, + current_page: Number(page), inventories: paginatedInventories, }); } catch (error) { + console.error("Error in getAllInventories:", error); res.status(500).json({ message: error.message }); } }; diff --git a/resources/Products/ProductController.js b/resources/Products/ProductController.js index 22f9271..dde518e 100644 --- a/resources/Products/ProductController.js +++ b/resources/Products/ProductController.js @@ -2,6 +2,8 @@ import { Product } from "./ProductModel.js"; import cloudinary from "../../Utils/cloudinary.js"; import { v4 as uuidv4 } from "uuid"; import { CategoryModel } from "../Category/CategoryModel.js"; +import { BrandModel } from "../Brands/BrandsModel.js"; +import User from "../user/userModel.js"; import { Tax } from "../Tax/tax_model.js"; import XLSX from "xlsx"; import fs from "fs"; @@ -9,6 +11,267 @@ import path from "path"; import mongoose from "mongoose"; // Function to handle product upload +// export const uploadProducts = async (req, res) => { +// try { +// if (!req.files || !req.files.file) { +// return res.status(400).json({ message: "No file uploaded" }); +// } + +// const file = req.files.file; +// const filePath = path.join("public", "uploads", file.name); + +// // Ensure 'uploads' directory exists +// if (!fs.existsSync(path.dirname(filePath))) { +// fs.mkdirSync(path.dirname(filePath), { recursive: true }); +// } + +// // Move the file from temp to the uploads directory +// await file.mv(filePath); + +// // Process the file +// const fileBuffer = fs.readFileSync(filePath); +// const workbook = XLSX.read(fileBuffer, { type: "buffer" }); +// const sheetName = workbook.SheetNames[0]; +// const worksheet = workbook.Sheets[sheetName]; +// const data = XLSX.utils.sheet_to_json(worksheet, { header: 1 }); + +// if (data.length <= 1) { +// return res.status(400).json({ message: "Empty spreadsheet or no data found" }); +// } + +// const headers = data[0]; + +// // Map headers from the Excel file to your schema +// const headerMapping = { +// SKU: "SKU", +// "Product Name": "name", +// "Category Name": "category", +// "Brand Name": "brand", +// Price: "price", +// "GST (in %)": "GST", +// "HSN Code": "HSN_Code", +// "Description (Optional)": "description", +// }; + +// const requiredHeaders = Object.keys(headerMapping); + +// if (!requiredHeaders.every((header) => headers.includes(header))) { +// return res.status(400).json({ message: "Missing required columns in spreadsheet" }); +// } + +// const errors = []; +// const newlyCreated = []; +// const updatedProducts = []; + +// for (let i = 1; i < data.length; i++) { +// const row = data[i]; +// const item = {}; + +// headers.forEach((header, index) => { +// if (headerMapping[header]) { +// item[headerMapping[header]] = row[index] !== undefined ? row[index] : ""; +// } +// }); + +// // Initialize error tracking for each item +// const missingFields = new Set(); +// const notFoundErrors = new Set(); + +// let { SKU, name, category, brand, price, GST, HSN_Code, description } = item; + +// // Trim leading and trailing spaces from product name and GST +// name = name ? name.trim() : ""; + +// // Validate required fields +// if (!SKU) missingFields.add("SKU"); +// if (!name) missingFields.add("name"); +// if (!category) missingFields.add("category"); +// if (!brand) missingFields.add("brand"); +// if (price === undefined || price === "") missingFields.add("price"); +// if (!GST) missingFields.add("GST"); +// if (!HSN_Code) missingFields.add("HSN_Code"); + +// // Validate or create category +// let categoryName = ""; +// if (category) { +// let categoryDoc = await CategoryModel.findOne({ +// categoryName: { $regex: new RegExp(`^${category.trim()}$`, "i") }, +// }).exec(); +// if (!categoryDoc) { +// // If category not found, create a new one +// categoryDoc = await CategoryModel.create({ +// categoryName: category.trim(), +// addedBy: req.user._id, +// }); +// } +// item.category = categoryDoc._id; +// categoryName = categoryDoc.categoryName; +// } + +// // Validate or create brand +// let brandName = ""; +// if (brand) { +// let brandDoc = await BrandModel.findOne({ +// brandName: { $regex: new RegExp(`^${brand.trim()}$`, "i") }, +// }).exec(); +// if (!brandDoc) { +// // If brand not found, create a new one +// brandDoc = await BrandModel.create({ +// brandName: brand.trim(), +// addedBy: req.user._id, +// }); +// } +// item.brand = brandDoc._id; +// brandName = brandDoc.brandName; +// } + +// // Combine all errors into a single message +// let errorMessage = ""; +// if (missingFields.size > 0) { +// errorMessage += `Missing fields: ${Array.from(missingFields).join(", ")}. `; +// } +// if (notFoundErrors.size > 0) { +// errorMessage += `Not found: ${Array.from(notFoundErrors).join(", ")}.`; +// } + +// // If there are errors, push them to the errors array +// if (errorMessage.trim()) { +// errors.push({ +// SKU: SKU || "N/A", +// productName: name || "N/A", +// category: category || "N/A", +// brand: brand || "N/A", +// GST: GST || "N/A", +// HSN_Code: HSN_Code || "N/A", +// price: price || "N/A", +// message: errorMessage.trim(), +// }); +// continue; +// } + +// // Ensure fields are set to empty strings if not provided +// description = description !== undefined ? description : ""; + +// // Check for existing product by SKU +// let existingProduct = await Product.findOne({ SKU }).exec(); + +// if (existingProduct) { +// // Track changes +// const updatedFields = []; +// let updatedProduct = { ...existingProduct._doc }; + +// // Fetch existing category name and brand name +// const existingCategory = await CategoryModel.findById(existingProduct.category).exec(); +// const existingBrand = await BrandModel.findById(existingProduct.brand).exec(); + +// // Update product fields if they have changed +// if (name !== existingProduct.name) { +// updatedFields.push("name"); +// updatedProduct.name = name; +// } +// if (category && existingProduct.category.toString() !== item.category.toString()) { +// updatedFields.push("category"); +// updatedProduct.category = categoryName; +// } else { +// updatedProduct.category = existingCategory ? existingCategory.categoryName : ""; +// } +// if (price !== undefined && price !== "" && existingProduct.price !== price) { +// updatedFields.push("price"); +// updatedProduct.price = price; +// } +// if (brand && existingProduct.brand.toString() !== item.brand.toString()) { +// updatedFields.push("brand"); +// updatedProduct.brand = brandName; +// } else { +// updatedProduct.brand = existingBrand ? existingBrand.brandName : ""; +// } +// if (HSN_Code !== existingProduct.HSN_Code) { +// updatedFields.push("HSN_Code"); +// updatedProduct.HSN_Code = HSN_Code; +// } +// if (GST !== existingProduct.GST) { +// updatedFields.push("GST"); +// updatedProduct.GST = GST; +// } +// if (description !== existingProduct.description) { +// updatedFields.push("description"); +// updatedProduct.description = description; +// } + +// // Only update if there are changes +// if (updatedFields.length > 0) { +// try { +// await Product.updateOne( +// { SKU: existingProduct.SKU }, +// { +// $set: { +// category: item.category || existingProduct.category, +// price: price !== undefined && price !== "" ? price : existingProduct.price, +// GST: GST || existingProduct.GST, +// HSN_Code: HSN_Code || existingProduct.HSN_Code, +// name: name, +// description: description, +// product_Status: item.product_Status || existingProduct.product_Status || "Active", +// }, +// } +// ); +// updatedProducts.push({ +// ...updatedProduct, +// updatedFields: updatedFields.join(", "), // Track updated fields +// }); +// } catch (error) { +// errors.push({ +// SKU, +// message: "Failed to update product", +// }); +// } +// } +// continue; +// } + +// // Create new product +// if (item.category && item.brand) { +// const productData = { +// SKU, +// name, +// category: item.category, +// brand: item.brand, +// price, +// GST, +// HSN_Code, +// description: description, +// product_Status: item.product_Status || "Active", +// addedBy: req.user._id, +// }; +// try { +// const newProduct = await Product.create(productData); +// newlyCreated.push({ +// ...newProduct._doc, +// category: categoryName, +// brand: brandName, +// }); +// } catch (error) { +// errors.push({ +// SKU, +// message: "Failed to create product", +// }); +// } +// } +// } + +// fs.unlinkSync(filePath); // Clean up uploaded file + +// res.status(201).json({ +// message: errors.length > 0 ? "Products processed with errors!" : "Products processed successfully!", +// newlyCreated: newlyCreated, +// updatedProducts: updatedProducts, +// errors, +// }); +// } catch (error) { +// console.error("Error:", error); +// res.status(500).json({ message: "Internal server error" }); +// } +// }; export const uploadProducts = async (req, res) => { try { if (!req.files || !req.files.file) { @@ -45,11 +308,12 @@ export const uploadProducts = async (req, res) => { const headerMapping = { SKU: "SKU", "Product Name": "name", - "category Name": "category", - price: "price", - "GST Name": "GST", - description: "description", - special_instructions: "special_instructions", + "Category Name": "category", + "Brand Name": "brand", + Price: "price", + "GST (in %)": "GST", + "HSN Code": "HSN_Code", + "Description (Optional)": "description", }; const requiredHeaders = Object.keys(headerMapping); @@ -64,6 +328,12 @@ export const uploadProducts = async (req, res) => { const newlyCreated = []; const updatedProducts = []; + const capitalizeWords = (str) => + str + .toLowerCase() + .replace(/\b\w/g, (char) => char.toUpperCase()) + .trim(); + for (let i = 1; i < data.length; i++) { const row = data[i]; const item = {}; @@ -75,61 +345,66 @@ export const uploadProducts = async (req, res) => { } }); + // Check if the row has meaningful data, skip if it's mostly empty + const hasValidData = Object.values(item).some((value) => value && value.trim()); + if (!hasValidData) { + continue; + } + // Initialize error tracking for each item const missingFields = new Set(); - const notFoundErrors = new Set(); - let { - SKU, - name, - category, - price, - GST, - description, - special_instructions, - } = item; + let { SKU, name, category, brand, price, GST, HSN_Code, description } = + item; - // Trim leading and trailing spaces from product name and GST + // Trim leading and trailing spaces and apply case formatting name = name ? name.trim() : ""; - GST = GST ? GST.toString().trim() : ""; + category = category ? capitalizeWords(category) : ""; + brand = brand ? capitalizeWords(brand) : ""; // Validate required fields if (!SKU) missingFields.add("SKU"); if (!name) missingFields.add("name"); if (!category) missingFields.add("category"); + if (!brand) missingFields.add("brand"); if (price === undefined || price === "") missingFields.add("price"); if (!GST) missingFields.add("GST"); + if (!HSN_Code) missingFields.add("HSN_Code"); - // Validate category - let categoryName = ""; + // Validate or create category + let categoryDoc = null; + let categoryname = ""; if (category) { - const categoryDoc = await CategoryModel.findOne({ - categoryName: { $regex: new RegExp(`^${category.trim()}$`, "i") }, + categoryDoc = await CategoryModel.findOne({ + categoryName: { $regex: new RegExp(`^${category}$`, "i") }, }).exec(); - if (categoryDoc) { - item.category = categoryDoc._id; - categoryName = categoryDoc.categoryName; - } else { - notFoundErrors.add("category"); + + if (!categoryDoc) { + categoryDoc = await CategoryModel.create({ + categoryName: category, + addedBy: req.user._id, + }); } - } else { - missingFields.add("category"); + categoryname = categoryDoc.categoryName; + item.category = categoryDoc._id; } - // Validate GST - let gstName = ""; - if (GST) { - const gstDoc = await Tax.findOne({ - name: { $regex: new RegExp(`^${GST}$`, "i") }, + // Validate or create brand + let brandDoc = null; + let brandname = ""; + if (brand) { + brandDoc = await BrandModel.findOne({ + brandName: { $regex: new RegExp(`^${brand}$`, "i") }, }).exec(); - if (gstDoc) { - item.GST = gstDoc._id; - gstName = gstDoc.name; - } else { - notFoundErrors.add("GST"); + + if (!brandDoc) { + brandDoc = await BrandModel.create({ + brandName: brand, + addedBy: req.user._id, + }); } - } else { - missingFields.add("GST"); + brandname = brandDoc.brandName; + item.brand = brandDoc._id; } // Combine all errors into a single message @@ -139,17 +414,16 @@ export const uploadProducts = async (req, res) => { ", " )}. `; } - if (notFoundErrors.size > 0) { - errorMessage += `Not found: ${Array.from(notFoundErrors).join(", ")}.`; - } // If there are errors, push them to the errors array if (errorMessage.trim()) { errors.push({ SKU: SKU || "N/A", productName: name || "N/A", - category: category || "N/A", + category: categoryname || "N/A", + brand: brandname || "N/A", GST: GST || "N/A", + HSN_Code: HSN_Code || "N/A", price: price || "N/A", message: errorMessage.trim(), }); @@ -158,8 +432,6 @@ export const uploadProducts = async (req, res) => { // Ensure fields are set to empty strings if not provided description = description !== undefined ? description : ""; - special_instructions = - special_instructions !== undefined ? special_instructions : ""; // Check for existing product by SKU let existingProduct = await Product.findOne({ SKU }).exec(); @@ -169,22 +441,19 @@ export const uploadProducts = async (req, res) => { const updatedFields = []; let updatedProduct = { ...existingProduct._doc }; - // Fetch existing category name and GST name - const existingCategory = await CategoryModel.findById( - existingProduct.category - ).exec(); - const existingGST = await Tax.findById(existingProduct.GST).exec(); - + // Update product fields if they have changed + if (name !== existingProduct.name) { + updatedFields.push("name"); + updatedProduct.name = name; + } if ( - category && + categoryDoc && existingProduct.category.toString() !== item.category.toString() ) { updatedFields.push("category"); - updatedProduct.category = categoryName; + updatedProduct.category = categoryname; } else { - updatedProduct.category = existingCategory - ? existingCategory.categoryName - : ""; + updatedProduct.category = categoryDoc.categoryName; } if ( price !== undefined && @@ -194,20 +463,27 @@ export const uploadProducts = async (req, res) => { updatedFields.push("price"); updatedProduct.price = price; } - if (GST && existingProduct.GST.toString() !== item.GST.toString()) { - updatedFields.push("GST"); - updatedProduct.GST = gstName; + if ( + brandDoc && + existingProduct.brand.toString() !== item.brand.toString() + ) { + updatedFields.push("brand"); + updatedProduct.brand = brandname; } else { - updatedProduct.GST = existingGST ? existingGST.name : ""; + updatedProduct.brand = brandDoc.brandName; + } + if (HSN_Code !== existingProduct.HSN_Code) { + updatedFields.push("HSN_Code"); + updatedProduct.HSN_Code = HSN_Code; + } + if (GST !== existingProduct.GST) { + updatedFields.push("GST"); + updatedProduct.GST = GST; } if (description !== existingProduct.description) { updatedFields.push("description"); updatedProduct.description = description; } - if (special_instructions !== existingProduct.special_instructions) { - updatedFields.push("special_instructions"); - updatedProduct.special_instructions = special_instructions; - } // Only update if there are changes if (updatedFields.length > 0) { @@ -217,13 +493,15 @@ export const uploadProducts = async (req, res) => { { $set: { category: item.category || existingProduct.category, + brand: item.brand || existingProduct.brand, price: price !== undefined && price !== "" ? price : existingProduct.price, - GST: item.GST || existingProduct.GST, + GST: GST || existingProduct.GST, + HSN_Code: HSN_Code || existingProduct.HSN_Code, + name: name, description: description, - special_instructions: special_instructions, product_Status: item.product_Status || existingProduct.product_Status || @@ -246,15 +524,16 @@ export const uploadProducts = async (req, res) => { } // Create new product - if (item.category && item.GST) { + if (item.category && item.brand) { const productData = { SKU, name, category: item.category, + brand: item.brand, price, - GST: item.GST, + GST, + HSN_Code, description: description, - special_instructions: special_instructions, product_Status: item.product_Status || "Active", addedBy: req.user._id, }; @@ -262,8 +541,8 @@ export const uploadProducts = async (req, res) => { const newProduct = await Product.create(productData); newlyCreated.push({ ...newProduct._doc, - category: categoryName, - GST: gstName, + category: categoryDoc.categoryName, + brand: brandDoc.brandName, }); } catch (error) { errors.push({ @@ -286,8 +565,8 @@ export const uploadProducts = async (req, res) => { errors, }); } catch (error) { - console.error("Error:", error); - res.status(500).json({ message: error.message || "Something went wrong!" }); + console.error("Error uploading products:", error); + res.status(500).json({ message: "Server error" }); } }; @@ -296,7 +575,7 @@ export const createProduct = async (req, res) => { let findProduct = ""; let product = { _id: "" }; const sku = req.body?.SKU; - + // console.log(req.body); if (!sku) { return res.status(400).json({ message: "SKU is required!" }); } @@ -450,13 +729,16 @@ export const getAllProductAdmin = async (req, res) => { if (req.query.category) { filter.category = mongoose.Types.ObjectId(req.query.category); } + if (req.query.brand) { + filter.brand = mongoose.Types.ObjectId(req.query.brand); + } const total = await Product.countDocuments(filter); const products = await Product.find(filter) .populate({ - path: "category addedBy GST", - select: "categoryName name tax", + path: "category addedBy brand", + select: "categoryName name brandName", }) .limit(PAGE_SIZE) .skip(skip) @@ -485,10 +767,12 @@ export const getAllProductUser = async (req, res) => { const PAGE_SIZE = parseInt(req.query?.show || "10"); const page = parseInt(req.query?.page || "1") - 1; let filter = {}; - + // Filter by category name if (req.query?.category) { - const category = await CategoryModel.findOne({ categoryName: req.query.category }); + const category = await CategoryModel.findOne({ + categoryName: req.query.category, + }); if (category) { filter.category = category._id; } else { @@ -498,7 +782,9 @@ export const getAllProductUser = async (req, res) => { }); } } - + if (req.query.brand) { + filter.brand = mongoose.Types.ObjectId(req.query.brand); + } // Filter by SKU if (req.query?.SKU) { filter.SKU = req.query.SKU; @@ -507,7 +793,7 @@ export const getAllProductUser = async (req, res) => { // Filter by product name using regex for case-insensitive partial matching if (req.query?.name) { filter.name = { - $regex: new RegExp(req.query.name, 'i'), + $regex: new RegExp(req.query.name, "i"), }; } @@ -520,8 +806,8 @@ export const getAllProductUser = async (req, res) => { // Retrieve products with pagination, filtering, and sorting const products = await Product.find(filter) .populate({ - path: "category addedBy GST", - select: "categoryName name tax", + path: "category addedBy brand", + select: "categoryName name brandName", }) .limit(PAGE_SIZE) .skip(PAGE_SIZE * page) @@ -588,8 +874,8 @@ export const ChangeProductStatus = async (req, res) => { export const getOneProduct = async (req, res) => { try { const data = await Product.findById(req.params.id).populate({ - path: "category addedBy GST", - select: "name categoryName tax", + path: "category addedBy brand", + select: "categoryName name brandName", }); if (data) { return res.status(200).json({ diff --git a/resources/Products/ProductModel.js b/resources/Products/ProductModel.js index 485de87..895925c 100644 --- a/resources/Products/ProductModel.js +++ b/resources/Products/ProductModel.js @@ -20,24 +20,27 @@ const productSchema = new Schema( type: Schema.Types.ObjectId, ref: "CategoryModel", }, - + brand: { + type: Schema.Types.ObjectId, + ref: "BrandModel", + }, price: { type: Number, required: true, }, GST: { - type: mongoose.Schema.ObjectId, - ref: "Tax", + type: Number, + required: true, + }, + HSN_Code: { + type: Number, + required: true, }, description: { type: String, maxLength: [400, "description cannot exceed 100 characters"], // required: [true, "Please Enter product Description"], }, - - special_instructions: { - type: String, - }, image: [ { public_id: {