import mongoose from "mongoose"; import RetailDistributor from "./RetailDistributorModel.js"; import validator from "validator"; import password from "secure-random-password"; import crypto from "crypto"; import sendEmail, { sendOtp } from "../../Utils/sendEmail.js"; export const loginRD = async (req, res) => { const { email, password } = req.body; try { if (!email || !password) { return res.status(400).json({ message: "Please Enter Email & Password" }); } const retailDistributor = await RetailDistributor.findOne({ email }).select( "+password" ); if (!retailDistributor) { return res.status(400).json({ message: "Invalid Email or Password" }); } const isPasswordMatched = await retailDistributor.comparePassword(password); if (!isPasswordMatched) { return res.status(400).json({ message: "Invalid Email or Password" }); } const token = retailDistributor.getJWTToken(); return res.status(200).json({ success: true, token, message: "Login Successfully", }); } catch (error) { return res.status(500).json({ message: error.message ? error.message : "Something went wrong!", }); } }; export const ChangePasswordRD = async (req, res) => { // Retrieve id from req.params const { oldPassword, newPassword, confirmPassword } = req.body; const userId = req.user._id; // Use the ID from the URL or from the authenticated user // console.log(userId); if (!oldPassword) { return res.status(400).json({ message: "Please Enter Old password" }); } if (!newPassword) { return res.status(400).json({ message: "Please Enter New Password " }); } if (!confirmPassword) { return res.status(400).json({ message: "Please Enter Confirm Password" }); } try { const retailDistributor = await RetailDistributor.findById(userId).select( "+password" ); if (!retailDistributor) { return res.status(404).json({ message: "Retail Distributer not found" }); } const isPasswordMatched = await retailDistributor.comparePassword( oldPassword ); if (!isPasswordMatched) { return res.status(400).json({ message: "Old password is incorrect" }); } if (newPassword !== confirmPassword) { return res .status(400) .json({ message: "New password and confirm Password do not match" }); } retailDistributor.password = newPassword; await retailDistributor.save(); return res .status(200) .json({ success: true, message: "Password updated successfully" }); } catch (error) { console.error("Error updating password:", error); return res.status(500).json({ message: error.message ? error.message : "Server error!", }); } }; export const forgotPasswordRD = async (req, res) => { try { // Check if email is provided const { email } = req.body; if (!email) { return res.status(400).json({ message: "Please Enter Email!" }); } // Find the Retail Distributor by email const retailDistributor = await RetailDistributor.findOne({ email }); if (!retailDistributor) { return res.status(404).json({ message: "Retail Distributor not found" }); } // Generate a random password const newPassword = password.randomPassword({ length: 12, characters: [ { characters: password.upper, exactly: 1 }, // At least 1 uppercase letter { characters: password.symbols, exactly: 1 }, // At least 1 symbol password.lower, // Lowercase letters password.digits, // Digits ], }); // Update the retail distributor's password retailDistributor.password = newPassword; await retailDistributor.save(); // The pre-save hook in your schema will handle password hashing // Send an email to the retail distributor with the new password await sendEmail({ to: retailDistributor.email, from: process.env.SEND_EMAIL_FROM, subject: `Cheminova Password Recovery`, html: `Your new password is: ${newPassword}

If you did not request this, please ignore this email.`, }); // Respond with success message return res.status(200).json({ success: true, message: `Email sent to ${retailDistributor.email} successfully`, }); } catch (error) { console.error("Error during password reset:", error); return res.status(500).json({ message: error.message || "Something went wrong!", }); } }; export const UpdateProfileRD = async (req, res) => { const { name, mobile_number } = req.body; // Only expecting name from the request body const userId = req.user._id; // User ID from authenticated user try { // Find the RetailDistributor by user ID const retailDistributor = await RetailDistributor.findById(userId); if (!retailDistributor) { return res.status(404).json({ message: "Retail Distributor not found" }); } // Assuming you have an 'isVerified' field in your RetailDistributor schema // Update name if provided if (name) { retailDistributor.name = name; retailDistributor.mobile_number = mobile_number ? mobile_number : retailDistributor.mobile_number; } else { return res.status(400).json({ message: "Name is required" }); } // Save the updated RetailDistributor await retailDistributor.save(); return res.status(200).json({ retailDistributor, message: "Profile updated successfully", }); } catch (error) { return res.status(500).json({ message: error.message || "Server error!", }); } }; export const getmyProfileRD = async (req, res) => { try { // Fetch the profile data using the authenticated user's ID const myData = await RetailDistributor.findById(req.user?._id); if (myData) { return res.status(200).json({ success: true, message: "Profile fetched successfully!", myData, }); } else { return res.status(404).json({ success: false, message: "Retail Distributor not found", }); } } catch (error) { return res.status(500).json({ success: false, message: error.message || "Something went wrong!", }); } }; //reatil distributor mapping export const getAllRetailDistributorApproved = async (req, res) => { try { // Extract query parameters const { page = 1, show = 10, tradename, name, mobile_number, principaldistributor, } = req.query; const skip = (page - 1) * show; // Build the aggregation pipeline let pipeline = [ { $lookup: { from: "kycs", // Assuming your KYC collection is named "kycs" localField: "kyc", foreignField: "_id", as: "kycDetails", }, }, { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } }, // Unwind kycDetails and allow null/empty arrays { $lookup: { from: "users", // Assuming your User collection is named "users" localField: "principal_distributer", foreignField: "_id", as: "principalDetails", }, }, { $unwind: { path: "$principalDetails", preserveNullAndEmptyArrays: true, }, }, // Unwind principalDetails and allow null/empty arrays // Lookup for mappedTM (Territory Manager) { $lookup: { from: "territorymanagers", // Assuming your Territory Manager collection localField: "mappedTM", foreignField: "_id", as: "mappedTMDetails", }, }, { $unwind: { path: "$mappedTMDetails", preserveNullAndEmptyArrays: true }, }, // Unwind mappedTMDetails and allow null/empty arrays // Lookup for mappedSC (Sales Coordinator) { $lookup: { from: "salescoordinators", // Assuming your Sales Coordinator collection localField: "mappedSC", foreignField: "_id", as: "mappedSCDetails", }, }, { $unwind: { path: "$mappedSCDetails", preserveNullAndEmptyArrays: true }, }, // Unwind mappedSCDetails and allow null/empty arrays // Filter to ensure data exists in kyc or principalDetails { $match: { $or: [ { "kycDetails.trade_name": { $exists: true } }, // Ensure KYC exists { "principalDetails.name": { $exists: true } }, // Ensure Principal Distributor exists ], }, }, ]; // Add filters based on query parameters // Filter by KYC trade_name (case-insensitive) if (tradename) { pipeline.push({ $match: { "kycDetails.trade_name": new RegExp(tradename, "i") }, }); } // Filter by principal_distributer name (case-insensitive) if (principaldistributor) { pipeline.push({ $match: { "principalDetails.name": new RegExp(principaldistributor, "i"), }, }); } // Filter by name (RetailDistributor model's name) if (name) { pipeline.push({ $match: { name: new RegExp(name, "i") }, // Case-insensitive search for name }); } // Filter by mobile_number (RetailDistributor model's mobile number) if (mobile_number) { pipeline.push({ $match: { mobile_number: new RegExp(mobile_number, "i") }, // Case-insensitive search for mobile_number }); } // Project only the required fields pipeline.push({ $project: { _id: 1, // RetailDistributor ID uniqueId: 1, // RetailDistributor uniqueId name: 1, // RetailDistributor name mobile_number: 1, // RetailDistributor mobile_number email: 1, // RetailDistributor email "kycDetails.trade_name": 1, // Only trade_name from kyc "principalDetails.name": 1, // Only name from principal_distributer "mappedTMDetails.name": 1, // Only name from mappedTM (Territory Manager) "mappedSCDetails.name": 1, // Only name from mappedSC (Sales Coordinator) createdAt: 1, // For sorting }, }); // Pagination and sorting pipeline.push({ $sort: { createdAt: -1 } }); pipeline.push({ $skip: skip }); pipeline.push({ $limit: parseInt(show) }); // Execute the aggregation pipeline const Retaildistributor = await RetailDistributor.aggregate(pipeline); // Get total count of documents matching the query const countPipeline = [ { $lookup: { from: "kycs", localField: "kyc", foreignField: "_id", as: "kycDetails", }, }, { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } }, { $lookup: { from: "users", localField: "principal_distributer", foreignField: "_id", as: "principalDetails", }, }, { $unwind: { path: "$principalDetails", preserveNullAndEmptyArrays: true, }, }, { $match: { $or: [ { "kycDetails.trade_name": { $exists: true } }, { "principalDetails.name": { $exists: true } }, ], }, }, ]; // Apply search filters to count query // Filter by KYC trade_name if (tradename) { countPipeline.push({ $match: { "kycDetails.trade_name": new RegExp(tradename, "i") }, }); } // Filter by principal_distributer name if (principaldistributor) { countPipeline.push({ $match: { "principalDetails.name": new RegExp(principaldistributor, "i"), }, }); } // Filter by name if (name) { countPipeline.push({ $match: { name: new RegExp(name, "i") }, }); } // Filter by mobile_number if (mobile_number) { countPipeline.push({ $match: { mobile_number: new RegExp(mobile_number, "i") }, }); } // Get the total count of filtered documents const total_data = await RetailDistributor.aggregate([ ...countPipeline, { $count: "total" }, ]); const totalCount = total_data[0]?.total || 0; // Ensure count is zero if no data found // Send the response with pagination data res.status(200).json({ success: true, total_data: totalCount, total_pages: Math.ceil(totalCount / show), Retaildistributor, }); } catch (error) { console.error(error); res.status(500).json({ message: "Server Error", error }); } }; //get RD by Id export const getRDId = async (req, res) => { try { const { id } = req.params; console.log(id); // Fetch the KYC document from the database by ID const RD = await RetailDistributor.findById(id) .populate("principal_distributer", "name") .populate("addedBy") .populate("kyc") .populate("mappedTM") .populate("mappedSC"); // Check if the KYC document exists if (!RD) { return res.status(404).json({ message: "No RetailDistributor found" }); } // Send the fetched KYC document as a response res.status(200).json(RD); } catch (error) { // Handle any errors that occur during the fetch operation res.status(500).json({ message: "Server Error", error }); } }; //mapping export const getAllRDbytmid = async (req, res) => { try { // Extract query parameters const { page = 1, show = 10, tradename, name, mobile_number, principaldistributor, } = req.query; const { mappedTMId } = req.params; // Extract mappedTM ID from request params // Convert mappedTMId to ObjectId if it's a valid ObjectId string let mappedTMObjectId; try { mappedTMObjectId = mongoose.Types.ObjectId(mappedTMId); } catch (error) { return res.status(400).json({ message: "Invalid mappedTM ID format" }); } const skip = (page - 1) * show; // Build the aggregation pipeline let pipeline = [ { $match: { mappedTM: mappedTMObjectId, // Filter by mappedTM ObjectId }, }, { $lookup: { from: "kycs", // Assuming your KYC collection is named "kycs" localField: "kyc", foreignField: "_id", as: "kycDetails", }, }, { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } }, // Unwind kycDetails and allow null/empty arrays { $lookup: { from: "users", // Assuming your User collection is named "users" localField: "principal_distributer", foreignField: "_id", as: "principalDetails", }, }, { $unwind: { path: "$principalDetails", preserveNullAndEmptyArrays: true, }, }, // Unwind principalDetails and allow null/empty arrays // Lookup for mappedTM (Territory Manager) { $lookup: { from: "territorymanagers", // Assuming your Territory Manager collection localField: "mappedTM", foreignField: "_id", as: "mappedTMDetails", }, }, { $unwind: { path: "$mappedTMDetails", preserveNullAndEmptyArrays: true }, }, // Unwind mappedTMDetails and allow null/empty arrays // Lookup for mappedSC (Sales Coordinator) { $lookup: { from: "salescoordinators", // Assuming your Sales Coordinator collection localField: "mappedSC", foreignField: "_id", as: "mappedSCDetails", }, }, { $unwind: { path: "$mappedSCDetails", preserveNullAndEmptyArrays: true }, }, // Unwind mappedSCDetails and allow null/empty arrays // Filter to ensure data exists in kyc or principalDetails { $match: { $or: [ { "kycDetails.trade_name": { $exists: true } }, // Ensure KYC exists { "principalDetails.name": { $exists: true } }, // Ensure Principal Distributor exists ], }, }, ]; // Add filters based on query parameters // Filter by KYC trade_name (case-insensitive) if (tradename) { pipeline.push({ $match: { "kycDetails.trade_name": new RegExp(tradename, "i") }, }); } // Filter by principal_distributer name (case-insensitive) if (principaldistributor) { pipeline.push({ $match: { "principalDetails.name": new RegExp(principaldistributor, "i"), }, }); } // Filter by name (RetailDistributor model's name) if (name) { pipeline.push({ $match: { name: new RegExp(name, "i") }, // Case-insensitive search for name }); } // Filter by mobile_number (RetailDistributor model's mobile number) if (mobile_number) { pipeline.push({ $match: { mobile_number: new RegExp(mobile_number, "i") }, // Case-insensitive search for mobile_number }); } // Project only the required fields pipeline.push({ $project: { _id: 1, // RetailDistributor ID uniqueId: 1, // RetailDistributor uniqueId name: 1, // RetailDistributor name mobile_number: 1, // RetailDistributor mobile_number email: 1, // RetailDistributor email "kycDetails.trade_name": 1, // Only trade_name from kyc "principalDetails.name": 1, // Only name from principal_distributer "mappedTMDetails.name": 1, // Only name from mappedTM (Territory Manager) "mappedSCDetails.name": 1, // Only name from mappedSC (Sales Coordinator) createdAt: 1, // For sorting }, }); // Pagination and sorting pipeline.push({ $sort: { createdAt: -1 } }); pipeline.push({ $skip: skip }); pipeline.push({ $limit: parseInt(show) }); // Execute the aggregation pipeline const Retaildistributor = await RetailDistributor.aggregate(pipeline); // Get total count of documents matching the query const countPipeline = [ { $match: { mappedTM: mappedTMObjectId, // Filter by mappedTM ObjectId }, }, { $lookup: { from: "kycs", localField: "kyc", foreignField: "_id", as: "kycDetails", }, }, { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } }, { $lookup: { from: "users", localField: "principal_distributer", foreignField: "_id", as: "principalDetails", }, }, { $unwind: { path: "$principalDetails", preserveNullAndEmptyArrays: true, }, }, { $match: { $or: [ { "kycDetails.trade_name": { $exists: true } }, { "principalDetails.name": { $exists: true } }, ], }, }, ]; // Apply search filters to count query // Filter by KYC trade_name if (tradename) { countPipeline.push({ $match: { "kycDetails.trade_name": new RegExp(tradename, "i") }, }); } // Filter by principal_distributer name if (principaldistributor) { countPipeline.push({ $match: { "principalDetails.name": new RegExp(principaldistributor, "i"), }, }); } // Filter by name if (name) { countPipeline.push({ $match: { name: new RegExp(name, "i") }, }); } // Filter by mobile_number if (mobile_number) { countPipeline.push({ $match: { mobile_number: new RegExp(mobile_number, "i") }, }); } // Get the total count of filtered documents const total_data = await RetailDistributor.aggregate([ ...countPipeline, { $count: "total" }, ]); const totalCount = total_data[0]?.total || 0; // Ensure count is zero if no data found // Send the response with pagination data res.status(200).json({ success: true, total_data: totalCount, total_pages: Math.ceil(totalCount / show), Retaildistributor, }); } catch (error) { console.error(error); res.status(500).json({ message: "Server Error", error }); } }; export const getAllRDbyscid = async (req, res) => { try { // Extract query parameters const { page = 1, show = 10, tradename, name, mobile_number, principaldistributor, } = req.query; const { mappedSCId } = req.params; // Extract mappedTM ID from request params // Convert mappedSCId to ObjectId if it's a valid ObjectId string let mappedSCObjectId; try { mappedSCObjectId = mongoose.Types.ObjectId(mappedSCId); } catch (error) { return res.status(400).json({ message: "Invalid mappedTM ID format" }); } const skip = (page - 1) * show; // Build the aggregation pipeline let pipeline = [ { $match: { mappedSC: mappedSCObjectId, // Filter by mappedSC ObjectId }, }, { $lookup: { from: "kycs", // Assuming your KYC collection is named "kycs" localField: "kyc", foreignField: "_id", as: "kycDetails", }, }, { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } }, // Unwind kycDetails and allow null/empty arrays { $lookup: { from: "users", // Assuming your User collection is named "users" localField: "principal_distributer", foreignField: "_id", as: "principalDetails", }, }, { $unwind: { path: "$principalDetails", preserveNullAndEmptyArrays: true, }, }, // Unwind principalDetails and allow null/empty arrays // Lookup for mappedTM (Territory Manager) { $lookup: { from: "territorymanagers", // Assuming your Territory Manager collection localField: "mappedTM", foreignField: "_id", as: "mappedTMDetails", }, }, { $unwind: { path: "$mappedTMDetails", preserveNullAndEmptyArrays: true }, }, // Unwind mappedTMDetails and allow null/empty arrays // Lookup for mappedSC (Sales Coordinator) { $lookup: { from: "salescoordinators", // Assuming your Sales Coordinator collection localField: "mappedSC", foreignField: "_id", as: "mappedSCDetails", }, }, { $unwind: { path: "$mappedSCDetails", preserveNullAndEmptyArrays: true }, }, // Unwind mappedSCDetails and allow null/empty arrays // Filter to ensure data exists in kyc or principalDetails { $match: { $or: [ { "kycDetails.trade_name": { $exists: true } }, // Ensure KYC exists { "principalDetails.name": { $exists: true } }, // Ensure Principal Distributor exists ], }, }, ]; // Add filters based on query parameters // Filter by KYC trade_name (case-insensitive) if (tradename) { pipeline.push({ $match: { "kycDetails.trade_name": new RegExp(tradename, "i") }, }); } // Filter by principal_distributer name (case-insensitive) if (principaldistributor) { pipeline.push({ $match: { "principalDetails.name": new RegExp(principaldistributor, "i"), }, }); } // Filter by name (RetailDistributor model's name) if (name) { pipeline.push({ $match: { name: new RegExp(name, "i") }, // Case-insensitive search for name }); } // Filter by mobile_number (RetailDistributor model's mobile number) if (mobile_number) { pipeline.push({ $match: { mobile_number: new RegExp(mobile_number, "i") }, // Case-insensitive search for mobile_number }); } // Project only the required fields pipeline.push({ $project: { _id: 1, // RetailDistributor ID uniqueId: 1, // RetailDistributor uniqueId name: 1, // RetailDistributor name mobile_number: 1, // RetailDistributor mobile_number email: 1, // RetailDistributor email "kycDetails.trade_name": 1, // Only trade_name from kyc "principalDetails.name": 1, // Only name from principal_distributer "mappedTMDetails.name": 1, // Only name from mappedTM (Territory Manager) "mappedSCDetails.name": 1, // Only name from mappedSC (Sales Coordinator) createdAt: 1, // For sorting }, }); // Pagination and sorting pipeline.push({ $sort: { createdAt: -1 } }); pipeline.push({ $skip: skip }); pipeline.push({ $limit: parseInt(show) }); // Execute the aggregation pipeline const Retaildistributor = await RetailDistributor.aggregate(pipeline); // Get total count of documents matching the query const countPipeline = [ { $match: { mappedSC: mappedSCObjectId, // Filter by mappedTM ObjectId }, }, { $lookup: { from: "kycs", localField: "kyc", foreignField: "_id", as: "kycDetails", }, }, { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } }, { $lookup: { from: "users", localField: "principal_distributer", foreignField: "_id", as: "principalDetails", }, }, { $unwind: { path: "$principalDetails", preserveNullAndEmptyArrays: true, }, }, { $match: { $or: [ { "kycDetails.trade_name": { $exists: true } }, { "principalDetails.name": { $exists: true } }, ], }, }, ]; // Apply search filters to count query // Filter by KYC trade_name if (tradename) { countPipeline.push({ $match: { "kycDetails.trade_name": new RegExp(tradename, "i") }, }); } // Filter by principal_distributer name if (principaldistributor) { countPipeline.push({ $match: { "principalDetails.name": new RegExp(principaldistributor, "i"), }, }); } // Filter by name if (name) { countPipeline.push({ $match: { name: new RegExp(name, "i") }, }); } // Filter by mobile_number if (mobile_number) { countPipeline.push({ $match: { mobile_number: new RegExp(mobile_number, "i") }, }); } // Get the total count of filtered documents const total_data = await RetailDistributor.aggregate([ ...countPipeline, { $count: "total" }, ]); const totalCount = total_data[0]?.total || 0; // Ensure count is zero if no data found // Send the response with pagination data res.status(200).json({ success: true, total_data: totalCount, total_pages: Math.ceil(totalCount / show), Retaildistributor, }); } catch (error) { console.error(error); res.status(500).json({ message: "Server Error", error }); } }; export const updateRDMapped = async (req, res) => { try { const { id } = req.params; const { principal_distributor, mappedTM, mappedSC } = req.body; // Find the RetailDistributor document by ID const RD = await RetailDistributor.findById(id); if (!RD) { return res.status(404).json({ message: "RetailDistributor not found" }); } // Update the fields if provided in the request body if (principal_distributor) { RD.principal_distributer = principal_distributor; } if (mappedTM) { RD.mappedTM = mappedTM; } if (mappedSC) { RD.mappedSC = mappedSC; } // Save the updated document await RD.save(); res.status(200).json({ message: "RetailDistributor record updated successfully", data: RD, }); } catch (error) { // Handle any errors during the update res.status(500).json({ message: "Error updating RD record", error: error.message, }); } }; export const updateunmapRD = async (req, res) => { try { const { id } = req.params; const { principal_distributor, mappedTM, mappedSC } = req.body; // Find the RetailDistributor document by ID const RD = await RetailDistributor.findById(id); if (!RD) { return res.status(404).json({ message: "RetailDistributor not found" }); } // Update the fields if provided in the request body if (principal_distributor) { RD.principal_distributer = null; } if (mappedTM ) { RD.mappedTM = null; } if (mappedSC) { RD.mappedSC = null; } // Save the updated document await RD.save(); res.status(200).json({ message: "RetailDistributor record updated successfully", data: RD, }); } catch (error) { // Handle any errors during the update res.status(500).json({ message: "Error updating RD record", error: error.message, }); } };