import mongoose from "mongoose";
import RetailDistributor from "./RetailDistributorModel.js";
import validator from "validator";
import password from "secure-random-password";
import crypto from "crypto";
import { RdOrder } from "../RD_Ordes/rdOrderModal.js";
import sendEmail, { sendOtp } from "../../Utils/sendEmail.js";
import { KYC } from "../KYC/KycModel.js";
import { generatePassword } from "../../Utils/generatepassword.js";
import XLSX from "xlsx";
import fs from "fs";
import path from "path";
import ShippingAddressRD from "../ShippingAddressesRD/RDShippingAddressModel.js";
export const uploadRetaildistributors = async (req, res) => {
try {
if (!mongoose.Types.ObjectId.isValid(req.user._id)) {
return res.status(400).json({ message: "Please login again" });
}
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 = {
"Retail Distributor Name": "name",
Email: "email",
"Phone Number": "mobile_number",
"PAN Number": "pan_number",
"Trade Name": "trade_name",
"GST Number": "gst_number",
"Aadhar Number": "aadhar_number",
State: "state",
City: "city",
District: "district",
Address: "address",
Pincode: "pincode",
};
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];
// Skip the row if it's completely empty
if (row.every((cell) => cell === undefined || cell === "")) {
continue;
}
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.name) missingFields.add("name");
if (!item.email) missingFields.add("email");
if (!item.mobile_number) missingFields.add("mobile_number");
if (!item.pan_number) missingFields.add("pan_number");
if (!item.gst_number) missingFields.add("gst_number");
if (!item.trade_name) missingFields.add("trade_name");
if (!item.aadhar_number) missingFields.add("aadhar_number");
if (!item.state) missingFields.add("state");
if (!item.city) missingFields.add("city");
if (!item.pincode) missingFields.add("pincode");
if (!item.district) missingFields.add("district");
if (!item.address) missingFields.add("address");
// Check email validity
if (item.email && !validator.isEmail(item.email)) {
validationErrors.add("incorrect mail");
}
// Validate mobile number
if (item.mobile_number && !/^\d{10}$/.test(item.mobile_number)) {
validationErrors.add("Invalid Mobile Number (should be 10 digits)");
}
// Check GST, PAN, and postal code validation
item.pan_number = item.pan_number ? item.pan_number.toUpperCase() : "";
item.gst_number = item.gst_number ? item.gst_number.toUpperCase() : "";
// Validate PAN Number
if (
item.pan_number &&
!/^[A-Z]{5}[0-9]{4}[A-Z]{1}$/.test(item.pan_number)
) {
validationErrors.add("Invalid PAN Number");
}
// Validate GST Number
if (
item.gst_number &&
!/^(\d{2}[A-Z]{5}\d{4}[A-Z]{1}\d[Z]{1}[A-Z\d]{1})$/.test(
item.gst_number
)
) {
validationErrors.add("Invalid GST Number");
}
// Validate Aadhar number
if (item.aadhar_number && !/^\d{12}$/.test(item.aadhar_number)) {
validationErrors.add("Invalid Aadhar Number (should be 12 digits)");
}
// Validate Postal Code
if (item.pincode && !/^\d{6}$/.test(item.pincode)) {
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({
name: item.name || "N/A",
email: item.email || "N/A",
TradeName: item.trade_name || "N/A",
phone: item.mobile_number || "N/A",
panNumber: item.pan_number || "N/A",
gstNumber: item.gst_number || "N/A",
AadharNumber: item.aadhar_number || "N/A",
message: errorMessage.trim(),
});
continue;
}
// Generate a password
const password = generatePassword(item.name, item.email);
// Check for existing user by uniqueId
let Kyc = await KYC.findOne({ email: item.email });
let Retaildistributor = await RetailDistributor.findOne({
email: item.email,
});
let existingAddress = await ShippingAddressRD.findOne({
user: Retaildistributor?._id,
isDefault: true,
}).exec();
if (!existingAddress) {
existingAddress = await ShippingAddressRD.findOne({
user: Retaildistributor?._id,
})
.sort({ createdAt: 1 })
.exec();
}
if (Kyc) {
// Track updated fields
const updatedFields = [];
const addressFields = [
"Name",
"phoneNumber",
"state",
"city",
"street",
"tradeName",
"postalCode",
"district",
];
// Check for changes in user details
let kycUpdated = false;
for (let field in item) {
const currentValue = Kyc[field]?.toString();
const newValue = item[field]?.toString();
if (currentValue !== newValue) {
updatedFields.push(field);
Kyc[field] = item[field]; // Update Kyc with the new value
if (Retaildistributor && field !== "email") {
Retaildistributor[field] = item[field];
}
kycUpdated = true;
}
}
// Update Kyc and Retaildistributor if there are any changes
if (kycUpdated) {
await Kyc.save();
await Retaildistributor.save();
// Check for changes in address details
const addressData = {
Name: item.name,
phoneNumber: item.mobile_number.toString(),
street: item.address,
city: item.city,
state: item.state,
postalCode: item.pincode,
district: item.district,
country: "India", // Default country
tradeName: item.trade_name,
user: Retaildistributor._id,
};
// console.log(addressData);
let addressUpdated = false;
if (existingAddress) {
const addressUpdates = [];
addressFields.forEach((field) => {
if (existingAddress[field] !== addressData[field]) {
addressUpdates.push(field);
addressUpdated = true;
}
});
if (addressUpdated) {
await ShippingAddressRD.updateOne(
{ user: Retaildistributor._id },
addressData
);
}
} else {
// Create new address
await ShippingAddressRD.create(addressData);
}
updatedDistributors.push({
...Kyc._doc,
updatedFields: updatedFields.join(", "),
});
}
} else {
// Create a new Kyc
Kyc = new KYC({
...item,
status: "approved",
});
const newkyc = await Kyc.save();
const retailDistributorData = {
name: item.name,
email: item.email,
mobile_number: item.mobile_number,
kyc: newkyc._id,
password,
};
Retaildistributor = new RetailDistributor(retailDistributorData);
const newRd = await Retaildistributor.save();
// Now create the address for the new user
const addressData = {
Name: item.name,
phoneNumber: item.mobile_number.toString(),
street: item.address,
city: item.city,
state: item.state,
postalCode: item.pincode,
district: item.district,
country: "India", // Default country
tradeName: item.trade_name,
user: newRd._id, // Use the saved user's ID
isDefault: true,
};
await ShippingAddressRD.create(addressData);
// Send email with the new password
await sendEmail({
to: `${item.email}`, // Change to your recipient
from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender
subject: `Cheminova Account Created`,
html: `Your Retail Distributor Account is created successfully.
name is: ${item.name}
MobileNumber is: ${item.mobile_number}
Email is: ${item.email}
password is: ${password}
If you have not requested this email, please ignore it.`,
});
newlyCreated.push({ Kyc });
}
}
// Clean up uploaded file if any error occurs
if (fs.existsSync(filePath)) {
fs.unlinkSync(filePath);
}
res.status(200).json({
message: "File processed successfully",
newlyCreated,
updatedDistributors,
errors,
});
} catch (error) {
console.error(error);
// Clean up uploaded file if any error occurs
if (fs.existsSync(filePath)) {
fs.unlinkSync(filePath);
}
res.status(500).json({ message: "Internal Server Error" });
}
};
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 });
}
};
export const getAllRetailDistributorwithTotalorder = async (req, res) => {
try {
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", // KYC collection
localField: "kyc",
foreignField: "_id",
as: "kycDetails",
},
},
{ $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } },
{
$lookup: {
from: "users", // Principal Distributor collection
localField: "principal_distributer",
foreignField: "_id",
as: "principalDetails",
},
},
{
$unwind: {
path: "$principalDetails",
preserveNullAndEmptyArrays: true,
},
},
{
$lookup: {
from: "territorymanagers", // Territory Manager collection
localField: "mappedTM",
foreignField: "_id",
as: "mappedTMDetails",
},
},
{
$unwind: { path: "$mappedTMDetails", preserveNullAndEmptyArrays: true },
},
{
$lookup: {
from: "salescoordinators", // Sales Coordinator collection
localField: "mappedSC",
foreignField: "_id",
as: "mappedSCDetails",
},
},
{
$unwind: { path: "$mappedSCDetails", preserveNullAndEmptyArrays: true },
},
];
// Add filters based on query parameters
const matchConditions = {};
if (tradename)
matchConditions["kycDetails.trade_name"] = new RegExp(tradename, "i");
if (name) matchConditions["name"] = new RegExp(name, "i");
if (mobile_number)
matchConditions["mobile_number"] = new RegExp(mobile_number, "i");
if (principaldistributor)
matchConditions["principalDetails.name"] = new RegExp(
principaldistributor,
"i"
);
if (Object.keys(matchConditions).length) {
pipeline.push({ $match: matchConditions });
}
// Project required fields early
pipeline.push({
$project: {
_id: 1,
uniqueId: 1,
name: 1,
mobile_number: 1,
email: 1,
"kycDetails.trade_name": 1,
"principalDetails.name": 1,
"mappedTMDetails.name": 1,
"mappedSCDetails.name": 1,
createdAt: 1,
},
});
// Pagination and sorting
pipeline.push({ $sort: { createdAt: -1 } });
pipeline.push({ $skip: skip });
pipeline.push({ $limit: parseInt(show) });
// Execute the main aggregation pipeline
const Retaildistributor = await RetailDistributor.aggregate(pipeline);
// Aggregate orders data for each distributor
const orderStats = await RdOrder.aggregate([
{
$match: { addedBy: { $in: Retaildistributor.map((user) => user._id) } },
},
{
$group: {
_id: "$addedBy", // Group by distributor ID
totalOrders: { $sum: 1 }, // Count total orders
lastOrderDate: { $max: "$createdAt" }, // Get last order date
},
},
]);
// Combine order stats with Retaildistributor data
const usersWithOrderStats = Retaildistributor.map((user) => {
const orderData = orderStats.find(
(order) => order._id.toString() === user._id.toString()
);
return {
...user,
totalOrders: orderData ? orderData.totalOrders : 0,
lastOrderDate: orderData ? orderData.lastOrderDate : null,
};
});
// Get total count of documents matching the query
const countPipeline = [{ $match: matchConditions }, { $count: "total" }];
const total_data = await RetailDistributor.aggregate(countPipeline);
const totalCount = total_data[0]?.total || 0;
// Send the response
res.status(200).json({
success: true,
total_data: totalCount,
total_pages: Math.ceil(totalCount / show),
Retaildistributor: usersWithOrderStats,
});
} 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 email phone")
.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" });
}
// console.log(RD);
// 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 mappedSC 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 getAllRDbypdid = async (req, res) => {
try {
// Extract query parameters
const { page = 1, show = 10, tradename, name, mobile_number } = req.query;
const { mappedPDId } = req.params; // Extract mappedTM ID from request params
// Convert mappedPDId to ObjectId if it's a valid ObjectId string
let mappedPDObjectId;
try {
mappedPDObjectId = mongoose.Types.ObjectId(mappedPDId);
} catch (error) {
return res.status(400).json({ message: "Invalid mappedPD ID format" });
}
const skip = (page - 1) * show;
// Build the aggregation pipeline
let pipeline = [
{
$match: {
principal_distributer: mappedPDObjectId, // Filter by principal_distributer 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 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
"mappedTMDetails.name": 1, // Only name from mappedTM (Territory Manager)
"mappedSCDetails.name": 1, // Only name from mappedSC (Sales Coordinator)
"principalDetails.name": 1, // Only name from principal_distributer
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: {
principal_distributer: mappedPDObjectId, // 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 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;
// console.log(req.body);
// console.log(req.params);
// 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,
});
}
};
export const saveFCMTokenForRD = async (req, res) => {
const { fcmToken } = req.body;
const userId = req.user._id;
try {
// Fetch the current FCM token for the user
const user = await RetailDistributor.findById(userId);
if (!user) {
return res.status(404).send("User not found");
}
// Check if the new FCM token is different from the current one
if (user.fcm_token && user.fcm_token === fcmToken) {
return res.status(200).send("FCM Token is already up to date");
}
// Update the FCM token
user.fcm_token = fcmToken;
await user.save();
res.status(200).send("FCM Token saved successfully");
} catch (error) {
console.error("Error saving FCM Token:", error);
res.status(500).send("Internal Server Error");
}
};