From 7f74a8c73be25f6d822604569407013eda08abc9 Mon Sep 17 00:00:00 2001 From: Sibunnayak Date: Thu, 17 Oct 2024 14:02:21 +0530 Subject: [PATCH] upload sc and tm fixed also register sc and tm fixed and get all tm for dropdown fixed --- public/uploads/Add-SC.xlsx | Bin 10654 -> 10751 bytes public/uploads/Add-TM.xlsx | Bin 10609 -> 10742 bytes .../SalesCoOrdinatorController.js | 134 +++++++++++----- .../TerritoryManagerController.js | 150 ++++++++++++++---- .../TerritoryManagerRoute.js | 7 + 5 files changed, 222 insertions(+), 69 deletions(-) diff --git a/public/uploads/Add-SC.xlsx b/public/uploads/Add-SC.xlsx index 744e40a9ebee70e3bad86e590f1de277c62f1dfc..eab142e4f223caebd125d3c08272d6d92d73806f 100644 GIT binary patch delta 2847 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 delta 2753 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 PDexFQm=Fjl`uFS~7h!K% delta 2773 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 { // Map headers from the Excel file to your schema const headerMapping = { + "Employee Code": "uniqueId", "Sales Coordinator Name": "name", Email: "email", "Phone Number": "mobileNumber", @@ -67,7 +68,7 @@ export const uploadSalesCoordinators = async (req, res) => { for (let i = 1; i < data.length; i++) { const row = data[i]; // Skip the row if it's completely empty - if (row.every(cell => cell === undefined || cell === "")) { + if (row.every((cell) => cell === undefined || cell === "")) { continue; } const item = {}; @@ -84,6 +85,7 @@ export const uploadSalesCoordinators = async (req, res) => { const validationErrors = new Set(); // Validate required fields + if (!item.uniqueId) missingFields.add("Employee Code"); if (!item.name) missingFields.add("name"); if (!item.email) missingFields.add("email"); if (!item.mobileNumber) missingFields.add("mobileNumber"); @@ -93,9 +95,33 @@ export const uploadSalesCoordinators = async (req, res) => { validationErrors.add("incorrect mail"); } - // Validate mobile number - if (item.mobileNumber && !/^\d{10}$/.test(item.mobileNumber)) { - validationErrors.add("Invalid Mobile Number (should be 10 digits)"); + // Normalize the mobileNumber + if (item.mobileNumber) { + item.mobileNumber = item.mobileNumber.toString().trim(); + + // Check if it already has +91 + if (item.mobileNumber.startsWith("+91")) { + // If it has +91, remove it for validation + const strippedNumber = item.mobileNumber.substring(3); + + // Validate that the remaining number is 10 digits + if (/^\d{10}$/.test(strippedNumber)) { + // Keep the mobile number with +91 for storage + item.mobileNumber = `+91${strippedNumber}`; + } else { + validationErrors.add( + "Invalid Mobile Number (should be 10 digits after +91)" + ); + } + } else { + // If not prefixed with +91, check if it is exactly 10 digits + if (/^\d{10}$/.test(item.mobileNumber)) { + // Add +91 for storage + item.mobileNumber = `+91${item.mobileNumber}`; + } else { + validationErrors.add("Invalid Mobile Number (should be 10 digits)"); + } + } } // Combine all errors into a single message @@ -114,6 +140,7 @@ export const uploadSalesCoordinators = async (req, res) => { // If there are errors, push them to the errors array if (errorMessage.trim()) { errors.push({ + uniqueId: item.uniqueId || "N/A", name: item.name || "N/A", email: item.email || "N/A", phone: item.mobileNumber || "N/A", @@ -126,37 +153,75 @@ export const uploadSalesCoordinators = async (req, res) => { const password = generatePassword(item.name, item.email); // Check for existing user by uniqueId - let salesCoordinator = await SalesCoOrdinator.findOne({ - email: item.email, + let salesCoordinatorByUniqueId = await SalesCoOrdinator.findOne({ + uniqueId: item.uniqueId, }); - if (salesCoordinator) { - // Track updated fields - const updatedFields = []; + // Search for sales coordinator by mobile number + let salesCoordinatorByMobileNumber = await SalesCoOrdinator.findOne({ + $or: [ + { mobileNumber: item.mobileNumber }, // Check stored mobile number with +91 + { mobileNumber: item.mobileNumber.substring(3) }, // Check 10-digit number (remove +91) + ], + }); - // Check for changes in user details - let territoryManagerUpdated = false; - for (let field in item) { - const currentValue = salesCoordinator[field]?.toString(); - const newValue = item[field]?.toString(); + // Case 1: Both uniqueId and mobileNumber exist + if (salesCoordinatorByUniqueId && salesCoordinatorByMobileNumber) { + if ( + salesCoordinatorByUniqueId._id.equals( + salesCoordinatorByMobileNumber._id + ) + ) { + // Both match and are the same person, proceed to update + let salescoordinatorUpdated = false; - if (currentValue !== newValue) { - updatedFields.push(field); - salesCoordinator[field] = item[field]; - territoryManagerUpdated = true; + for (let field in item) { + const currentValue = salesCoordinatorByUniqueId[field]?.toString(); + const newValue = item[field]?.toString(); + + if (currentValue !== newValue) { + salesCoordinatorByUniqueId[field] = item[field]; + salescoordinatorUpdated = true; + } } - } - if (territoryManagerUpdated) { - await salesCoordinator.save(); - updatedsalesCoordinators.push({ - ...salesCoordinator._doc, - updatedFields: updatedFields.join(", "), + if (salescoordinatorUpdated) { + await salesCoordinatorByUniqueId.save(); + updatedsalesCoordinators.push({ + ...salesCoordinatorByUniqueId._doc, + updatedFields: updatedFields.join(", "), + }); + } + } else { + // Both exist but refer to different users + errors.push({ + uniqueId: item.uniqueId, + name: item.name, + email: item.email, + phone: item.mobileNumber, + message: ` Employee Code (${salesCoordinatorByUniqueId.uniqueId}) is refer to (${salesCoordinatorByUniqueId.name}) and Mobile Number (${salesCoordinatorByMobileNumber.mobileNumber}) refer to (${salesCoordinatorByMobileNumber.name}) Sales Coordinator. Please provide the correct employee code or mobile number.`, }); } + } else if (salesCoordinatorByUniqueId) { + // Case 2: uniqueId exists, but mobileNumber is new + salesCoordinatorByUniqueId.mobileNumber = item.mobileNumber; // Update mobile number + await salesCoordinatorByUniqueId.save(); + updatedsalesCoordinators.push({ + ...salesCoordinatorByUniqueId._doc, + updatedFields: "mobileNumber", + }); + } else if (salesCoordinatorByMobileNumber) { + // Case 3: mobileNumber exists but uniqueId is new + errors.push({ + uniqueId: item.uniqueId, + name: item.name, + email: item.email, + phone: item.mobileNumber, + message: `Mobile number already exists for ${salesCoordinatorByMobileNumber.name} user.`, + }); } else { - // Create a new salesCoordinator - salesCoordinator = new SalesCoOrdinator({ + // Case 4: Both uniqueId and mobileNumber are new, create a new salesCoordinator + const salesCoordinator = new SalesCoOrdinator({ ...item, password, isVerified: true, @@ -168,9 +233,9 @@ export const uploadSalesCoordinators = async (req, res) => { from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender subject: `Cheminova Account Created`, html: `Your Sales Coordinator Account is created successfully. -
name is: ${item?.name}
-
MobileNumber is: ${item?.mobileNumber}
-
password is: ${password}

