diff --git a/resources/PD_Orders/invoiceModel.js b/resources/PD_Orders/invoiceModel.js
index 77abefb..0c9b26e 100644
--- a/resources/PD_Orders/invoiceModel.js
+++ b/resources/PD_Orders/invoiceModel.js
@@ -70,4 +70,11 @@ const invoiceSchema = new mongoose.Schema({
delivered: { type: Date },
},
});
+// Middleware to set the processing date only when the invoice is created
+invoiceSchema.pre('save', function (next) {
+ if (this.isNew && !this.courierstatus_timeline.processing) {
+ this.courierstatus_timeline.processing = new Date();
+ }
+ next();
+});
export const Invoice = mongoose.model("Invoice", invoiceSchema);
\ No newline at end of file
diff --git a/resources/PD_Orders/pdOrderController.js b/resources/PD_Orders/pdOrderController.js
index bd9e918..f4960e9 100644
--- a/resources/PD_Orders/pdOrderController.js
+++ b/resources/PD_Orders/pdOrderController.js
@@ -93,11 +93,9 @@ export const processOrder = async (req, res) => {
(i) => i.productId.toString() === item.productId.toString()
);
if (orderItem && item.processquantity > orderItem.remainingQuantity) {
- return res
- .status(400)
- .json({
- error: `Product '${item.name}' has more quantity than remaining in the order.`,
- });
+ return res.status(400).json({
+ error: `Product '${item.name}' has more quantity than remaining in the order.`,
+ });
}
}
@@ -329,12 +327,10 @@ export const processOrder = async (req, res) => {
`,
});
- res
- .status(200)
- .json({
- message: "Order processed and invoice created successfully",
- invoiceId: savedInvoice.invoiceId,
- });
+ res.status(200).json({
+ message: "Order processed and invoice created successfully",
+ invoiceId: savedInvoice.invoiceId,
+ });
} catch (error) {
console.error("Error processing order:", error);
res
@@ -344,7 +340,7 @@ export const processOrder = async (req, res) => {
};
export const cancelOrderController = async (req, res) => {
// const { cancellationReason, id: _id } = req.bodyconst
- const cancellationReason= req.body.cancellationReason;
+ const cancellationReason = req.body.cancellationReason;
const _id = req.params.id;
try {
// Find the order by ID
@@ -420,7 +416,7 @@ export const cancelOrderController = async (req, res) => {
item.price
}
₹${
- (item.price * item.GST)/100
+ (item.price * item.GST) / 100
} |
₹${
itemSubtotal + itemGST
@@ -471,7 +467,7 @@ export const cancelOrderController = async (req, res) => {
item.price
} |
₹${
- (item.price * item.GST)/100
+ (item.price * item.GST) / 100
} |
₹${
itemSubtotal + itemGST
@@ -778,7 +774,388 @@ export const getProcessingOrdersAdmin = async (req, res) => {
return res.status(500).json({ error: "Internal Server Error" });
}
};
+export const getProcessingInvoices = async (req, res) => {
+ try {
+ 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;
+
+ // Get the total count of 'processing' invoices
+ const totalInvoices = await Invoice.countDocuments({
+ courierStatus: "processing",
+ });
+
+ // Fetch the invoices with pagination
+ const invoices = await Invoice.find({ courierStatus: "processing" })
+ .sort({ createdAt: -1 })
+ .skip(skip)
+ .limit(limit);
+ // Respond with the invoices and the total count
+ res.status(200).json({
+ totalCount: totalInvoices,
+ currentPage: page,
+ totalPages: Math.ceil(totalInvoices / limit),
+ invoices,
+ });
+ } catch (error) {
+ res.status(500).json({ error: error.message });
+ }
+};
+export const getInvoiceDetailsById = async (req, res) => {
+ const { invoiceId } = req.params;
+
+ try {
+ // Find the invoice by ID and populate the orderId and addedBy fields
+ const invoice = await Invoice.findById(invoiceId).populate({
+ path: "orderId",
+ model: "PdOrder",
+ populate: {
+ path: "addedBy",
+ model: "User",
+ 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 updateCourierStatusToDispatched = async (req, res) => {
+ const { invoiceId } = req.params;
+ const { courierName, couriertrackingId } = req.body;
+ try {
+ // Find the invoice by ID
+ const invoice = await Invoice.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 getDispatchedInvoices = async (req, res) => {
+ try {
+ 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;
+
+ // Get the total count of 'processing' invoices
+ const totalInvoices = await Invoice.countDocuments({
+ courierStatus: "dispatched",
+ });
+
+ // Fetch the invoices with pagination
+ const invoices = await Invoice.find({ courierStatus: "dispatched" })
+ .sort({ createdAt: -1 })
+ .skip(skip)
+ .limit(limit);
+ // Respond with the invoices and the total count
+ res.status(200).json({
+ totalCount: totalInvoices,
+ currentPage: page,
+ totalPages: Math.ceil(totalInvoices / limit),
+ invoices,
+ });
+ } catch (error) {
+ res.status(500).json({ error: error.message });
+ }
+};
+export const updateCourierStatusToDelivered = async (req, res) => {
+ const { invoiceId } = req.params;
+
+ try {
+ // Find the invoice by ID
+ const invoice = await Invoice.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();
+ }
+
+ // 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 getDeliveredInvoices = async (req, res) => {
+ try {
+ 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;
+
+ // Get the total count of 'processing' invoices
+ const totalInvoices = await Invoice.countDocuments({
+ courierStatus: "delivered",
+ });
+
+ // Fetch the invoices with pagination
+ const invoices = await Invoice.find({ courierStatus: "delivered" })
+ .sort({ createdAt: -1 })
+ .skip(skip)
+ .limit(limit);
+ // Respond with the invoices and the total count
+ res.status(200).json({
+ totalCount: totalInvoices,
+ currentPage: page,
+ totalPages: Math.ceil(totalInvoices / limit),
+ invoices,
+ });
+ } catch (error) {
+ res.status(500).json({ error: error.message });
+ }
+};
export const getDeliveredOrdersAdmin = async (req, res) => {
try {
// Extract page and limit from query parameters
@@ -809,7 +1186,60 @@ export const getDeliveredOrdersAdmin = async (req, res) => {
return res.status(500).json({ error: "Internal Server Error" });
}
};
+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 getOrderCounts = async (req, res) => {
+ try {
+ // console.log(req.user._id,"");
+ const userId = req.user._id;
+ const statusCounts = await PdOrder.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!" });
+ }
+};
+
+// no need
export const updateOrderStatusById = async (req, res) => {
try {
let body = { status: req.body.status };
@@ -1223,56 +1653,4 @@ export const updateOrderStatusById = async (req, res) => {
.status(500)
.json({ message: error?.message || "Something went wrong!" });
}
-};
-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 getOrderCounts = async (req, res) => {
- try {
- // console.log(req.user._id,"");
- const userId = req.user._id;
- const statusCounts = await PdOrder.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!" });
- }
-};
+};
\ No newline at end of file
diff --git a/resources/PD_Orders/pdOrderRoute.js b/resources/PD_Orders/pdOrderRoute.js
index 5784dc6..33d1be8 100644
--- a/resources/PD_Orders/pdOrderRoute.js
+++ b/resources/PD_Orders/pdOrderRoute.js
@@ -14,6 +14,12 @@ import {
processOrder,
cancelOrderController,
getPlacedPendingOrderAdmin,
+ getProcessingInvoices,
+ updateCourierStatusToDispatched,
+ getInvoiceDetailsById,
+ getDeliveredInvoices,
+ getDispatchedInvoices,
+ updateCourierStatusToDelivered,
} from "./pdOrderController.js";
const router = express.Router();
@@ -65,9 +71,36 @@ router
router
.route("/get-delivered-order-admin")
.get(isAuthenticatedUser, authorizeRoles("admin"), getDeliveredOrdersAdmin);
+router
+ .route("/get-processing-invoice-admin")
+ .get(isAuthenticatedUser, authorizeRoles("admin"), getProcessingInvoices);
+router
+ .route("/get-dispatched-invoice-admin")
+ .get(isAuthenticatedUser, authorizeRoles("admin"), getDispatchedInvoices);
+router
+ .route("/get-delivered-invoice-admin")
+ .get(isAuthenticatedUser, authorizeRoles("admin"), getDeliveredInvoices);
+router
+ .route("/invoice/details/:invoiceId")
+ .get(isAuthenticatedUser, authorizeRoles("admin"), getInvoiceDetailsById);
+router
+ .route("/invoice/dispatched/:invoiceId")
+ .put(
+ isAuthenticatedUser,
+ authorizeRoles("admin"),
+ updateCourierStatusToDispatched
+ );
+router
+ .route("/invoice/delivered/:invoiceId")
+ .put(
+ isAuthenticatedUser,
+ authorizeRoles("admin"),
+ updateCourierStatusToDelivered
+ );
router
.route("/change/status/:id")
.patch(isAuthenticatedUser, authorizeRoles("admin"), updateOrderStatusById);
+
router.route("/get-counts-pdOrders").get(isAuthenticatedUser, getOrderCounts);
export default router;
|