From c77851d5f740b42a33ee8b7a4e66eb710cdb571e Mon Sep 17 00:00:00 2001 From: Sibunnayak Date: Tue, 10 Sep 2024 15:04:32 +0530 Subject: [PATCH 1/4] mapped TM with RD --- resources/KYC/KycController.js | 83 --- resources/KYC/KycRoutes.js | 9 - .../RetailDistributerRoutes.js | 27 + .../RetailDistributorController.js | 565 ++++++++++++++++++ .../RetailDistributorModel.js | 15 +- 5 files changed, 602 insertions(+), 97 deletions(-) diff --git a/resources/KYC/KycController.js b/resources/KYC/KycController.js index 8406c91..f02ea0c 100644 --- a/resources/KYC/KycController.js +++ b/resources/KYC/KycController.js @@ -569,87 +569,4 @@ export const saveFCMTokenForTM = async (req, res) => { res.status(500).send("Internal Server Error"); } }; -export const getAllKycApprovedbytmid = async (req, res) => { - try { - const { id } = req.params; // Extracting `mappedTM` ID from req.params - // Extract query parameters with default values - const { tradename, page = 1, show = 10 } = req.query; - const skip = (page - 1) * show; - - // Build query object - const query = { status: "approved", mappedTM: id }; - if (tradename) { - query.trade_name = new RegExp(tradename, "i"); - } - - // Fetch KYC records with pagination and population - const retaildistributor = await KYC.find(query) - .sort({ createdAt: -1 }) - .populate("principal_distributer") - .populate("mappedTM") - .populate("mappedSC") - .populate("addedBy") - .skip(skip) - .limit(parseInt(show)); - - // Get total count of documents matching the query - const total_data = await KYC.countDocuments(query); - - // Calculate total pages - const total_pages = Math.ceil(total_data / show); - - // Send the response - res.status(200).json({ - success: true, - total_data: total_data, - total_pages: total_pages, - retaildistributor, - }); - } catch (error) { - // Handle any errors that occur during the fetch operation - console.error(error); - res.status(500).json({ message: "Server Error", error }); - } -}; - -export const updateKYCMapped = async (req, res) => { - try { - const { id } = req.params; // KYC document ID from params - const { principal_distributor, mappedTM, mappedSC } = req.body; // Fields to update from the request body - - // Find the KYC document by ID - const kyc = await KYC.findById(id); - - // If KYC not found, return 404 - if (!kyc) { - return res.status(404).json({ message: "KYC record not found" }); - } - - // Update the fields only if they are provided in the request body - if (principal_distributor) { - kyc.principal_distributer = principal_distributor; - } - if (mappedTM) { - kyc.mappedTM = mappedTM; - } - if (mappedSC) { - kyc.mappedSC = mappedSC; - } - - // Save the updated KYC document - await kyc.save(); - - // Send the updated KYC data as a response - res.status(200).json({ - message: "KYC record updated successfully", - data: kyc, - }); - } catch (error) { - // Handle any errors during the update - res.status(500).json({ - message: "Error updating KYC record", - error: error.message, - }); - } -}; diff --git a/resources/KYC/KycRoutes.js b/resources/KYC/KycRoutes.js index b03e1a0..60281df 100644 --- a/resources/KYC/KycRoutes.js +++ b/resources/KYC/KycRoutes.js @@ -7,13 +7,11 @@ import { createretaildistributor, getAllKyc, getAllKycApproved, - getAllKycApprovedbytmid, getAllKycRejected, getAllPrincipalDistributers, getKycById, saveFCMTokenForSC, saveFCMTokenForTM, - updateKYCMapped, updateKycStatus, } from "./KycController.js"; import { isAuthenticatedSalesCoOrdinator } from "../../middlewares/SalesCoOrdinatorAuth.js"; @@ -78,11 +76,4 @@ router router .route("/kyc/save-fcm-tm/") .post(isAuthenticatedTerritoryManager, saveFCMTokenForTM); -//mapping part -router - .route("/kyc/getAllapprovedbytmid/:id") - .get(isAuthenticatedUser, authorizeRoles("admin"), getAllKycApprovedbytmid); -router - .route("/kyc/mapped/:id") - .get(isAuthenticatedUser, authorizeRoles("admin"), updateKYCMapped); export default router; diff --git a/resources/RetailDistributor/RetailDistributerRoutes.js b/resources/RetailDistributor/RetailDistributerRoutes.js index 5bbad7b..d9ab800 100644 --- a/resources/RetailDistributor/RetailDistributerRoutes.js +++ b/resources/RetailDistributor/RetailDistributerRoutes.js @@ -2,11 +2,17 @@ import express from "express"; import { ChangePasswordRD, forgotPassword, + getAllRDbytmid, + getAllRetailDistributorApproved, getmyProfile, + getRDId, loginRD, UpdateProfile, + updateRDMapped, + updateunmapRD, } from "./RetailDistributorController.js"; import { isAuthenticatedRD } from "../../middlewares/rdAuth.js"; +import { authorizeRoles, isAuthenticatedUser } from "../../middlewares/auth.js"; const router = express.Router(); @@ -25,4 +31,25 @@ router.patch( UpdateProfile ); +//admin and maping +router + .route("/getAllRD") + .get( + isAuthenticatedUser, + authorizeRoles("admin"), + getAllRetailDistributorApproved + ); +router + .route("/getRD/:id") + .get(isAuthenticatedUser, authorizeRoles("admin"), getRDId); +//mapping part +router + .route("/getAllRDbytmid/:mappedTMId") + .get(isAuthenticatedUser, authorizeRoles("admin"), getAllRDbytmid); +router + .route("/mapped/:id") + .put(isAuthenticatedUser, authorizeRoles("admin"), updateRDMapped); + router + .route("/unmap/:id") + .patch(isAuthenticatedUser, authorizeRoles("admin"), updateunmapRD); export default router; diff --git a/resources/RetailDistributor/RetailDistributorController.js b/resources/RetailDistributor/RetailDistributorController.js index aa3c66e..eecebea 100644 --- a/resources/RetailDistributor/RetailDistributorController.js +++ b/resources/RetailDistributor/RetailDistributorController.js @@ -1,3 +1,4 @@ +import mongoose from "mongoose"; import RetailDistributor from "./RetailDistributorModel.js"; import validator from "validator"; export const loginRD = async (req, res) => { @@ -216,3 +217,567 @@ export const getmyProfile = async (req, res) => { }); } }; + +//reatil distributor mapping +export const getAllRetailDistributorApproved = async (req, res) => { + try { + // Extract query parameters + const { + page = 1, + show = 10, + tradename, + name, + mobile_number, + principaldistributor, + } = req.query; + const skip = (page - 1) * show; + + // Build the aggregation pipeline + let pipeline = [ + { + $lookup: { + from: "kycs", // Assuming your KYC collection is named "kycs" + localField: "kyc", + foreignField: "_id", + as: "kycDetails", + }, + }, + { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } }, // Unwind kycDetails and allow null/empty arrays + { + $lookup: { + from: "users", // Assuming your User collection is named "users" + localField: "principal_distributer", + foreignField: "_id", + as: "principalDetails", + }, + }, + { + $unwind: { + path: "$principalDetails", + preserveNullAndEmptyArrays: true, + }, + }, // Unwind principalDetails and allow null/empty arrays + + // Lookup for mappedTM (Territory Manager) + { + $lookup: { + from: "territorymanagers", // Assuming your Territory Manager collection + localField: "mappedTM", + foreignField: "_id", + as: "mappedTMDetails", + }, + }, + { + $unwind: { path: "$mappedTMDetails", preserveNullAndEmptyArrays: true }, + }, // Unwind mappedTMDetails and allow null/empty arrays + + // Lookup for mappedSC (Sales Coordinator) + { + $lookup: { + from: "salescoordinators", // Assuming your Sales Coordinator collection + localField: "mappedSC", + foreignField: "_id", + as: "mappedSCDetails", + }, + }, + { + $unwind: { path: "$mappedSCDetails", preserveNullAndEmptyArrays: true }, + }, // Unwind mappedSCDetails and allow null/empty arrays + + // Filter to ensure data exists in kyc or principalDetails + { + $match: { + $or: [ + { "kycDetails.trade_name": { $exists: true } }, // Ensure KYC exists + { "principalDetails.name": { $exists: true } }, // Ensure Principal Distributor exists + ], + }, + }, + ]; + + // Add filters based on query parameters + + // Filter by KYC trade_name (case-insensitive) + if (tradename) { + pipeline.push({ + $match: { "kycDetails.trade_name": new RegExp(tradename, "i") }, + }); + } + + // Filter by principal_distributer name (case-insensitive) + if (principaldistributor) { + pipeline.push({ + $match: { + "principalDetails.name": new RegExp(principaldistributor, "i"), + }, + }); + } + + // Filter by name (RetailDistributor model's name) + if (name) { + pipeline.push({ + $match: { name: new RegExp(name, "i") }, // Case-insensitive search for name + }); + } + + // Filter by mobile_number (RetailDistributor model's mobile number) + if (mobile_number) { + pipeline.push({ + $match: { mobile_number: new RegExp(mobile_number, "i") }, // Case-insensitive search for mobile_number + }); + } + + // Project only the required fields + pipeline.push({ + $project: { + _id: 1, // RetailDistributor ID + uniqueId: 1, // RetailDistributor uniqueId + name: 1, // RetailDistributor name + mobile_number: 1, // RetailDistributor mobile_number + email: 1, // RetailDistributor email + "kycDetails.trade_name": 1, // Only trade_name from kyc + "principalDetails.name": 1, // Only name from principal_distributer + "mappedTMDetails.name": 1, // Only name from mappedTM (Territory Manager) + "mappedSCDetails.name": 1, // Only name from mappedSC (Sales Coordinator) + createdAt: 1, // For sorting + }, + }); + + // Pagination and sorting + pipeline.push({ $sort: { createdAt: -1 } }); + pipeline.push({ $skip: skip }); + pipeline.push({ $limit: parseInt(show) }); + + // Execute the aggregation pipeline + const Retaildistributor = await RetailDistributor.aggregate(pipeline); + + // Get total count of documents matching the query + const countPipeline = [ + { + $lookup: { + from: "kycs", + localField: "kyc", + foreignField: "_id", + as: "kycDetails", + }, + }, + { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } }, + { + $lookup: { + from: "users", + localField: "principal_distributer", + foreignField: "_id", + as: "principalDetails", + }, + }, + { + $unwind: { + path: "$principalDetails", + preserveNullAndEmptyArrays: true, + }, + }, + { + $match: { + $or: [ + { "kycDetails.trade_name": { $exists: true } }, + { "principalDetails.name": { $exists: true } }, + ], + }, + }, + ]; + + // Apply search filters to count query + + // Filter by KYC trade_name + if (tradename) { + countPipeline.push({ + $match: { "kycDetails.trade_name": new RegExp(tradename, "i") }, + }); + } + + // Filter by principal_distributer name + if (principaldistributor) { + countPipeline.push({ + $match: { + "principalDetails.name": new RegExp(principaldistributor, "i"), + }, + }); + } + + // Filter by name + if (name) { + countPipeline.push({ + $match: { name: new RegExp(name, "i") }, + }); + } + + // Filter by mobile_number + if (mobile_number) { + countPipeline.push({ + $match: { mobile_number: new RegExp(mobile_number, "i") }, + }); + } + + // Get the total count of filtered documents + const total_data = await RetailDistributor.aggregate([ + ...countPipeline, + { $count: "total" }, + ]); + + const totalCount = total_data[0]?.total || 0; // Ensure count is zero if no data found + + // Send the response with pagination data + res.status(200).json({ + success: true, + total_data: totalCount, + total_pages: Math.ceil(totalCount / show), + Retaildistributor, + }); + } catch (error) { + console.error(error); + res.status(500).json({ message: "Server Error", error }); + } +}; + +//get RD by Id +export const getRDId = async (req, res) => { + try { + const { id } = req.params; + console.log(id); + // Fetch the KYC document from the database by ID + const RD = await RetailDistributor.findById(id) + .populate("principal_distributer", "name") + .populate("addedBy") + .populate("kyc") + .populate("mappedTM") + .populate("mappedSC"); + + // Check if the KYC document exists + if (!RD) { + return res.status(404).json({ message: "No RetailDistributor found" }); + } + + // Send the fetched KYC document as a response + res.status(200).json(RD); + } catch (error) { + // Handle any errors that occur during the fetch operation + res.status(500).json({ message: "Server Error", error }); + } +}; +//mapping + +export const getAllRDbytmid = async (req, res) => { + try { + // Extract query parameters + const { + page = 1, + show = 10, + tradename, + name, + mobile_number, + principaldistributor, + } = req.query; + const { mappedTMId } = req.params; // Extract mappedTM ID from request params + + // Convert mappedTMId to ObjectId if it's a valid ObjectId string + let mappedTMObjectId; + try { + mappedTMObjectId = mongoose.Types.ObjectId(mappedTMId); + } catch (error) { + return res.status(400).json({ message: "Invalid mappedTM ID format" }); + } + + const skip = (page - 1) * show; + + // Build the aggregation pipeline + let pipeline = [ + { + $match: { + mappedTM: mappedTMObjectId, // Filter by mappedTM ObjectId + }, + }, + { + $lookup: { + from: "kycs", // Assuming your KYC collection is named "kycs" + localField: "kyc", + foreignField: "_id", + as: "kycDetails", + }, + }, + { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } }, // Unwind kycDetails and allow null/empty arrays + { + $lookup: { + from: "users", // Assuming your User collection is named "users" + localField: "principal_distributer", + foreignField: "_id", + as: "principalDetails", + }, + }, + { + $unwind: { + path: "$principalDetails", + preserveNullAndEmptyArrays: true, + }, + }, // Unwind principalDetails and allow null/empty arrays + + // Lookup for mappedTM (Territory Manager) + { + $lookup: { + from: "territorymanagers", // Assuming your Territory Manager collection + localField: "mappedTM", + foreignField: "_id", + as: "mappedTMDetails", + }, + }, + { + $unwind: { path: "$mappedTMDetails", preserveNullAndEmptyArrays: true }, + }, // Unwind mappedTMDetails and allow null/empty arrays + + // Lookup for mappedSC (Sales Coordinator) + { + $lookup: { + from: "salescoordinators", // Assuming your Sales Coordinator collection + localField: "mappedSC", + foreignField: "_id", + as: "mappedSCDetails", + }, + }, + { + $unwind: { path: "$mappedSCDetails", preserveNullAndEmptyArrays: true }, + }, // Unwind mappedSCDetails and allow null/empty arrays + + // Filter to ensure data exists in kyc or principalDetails + { + $match: { + $or: [ + { "kycDetails.trade_name": { $exists: true } }, // Ensure KYC exists + { "principalDetails.name": { $exists: true } }, // Ensure Principal Distributor exists + ], + }, + }, + ]; + + // Add filters based on query parameters + + // Filter by KYC trade_name (case-insensitive) + if (tradename) { + pipeline.push({ + $match: { "kycDetails.trade_name": new RegExp(tradename, "i") }, + }); + } + + // Filter by principal_distributer name (case-insensitive) + if (principaldistributor) { + pipeline.push({ + $match: { + "principalDetails.name": new RegExp(principaldistributor, "i"), + }, + }); + } + + // Filter by name (RetailDistributor model's name) + if (name) { + pipeline.push({ + $match: { name: new RegExp(name, "i") }, // Case-insensitive search for name + }); + } + + // Filter by mobile_number (RetailDistributor model's mobile number) + if (mobile_number) { + pipeline.push({ + $match: { mobile_number: new RegExp(mobile_number, "i") }, // Case-insensitive search for mobile_number + }); + } + + // Project only the required fields + pipeline.push({ + $project: { + _id: 1, // RetailDistributor ID + uniqueId: 1, // RetailDistributor uniqueId + name: 1, // RetailDistributor name + mobile_number: 1, // RetailDistributor mobile_number + email: 1, // RetailDistributor email + "kycDetails.trade_name": 1, // Only trade_name from kyc + "principalDetails.name": 1, // Only name from principal_distributer + "mappedTMDetails.name": 1, // Only name from mappedTM (Territory Manager) + "mappedSCDetails.name": 1, // Only name from mappedSC (Sales Coordinator) + createdAt: 1, // For sorting + }, + }); + + // Pagination and sorting + pipeline.push({ $sort: { createdAt: -1 } }); + pipeline.push({ $skip: skip }); + pipeline.push({ $limit: parseInt(show) }); + + // Execute the aggregation pipeline + const Retaildistributor = await RetailDistributor.aggregate(pipeline); + + // Get total count of documents matching the query + const countPipeline = [ + { + $match: { + mappedTM: mappedTMObjectId, // Filter by mappedTM ObjectId + }, + }, + { + $lookup: { + from: "kycs", + localField: "kyc", + foreignField: "_id", + as: "kycDetails", + }, + }, + { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } }, + { + $lookup: { + from: "users", + localField: "principal_distributer", + foreignField: "_id", + as: "principalDetails", + }, + }, + { + $unwind: { + path: "$principalDetails", + preserveNullAndEmptyArrays: true, + }, + }, + { + $match: { + $or: [ + { "kycDetails.trade_name": { $exists: true } }, + { "principalDetails.name": { $exists: true } }, + ], + }, + }, + ]; + + // Apply search filters to count query + + // Filter by KYC trade_name + if (tradename) { + countPipeline.push({ + $match: { "kycDetails.trade_name": new RegExp(tradename, "i") }, + }); + } + + // Filter by principal_distributer name + if (principaldistributor) { + countPipeline.push({ + $match: { + "principalDetails.name": new RegExp(principaldistributor, "i"), + }, + }); + } + + // Filter by name + if (name) { + countPipeline.push({ + $match: { name: new RegExp(name, "i") }, + }); + } + + // Filter by mobile_number + if (mobile_number) { + countPipeline.push({ + $match: { mobile_number: new RegExp(mobile_number, "i") }, + }); + } + + // Get the total count of filtered documents + const total_data = await RetailDistributor.aggregate([ + ...countPipeline, + { $count: "total" }, + ]); + + const totalCount = total_data[0]?.total || 0; // Ensure count is zero if no data found + + // Send the response with pagination data + res.status(200).json({ + success: true, + total_data: totalCount, + total_pages: Math.ceil(totalCount / show), + Retaildistributor, + }); + } catch (error) { + console.error(error); + res.status(500).json({ message: "Server Error", error }); + } +}; + +export const updateRDMapped = async (req, res) => { + try { + const { id } = req.params; + const { principal_distributor, mappedTM, mappedSC } = req.body; + + // Find the RetailDistributor document by ID + const RD = await RetailDistributor.findById(id); + + if (!RD) { + return res.status(404).json({ message: "RetailDistributor not found" }); + } + + // Update the fields if provided in the request body + if (principal_distributor) { + RD.principal_distributer = principal_distributor; + } + if (mappedTM) { + RD.mappedTM = mappedTM; + } + if (mappedSC) { + RD.mappedSC = mappedSC; + } + + // Save the updated document + await RD.save(); + + res.status(200).json({ + message: "RetailDistributor record updated successfully", + data: RD, + }); + } catch (error) { + // Handle any errors during the update + res.status(500).json({ + message: "Error updating RD record", + error: error.message, + }); + } +}; +export const updateunmapRD = async (req, res) => { + try { + const { id } = req.params; + const { principal_distributor, mappedTM, mappedSC } = req.body; + + // Find the RetailDistributor document by ID + const RD = await RetailDistributor.findById(id); + + if (!RD) { + return res.status(404).json({ message: "RetailDistributor not found" }); + } + + // Update the fields if provided in the request body + if (principal_distributor) { + RD.principal_distributer = null; + } + if (mappedTM ) { + RD.mappedTM = null; + } + if (mappedSC) { + RD.mappedSC = null; + } + // Save the updated document + await RD.save(); + + res.status(200).json({ + message: "RetailDistributor record updated successfully", + data: RD, + }); + } catch (error) { + // Handle any errors during the update + res.status(500).json({ + message: "Error updating RD record", + error: error.message, + }); + } +}; diff --git a/resources/RetailDistributor/RetailDistributorModel.js b/resources/RetailDistributor/RetailDistributorModel.js index 96f5452..607b646 100644 --- a/resources/RetailDistributor/RetailDistributorModel.js +++ b/resources/RetailDistributor/RetailDistributorModel.js @@ -73,12 +73,17 @@ const RetailDistributorSchema = new mongoose.Schema( }, { timestamps: true } ); -// Pre-save middleware to set 'mapped' based on 'userType' + +// Pre-save middleware to set 'mappedSC' or 'mappedTM' if not provided, based on 'userType' and 'addedBy' RetailDistributorSchema.pre("save", function (next) { - if (this.userType === "SalesCoOrdinator" && this.addedBy) { - this.mappedSC = this.addedBy; - } else if (this.userType === "TerritoryManager" && this.addedBy) { - this.mappedTM = this.addedBy; + // Only set defaults if the document is new (not yet saved) + if (this.isNew) { + if (!this.mappedSC && this.userType === "SalesCoOrdinator" && this.addedBy) { + this.mappedSC = this.addedBy; + } + if (!this.mappedTM && this.userType === "TerritoryManager" && this.addedBy) { + this.mappedTM = this.addedBy; + } } next(); }); From 264cf42a57f7818d2e3c9af9fe18adce19d222c1 Mon Sep 17 00:00:00 2001 From: Sibunnayak Date: Tue, 10 Sep 2024 15:24:00 +0530 Subject: [PATCH 2/4] mapped TM with RD --- .../RetailDistributerRoutes.js | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/resources/RetailDistributor/RetailDistributerRoutes.js b/resources/RetailDistributor/RetailDistributerRoutes.js index d9ab800..3975551 100644 --- a/resources/RetailDistributor/RetailDistributerRoutes.js +++ b/resources/RetailDistributor/RetailDistributerRoutes.js @@ -1,13 +1,13 @@ import express from "express"; import { ChangePasswordRD, - forgotPassword, + forgotPasswordRD, getAllRDbytmid, getAllRetailDistributorApproved, - getmyProfile, + getmyProfileRD, getRDId, loginRD, - UpdateProfile, + UpdateProfileRD, updateRDMapped, updateunmapRD, } from "./RetailDistributorController.js"; @@ -17,20 +17,15 @@ import { authorizeRoles, isAuthenticatedUser } from "../../middlewares/auth.js"; const router = express.Router(); router.route("/rd-login").post(loginRD); -router.route("/rd-get-me").get(isAuthenticatedRD, getmyProfile); -router.post("/forgot-password", forgotPassword); +router.route("/rd-get-me").get(isAuthenticatedRD, getmyProfileRD); +router.post("/forgot-password", forgotPasswordRD); router.put( "/rd-password/update", isAuthenticatedRD, ChangePasswordRD ); -router.patch( - "/rd-profile/update", - isAuthenticatedRD, - - UpdateProfile -); +router.patch("/rd-profile/update", isAuthenticatedRD, UpdateProfileRD); //admin and maping router .route("/getAllRD") From 38a5fde457cc638a3cb16192c396763caf6a7466 Mon Sep 17 00:00:00 2001 From: Sibunnayak Date: Tue, 10 Sep 2024 16:02:06 +0530 Subject: [PATCH 3/4] mapped SC with RD --- .../RetailDistributerRoutes.js | 4 + .../RetailDistributorController.js | 238 ++++++++++++++++++ 2 files changed, 242 insertions(+) diff --git a/resources/RetailDistributor/RetailDistributerRoutes.js b/resources/RetailDistributor/RetailDistributerRoutes.js index 3975551..e60e831 100644 --- a/resources/RetailDistributor/RetailDistributerRoutes.js +++ b/resources/RetailDistributor/RetailDistributerRoutes.js @@ -2,6 +2,7 @@ import express from "express"; import { ChangePasswordRD, forgotPasswordRD, + getAllRDbyscid, getAllRDbytmid, getAllRetailDistributorApproved, getmyProfileRD, @@ -41,6 +42,9 @@ router router .route("/getAllRDbytmid/:mappedTMId") .get(isAuthenticatedUser, authorizeRoles("admin"), getAllRDbytmid); + router + .route("/getAllRDbyscid/:mappedSCId") + .get(isAuthenticatedUser, authorizeRoles("admin"), getAllRDbyscid); router .route("/mapped/:id") .put(isAuthenticatedUser, authorizeRoles("admin"), updateRDMapped); diff --git a/resources/RetailDistributor/RetailDistributorController.js b/resources/RetailDistributor/RetailDistributorController.js index 06c2b28..b7dd090 100644 --- a/resources/RetailDistributor/RetailDistributorController.js +++ b/resources/RetailDistributor/RetailDistributorController.js @@ -692,7 +692,245 @@ export const getAllRDbytmid = async (req, res) => { res.status(500).json({ message: "Server Error", error }); } }; +export const getAllRDbyscid = async (req, res) => { + try { + // Extract query parameters + const { + page = 1, + show = 10, + tradename, + name, + mobile_number, + principaldistributor, + } = req.query; + const { mappedSCId } = req.params; // Extract mappedTM ID from request params + // Convert mappedSCId to ObjectId if it's a valid ObjectId string + let mappedSCObjectId; + try { + mappedSCObjectId = mongoose.Types.ObjectId(mappedSCId); + } catch (error) { + return res.status(400).json({ message: "Invalid mappedTM ID format" }); + } + + const skip = (page - 1) * show; + + // Build the aggregation pipeline + let pipeline = [ + { + $match: { + mappedSC: mappedSCObjectId, // Filter by mappedSC ObjectId + }, + }, + { + $lookup: { + from: "kycs", // Assuming your KYC collection is named "kycs" + localField: "kyc", + foreignField: "_id", + as: "kycDetails", + }, + }, + { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } }, // Unwind kycDetails and allow null/empty arrays + { + $lookup: { + from: "users", // Assuming your User collection is named "users" + localField: "principal_distributer", + foreignField: "_id", + as: "principalDetails", + }, + }, + { + $unwind: { + path: "$principalDetails", + preserveNullAndEmptyArrays: true, + }, + }, // Unwind principalDetails and allow null/empty arrays + + // Lookup for mappedTM (Territory Manager) + { + $lookup: { + from: "territorymanagers", // Assuming your Territory Manager collection + localField: "mappedTM", + foreignField: "_id", + as: "mappedTMDetails", + }, + }, + { + $unwind: { path: "$mappedTMDetails", preserveNullAndEmptyArrays: true }, + }, // Unwind mappedTMDetails and allow null/empty arrays + + // Lookup for mappedSC (Sales Coordinator) + { + $lookup: { + from: "salescoordinators", // Assuming your Sales Coordinator collection + localField: "mappedSC", + foreignField: "_id", + as: "mappedSCDetails", + }, + }, + { + $unwind: { path: "$mappedSCDetails", preserveNullAndEmptyArrays: true }, + }, // Unwind mappedSCDetails and allow null/empty arrays + + // Filter to ensure data exists in kyc or principalDetails + { + $match: { + $or: [ + { "kycDetails.trade_name": { $exists: true } }, // Ensure KYC exists + { "principalDetails.name": { $exists: true } }, // Ensure Principal Distributor exists + ], + }, + }, + ]; + + // Add filters based on query parameters + + // Filter by KYC trade_name (case-insensitive) + if (tradename) { + pipeline.push({ + $match: { "kycDetails.trade_name": new RegExp(tradename, "i") }, + }); + } + + // Filter by principal_distributer name (case-insensitive) + if (principaldistributor) { + pipeline.push({ + $match: { + "principalDetails.name": new RegExp(principaldistributor, "i"), + }, + }); + } + + // Filter by name (RetailDistributor model's name) + if (name) { + pipeline.push({ + $match: { name: new RegExp(name, "i") }, // Case-insensitive search for name + }); + } + + // Filter by mobile_number (RetailDistributor model's mobile number) + if (mobile_number) { + pipeline.push({ + $match: { mobile_number: new RegExp(mobile_number, "i") }, // Case-insensitive search for mobile_number + }); + } + + // Project only the required fields + pipeline.push({ + $project: { + _id: 1, // RetailDistributor ID + uniqueId: 1, // RetailDistributor uniqueId + name: 1, // RetailDistributor name + mobile_number: 1, // RetailDistributor mobile_number + email: 1, // RetailDistributor email + "kycDetails.trade_name": 1, // Only trade_name from kyc + "principalDetails.name": 1, // Only name from principal_distributer + "mappedTMDetails.name": 1, // Only name from mappedTM (Territory Manager) + "mappedSCDetails.name": 1, // Only name from mappedSC (Sales Coordinator) + createdAt: 1, // For sorting + }, + }); + + // Pagination and sorting + pipeline.push({ $sort: { createdAt: -1 } }); + pipeline.push({ $skip: skip }); + pipeline.push({ $limit: parseInt(show) }); + + // Execute the aggregation pipeline + const Retaildistributor = await RetailDistributor.aggregate(pipeline); + + // Get total count of documents matching the query + const countPipeline = [ + { + $match: { + mappedSC: mappedSCObjectId, // Filter by mappedTM ObjectId + }, + }, + { + $lookup: { + from: "kycs", + localField: "kyc", + foreignField: "_id", + as: "kycDetails", + }, + }, + { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } }, + { + $lookup: { + from: "users", + localField: "principal_distributer", + foreignField: "_id", + as: "principalDetails", + }, + }, + { + $unwind: { + path: "$principalDetails", + preserveNullAndEmptyArrays: true, + }, + }, + { + $match: { + $or: [ + { "kycDetails.trade_name": { $exists: true } }, + { "principalDetails.name": { $exists: true } }, + ], + }, + }, + ]; + + // Apply search filters to count query + + // Filter by KYC trade_name + if (tradename) { + countPipeline.push({ + $match: { "kycDetails.trade_name": new RegExp(tradename, "i") }, + }); + } + + // Filter by principal_distributer name + if (principaldistributor) { + countPipeline.push({ + $match: { + "principalDetails.name": new RegExp(principaldistributor, "i"), + }, + }); + } + + // Filter by name + if (name) { + countPipeline.push({ + $match: { name: new RegExp(name, "i") }, + }); + } + + // Filter by mobile_number + if (mobile_number) { + countPipeline.push({ + $match: { mobile_number: new RegExp(mobile_number, "i") }, + }); + } + + // Get the total count of filtered documents + const total_data = await RetailDistributor.aggregate([ + ...countPipeline, + { $count: "total" }, + ]); + + const totalCount = total_data[0]?.total || 0; // Ensure count is zero if no data found + + // Send the response with pagination data + res.status(200).json({ + success: true, + total_data: totalCount, + total_pages: Math.ceil(totalCount / show), + Retaildistributor, + }); + } catch (error) { + console.error(error); + res.status(500).json({ message: "Server Error", error }); + } +}; export const updateRDMapped = async (req, res) => { try { const { id } = req.params; From 6dd45ecd939e9cf3801902f7b15f0f58fbe84085 Mon Sep 17 00:00:00 2001 From: Sibunnayak Date: Tue, 10 Sep 2024 17:32:13 +0530 Subject: [PATCH 4/4] RD map with PD and fixing the mapping of getting RD and PD of SC and TM --- resources/Inventory/InventoryController.js | 7 +- .../RetailDistributerRoutes.js | 6 +- .../RetailDistributorController.js | 221 +++++++++++++++++- .../SalesCoOrdinatorController.js | 2 + .../SalesCoOrdinatorRoute.js | 2 + resources/user/userController.js | 2 + resources/user/userRoute.js | 2 + 7 files changed, 234 insertions(+), 8 deletions(-) diff --git a/resources/Inventory/InventoryController.js b/resources/Inventory/InventoryController.js index 4b2a151..c2a7e8b 100644 --- a/resources/Inventory/InventoryController.js +++ b/resources/Inventory/InventoryController.js @@ -5,6 +5,7 @@ import ShippingAddress from "../ShippingAddresses/ShippingAddressModel.js"; import TerritoryManager from "../TerritoryManagers/TerritoryManagerModel.js"; import SalesCoordinator from "../SalesCoOrdinators/SalesCoOrdinatorModel.js"; import crypto from "crypto"; +import RetailDistributor from "../RetailDistributor/RetailDistributorModel.js"; // Add inventory data export const addInventory = async (req, res) => { try { @@ -45,7 +46,7 @@ export const getDistributors = async (req, res) => { return res.status(400).json({ message: "Invalid distributor type" }); } let filter = { role: "principal-Distributor" }; - let query={status: "approved"}; + let query={}; // Check the user type and adjust the filter accordingly if (req.userType === "SalesCoOrdinator") { // If userType is "SalesCoOrdinator", filter by req.user.mappedBy @@ -56,8 +57,6 @@ export const getDistributors = async (req, res) => { filter.mappedby = req.user._id; query.mappedTM = req.user._id; } - console.log("filter",filter); - console.log("query",query); let distributors; // console.log("type",type); if (type === "PrincipalDistributor") { @@ -78,7 +77,7 @@ export const getDistributors = async (req, res) => { ); } else { // For RetailDistributor, fetch approved KYC documents - distributors = await KYC.find(query); + distributors = await RetailDistributor.find(query).populate("kyc"); } res.status(200).json(distributors); diff --git a/resources/RetailDistributor/RetailDistributerRoutes.js b/resources/RetailDistributor/RetailDistributerRoutes.js index e60e831..2da3d94 100644 --- a/resources/RetailDistributor/RetailDistributerRoutes.js +++ b/resources/RetailDistributor/RetailDistributerRoutes.js @@ -2,6 +2,7 @@ import express from "express"; import { ChangePasswordRD, forgotPasswordRD, + getAllRDbypdid, getAllRDbyscid, getAllRDbytmid, getAllRetailDistributorApproved, @@ -42,9 +43,12 @@ router router .route("/getAllRDbytmid/:mappedTMId") .get(isAuthenticatedUser, authorizeRoles("admin"), getAllRDbytmid); - router +router .route("/getAllRDbyscid/:mappedSCId") .get(isAuthenticatedUser, authorizeRoles("admin"), getAllRDbyscid); +router + .route("/getAllRDbypdid/:mappedPDId") + .get(isAuthenticatedUser, authorizeRoles("admin"), getAllRDbypdid); router .route("/mapped/:id") .put(isAuthenticatedUser, authorizeRoles("admin"), updateRDMapped); diff --git a/resources/RetailDistributor/RetailDistributorController.js b/resources/RetailDistributor/RetailDistributorController.js index b7dd090..1a22e4a 100644 --- a/resources/RetailDistributor/RetailDistributorController.js +++ b/resources/RetailDistributor/RetailDistributorController.js @@ -710,7 +710,7 @@ export const getAllRDbyscid = async (req, res) => { try { mappedSCObjectId = mongoose.Types.ObjectId(mappedSCId); } catch (error) { - return res.status(400).json({ message: "Invalid mappedTM ID format" }); + return res.status(400).json({ message: "Invalid mappedSC ID format" }); } const skip = (page - 1) * show; @@ -931,11 +931,226 @@ export const getAllRDbyscid = async (req, res) => { 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); @@ -985,7 +1200,7 @@ export const updateunmapRD = async (req, res) => { if (principal_distributor) { RD.principal_distributer = null; } - if (mappedTM ) { + if (mappedTM) { RD.mappedTM = null; } if (mappedSC) { diff --git a/resources/SalesCoOrdinators/SalesCoOrdinatorController.js b/resources/SalesCoOrdinators/SalesCoOrdinatorController.js index c5f6556..56cce6d 100644 --- a/resources/SalesCoOrdinators/SalesCoOrdinatorController.js +++ b/resources/SalesCoOrdinators/SalesCoOrdinatorController.js @@ -200,6 +200,7 @@ export const getAllSalesCoOrdinator = async (req, res) => { } const total = await SalesCoOrdinator.countDocuments(filter); const salesCoOrinators = await SalesCoOrdinator.find(filter) + .populate("mappedby", "name") .limit(PAGE_SIZE) .skip(PAGE_SIZE * page) .sort({ createdAt: -1 }); @@ -285,6 +286,7 @@ export const getAllSalesCoOrdinatorbytmId = async (req, res) => { const total = await SalesCoOrdinator.countDocuments(filter); const salesCoOrinators = await SalesCoOrdinator.find(filter) + .populate("mappedby", "name") .limit(PAGE_SIZE) .skip(PAGE_SIZE * page) .sort({ createdAt: -1 }); diff --git a/resources/SalesCoOrdinators/SalesCoOrdinatorRoute.js b/resources/SalesCoOrdinators/SalesCoOrdinatorRoute.js index e37a7da..a543544 100644 --- a/resources/SalesCoOrdinators/SalesCoOrdinatorRoute.js +++ b/resources/SalesCoOrdinators/SalesCoOrdinatorRoute.js @@ -41,6 +41,7 @@ router.get( isAuthenticatedTerritoryManager, getAllSalesCoOrdinatorforTM_App ); +// mapping start router.get( "/getbyTmId/:id", isAuthenticatedUser, @@ -59,6 +60,7 @@ router.delete( authorizeRoles("admin"), unmapSalesCoOrdinator ); +// mapping end router.get( "/getOne/:id", isAuthenticatedUser, diff --git a/resources/user/userController.js b/resources/user/userController.js index d719e01..3ec8cf6 100644 --- a/resources/user/userController.js +++ b/resources/user/userController.js @@ -1024,6 +1024,8 @@ export const getAllUser = catchAsyncErrors(async (req, res, next) => { // Find users with the filter, pagination, and sorting const users = await User.find(filter) + .populate("mappedby", "name") + .populate("mappedbySC", "name") .sort({ createdAt: -1 }) .skip(skip) .limit(limit); diff --git a/resources/user/userRoute.js b/resources/user/userRoute.js index 4fc11c1..e54953a 100644 --- a/resources/user/userRoute.js +++ b/resources/user/userRoute.js @@ -44,6 +44,7 @@ router authorizeRoles("admin"), uploadPrincipaldistributors ); + //mapping start router .route("/admin/users") .get(isAuthenticatedUser, authorizeRoles("admin", "Employee"), getAllUser); @@ -85,6 +86,7 @@ router.patch( authorizeRoles("admin"), unmappedSCinPrincipalDistributor ); +//mapping end router .route("/admin/delete-employee/:id") .delete(