1617 lines
47 KiB
JavaScript
1617 lines
47 KiB
JavaScript
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";
|
|
|
|
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];
|
|
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,
|
|
});
|
|
if (Kyc) {
|
|
// Track updated fields
|
|
const updatedFields = [];
|
|
|
|
// 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();
|
|
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);
|
|
await Retaildistributor.save();
|
|
// 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.
|
|
<br/>name is: <strong>${item.name}</strong>
|
|
<br/>
|
|
<br/>MobileNumber is: <strong>${item.mobile_number}</strong><br/>
|
|
<br/>Email is: <strong>${item.email}</strong><br/>
|
|
<br/>password is: <strong>${password}</strong><br/><br/>If you have not requested this email, please ignore it.`,
|
|
});
|
|
newlyCreated.push({ Kyc });
|
|
}
|
|
}
|
|
|
|
res.status(200).json({
|
|
message: "File processed successfully",
|
|
newlyCreated,
|
|
updatedDistributors,
|
|
errors,
|
|
});
|
|
} catch (error) {
|
|
console.error(error);
|
|
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: <strong>${newPassword}</strong><br/><br/>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(principal_distributor);
|
|
// 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,
|
|
});
|
|
}
|
|
};
|