If you have not requested this email, please ignore it.`, +
Name: ${item?.name}
+
Mobile Number: ${item?.mobileNumber}
+
Password: ${password}

If you have not requested this email, please ignore it.`, }); newlyCreated.push({ salesCoordinator }); } @@ -188,7 +253,8 @@ export const uploadSalesCoordinators = async (req, res) => { } }; export const register = async (req, res) => { - let { name, email, countryCode, mobileNumber, territoryManager } = req.body; + let { name, email, countryCode, mobileNumber, territoryManager, uniqueId } = + req.body; // console.log(req.body); countryCode = countryCode?.trim(); mobileNumber = mobileNumber?.trim(); @@ -196,6 +262,7 @@ export const register = async (req, res) => { try { let salesCoordinator = await SalesCoOrdinator.findOne({ + uniqueId, mobileNumber: fullMobileNumber, }); @@ -221,14 +288,9 @@ export const register = async (req, res) => { otp, otpExpires, mappedby: territoryManager, + uniqueId, }); } - // Generate uniqueId if not already present - if (!salesCoordinator.uniqueId) { - const currentYear = new Date().getFullYear().toString().slice(-2); - const randomChars = crypto.randomBytes(4).toString("hex").toUpperCase(); - salesCoordinator.uniqueId = `${currentYear}-${randomChars}`; - } await salesCoordinator.save(); // await sendOtp( // fullMobileNumber, diff --git a/resources/TerritoryManagers/TerritoryManagerController.js b/resources/TerritoryManagers/TerritoryManagerController.js index 3194761..e083a5e 100644 --- a/resources/TerritoryManagers/TerritoryManagerController.js +++ b/resources/TerritoryManagers/TerritoryManagerController.js @@ -47,6 +47,7 @@ export const uploadTerritoryManagers = async (req, res) => { // Map headers from the Excel file to your schema const headerMapping = { + "Employee Code": "uniqueId", "Territory Manager Name": "name", Email: "email", "Phone Number": "mobileNumber", @@ -84,6 +85,7 @@ export const uploadTerritoryManagers = async (req, res) => { const validationErrors = new Set(); // Validate required fields + if (!item.uniqueId) missingFields.add("Employee Code"); if (!item.name) missingFields.add("name"); if (!item.email) missingFields.add("email"); if (!item.mobileNumber) missingFields.add("mobileNumber"); @@ -93,9 +95,33 @@ export const uploadTerritoryManagers = async (req, res) => { validationErrors.add("incorrect mail"); } - // Validate mobile number - if (item.mobileNumber && !/^\d{10}$/.test(item.mobileNumber)) { - validationErrors.add("Invalid Mobile Number (should be 10 digits)"); + // Normalize the mobileNumber + if (item.mobileNumber) { + item.mobileNumber = item.mobileNumber.toString().trim(); + + // Check if it already has +91 + if (item.mobileNumber.startsWith("+91")) { + // If it has +91, remove it for validation + const strippedNumber = item.mobileNumber.substring(3); + + // Validate that the remaining number is 10 digits + if (/^\d{10}$/.test(strippedNumber)) { + // Keep the mobile number with +91 for storage + item.mobileNumber = `+91${strippedNumber}`; + } else { + validationErrors.add( + "Invalid Mobile Number (should be 10 digits after +91)" + ); + } + } else { + // If not prefixed with +91, check if it is exactly 10 digits + if (/^\d{10}$/.test(item.mobileNumber)) { + // Add +91 for storage + item.mobileNumber = `+91${item.mobileNumber}`; + } else { + validationErrors.add("Invalid Mobile Number (should be 10 digits)"); + } + } } // Combine all errors into a single message @@ -114,6 +140,7 @@ export const uploadTerritoryManagers = async (req, res) => { // If there are errors, push them to the errors array if (errorMessage.trim()) { errors.push({ + uniqueId: item.uniqueId || "N/A", name: item.name || "N/A", email: item.email || "N/A", phone: item.mobileNumber || "N/A", @@ -126,37 +153,73 @@ export const uploadTerritoryManagers = async (req, res) => { const password = generatePassword(item.name, item.email); // Check for existing user by uniqueId - let territoryManager = await TerritoryManager.findOne({ - email: item.email, + let territotymanagerByUniqueId = await TerritoryManager.findOne({ + uniqueId: item.uniqueId, }); + // Search for Territory Manager by mobile number + let territorymanagerByMobileNumber = await TerritoryManager.findOne({ + $or: [ + { mobileNumber: item.mobileNumber }, // Check stored mobile number with +91 + { mobileNumber: item.mobileNumber.substring(3) }, // Check 10-digit number (remove +91) + ], + }); + // Case 1: Both uniqueId and mobileNumber exist + if (territotymanagerByUniqueId && territorymanagerByMobileNumber) { + if ( + territotymanagerByUniqueId._id.equals( + territorymanagerByMobileNumber._id + ) + ) { + // Both match and are the same person, proceed to update + let territorymanagerUpdated = false; - if (territoryManager) { - // Track updated fields - const updatedFields = []; + for (let field in item) { + const currentValue = territotymanagerByUniqueId[field]?.toString(); + const newValue = item[field]?.toString(); - // Check for changes in user details - let territoryManagerUpdated = false; - for (let field in item) { - const currentValue = territoryManager[field]?.toString(); - const newValue = item[field]?.toString(); - - if (currentValue !== newValue) { - updatedFields.push(field); - territoryManager[field] = item[field]; - territoryManagerUpdated = true; + if (currentValue !== newValue) { + territotymanagerByUniqueId[field] = item[field]; + territorymanagerUpdated = true; + } } - } - if (territoryManagerUpdated) { - await territoryManager.save(); - updatedtrritoryManagers.push({ - ...territoryManager._doc, - updatedFields: updatedFields.join(", "), + if (territorymanagerUpdated) { + await territotymanagerByUniqueId.save(); + updatedtrritoryManagers.push({ + ...territotymanagerByUniqueId._doc, + updatedFields: updatedFields.join(", "), + }); + } + } else { + // Both exist but refer to different users + errors.push({ + uniqueId: item.uniqueId, + name: item.name, + email: item.email, + phone: item.mobileNumber, + message: ` Employee Code (${territotymanagerByUniqueId.uniqueId}) is refer to (${territotymanagerByUniqueId.name}) and Mobile Number (${territorymanagerByMobileNumber.mobileNumber}) refer to (${territorymanagerByMobileNumber.name}) Territory Manager. Please provide the correct employee code or mobile number.`, }); } + } else if (territotymanagerByUniqueId) { + // Case 2: uniqueId exists, but mobileNumber is new + territotymanagerByUniqueId.mobileNumber = item.mobileNumber; // Update mobile number + await territotymanagerByUniqueId.save(); + updatedtrritoryManagers.push({ + ...territotymanagerByUniqueId._doc, + updatedFields: "mobileNumber", + }); + } else if (territorymanagerByMobileNumber) { + // Case 3: mobileNumber exists but uniqueId is new + errors.push({ + uniqueId: item.uniqueId, + name: item.name, + email: item.email, + phone: item.mobileNumber, + message: `Mobile number already exists for ${territorymanagerByMobileNumber.name} user.`, + }); } else { - // Create a new territoryManager - territoryManager = new TerritoryManager({ + // Case 4: Both uniqueId and mobileNumber are new, create a new salesCoordinator + const territoryManager = new TerritoryManager({ ...item, password, isVerified: true, @@ -188,13 +251,14 @@ export const uploadTerritoryManagers = async (req, res) => { } }; export const register = async (req, res) => { - let { name, email, countryCode, mobileNumber } = req.body; + let { name, email, countryCode, mobileNumber, uniqueId } = req.body; countryCode = countryCode?.trim(); mobileNumber = mobileNumber?.trim(); const fullMobileNumber = `${countryCode}${mobileNumber}`; try { let territoryManager = await TerritoryManager.findOne({ + uniqueId, mobileNumber: fullMobileNumber, }); @@ -218,14 +282,9 @@ export const register = async (req, res) => { mobileNumber: fullMobileNumber, otp, otpExpires, + uniqueId, }); } - // Generate uniqueId if not already present - if (!territoryManager.uniqueId) { - const currentYear = new Date().getFullYear().toString().slice(-2); - const randomChars = crypto.randomBytes(4).toString("hex").toUpperCase(); - territoryManager.uniqueId = `${currentYear}-${randomChars}`; - } await territoryManager.save(); // await sendOtp( // fullMobileNumber, @@ -390,7 +449,32 @@ export const getAllTerritoryManager = async (req, res) => { }); } }; +//for dropdown +export const getAllTerritoryManagerdropdown = async (req, res) => { + try { + let filter = {}; + if (req.query?.name) { + filter.name = { + $regex: new RegExp(req.query.name, "i"), + }; + } + const total = await TerritoryManager.countDocuments(filter); + const territoryManager = await TerritoryManager.find(filter).sort({ + createdAt: -1, + }); + return res.status(200).json({ + success: true, + total_data: total, + territoryManager, + }); + } catch (error) { + res.status(500).json({ + success: false, + message: error.message ? error.message : "Something went wrong!", + }); + } +}; export const getOneTerritoryManager = async (req, res) => { try { if (!req.params.id) { diff --git a/resources/TerritoryManagers/TerritoryManagerRoute.js b/resources/TerritoryManagers/TerritoryManagerRoute.js index 8c24a17..ded5955 100644 --- a/resources/TerritoryManagers/TerritoryManagerRoute.js +++ b/resources/TerritoryManagers/TerritoryManagerRoute.js @@ -17,6 +17,7 @@ import { getOneTerritoryManager, logout, uploadTerritoryManagers, + getAllTerritoryManagerdropdown, } from "./TerritoryManagerController.js"; import { isAuthenticatedTerritoryManager } from "../../middlewares/TerritoryManagerAuth.js"; import { authorizeRoles, isAuthenticatedUser } from "../../middlewares/auth.js"; @@ -35,6 +36,12 @@ router.get( authorizeRoles("admin"), getAllTerritoryManager ); +router.get( + "/getAll-dropdown", + isAuthenticatedUser, + authorizeRoles("admin"), + getAllTerritoryManagerdropdown +); router.get( "/getOne/:id", isAuthenticatedUser,