diff --git a/resources/RD_Ordes/rdOrderController.js b/resources/RD_Ordes/rdOrderController.js
index 30b9bd7..f1e2498 100644
--- a/resources/RD_Ordes/rdOrderController.js
+++ b/resources/RD_Ordes/rdOrderController.js
@@ -600,7 +600,525 @@ export const processOrder = async (req, res) => {
.json({ error: "An error occurred while processing the order" });
}
};
+// get invoice by id
+export const getProcessingInvoicesForPd = async (req, res) => {
+ console.log("req , cames");
+ try {
+ // Ensure this is passed in your route, or retrieve it from the logged-in user
+ const page = parseInt(req.query.page, 10) || 1; // Default page is 1
+ const limit = parseInt(req.query.limit, 10) || 5; // Default limit is 5
+ const skip = (page - 1) * limit;
+ const { invoiceId, orderId } = req.query; // Search parameters
+ const pdId = req.user._id;
+ if (!pdId) {
+ return res.status(400).json({ message: "PD ID is required" });
+ }
+ console.log(pdId);
+ // Build the base query for fetching processing invoices
+ let query = { courierStatus: "processing" };
+
+ // If invoiceId is provided, add regex search for invoiceId
+ if (invoiceId) {
+ query.invoiceId = { $regex: invoiceId, $options: "i" }; // Case-insensitive search
+ }
+
+ // Fetch the invoices matching the query, along with pagination and population
+ const invoices = await InvoiceRd.find(query)
+ .skip(skip)
+ .limit(limit)
+ .populate({
+ path: "orderId",
+ match: { pd: pdId }, // Match the associated PD in the RdOrder model
+ select: "uniqueId", // Only select uniqueId from the order
+ })
+ .sort({ "courierstatus_timeline.processing": -1 }); // Sort by processing date, newest first
+ console.log(invoices);
+ // Filter invoices where the orderId exists and matches the search (if orderId is provided)
+ let filteredInvoices = invoices.filter(
+ (invoice) => invoice.orderId !== null
+ );
+
+ if (orderId) {
+ filteredInvoices = filteredInvoices.filter(
+ (invoice) =>
+ invoice.orderId &&
+ invoice.orderId.uniqueId &&
+ invoice.orderId.uniqueId.toLowerCase().includes(orderId.toLowerCase())
+ );
+ }
+
+ // Pagination metadata
+ const totalCount = filteredInvoices.length;
+ const totalPages = Math.ceil(totalCount / limit);
+
+ // Send the filtered invoices with pagination details
+ res.status(200).json({
+ totalCount,
+ currentPage: page,
+ totalPages,
+ invoices: filteredInvoices,
+ });
+ } catch (error) {
+ console.error(error);
+ res.status(500).json({ error: error.message });
+ }
+};
+
+export const getInvoiceDetailsByIdForPD = async (req, res) => {
+ const { invoiceId } = req.params;
+
+ try {
+ // Find the invoice by ID and populate the orderId and addedBy fields
+ const invoice = await InvoiceRd.findById(invoiceId).populate({
+ path: "orderId",
+ model: "PdOrder",
+ populate: {
+ path: "addedBy",
+ model: "RetailDistributor",
+ select: "name email phone ", // Select only specific fields
+ },
+ });
+
+ if (!invoice) {
+ return res.status(404).json({ error: "Invoice not found" });
+ }
+
+ res.status(200).json(invoice);
+ } catch (error) {
+ res.status(500).json({ error: error.message });
+ }
+};
+export const updateCourierStatusToDispatchedForPD = async (req, res) => {
+ const { invoiceId } = req.params;
+ const { courierName, couriertrackingId } = req.body;
+ try {
+ // Find the invoice by ID
+ const invoice = await InvoiceRd.findById(invoiceId).populate({
+ path: "orderId",
+ populate: {
+ path: "addedBy",
+ select: "email",
+ },
+ });
+
+ if (!invoice) {
+ return res.status(404).json({ error: "Invoice not found" });
+ }
+
+ invoice.courierStatus = "dispatched";
+ invoice.courierstatus_timeline.dispatched = new Date();
+ invoice.courier_name = courierName;
+ invoice.courier_tracking_id = couriertrackingId;
+
+ // Save the updated invoice
+ await invoice.save();
+
+ const order = invoice.orderId;
+ const allItemsDispatched = order.orderItem.every(
+ (item) => item.remainingQuantity === 0
+ );
+
+ if (allItemsDispatched) {
+ order.status = "dispatched";
+ await order.save();
+ }
+
+ // Send email to the user
+ await sendEmail({
+ to: `${order?.addedBy?.email}`, // Assuming 'addedBy' references the user who placed the order
+ from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender
+ subject: `Your Order #${order?.uniqueId} is On Its Way!`,
+ html: `
+ Hi,
+
Exciting news! Your order #${
+ order?.uniqueId
+ } has been dispatched and is en route to you. 🚚 Here are the details:
+
+ Courier Name: ${
+ invoice?.courier_name || "N/A"
+ }
+ Courier Tracking ID: ${
+ invoice?.courier_tracking_id || "N/A"
+ }
+
+ Items:
+
+
+
+ S No. |
+ Product Name |
+ SKU |
+ Image |
+ Quantity |
+ Price |
+ GST Amount |
+ SubTotal |
+
+
+
+ ${invoice?.items
+ ?.map(
+ (product, index) => `
+
+ ${
+ index + 1
+ } |
+ ${
+ product.name
+ } |
+ ${
+ product.SKU
+ } |
+
+ ${
+ product.image && product.image.length > 0
+ ? ` `
+ : "No Image"
+ }
+ |
+ ${
+ product.processquantity
+ } |
+ ₹${
+ product.price
+ } |
+ ₹${(
+ (product.GST * product.price) /
+ 100
+ ).toFixed(2)} |
+ ₹${(
+ (product.price + (product.GST * product.price) / 100) *
+ product.processquantity
+ ).toFixed(2)} |
+
+ `
+ )
+ .join("")}
+
+ Total Amount: |
+ ₹${
+ invoice.invoiceAmount
+ } |
+
+
+
+
+ Order Status: Dispatched
+ If you have any questions or need assistance, feel free to reply to this email.
+ Thanks for choosing Cheminova! We hope you enjoy your purchase.
+
+ Best regards,
+ Team Cheminova
+ `,
+ });
+
+ res.status(200).json({
+ message: "Courier status updated to dispatched",
+ orderStatus: order.status,
+ });
+ } catch (error) {
+ res.status(500).json({ error: error.message });
+ }
+};
+export const updateCourierStatusToDeliveredForPD = async (req, res) => {
+ const { invoiceId } = req.params;
+
+ try {
+ // Find the invoice by ID
+ const invoice = await InvoiceRd.findById(invoiceId).populate({
+ path: "orderId",
+ populate: {
+ path: "addedBy",
+ select: "email",
+ },
+ });
+ if (!invoice) {
+ return res.status(404).json({ error: "Invoice not found" });
+ }
+
+ // Update courier status and timeline
+ invoice.courierStatus = "delivered";
+ invoice.courierstatus_timeline.delivered = new Date();
+
+ // Save the updated invoice
+ await invoice.save();
+
+ const order = invoice.orderId;
+ const allItemsDelivered = order.orderItem.every(
+ (item) => item.remainingQuantity === 0
+ );
+
+ if (allItemsDelivered) {
+ order.status = "delivered";
+ await order.save();
+ }
+ // Get the userId from the order's addedBy
+ const userId = order?.addedBy?._id;
+
+ if (!userId) {
+ return res.status(400).json({ error: "User not found for the order" });
+ }
+ // Check if PDStock exists for the user
+ // let pdStock = await PDStock.findOne({ userId });
+
+ // if (!pdStock) {
+ // // If no stock record exists, create a new one
+ // pdStock = new PDStock({
+ // userId,
+ // products: [], // Initialize with empty products array
+ // });
+ // }
+ // // Iterate over each item in the invoice
+ // for (let item of invoice.items) {
+ // const { productId, processquantity } = item;
+
+ // // Check if the product already exists in the PDStock for the user
+ // const existingProduct = pdStock.products.find(
+ // (p) => p.productid.toString() === productId.toString()
+ // );
+
+ // if (existingProduct) {
+ // // If the product exists, update the stock by adding the processquantity
+ // existingProduct.Stock += processquantity;
+ // } else {
+ // // If the product doesn't exist, add a new entry for the product
+ // pdStock.products.push({
+ // productid: productId,
+ // Stock: processquantity,
+ // });
+ // }
+ // }
+ // Save the updated PDStock
+ // await pdStock.save();
+ // Format the current date for display
+ const formattedDate = formatDate(new Date());
+
+ // Send email to the user
+ await sendEmail({
+ to: `${order?.addedBy?.email}`, // Using 'addedBy' to reference the user's email
+ from: `${process.env.SEND_EMAIL_FROM}`, // Your verified sender
+ subject: `Your Order #${order?.uniqueId} Has Been Delivered!`,
+ html: `
+ Hi,
+
+ Great news! Your order #${
+ order?.uniqueId
+ } has been successfully delivered to your doorstep. We hope everything is just as you expected!
+
+
+ Items:
+
+
+
+ S No. |
+ Product Name |
+ SKU |
+ Image |
+ Quantity |
+ Price |
+ GST Amount |
+ SubTotal |
+
+
+
+ ${invoice?.items
+ ?.map(
+ (product, index) => `
+
+ ${
+ index + 1
+ } |
+ ${
+ product.name
+ } |
+ ${
+ product.SKU
+ } |
+
+ ${
+ product.image && product.image.length > 0
+ ? ` `
+ : "No Image"
+ }
+ |
+ ${
+ product.processquantity
+ } |
+ ₹${
+ product.price
+ } |
+ ₹${(
+ (product.GST * product.price) /
+ 100
+ ).toFixed(2)} |
+ ₹${(
+ (product.price + (product.GST * product.price) / 100) *
+ product.processquantity
+ ).toFixed(2)} |
+
+ `
+ )
+ .join("")}
+
+ Total Amount: |
+ ₹${invoice.invoiceAmount.toFixed(
+ 2
+ )} |
+
+
+
+
+ Delivery Date: ${formattedDate}
+
+
+ Your satisfaction is our priority, and we'd love to hear about your experience. Please take a moment to share your thoughts by leaving a review. Your feedback is invaluable to us!
+
+
+
+ If you have any questions or concerns about your order, feel free to reply to this email.
+
+
+
+ Thank you for choosing Cheminova! We hope to serve you again soon.
+
+
+
+ Best regards,
+ Team Cheminova
+ `,
+ });
+
+ res.status(200).json({
+ message: "Courier status updated to delivered",
+ orderStatus: order.status,
+ });
+ } catch (error) {
+ res.status(500).json({ error: error.message });
+ }
+};
+export const getDispatchedInvoicesForPd = async (req, res) => {
+ try {
+ const pdId = req.params.pdId; // Ensure this is passed in your route, or retrieve it from the logged-in user
+ const page = parseInt(req.query.page, 10) || 1; // Default page is 1
+ const limit = parseInt(req.query.limit, 10) || 5; // Default limit is 5
+ const skip = (page - 1) * limit;
+ const { invoiceId, orderId } = req.query; // Search parameters
+
+ if (!pdId) {
+ return res.status(400).json({ message: "PD ID is required" });
+ }
+
+ // Build the base query for fetching processing invoices
+ let query = { courierStatus: "dispatched" };
+
+ // If invoiceId is provided, add regex search for invoiceId
+ if (invoiceId) {
+ query.invoiceId = { $regex: invoiceId, $options: "i" }; // Case-insensitive search
+ }
+
+ // Fetch the invoices matching the query, along with pagination and population
+ const invoices = await InvoiceRd.find(query)
+ .skip(skip)
+ .limit(limit)
+ .populate({
+ path: "orderId",
+ match: { pd: pdId }, // Match the associated PD in the RdOrder model
+ select: "uniqueId", // Only select uniqueId from the order
+ })
+ .sort({ "courierstatus_timeline.processing": -1 }); // Sort by processing date, newest first
+
+ // Filter invoices where the orderId exists and matches the search (if orderId is provided)
+ let filteredInvoices = invoices.filter(
+ (invoice) => invoice.orderId !== null
+ );
+
+ if (orderId) {
+ filteredInvoices = filteredInvoices.filter(
+ (invoice) =>
+ invoice.orderId &&
+ invoice.orderId.uniqueId &&
+ invoice.orderId.uniqueId.toLowerCase().includes(orderId.toLowerCase())
+ );
+ }
+
+ // Pagination metadata
+ const totalCount = filteredInvoices.length;
+ const totalPages = Math.ceil(totalCount / limit);
+
+ // Send the filtered invoices with pagination details
+ res.status(200).json({
+ totalCount,
+ currentPage: page,
+ totalPages,
+ invoices: filteredInvoices,
+ });
+ } catch (error) {
+ console.error(error);
+ res.status(500).json({ error: error.message });
+ }
+};
+export const getDeliveredInvoicesForPd = async (req, res) => {
+ try {
+ const pdId = req.params.pdId; // Ensure this is passed in your route, or retrieve it from the logged-in user
+ const page = parseInt(req.query.page, 10) || 1; // Default page is 1
+ const limit = parseInt(req.query.limit, 10) || 5; // Default limit is 5
+ const skip = (page - 1) * limit;
+ const { invoiceId, orderId } = req.query; // Search parameters
+
+ if (!pdId) {
+ return res.status(400).json({ message: "PD ID is required" });
+ }
+
+ // Build the base query for fetching processing invoices
+ let query = { courierStatus: "delivered" };
+
+ // If invoiceId is provided, add regex search for invoiceId
+ if (invoiceId) {
+ query.invoiceId = { $regex: invoiceId, $options: "i" }; // Case-insensitive search
+ }
+
+ // Fetch the invoices matching the query, along with pagination and population
+ const invoices = await InvoiceRd.find(query)
+ .skip(skip)
+ .limit(limit)
+ .populate({
+ path: "orderId",
+ match: { pd: pdId }, // Match the associated PD in the RdOrder model
+ select: "uniqueId", // Only select uniqueId from the order
+ })
+ .sort({ "courierstatus_timeline.processing": -1 }); // Sort by processing date, newest first
+
+ // Filter invoices where the orderId exists and matches the search (if orderId is provided)
+ let filteredInvoices = invoices.filter(
+ (invoice) => invoice.orderId !== null
+ );
+
+ if (orderId) {
+ filteredInvoices = filteredInvoices.filter(
+ (invoice) =>
+ invoice.orderId &&
+ invoice.orderId.uniqueId &&
+ invoice.orderId.uniqueId.toLowerCase().includes(orderId.toLowerCase())
+ );
+ }
+
+ // Pagination metadata
+ const totalCount = filteredInvoices.length;
+ const totalPages = Math.ceil(totalCount / limit);
+
+ // Send the filtered invoices with pagination details
+ res.status(200).json({
+ totalCount,
+ currentPage: page,
+ totalPages,
+ invoices: filteredInvoices,
+ });
+ } catch (error) {
+ console.error(error);
+ res.status(500).json({ error: error.message });
+ }
+};
// cancell order
export const cancelOrderController = async (req, res) => {
@@ -832,3 +1350,15 @@ export const cancelOrderController = async (req, res) => {
.json({ message: "An error occurred while cancelling the order" });
}
};
+const formatDate = (date) => {
+ const options = {
+ weekday: "short",
+ year: "numeric",
+ month: "short",
+ day: "2-digit",
+ // hour: "2-digit",
+ // minute: "2-digit",
+ // hour12: true,
+ };
+ return new Intl.DateTimeFormat("en-US", options).format(new Date(date));
+};
diff --git a/resources/RD_Ordes/rdOrderRoutes.js b/resources/RD_Ordes/rdOrderRoutes.js
index 5432ea0..239eef4 100644
--- a/resources/RD_Ordes/rdOrderRoutes.js
+++ b/resources/RD_Ordes/rdOrderRoutes.js
@@ -3,16 +3,26 @@ import {
cancelOrderController,
createOrderRD,
getCancelledOrders,
+ getDeliveredInvoicesForPd,
+ getDispatchedInvoicesForPd,
+ getInvoiceDetailsByIdForPD,
getNewOrders,
getPendignOrders,
getPlacedOrdersForPD,
getPlacedOrdersForRD,
+ getProcessingInvoicesForPd,
getSinglePlacedOrderForPD,
getSinglePlacedOrderForRD,
processOrder,
+ updateCourierStatusToDeliveredForPD,
+ updateCourierStatusToDispatchedForPD,
} from "./rdOrderController.js";
import { isAuthenticatedRD } from "../../middlewares/rdAuth.js";
import { isAuthenticatedUser } from "../../middlewares/auth.js";
+import {
+ getDispatchedInvoices,
+ getProcessingInvoices,
+} from "../PD_Orders/pdOrderController.js";
const router = express.Router();
router.route("/rd-place-order").post(isAuthenticatedRD, createOrderRD);
@@ -38,8 +48,32 @@ router
router
.route("/pd-get-cancelled-orders")
.get(isAuthenticatedUser, getCancelledOrders);
+
+router
+ .route("/pd-get-processing-invoices")
+ .get(isAuthenticatedUser, getProcessingInvoicesForPd);
+router
+ .route("/pd-get-dispatched-invoices")
+ .get(isAuthenticatedUser, getDispatchedInvoicesForPd);
+router
+ .route("/pd-get-delivered-invoices")
+ .get(isAuthenticatedUser, getDeliveredInvoicesForPd);
+router
+ .route("/pd-get-invoices/:invoiceId")
+ .get(isAuthenticatedUser, getInvoiceDetailsByIdForPD);
router
.route("/pd-cancel-order/:id")
.put(isAuthenticatedUser, cancelOrderController);
+router.route("/invoice/dispatched/:invoiceId").put(
+ isAuthenticatedUser,
+
+ updateCourierStatusToDispatchedForPD
+);
+
+router.route("/invoice/delivered/:invoiceId").put(
+ isAuthenticatedUser,
+
+ updateCourierStatusToDeliveredForPD
+);
export default router;