1397 lines
40 KiB
JavaScript
1397 lines
40 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";
|
|
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,
|
|
});
|
|
}
|
|
};
|
|
|
|
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");
|
|
}
|
|
};
|