PD updated with add new field SBU
This commit is contained in:
parent
69dc2cb1b4
commit
692a69ee61
3
app.js
3
app.js
@ -163,7 +163,6 @@ import CurrencyRoute from "./resources/Currency/CurrencyRoute.js";
|
|||||||
|
|
||||||
import ConfigRouter from "./resources/setting/Configration/Config_routes.js";
|
import ConfigRouter from "./resources/setting/Configration/Config_routes.js";
|
||||||
|
|
||||||
import TaxRouter from "./resources/Tax/tax_routes.js";
|
|
||||||
//specialties
|
//specialties
|
||||||
import SpecialtiesRouter from "./resources/Specialties/SpecialtiesRoute.js";
|
import SpecialtiesRouter from "./resources/Specialties/SpecialtiesRoute.js";
|
||||||
import ShippingAddressRoute from "./resources/ShippingAddresses/ShippingAddressRoute.js";
|
import ShippingAddressRoute from "./resources/ShippingAddresses/ShippingAddressRoute.js";
|
||||||
@ -233,8 +232,6 @@ app.use("/api/language", LanguageRoute);
|
|||||||
//Purpose
|
//Purpose
|
||||||
app.use("/api/purpose", PurposeRoute);
|
app.use("/api/purpose", PurposeRoute);
|
||||||
app.use("/api/business", orderRoute);
|
app.use("/api/business", orderRoute);
|
||||||
//Tax
|
|
||||||
app.use("/api/tax", TaxRouter);
|
|
||||||
//Currency Route
|
//Currency Route
|
||||||
app.use("/api/currency", CurrencyRoute);
|
app.use("/api/currency", CurrencyRoute);
|
||||||
//config
|
//config
|
||||||
|
BIN
public/uploads/Add-PD.xlsx
Normal file
BIN
public/uploads/Add-PD.xlsx
Normal file
Binary file not shown.
@ -3,275 +3,12 @@ import cloudinary from "../../Utils/cloudinary.js";
|
|||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
import { CategoryModel } from "../Category/CategoryModel.js";
|
import { CategoryModel } from "../Category/CategoryModel.js";
|
||||||
import { BrandModel } from "../Brands/BrandsModel.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 XLSX from "xlsx";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import mongoose from "mongoose";
|
import mongoose from "mongoose";
|
||||||
|
|
||||||
// Function to handle product upload
|
// 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) => {
|
export const uploadProducts = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
if (!req.files || !req.files.file) {
|
if (!req.files || !req.files.file) {
|
||||||
|
@ -1,77 +0,0 @@
|
|||||||
import { Tax } from "./tax_model.js";
|
|
||||||
|
|
||||||
export const addTax = async (req, res) => {
|
|
||||||
if (!req.user) {
|
|
||||||
return res.status(400).json({ message: "User Not Found" });
|
|
||||||
}
|
|
||||||
const tax = new Tax({
|
|
||||||
name: req.body.name,
|
|
||||||
tax: req.body.tax,
|
|
||||||
hsn_code: req.body.hsn_code,
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
const data = await tax.save();
|
|
||||||
res.status(201).json({ message: "Success", data: data });
|
|
||||||
} catch (error) {
|
|
||||||
res.status(500).json({ message: error.message ? error.message : "Something went Wrong" });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const updateTax = async (req, res) => {
|
|
||||||
if (!req.user) {
|
|
||||||
return res.status(400).json({ message: "User Not Found" });
|
|
||||||
}
|
|
||||||
const id = req.params.id;
|
|
||||||
const queryObj = req.body;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const data = await Tax.findByIdAndUpdate(id, queryObj, {
|
|
||||||
new: true,
|
|
||||||
});
|
|
||||||
res.status(200).json({ message: "Success", data: data });
|
|
||||||
} catch (error) {
|
|
||||||
res.status(500).json({ message: error.message, message: "failed" });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const deleteTax = async (req, res) => {
|
|
||||||
if (!req.user) {
|
|
||||||
return res.status(400).json({ message: "User Not Found" });
|
|
||||||
}
|
|
||||||
const id = req.params.id;
|
|
||||||
try {
|
|
||||||
const data = await Tax.findByIdAndDelete(id);
|
|
||||||
res.status(200).json({ message: "Success" });
|
|
||||||
} catch (error) {
|
|
||||||
res.status(500).json({ message: error.message, message: "failed" });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getTaxes = async (req, res) => {
|
|
||||||
if (!req.user) {
|
|
||||||
return res.status(400).json({ message: "User Not Found" });
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const data = await Tax.find().sort({ createdAt: -1 });
|
|
||||||
res.status(200).json(data);
|
|
||||||
} catch (error) {
|
|
||||||
res.status(500).json({ message: error.message, message: "failed" });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getTax = async (req, res) => {
|
|
||||||
if (!req.user) {
|
|
||||||
return res.status(400).json({ message: "User Not Found" });
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
let { id } = req.params;
|
|
||||||
const tax = await Tax.findById({ _id: id });
|
|
||||||
return res.status(200).json(tax);
|
|
||||||
} catch (error) {
|
|
||||||
return res.status(504).json({
|
|
||||||
status: "failed",
|
|
||||||
error,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,14 +0,0 @@
|
|||||||
import mongoose from "mongoose";
|
|
||||||
|
|
||||||
const { Schema, model } = mongoose;
|
|
||||||
|
|
||||||
const TaxSchema = new Schema(
|
|
||||||
{
|
|
||||||
name: String,
|
|
||||||
hsn_code: Number,
|
|
||||||
tax: Number,
|
|
||||||
},
|
|
||||||
{ timestamps: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
export const Tax = model("Tax", TaxSchema);
|
|
@ -1,23 +0,0 @@
|
|||||||
import { Router } from "express";
|
|
||||||
import { authorizeRoles, isAuthenticatedUser } from "../../middlewares/auth.js";
|
|
||||||
import {
|
|
||||||
addTax,
|
|
||||||
updateTax,
|
|
||||||
deleteTax,
|
|
||||||
getTaxes,
|
|
||||||
getTax,
|
|
||||||
} from "./tax_controller.js";
|
|
||||||
const router = Router();
|
|
||||||
|
|
||||||
router
|
|
||||||
.route("/add_tax")
|
|
||||||
.post(isAuthenticatedUser, authorizeRoles("admin", "Employee"), addTax);
|
|
||||||
router
|
|
||||||
.route("/update_tax/:id")
|
|
||||||
.patch(isAuthenticatedUser, authorizeRoles("admin", "Employee"), updateTax);
|
|
||||||
router
|
|
||||||
.route("/delete_tax/:id")
|
|
||||||
.delete(isAuthenticatedUser, authorizeRoles("admin", "Employee"), deleteTax);
|
|
||||||
router.route("/view_tax/:id").get(isAuthenticatedUser, getTax);
|
|
||||||
router.route("/view_tax").get(isAuthenticatedUser, getTaxes);
|
|
||||||
export default router;
|
|
@ -59,6 +59,278 @@ const generatePassword = (name, email) => {
|
|||||||
return password;
|
return password;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// export const uploadPrincipaldistributors = 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 = {
|
||||||
|
// "PD ID (From SAP)": "uniqueId",
|
||||||
|
// "SBU":"SBU",
|
||||||
|
// "Principal Distributor Name": "name",
|
||||||
|
// "Email": "email",
|
||||||
|
// "Phone Number": "phone",
|
||||||
|
// "PAN Number": "panNumber",
|
||||||
|
// "Trade Name": "tradeName",
|
||||||
|
// "GST Number": "gstNumber",
|
||||||
|
// "State": "state",
|
||||||
|
// "City": "city",
|
||||||
|
// "Street": "street",
|
||||||
|
// "Pincode": "postalCode",
|
||||||
|
// };
|
||||||
|
|
||||||
|
// 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 updatedDistributors = [];
|
||||||
|
|
||||||
|
// 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 validationErrors = new Set();
|
||||||
|
|
||||||
|
// // Validate required fields
|
||||||
|
// if (!item.uniqueId) missingFields.add("uniqueId");
|
||||||
|
// if(!item.SBU) missingFields.add("SBU");
|
||||||
|
// if (!item.name) missingFields.add("name");
|
||||||
|
// if (!item.email) missingFields.add("email");
|
||||||
|
// if (!item.phone) missingFields.add("phone");
|
||||||
|
// if (!item.panNumber) missingFields.add("panNumber");
|
||||||
|
// if (!item.tradeName) missingFields.add("tradeName");
|
||||||
|
// if (!item.gstNumber) missingFields.add("gstNumber");
|
||||||
|
// if (!item.state) missingFields.add("state");
|
||||||
|
// if (!item.city) missingFields.add("city");
|
||||||
|
// if (!item.street) missingFields.add("street");
|
||||||
|
// if (!item.postalCode) missingFields.add("postalCode");
|
||||||
|
|
||||||
|
// // Check email validity
|
||||||
|
// if (item.email && !validator.isEmail(item.email)) {
|
||||||
|
// validationErrors.add("incorrect mail");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Validate mobile number
|
||||||
|
// if (item.phone && !/^\d{10}$/.test(item.phone)) {
|
||||||
|
// validationErrors.add("Invalid Mobile Number (should be 10 digits)");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Check GST, PAN, and postal code validation
|
||||||
|
// item.panNumber = item.panNumber ? item.panNumber.toUpperCase() : "";
|
||||||
|
// item.gstNumber = item.gstNumber ? item.gstNumber.toUpperCase() : "";
|
||||||
|
|
||||||
|
// // Validate PAN Number
|
||||||
|
// if (item.panNumber && !/^[A-Z]{5}[0-9]{4}[A-Z]{1}$/.test(item.panNumber)) {
|
||||||
|
// validationErrors.add("Invalid PAN Number");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Validate GST Number
|
||||||
|
// if (item.gstNumber && !/^(\d{2}[A-Z]{5}\d{4}[A-Z]{1}\d[Z]{1}[A-Z\d]{1})$/.test(item.gstNumber)) {
|
||||||
|
// validationErrors.add("Invalid GST Number");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Validate Postal Code
|
||||||
|
// if (item.postalCode && !/^\d{6}$/.test(item.postalCode)) {
|
||||||
|
// validationErrors.add("Invalid Postal Code");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Combine all errors into a single message
|
||||||
|
// let errorMessage = "";
|
||||||
|
// if (missingFields.size > 0) {
|
||||||
|
// errorMessage += `Missing fields: ${Array.from(missingFields).join(", ")}. `;
|
||||||
|
// }
|
||||||
|
// if (validationErrors.size > 0) {
|
||||||
|
// errorMessage += `Validation errors: ${Array.from(validationErrors).join(", ")}.`;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // If there are errors, push them to the errors array
|
||||||
|
// if (errorMessage.trim()) {
|
||||||
|
// errors.push({
|
||||||
|
// uniqueId: item.uniqueId || "N/A",
|
||||||
|
// SBU:item.SBU || "N/A",
|
||||||
|
// name: item.name || "N/A",
|
||||||
|
// email: item.email || "N/A",
|
||||||
|
// phone: item.phone || "N/A",
|
||||||
|
// panNumber: item.panNumber || "N/A",
|
||||||
|
// gstNumber: item.gstNumber || "N/A",
|
||||||
|
// message: errorMessage.trim(),
|
||||||
|
// });
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Generate a password
|
||||||
|
// const password = generatePassword(item.name, item.email);
|
||||||
|
// item.role = "principal-Distributor";
|
||||||
|
|
||||||
|
// // Check for existing user by uniqueId
|
||||||
|
// let distributor = await User.findOne({ uniqueId: item.uniqueId });
|
||||||
|
|
||||||
|
// if (distributor) {
|
||||||
|
// // Track updated fields
|
||||||
|
// const updatedFields = [];
|
||||||
|
// const addressFields = ['panNumber', 'gstNumber', 'state', 'city', 'street', 'tradeName', 'postalCode'];
|
||||||
|
// const existingAddress = await ShippingAddress.findOne({ user: distributor._id });
|
||||||
|
|
||||||
|
// // Check for changes in user details
|
||||||
|
// let userUpdated = false;
|
||||||
|
// if (distributor.name !== item.name) {
|
||||||
|
// updatedFields.push("name");
|
||||||
|
// distributor.name = item.name;
|
||||||
|
// userUpdated = true;
|
||||||
|
// }
|
||||||
|
// if (distributor.email !== item.email) {
|
||||||
|
// updatedFields.push("email");
|
||||||
|
// distributor.email = item.email;
|
||||||
|
// userUpdated = true;
|
||||||
|
// }
|
||||||
|
// if(distributor.SBU !== item.SBU){
|
||||||
|
// updatedFields.push("SBU");
|
||||||
|
// distributor.SBU = item.SBU;
|
||||||
|
// userUpdated = true;
|
||||||
|
// }
|
||||||
|
// if (distributor.phone !== item.phone.toString()) {
|
||||||
|
// updatedFields.push("phone");
|
||||||
|
// distributor.phone = item.phone;
|
||||||
|
// userUpdated = true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Update user
|
||||||
|
// if (userUpdated) {
|
||||||
|
// await distributor.save();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Check for changes in address details
|
||||||
|
// const addressData = {
|
||||||
|
// street: item.street,
|
||||||
|
// city: item.city,
|
||||||
|
// state: item.state,
|
||||||
|
// postalCode: item.postalCode.toString(),
|
||||||
|
// country: "India", // Default country
|
||||||
|
// panNumber: item.panNumber,
|
||||||
|
// tradeName: item.tradeName,
|
||||||
|
// gstNumber: item.gstNumber,
|
||||||
|
// user: distributor._id,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// let addressUpdated = false;
|
||||||
|
// if (existingAddress) {
|
||||||
|
// const addressUpdates = [];
|
||||||
|
// addressFields.forEach(field => {
|
||||||
|
// if (existingAddress[field] !== addressData[field]) {
|
||||||
|
// addressUpdates.push(field);
|
||||||
|
// addressUpdated = true;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// if (addressUpdated) {
|
||||||
|
// await ShippingAddress.updateOne({ user: distributor._id }, addressData);
|
||||||
|
// if (addressUpdates.length > 0) {
|
||||||
|
// updatedFields.push(`Address fields: ${addressUpdates.join(", ")}`);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// // Create new address
|
||||||
|
// await ShippingAddress.create(addressData);
|
||||||
|
// updatedFields.push("New address created");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Add to updatedDistributors only if there are updated fields
|
||||||
|
// if (updatedFields.length > 0) {
|
||||||
|
// updatedDistributors.push({
|
||||||
|
// ...distributor._doc,
|
||||||
|
// updatedFields: updatedFields.join(", ")
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// // Create a new user
|
||||||
|
// distributor = new User({
|
||||||
|
// name: item.name,
|
||||||
|
// SBU:item.SBU,
|
||||||
|
// email: item.email,
|
||||||
|
// phone: item.phone,
|
||||||
|
// password,
|
||||||
|
// role: item.role,
|
||||||
|
// uniqueId: item.uniqueId,
|
||||||
|
// });
|
||||||
|
// await distributor.save();
|
||||||
|
|
||||||
|
// // Send email with the new user details
|
||||||
|
// await sendEmail({
|
||||||
|
// to: item.email,
|
||||||
|
// from: process.env.SEND_EMAIL_FROM,
|
||||||
|
// subject: `Cheminova Account Created`,
|
||||||
|
// html: `
|
||||||
|
// Your Principal Distributor Account is created successfully.
|
||||||
|
// <br/>Name: <strong>${item.name}</strong><br/>
|
||||||
|
// <br/>Mobile Number: <strong>${item.phone}</strong><br/>
|
||||||
|
// <br/>Password: <strong>${password}</strong><br/><br/>
|
||||||
|
// <a href="${process.env.PD_APP_URL}/login">Click here to login</a><br/><br/>
|
||||||
|
// If you have not requested this email, please ignore it.
|
||||||
|
// `,
|
||||||
|
// });
|
||||||
|
|
||||||
|
// newlyCreated.push(distributor._doc);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fs.unlinkSync(filePath); // Clean up uploaded file
|
||||||
|
|
||||||
|
// res.status(201).json({
|
||||||
|
// message:
|
||||||
|
// errors.length > 0
|
||||||
|
// ? "File processed with errors!"
|
||||||
|
// : "File processed successfully!",
|
||||||
|
// processedUsers: {
|
||||||
|
// newlyCreated: newlyCreated.length,
|
||||||
|
// updatedDistributors: updatedDistributors.length
|
||||||
|
// },
|
||||||
|
// errors,
|
||||||
|
// newlyCreated,
|
||||||
|
// updatedDistributors
|
||||||
|
// });
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error("Error processing file:", error);
|
||||||
|
// res.status(500).json({ message: "Error processing file", error: error.message });
|
||||||
|
// }
|
||||||
|
// };
|
||||||
export const uploadPrincipaldistributors = async (req, res) => {
|
export const uploadPrincipaldistributors = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
if (!req.files || !req.files.file) {
|
if (!req.files || !req.files.file) {
|
||||||
@ -92,6 +364,7 @@ export const uploadPrincipaldistributors = async (req, res) => {
|
|||||||
// Map headers from the Excel file to your schema
|
// Map headers from the Excel file to your schema
|
||||||
const headerMapping = {
|
const headerMapping = {
|
||||||
"PD ID (From SAP)": "uniqueId",
|
"PD ID (From SAP)": "uniqueId",
|
||||||
|
"SBU":"SBU",
|
||||||
"Principal Distributor Name": "name",
|
"Principal Distributor Name": "name",
|
||||||
"Email": "email",
|
"Email": "email",
|
||||||
"Phone Number": "phone",
|
"Phone Number": "phone",
|
||||||
@ -130,6 +403,7 @@ export const uploadPrincipaldistributors = async (req, res) => {
|
|||||||
|
|
||||||
// Validate required fields
|
// Validate required fields
|
||||||
if (!item.uniqueId) missingFields.add("uniqueId");
|
if (!item.uniqueId) missingFields.add("uniqueId");
|
||||||
|
if(!item.SBU) missingFields.add("SBU");
|
||||||
if (!item.name) missingFields.add("name");
|
if (!item.name) missingFields.add("name");
|
||||||
if (!item.email) missingFields.add("email");
|
if (!item.email) missingFields.add("email");
|
||||||
if (!item.phone) missingFields.add("phone");
|
if (!item.phone) missingFields.add("phone");
|
||||||
@ -183,6 +457,7 @@ export const uploadPrincipaldistributors = async (req, res) => {
|
|||||||
if (errorMessage.trim()) {
|
if (errorMessage.trim()) {
|
||||||
errors.push({
|
errors.push({
|
||||||
uniqueId: item.uniqueId || "N/A",
|
uniqueId: item.uniqueId || "N/A",
|
||||||
|
SBU:item.SBU || "N/A",
|
||||||
name: item.name || "N/A",
|
name: item.name || "N/A",
|
||||||
email: item.email || "N/A",
|
email: item.email || "N/A",
|
||||||
phone: item.phone || "N/A",
|
phone: item.phone || "N/A",
|
||||||
@ -213,6 +488,16 @@ export const uploadPrincipaldistributors = async (req, res) => {
|
|||||||
distributor.name = item.name;
|
distributor.name = item.name;
|
||||||
userUpdated = true;
|
userUpdated = true;
|
||||||
}
|
}
|
||||||
|
if (distributor.email !== item.email) {
|
||||||
|
updatedFields.push("email");
|
||||||
|
distributor.email = item.email;
|
||||||
|
userUpdated = true;
|
||||||
|
}
|
||||||
|
if(distributor.SBU !== item.SBU){
|
||||||
|
updatedFields.push("SBU");
|
||||||
|
distributor.SBU = item.SBU;
|
||||||
|
userUpdated = true;
|
||||||
|
}
|
||||||
if (distributor.phone !== item.phone.toString()) {
|
if (distributor.phone !== item.phone.toString()) {
|
||||||
updatedFields.push("phone");
|
updatedFields.push("phone");
|
||||||
distributor.phone = item.phone;
|
distributor.phone = item.phone;
|
||||||
@ -270,6 +555,7 @@ export const uploadPrincipaldistributors = async (req, res) => {
|
|||||||
// Create a new user
|
// Create a new user
|
||||||
distributor = new User({
|
distributor = new User({
|
||||||
name: item.name,
|
name: item.name,
|
||||||
|
SBU: item.SBU,
|
||||||
email: item.email,
|
email: item.email,
|
||||||
phone: item.phone,
|
phone: item.phone,
|
||||||
password,
|
password,
|
||||||
@ -278,123 +564,44 @@ export const uploadPrincipaldistributors = async (req, res) => {
|
|||||||
});
|
});
|
||||||
await distributor.save();
|
await distributor.save();
|
||||||
|
|
||||||
// Send email with the new user details
|
// Now create the address for the new user
|
||||||
await sendEmail({
|
const addressData = {
|
||||||
to: item.email,
|
street: item.street,
|
||||||
from: process.env.SEND_EMAIL_FROM,
|
city: item.city,
|
||||||
subject: `Cheminova Account Created`,
|
state: item.state,
|
||||||
html: `
|
postalCode: item.postalCode.toString(),
|
||||||
Your Principal Distributor Account is created successfully.
|
country: "India", // Default country
|
||||||
<br/>Name: <strong>${item.name}</strong><br/>
|
panNumber: item.panNumber,
|
||||||
<br/>Mobile Number: <strong>${item.phone}</strong><br/>
|
tradeName: item.tradeName,
|
||||||
<br/>Password: <strong>${password}</strong><br/><br/>
|
gstNumber: item.gstNumber,
|
||||||
<a href="${process.env.PD_APP_URL}/login">Click here to login</a><br/><br/>
|
user: distributor._id, // Use the saved user's ID
|
||||||
If you have not requested this email, please ignore it.
|
};
|
||||||
`,
|
const newAddress = await ShippingAddress.create(addressData);
|
||||||
});
|
|
||||||
|
|
||||||
newlyCreated.push(distributor._doc);
|
// Push both the distributor and the addressData to the newlyCreated array
|
||||||
|
newlyCreated.push({
|
||||||
|
distributor,
|
||||||
|
address: newAddress,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.unlinkSync(filePath); // Clean up uploaded file
|
res.status(200).json({
|
||||||
|
message: "File processed successfully",
|
||||||
res.status(201).json({
|
|
||||||
message:
|
|
||||||
errors.length > 0
|
|
||||||
? "File processed with errors!"
|
|
||||||
: "File processed successfully!",
|
|
||||||
processedUsers: {
|
|
||||||
newlyCreated: newlyCreated.length,
|
|
||||||
updatedDistributors: updatedDistributors.length
|
|
||||||
},
|
|
||||||
errors,
|
|
||||||
newlyCreated,
|
newlyCreated,
|
||||||
updatedDistributors
|
updatedDistributors,
|
||||||
|
errors,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error processing file:", error);
|
console.error(error);
|
||||||
res.status(500).json({ message: "Error processing file", error: error.message });
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 1.Register a User
|
// 1.Register a User
|
||||||
// export const registerUser = async (req, res) => {
|
|
||||||
// try {
|
|
||||||
// const { name, email, password, phone, accessTo, role } = req.body;
|
|
||||||
// // console.log("this is the password ", password, name, req.body);
|
|
||||||
|
|
||||||
// let findUser = await User.findOne({ email });
|
|
||||||
// if (findUser) {
|
|
||||||
// return res
|
|
||||||
// .status(400)
|
|
||||||
// .json({ success: false, message: "User already exists" });
|
|
||||||
// }
|
|
||||||
// if (req.files) {
|
|
||||||
// const files = req.files.avatar;
|
|
||||||
// const myCloud = await cloudinary.uploader.upload(
|
|
||||||
// files.tempFilePath,
|
|
||||||
// {
|
|
||||||
// folder: "Cheminova/user-image",
|
|
||||||
// },
|
|
||||||
// function (error, result) {
|
|
||||||
// result, error;
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const user = await User.create({
|
|
||||||
// name,
|
|
||||||
// email,
|
|
||||||
// password,
|
|
||||||
// phone,
|
|
||||||
// role,
|
|
||||||
// accessTo,
|
|
||||||
// // avatar: {
|
|
||||||
// // public_id: myCloud.public_id,
|
|
||||||
// // url: myCloud.secure_url,
|
|
||||||
// // },
|
|
||||||
// });
|
|
||||||
// // const emailData = await RegisterEmail.find();
|
|
||||||
// // let emailSubject = emailData[0]?.subject;
|
|
||||||
// // let emailDescription = emailData[0]?.description;
|
|
||||||
// const config = await Config.find();
|
|
||||||
// let appName = config[0]?.appName;
|
|
||||||
|
|
||||||
// // await sendEmail({
|
|
||||||
// // to: `${email}`, // Change to your recipient
|
|
||||||
|
|
||||||
// // from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender
|
|
||||||
|
|
||||||
// // subject: `Welcome to Cheminova - Let the Shopping Begin!`,
|
|
||||||
// // html: ` <h1 style="color: #333; text-align: left; font-family: Arial, sans-serif;">Welcome to ${appName} - Let the Shopping Begin!</h1>
|
|
||||||
// // <strong style="color: #1b03a3; font-size: 16px"> Hey ${name},</strong>
|
|
||||||
|
|
||||||
// // <p style="color: #555; font-size: 15px;">
|
|
||||||
|
|
||||||
// // Welcome to Cheminova - Let the Shopping Begin!
|
|
||||||
// // </p>
|
|
||||||
// // <br/>
|
|
||||||
// // <p style="color: #555; font-size: 15px;">You can login into :${role === "Employee" || role === "admin"
|
|
||||||
// // ? `https://admin.smellika.com/`
|
|
||||||
// // : `https://smellika.com`
|
|
||||||
// // } </p>
|
|
||||||
// // <br/>
|
|
||||||
// // <p style="color: #555; font-size: 15px;">Below are your login credentials:</p>
|
|
||||||
// // <p style="color: #555; font-size: 15px;">Email: ${email}</p>
|
|
||||||
// // <p style="color: #555; font-size: 15px;">Password: ${password}</p>
|
|
||||||
// // <span style="color: #555; font-size: 13px;">Happy shopping,</span><br/>
|
|
||||||
|
|
||||||
// // <span style="color: #555; font-size: 13px;">Team ${appName}</span>`,
|
|
||||||
// // });
|
|
||||||
// sendToken(user, 201, res);
|
|
||||||
// } catch (e) {
|
|
||||||
// return res.status(400).json({ success: false, message: e.message });
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
export const registerUser = async (req, res) => {
|
export const registerUser = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { name, email, phone, accessTo, role,PD_ID } = req.body;
|
const { name, email, phone, accessTo, role,PD_ID,SBU } = req.body;
|
||||||
// console.log(req.body);
|
// console.log(req.body);
|
||||||
const password = generatePassword(name, email);
|
const password = generatePassword(name, email);
|
||||||
// console.log(password);
|
// console.log(password);
|
||||||
@ -408,7 +615,7 @@ export const registerUser = async (req, res) => {
|
|||||||
user.phone = phone;
|
user.phone = phone;
|
||||||
user.role = role;
|
user.role = role;
|
||||||
user.accessTo = accessTo;
|
user.accessTo = accessTo;
|
||||||
|
user.SBU=SBU;
|
||||||
// Save updates
|
// Save updates
|
||||||
await user.save();
|
await user.save();
|
||||||
// console.log("finduser", user);
|
// console.log("finduser", user);
|
||||||
@ -423,6 +630,7 @@ export const registerUser = async (req, res) => {
|
|||||||
// Create a new user if not found
|
// Create a new user if not found
|
||||||
user = new User({
|
user = new User({
|
||||||
uniqueId: PD_ID,
|
uniqueId: PD_ID,
|
||||||
|
SBU,
|
||||||
name,
|
name,
|
||||||
email,
|
email,
|
||||||
password,
|
password,
|
||||||
|
@ -13,11 +13,14 @@ const userSchema = new mongoose.Schema(
|
|||||||
unique: true,
|
unique: true,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
SBU: {
|
||||||
|
type: String,
|
||||||
|
required: [true, "Please Enter Your SBU"],
|
||||||
|
},
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
required: [true, "Please Enter Your Name"],
|
required: [true, "Please Enter Your Name"],
|
||||||
maxLength: [30, "Name cannot exceed 30 characters"],
|
maxLength: [30, "Name cannot exceed 30 characters"],
|
||||||
minLength: [4, "Name should have more than 4 characters"],
|
|
||||||
},
|
},
|
||||||
email: {
|
email: {
|
||||||
type: String,
|
type: String,
|
||||||
|
Loading…
Reference in New Issue
Block a user