api/resources/RD_Ordes/rdOrderController.js
2025-02-07 12:32:36 +05:30

1689 lines
60 KiB
JavaScript

import mongoose from "mongoose";
import sendEmail from "../../Utils/sendEmail.js";
import RetailDistributor from "../RetailDistributor/RetailDistributorModel.js";
import { InvoiceRd } from "./invoiceModalRD.js";
import { RdOrder } from "./rdOrderModal.js";
import { PDStock } from "../Stock/PdStockModel.js";
import { createKYC } from "../../Utils/rejectKyc.js";
import { Notification } from "../Notification/notificationModal.js";
import { sendPushNotification } from "../../Utils/sendPushNotification.js";
import { RDStock } from "../Stock/RdStockModel.js";
// Controller to create a new order by RD
export const createOrderRD = async (req, res) => {
try {
const {
paymentMode,
shipTo,
billTo,
orderItems,
subtotal,
gstTotal,
grandTotal,
} = req.body;
const rdId = req.user._id;
console.log(rdId);
// Fetch the Retail Distributor (RD) to find the associated Principal Distributor (PD)
const rd = await RetailDistributor.findById(rdId).populate(
"principal_distributer"
);
if (!rd) {
return res.status(404).json({ message: "Retail Distributor not found" });
}
if (!rd.principal_distributer) {
return res.status(422).json({
msg: "You are not assoicated with any Pd please contact support team",
});
}
const pdId = rd.principal_distributer._id;
if (pdId) {
await createKYC(
rd.principal_distributer._id,
"New order placed ",
`New Order placed.`
);
await Notification.create({
title: "New order placed ",
msg: `New order placed `,
added_for: rd.principal_distributer._id,
});
}
const newOrder = new RdOrder({
paymentMode,
shipTo,
billTo,
orderItem: orderItems.map((item) => ({
productId: item._id,
SKU: item.SKU,
name: item.name,
categoryName: item.category.categoryName, // Store category name
brandName: item.brand.brandName, // Store brand name
price: item.price,
GST: item.GST,
HSN_Code: item.HSN_Code,
description: item.description,
image: item.brand?.image?.length > 0 ? item.brand.image[0] : item.image,
quantity: item.count,
remainingQuantity: item.count,
})),
subtotal,
gstTotal,
grandTotal,
addedBy: rdId, // The RD who placed the order (Retail Distributor)
pd: pdId, // Reference to the PD associated with the RD
});
await newOrder.save();
res
.status(201)
.json({ message: "Order placed successfully", order: newOrder });
} catch (error) {
console.log(error.message);
res.status(500).json({ message: "Server error", error });
}
};
export const getPlacedOrdersForRD = async (req, res) => {
try {
const rdId = req.user?._id; // Assuming the Retail Distributor's ID is obtained from the authenticated request
if (!rdId) {
return res.status(401).json({ message: "Unauthorized access" });
}
// Extract page and limit from query parameters, with default values
const page = parseInt(req.query.page, 10) || 1;
const limit = parseInt(req.query.limit, 10) || 5;
// Calculate how many documents to skip for pagination
const skip = (page - 1) * limit;
// Fetch total count of orders for this RD (for pagination purposes)
const totalOrders = await RdOrder.countDocuments({ addedBy: rdId });
// Fetch orders for the logged-in RD
const placedOrders = await RdOrder.find({ addedBy: rdId })
.sort({ createdAt: -1 }) // Sort by creation date, newest first
.skip(skip) // Skip documents for pagination
.limit(limit); // Limit number of documents returned
if (!placedOrders || placedOrders.length === 0) {
return res
.status(404)
.json({ message: "No orders found for this Retail Distributor" });
}
// Send the paginated order list and total count of orders
res.status(200).json({ placedOrders, totalOrders });
} catch (error) {
console.error(error);
res.status(500).json({ message: "Server error", error });
}
};
export const getSinglePlacedOrderForRD = async (req, res) => {
try {
const rdId = req.user?._id;
if (!rdId) {
return res.status(401).json({ message: "Unauthorized access" });
} // Assuming the Retail Distributor's ID is obtained from the authenticated request
const orderId = req.params.id; // Assuming the order ID is passed in the URL as a parameter
if (!rdId) {
return res.status(401).json({ message: "Unauthorized access" });
}
if (!orderId) {
return res.status(400).json({ message: "Order ID is required" });
}
// Fetch the specific order for the logged-in RD
const order = await RdOrder.findOne({ _id: orderId, addedBy: rdId });
if (!order) {
return res
.status(404)
.json({ message: "Order not found for this Retail Distributor" });
}
// Send the single order document
res.status(200).json({ singleOrder: order });
} catch (error) {
console.error(error);
res.status(500).json({ message: "Server error", error });
}
};
export const getPlacedOrderById = async (req, res) => {
try {
const id = req.params.id;
if (!mongoose.Types.ObjectId.isValid(id)) {
return res
.status(404)
.json({ return_msg: "Not Valid id to search the doc " });
}
const doc = await RdOrder.findById(id)
.populate({
path: "orderItem.productId",
populate: {
path: "brand",
},
})
.populate({ path: "invoices" });
if (doc) {
return res
.status(200)
.json({ singleOrder: doc, return_msg: "Doc found" });
}
return res.status(404).json({ return_msg: "Not Found doc " });
} catch (error) {
console.log(error);
return res.status(500).json({ return_msg: "Internal Server Error" });
}
};
export const getPlacedOrdersForPD = async (req, res) => {
try {
const pdId = req.user?._id;
if (!pdId) {
return res.status(401).json({ return_message: "Unauthorized access " });
}
// Extract page and limit from query parameters
const page = parseInt(req.query.page, 10) || 1;
const limit = parseInt(req.query.limit, 10) || 5;
// Calculate the number of documents to skip
const skip = (page - 1) * limit;
const totalOrders = await RdOrder.countDocuments({ pd: pdId });
// Fetch all orders where the PD is associated with the order
const plcaedOrders = await RdOrder.find({ pd: pdId })
.sort({ createdAt: -1 })
.skip(skip)
.limit(limit);
if (!plcaedOrders || plcaedOrders.length === 0) {
return res
.status(404)
.json({ message: "No orders found for this Principal Distributor" });
}
res.status(200).json({ plcaedOrders, totalOrders });
} catch (error) {
console.error(error);
res.status(500).json({ message: "Server error", error });
}
};
export const getSinglePlacedOrderForPD = async (req, res) => {
try {
const pdId = req.user?._id; // Assuming the Principal Distributor's ID is obtained from the authenticated request
const orderId = req.params.id; // Assuming the order ID is passed in the URL as a parameter
if (!pdId) {
return res.status(401).json({ message: "Unauthorized access" });
}
if (!orderId) {
return res.status(400).json({ message: "Order ID is required" });
}
// Fetch the specific order for the logged-in PD
const order = await RdOrder.findOne({ _id: orderId, pd: pdId })
.populate({ path: "addedBy" })
.populate({ path: "invoices" });
if (!order) {
return res
.status(404)
.json({ message: "Order not found for this Principal Distributor" });
}
// Send the single order document
res.status(200).json({ singleOrder: order });
} catch (error) {
console.error(error);
res.status(500).json({ message: "Server error", error });
}
};
export const getNewOrders = async (req, res) => {
try {
const pdId = req.user?._id;
if (!pdId) {
return res.status(401).json({ return_message: "Unauthorized access " });
}
// Extract page and limit from query parameters
const page = parseInt(req.query.page, 10) || 1;
const limit = parseInt(req.query.limit, 10) || 5;
// Calculate the number of documents to skip
const skip = (page - 1) * limit;
const totalOrders = await RdOrder.countDocuments({
pd: pdId,
status: "new",
});
// Fetch all orders where the PD is associated with the order
const plcaedOrders = await RdOrder.find({ pd: pdId, status: "new" })
.sort({ createdAt: -1 })
.skip(skip)
.limit(limit);
if (!plcaedOrders || plcaedOrders.length === 0) {
return res
.status(404)
.json({ message: "No orders found for this Principal Distributor" });
}
res.status(200).json({ plcaedOrders, totalOrders });
} catch (error) {
console.error(error);
res.status(500).json({ message: "Server error", error });
}
};
export const getPendignOrders = async (req, res) => {
try {
const pdId = req.user?._id;
if (!pdId) {
return res.status(401).json({ return_message: "Unauthorized access " });
}
// Extract page and limit from query parameters
const page = parseInt(req.query.page, 10) || 1;
const limit = parseInt(req.query.limit, 10) || 5;
// Calculate the number of documents to skip
const skip = (page - 1) * limit;
const totalOrders = await RdOrder.countDocuments({
pd: pdId,
status: "new",
});
// Fetch all orders where the PD is associated with the order
const plcaedOrders = await RdOrder.find({ pd: pdId, status: "pending" })
.sort({ createdAt: -1 })
.skip(skip)
.limit(limit);
if (!plcaedOrders || plcaedOrders.length === 0) {
return res
.status(404)
.json({ message: "No orders found for this Principal Distributor" });
}
res.status(200).json({ plcaedOrders, totalOrders });
} catch (error) {
console.error(error);
res.status(500).json({ message: "Server error", error });
}
};
export const getCancelledOrders = async (req, res) => {
try {
const pdId = req.user?._id;
if (!pdId) {
return res.status(401).json({ return_message: "Unauthorized access " });
}
// Extract page and limit from query parameters
const page = parseInt(req.query.page, 10) || 1;
const limit = parseInt(req.query.limit, 10) || 5;
// Calculate the number of documents to skip
const skip = (page - 1) * limit;
const totalOrders = await RdOrder.countDocuments({
pd: pdId,
status: "new",
});
// Fetch all orders where the PD is associated with the order
const plcaedOrders = await RdOrder.find({ pd: pdId, status: "cancelled" })
.sort({ createdAt: -1 })
.skip(skip)
.limit(limit);
if (!plcaedOrders || plcaedOrders.length === 0) {
return res
.status(404)
.json({ message: "No orders found for this Principal Distributor" });
}
res.status(200).json({ plcaedOrders, totalOrders });
} catch (error) {
console.error(error);
res.status(500).json({ message: "Server error", error });
}
};
export const processOrder = async (req, res) => {
try {
const { orderId, invoiceItems } = req.body;
if (!orderId || !invoiceItems || !Array.isArray(invoiceItems)) {
return res
.status(400)
.json({ error: "Missing required fields or invalid data" });
}
// Find the order by ID
const order = await RdOrder.findById(orderId).populate("addedBy");
if (!order) {
return res.status(404).json({ error: "Order not found" });
}
// Validate quantities
const exceededItems = invoiceItems
.filter((item) => {
const orderItem = order.orderItem.find(
(i) => i.productId.toString() === item.productId.toString()
);
return orderItem && item.processquantity > orderItem.remainingQuantity;
})
.map((item) => item.name);
if (exceededItems.length > 0) {
return res.status(400).json({
error: `The following items have more quantity than remaining in the order: ${exceededItems.join(
", "
)}`,
});
}
// If there are any exceeded items, return an error with their names
if (exceededItems.length > 0) {
return res.status(400).json({
error: `The following items have more quantity than remaining in the order: ${exceededItems.join(
", "
)}`,
});
}
// Continue with the rest of the logic if no quantity limits are exceeded
// Stock calculation part
const pdStock = await PDStock.findOne({ userId: order.pd });
if (!pdStock) {
return res.status(404).json({ error: "Stock not available" });
}
// Update stock and validate
const updatedInvoiceItems = invoiceItems.filter((item) => {
// Find the product in the stock
const productInStock = pdStock.products.find(
(p) => p.productid.toString() === item.productId.toString()
);
// If the product exists in stock
if (productInStock) {
// Check if the processquantity is less than or equal to available stock
if (item.processquantity <= productInStock.Stock) {
// Deduct the quantity from the stock
productInStock.Stock -= item.processquantity;
productInStock.liquidation += item.processquantity;
// Add the item to updatedInvoiceItems (since stock is sufficient)
return true;
}
}
// If no stock or insufficient stock, don't add the item
return false;
});
// If no items are left after stock validation, return an error
if (updatedInvoiceItems.length === 0) {
return res
.status(400)
.json({ error: "No stock available for the requested items." });
}
// Save updated stock
await pdStock.save();
// Generate unique invoice number
const existingInvoices = await InvoiceRd.find({ orderId });
const invoiceNumber = existingInvoices.length + 1;
const invoiceId = `ch/${order.uniqueId}/${updatedInvoiceItems.length}/${invoiceNumber}`;
// Calculate subtotal, gstTotal, and invoiceAmount for processed items
let subtotal = 0;
let gstTotal = 0;
let invoiceAmount = 0;
updatedInvoiceItems.forEach((item) => {
const itemSubtotal = item.price * item.processquantity;
const itemGST = ((item.price * item.GST) / 100) * item.processquantity;
subtotal += itemSubtotal;
gstTotal += itemGST;
invoiceAmount += itemSubtotal + itemGST;
});
// Create a new invoice
const newInvoice = new InvoiceRd({
invoiceId,
orderId,
items: updatedInvoiceItems,
subtotal,
gstTotal,
invoiceAmount,
});
// Save the invoice
const savedInvoice = await newInvoice.save();
// Update the order's order items with the remaining quantity
let allItemsProcessed = true; // Flag to check if all items are processed
order.orderItem.forEach((item) => {
const invoicedItem = updatedInvoiceItems.find(
(i) => i.productId.toString() === item.productId.toString()
);
// If the item was invoiced, update the remaining quantity
if (invoicedItem) {
// Deduct the processed quantity from remaining quantity
item.remainingQuantity -= invoicedItem.processquantity;
// Ensure remaining quantity does not go negative
if (item.remainingQuantity < 0) {
item.remainingQuantity = 0;
}
}
// Check if the remaining quantity is greater than 0, even for items not invoiced
if (item.remainingQuantity > 0) {
allItemsProcessed = false;
}
});
// Calculate total amount for pending items
let pendingTotalAmount = 0;
order.orderItem.forEach((item) => {
if (item.remainingQuantity > 0) {
const itemPendingSubtotal = item.price * item.remainingQuantity;
const itemPendingGST =
((item.price * item.GST) / 100) * item.remainingQuantity;
pendingTotalAmount += itemPendingSubtotal + itemPendingGST;
}
});
// Only update order status if all items have been fully processed
if (allItemsProcessed) {
order.status = "processing";
await sendPushNotification(
order.addedBy?.fcm_token,
"Exciting news",
"Your order got processed"
);
await Notification.create({
title: "Exciting news",
msg: `Your order got processed`,
added_for: order.addedBy?._id,
});
// All items are fully processed
} else {
order.status = "pending";
await sendPushNotification(
order.addedBy?.fcm_token,
"Exciting news",
"Some of your items got in processing "
);
await Notification.create({
title: "Exciting news",
msg: `Some of your items got in processing `,
added_for: order.addedBy?._id,
}); // There are still remaining quantities
}
// Add the invoice to the order
order.invoices.push(savedInvoice._id);
// Save the updated order
await order.save();
// Prepare the email content
const processedItems = updatedInvoiceItems
.map(
(item, index) => `
<tr>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
index + 1
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
item.name
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">
${
item.image && item.image.length > 0
? `<img src="${item.image[0]?.url}" alt="${item.name}" style="max-width: 40px; height: auto;">`
: "No Image"
}
</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
item.processquantity
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${
item.price
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${
(item.GST * item.price) / 100
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${
(item.price + (item.GST * item.price) / 100) * item.processquantity
}</td>
</tr>
`
)
.join("");
const pendingItems = order.orderItem
.filter((item) => item.remainingQuantity > 0)
.map(
(item, index) => `
<tr>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
index + 1
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
item.name
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">
${
item.image && item.image.length > 0
? `<img src="${item.image[0]?.url}" alt="${item.name}" style="max-width: 40px; height: auto;">`
: "No Image"
}
</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
item.remainingQuantity
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${
item.price
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${
(item.GST * item.price) / 100
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${
(item.price + (item.GST * item.price) / 100) * item.remainingQuantity
}</td>
</tr>
`
)
.join("");
// Dynamic email subject and message based on the order status
const emailSubject = allItemsProcessed
? `Your Order #${order.uniqueId} is in Processing!`
: `Your Order #${order.uniqueId} is Partially Processed!`;
const emailMessage = allItemsProcessed
? `
<h3>Exciting news! Your order #${order.uniqueId} has entered the processing phase. We're working hard to ensure everything is perfect for you.</h3>
<p>Your invoice ID is: <strong>${savedInvoice.invoiceId}</strong></p>
`
: `
<h3>Good news! Some items of your order #${order.uniqueId} have been processed. The remaining items will be processed soon.</h3>
<p>Your invoice ID is: <strong>${savedInvoice.invoiceId}</strong></p>
`;
await sendEmail({
to: order.addedBy.email,
from: process.env.SEND_EMAIL_FROM,
subject: emailSubject,
html: `
<div style="font-family: Arial, sans-serif; color: #333;">
${emailMessage}
<strong style="color: #1b03a3; font-size: 16px;">Hi ${
order.addedBy.name
},</strong>
<h4 style="color: #333;">Order Status: ${
order.status.charAt(0).toUpperCase() + order.status.slice(1)
}</h4>
<h4 style="color: #333;">Processed Items:</h4>
<table style="border-collapse: collapse; width: 100%;">
<thead>
<tr>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">S No.</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Product Name</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Image</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Quantity</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Price</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">GST Amount</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">SubTotal</th>
</tr>
</thead>
<tbody>
${processedItems}
<tr>
<th colspan="6" style="border: 1px solid #555; padding: 2px; text-align: right;">Total Amount:</th>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${savedInvoice.invoiceAmount.toFixed(
2
)}</td>
</tr>
</tbody>
</table>
${
pendingItems.length > 0
? `
<h4 style="color: #333;">Pending Items:</h4>
<table style="border-collapse: collapse; width: 100%;">
<thead>
<tr>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">S No.</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Product Name</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Image</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Quantity</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Price</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">GST Amount</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">SubTotal</th>
</tr>
</thead>
<tbody>
${pendingItems}
<tr>
<th colspan="6" style="border: 1px solid #555; padding: 2px; text-align: right;">Pending Amount:</th>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${pendingTotalAmount.toFixed(
2
)}</td>
</tr>
</tbody>
</table>
`
: ""
}
<br/>
<h5 style="color: #333; font-family: Arial, sans-serif;">If you have any concerns or further questions, please feel free to reply to this email.</h5>
<br/>
<span style="color: #555; font-size: 13px;">Best regards,</span><br/>
<span style="color: #555; font-size: 13px;">Team Cheminova</span>
</div>
`,
});
res.status(200).json({
message: "Order processed and invoice created successfully",
invoiceId: savedInvoice.invoiceId,
});
} catch (error) {
res
.status(500)
.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" });
}
// 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: "RdOrder",
populate: {
path: "addedBy",
model: "RetailDistributor",
select: "name email mobile_number fcm_token ",
},
});
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 fcm_token",
},
});
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();
}
await sendPushNotification(
order.addedBy?.fcm_token,
"Exciting news",
"Order dispatched "
);
await Notification.create({
title: "Exciting news",
msg: `Order dispatched`,
added_for: order.addedBy?._id,
});
// 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: `
<strong style="color: #1b03a3; font-size: 16px">Hi,</strong>
<h3 style="color: #333; font-family: Arial, sans-serif;">Exciting news! Your order #${
order?.uniqueId
} has been dispatched and is en route to you. 🚚 Here are the details:</h3>
<h4 style="color: #333; font-family: Arial, sans-serif;">Courier Name: ${
invoice?.courier_name || "N/A"
}</h4>
<h4 style="color: #333; font-family: Arial, sans-serif;">Courier Tracking ID: ${
invoice?.courier_tracking_id || "N/A"
}</h4>
<h4 style="color: #333; font-family: Arial, sans-serif;">Items:</h4>
<table style="border-collapse: collapse; width: 100%;">
<thead>
<tr>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">S No.</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Product Name</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">SKU</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Image</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Quantity</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Price</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">GST Amount</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">SubTotal</th>
</tr>
</thead>
<tbody>
${invoice?.items
?.map(
(product, index) => `
<tr>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
index + 1
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
product.name
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
product.SKU
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">
${
product.image && product.image.length > 0
? `<img src="${product.image[0]?.url}" alt="${product.name}" style="max-width: 40px; height: auto;">`
: "No Image"
}
</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
product.processquantity
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${
product.price
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${(
(product.GST * product.price) /
100
).toFixed(2)}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${(
(product.price + (product.GST * product.price) / 100) *
product.processquantity
).toFixed(2)}</td>
</tr>
`
)
.join("")}
<tr>
<th colspan="7" style="border: 1px solid #555; padding: 2px; text-align: right;">Total Amount:</th>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${
invoice.invoiceAmount
}</td>
</tr>
</tbody>
</table>
<h3 style="color: #333; font-family: Arial, sans-serif;">Order Status: Dispatched</h3>
<h4 style="color: #333; font-family: Arial, sans-serif;">If you have any questions or need assistance, feel free to reply to this email.</h4>
<h5 style="color: #333; font-family: Arial, sans-serif;">Thanks for choosing Cheminova! We hope you enjoy your purchase.</h5>
<br/>
<span style="color: #555; font-size: 13px;">Best regards,</span><br/>
<span style="color: #555; font-size: 13px;">Team Cheminova</span>
`,
});
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 fcm_token",
},
});
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;
await sendPushNotification(
order?.addedBy?.fcm_token,
"Exciting news",
"Order Delivered "
);
await Notification.create({
title: "Exciting news",
msg: `Order Delivered `,
added_for: order?.addedBy?._id,
});
if (!userId) {
return res.status(400).json({ error: "User not found for the order" });
}
// Check if RDStock exists for the user
let rdStock = await RDStock.findOne({ userId });
if (!rdStock) {
// If no stock record exists, create a new one
rdStock = new RDStock({
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 = rdStock.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
rdStock.products.push({
productid: productId,
Stock: processquantity,
});
}
}
// Save the updated PDStock
await rdStock.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: `
<strong style="color: #1b03a3; font-size: 16px">Hi,</strong>
<h3 style="color: #333; font-family: Arial, sans-serif;">
Great news! Your order #${
order?.uniqueId
} has been successfully delivered to your doorstep. We hope everything is just as you expected!
</h3>
<h4 style="color: #333; font-family: Arial, sans-serif;">Items:</h4>
<table style="border-collapse: collapse; width: 100%;">
<thead>
<tr>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">S No.</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Product Name</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">SKU</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Image</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Quantity</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Price</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">GST Amount</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">SubTotal</th>
</tr>
</thead>
<tbody>
${invoice?.items
?.map(
(product, index) => `
<tr>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
index + 1
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
product.name
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
product.SKU
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">
${
product.image && product.image.length > 0
? `<img src="${product.image[0]?.url}" alt="${product.name}" style="max-width: 40px; height: auto;">`
: "No Image"
}
</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
product.processquantity
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${
product.price
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${(
(product.GST * product.price) /
100
).toFixed(2)}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${(
(product.price + (product.GST * product.price) / 100) *
product.processquantity
).toFixed(2)}</td>
</tr>
`
)
.join("")}
<tr>
<th colspan="7" style="border: 1px solid #555; padding: 2px; text-align: right;">Total Amount:</th>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${invoice.invoiceAmount.toFixed(
2
)}</td>
</tr>
</tbody>
</table>
<h3 style="color: #333; font-family: Arial, sans-serif;">Delivery Date: ${formattedDate}</h3>
<h4 style="color: #333; font-family: Arial, sans-serif;">
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!
</h4>
<h5 style="color: #333; font-family: Arial, sans-serif;">
If you have any questions or concerns about your order, feel free to reply to this email.
</h5>
<h5 style="color: #333; font-family: Arial, sans-serif;">
Thank you for choosing Cheminova! We hope to serve you again soon.
</h5>
<br/>
<span style="color: #555; font-size: 13px;">Best regards,</span><br/>
<span style="color: #555; font-size: 13px;">Team Cheminova</span>
`,
});
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.user._id; // 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.user._id; // 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) => {
// const { cancellationReason, id: _id } = req.bodyconst
const pdId = req.user?._id;
const cancellationReason = req.body.cancellationReason;
const _id = req.params.id;
try {
// Find the order by ID
const order = await RdOrder.findOne({ _id, pd: pdId })
.populate("invoices")
.populate("addedBy");
if (!order) {
return res.status(404).json({ message: "Order not found" });
}
// Update the order status to 'cancelled'
order.status = "cancelled";
order.iscancelled = true;
order.order_Cancelled_Reason =
cancellationReason || "No specific reason provided.";
await order.save();
if (order.invoices.length === 0) {
// If no invoices are associated with the order
await sendPushNotification(
order.addedBy?.fcm_token,
"Sorry! order cancelled fully.",
`Order has been cancelled due to ${cancellationReason}`
);
await Notification.create({
title: "Sorry! order cancelled fully.",
msg: `Order dispatched`,
added_for: order.addedBy?._id,
});
await sendEmail({
to: `${order.addedBy.email}`, // Change to your recipient
from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender
subject: `Order #${order.uniqueId} Cancellation Confirmation`,
html: `
<strong style="color: #1b03a3; font-size: 16px">Hi ${order.addedBy.name},</strong>
<h3 style="color: #333; font-family: Arial, sans-serif;">We regret to inform you that your order #${order.uniqueId} has been fully cancelled.</h3>
<h4 style="color: #333; font-family: Arial, sans-serif;">Cancellation Reason: ${order.order_Cancelled_Reason}</h4>
<h5 style="color: #333; font-family: Arial, sans-serif;">If you have any concerns or further questions, please feel free to reply to this email.</h5>
<br/>
<span style="color: #555; font-size: 13px;">Best regards,</span><br/>
<span style="color: #555; font-size: 13px;">Team Cheminova</span>
`,
});
} else {
// If invoices are present
const invoices = await InvoiceRd.find({ _id: { $in: order.invoices } });
// Collect all invoice data
const invoiceDetails = invoices.map((invoice) => {
let subtotal = 0;
let gstTotal = 0;
let totalAmount = 0;
const processedItems = invoice.items
.map((item) => {
const itemSubtotal = item.price * item.processquantity;
const itemGST =
((item.price * item.GST) / 100) * item.processquantity;
subtotal += itemSubtotal;
gstTotal += itemGST;
totalAmount += itemSubtotal + itemGST;
const itemImage =
item.image && Array.isArray(item.image) ? item.image[0]?.url : "";
return `
<tr>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
item.SKU
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
item.name
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;"><img src="${itemImage}" alt="${
item.name
}" style="max-width: 40px; height: auto;"></td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
item.processquantity
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${
item.price
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${
(item.price * item.GST) / 100
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${
itemSubtotal + itemGST
}</td>
</tr>
`;
})
.join("");
return {
invoiceId: invoice.invoiceId,
processedItems,
totalAmount,
};
});
// Collect all delivered and remaining items
let cancelItems = "";
let totalCancelAmount = 0;
if (Array.isArray(order.orderItem)) {
order.orderItem.forEach((item) => {
if (item.remainingQuantity > 0) {
const itemSubtotal = item.price * item.remainingQuantity;
const itemGST =
((item.price * item.GST) / 100) * item.remainingQuantity;
totalCancelAmount += itemSubtotal + itemGST;
const itemImage =
item.image && Array.isArray(item.image) ? item.image[0]?.url : "";
cancelItems += `
<tr>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
item.SKU
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
item.name
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;"><img src="${itemImage}" alt="${
item.name
}" style="max-width: 40px; height: auto;"></td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">${
item.remainingQuantity
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${
item.price
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${
(item.price * item.GST) / 100
}</td>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${
itemSubtotal + itemGST
}</td>
</tr>
`;
}
});
}
await sendPushNotification(
order.addedBy?.fcm_token,
"Sorry! order cancelled partially.",
`Order has been cancelled due to ${
cancellationReason ? cancellationReason : "some reason"
}`
);
await Notification.create({
title: "Sorry! order cancelled fully.",
msg: `Order dispatched`,
added_for: order.addedBy?._id,
});
await sendEmail({
to: `${order.addedBy.email}`, // Change to your recipient
from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender
subject: `Order #${order.uniqueId} is Partially Cancelled!`,
html: `
<strong style="color: #1b03a3; font-size: 16px">Hi ${
order.addedBy.name
},</strong>
<h3 style="color: #333; font-family: Arial, sans-serif;">We would like to inform you that your order #${
order.uniqueId
} has been partially cancelled.</h3>
<h4 style="color: #333; font-family: Arial, sans-serif;">Cancellation Reason: ${
order.order_Cancelled_Reason
}</h4>
<h4 style="color: #333; font-family: Arial, sans-serif;">Delivered Items:</h4>
${invoiceDetails
.map(
(details) => `
<h5 style="color: #333; font-family: Arial, sans-serif;">Invoice ID: ${
details.invoiceId
}</h5>
<table style="border-collapse: collapse; width: 100%;">
<thead>
<tr>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">S No.</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Product Name</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Image</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Quantity</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Price</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">GST Amount</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">SubTotal</th>
</tr>
</thead>
<tbody>
${details.processedItems}
<tr>
<th colspan="6" style="border: 1px solid #555; padding: 2px; text-align: right;">Total Amount:</th>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${details.totalAmount.toFixed(
2
)}</td>
</tr>
</tbody>
</table>
`
)
.join("")}
<h4 style="color: #333; font-family: Arial, sans-serif;">Cancelled Items:</h4>
<table style="border-collapse: collapse; width: 100%;">
<thead>
<tr>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">S No.</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Product Name</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Image</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Quantity</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">Price</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">GST Amount</th>
<th style="border: 1px solid #555; padding: 2px; text-align: center;">SubTotal</th>
</tr>
</thead>
<tbody>
${cancelItems}
<tr>
<th colspan="6" style="border: 1px solid #555; padding: 2px; text-align: right;">Total Refund Amount:</th>
<td style="border: 1px solid #555; padding: 2px; text-align: center;">₹${totalCancelAmount.toFixed(
2
)}</td>
</tr>
</tbody>
</table>
<br/>
<h5 style="color: #333; font-family: Arial, sans-serif;">If you have any concerns or further questions, please feel free to reply to this email.</h5>
<br/>
<span style="color: #555; font-size: 13px;">Best regards,</span><br/>
<span style="color: #555; font-size: 13px;">Team Cheminova</span>
`,
});
}
res.status(200).json({ message: "Order cancelled successfully" });
} catch (error) {
console.error("Error cancelling order:", error);
res
.status(500)
.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));
};
export const getAllOrdersByDistributor = async (req, res) => {
const { distributorId } = req.params;
const { orderId, status } = req.query; // Added status to query parameters
// console.log(distributorId, orderId, status);
// Handle pagination parameters
const page = parseInt(req.query.page, 10) || 1;
const limit = parseInt(req.query.limit, 10) || 5;
const skip = (page - 1) * limit;
// console.log(distributorId, orderId, status, page, limit, skip);
try {
let orders;
// Search by orderId
if (orderId) {
const id = new RegExp(orderId, "i");
orders = await RdOrder.find({
addedBy: distributorId,
uniqueId: { $regex: id },
})
.sort({ createdAt: -1 })
.skip(skip)
.limit(limit);
// console.log(orders);
// Return empty array if no orders are found
if (!orders || orders.length === 0) {
return res.status(200).json([]);
}
// Get total count for pagination
const totalOrders = await RdOrder.countDocuments({
addedBy: distributorId,
uniqueId: { $regex: id },
});
// Send response with pagination info
return res.status(200).json({
totalOrders,
totalPages: Math.ceil(totalOrders / limit),
currentPage: page,
orders,
});
}
// Search by status
else if (status) {
// Create a regex for case-insensitive search
const regex = new RegExp(status, "i");
orders = await RdOrder.find({
addedBy: distributorId,
status: { $regex: regex },
})
.sort({ createdAt: -1 })
.skip(skip)
.limit(limit);
// console.log(orders);
// Return empty array if no orders are found
if (!orders || orders.length === 0) {
return res.status(200).json([]);
}
// Get total count for pagination
const totalOrders = await RdOrder.countDocuments({
addedBy: distributorId,
status: { $regex: regex },
});
// console.log(totalOrders);
// Send response with pagination info
return res.status(200).json({
totalOrders,
totalPages: Math.ceil(totalOrders / limit),
currentPage: page,
orders,
});
}
// Default behavior to return all orders
else {
orders = await RdOrder.find({ addedBy: distributorId })
.sort({ createdAt: -1 })
.skip(skip)
.limit(limit);
// Return empty array if no orders are found
if (!orders || orders.length === 0) {
return res.status(200).json([]);
}
// Get total count for pagination
const totalOrders = await RdOrder.countDocuments({
addedBy: distributorId,
});
// Send response with pagination info
return res.status(200).json({
totalOrders,
totalPages: Math.ceil(totalOrders / limit),
currentPage: page,
orders,
});
}
} catch (error) {
console.error("Error fetching orders:", error);
res.status(500).json({ message: "Server error", error });
}
};
export const gettotalorderandvalueofrd = async (req, res) => {
const { distributorId } = req.params;
try {
const orders = await RdOrder.find({ addedBy: distributorId }).sort({
createdAt: -1,
});
const totalOrders = orders.length;
const totalValue = orders
.reduce((acc, order) => acc + order.grandTotal, 0)
.toFixed(2);
// Get the date of the last order
const lastPurchaseOrderDate = totalOrders > 0 ? orders[0].createdAt : null;
res.status(200).json({
totalOrders,
totalValue: parseFloat(totalValue),
lastPurchaseOrderDate,
});
} catch (error) {
console.error("Error fetching orders:", error);
res.status(500).json({ message: "Server error", error });
}
};
export const getOrderCounts = async (req, res) => {
try {
// console.log(req.user._id,"");
const userId = req.user._id;
const statusCounts = await RdOrder.aggregate([
{
$match: {
addedBy: userId, // Only match orders added by the current user
},
},
{
$group: {
_id: "$status", // Group by status
count: { $sum: 1 }, // Count the number of orders per status
},
},
]);
// Restructure the result to make it easier to consume
const result = {
new: 0,
dispatched: 0,
cancelled: 0,
processing: 0,
delivered: 0,
};
statusCounts.forEach((status) => {
result[status._id] = status.count;
});
res.status(200).json({ counts: result });
} catch (error) {
console.log(error.message);
res
.status(500)
.json({ message: error?.message || "Something went wrong!" });
}
};