apis for patial order Done

This commit is contained in:
ROSHAN GARG 2024-09-27 10:54:11 +05:30
parent a6d632e663
commit 9aedd32553
5 changed files with 774 additions and 33 deletions

View File

@ -12,7 +12,7 @@ export const isAuthenticatedRD = async (req, res, next) => {
}); });
} }
const getToken = req.headers; const getToken = req.headers;
console.log(getToken);
// console.log(getToken); // console.log(getToken);
//remove Bearer from token //remove Bearer from token
const fronttoken = getToken.authorization.slice(7); const fronttoken = getToken.authorization.slice(7);
@ -24,7 +24,7 @@ export const isAuthenticatedRD = async (req, res, next) => {
message: "incorrect token", message: "incorrect token",
}); });
} }
console.log(frontdecoded);
const fuser = await RetailDistributor.findById(frontdecoded._id); const fuser = await RetailDistributor.findById(frontdecoded._id);
// console.log(fuser); // console.log(fuser);
req.user = fuser; req.user = fuser;

View File

@ -0,0 +1,81 @@
import mongoose, { Schema } from "mongoose";
const orderItemSchema = new Schema({
productId: {
type: Schema.Types.ObjectId,
ref: "Product",
required: true,
},
SKU: {
type: String,
required: true,
},
name: {
type: String,
required: true,
},
categoryName: {
type: String, // Directly store category name
required: true,
},
brandName: {
type: String, // Directly store brand name
required: true,
},
price: {
type: Number,
required: true,
},
GST: {
type: Number,
required: true,
},
HSN_Code: {
type: Number,
required: true,
},
processquantity: {
//updated quantity
type: Number,
required: true,
default: 1,
},
});
const invoiceSchema = new mongoose.Schema({
invoiceId: { type: String, required: true, unique: true },
orderId: {
type: mongoose.Schema.Types.ObjectId,
ref: "RdOrder",
required: true,
},
items: [orderItemSchema],
subtotal: {
type: Number,
required: true,
},
gstTotal: {
type: Number,
required: true,
},
invoiceAmount: { type: Number, required: true },
courier_name: { type: String },
courier_tracking_id: { type: String },
courierStatus: {
type: String,
enum: ["processing", "dispatched", "delivered"],
default: "processing",
},
courierstatus_timeline: {
processing: { type: Date },
dispatched: { type: Date },
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 InvoiceRd = mongoose.model("InvoiceRd", invoiceSchema);

View File

@ -1,4 +1,6 @@
import sendEmail from "../../Utils/sendEmail.js";
import RetailDistributor from "../RetailDistributor/RetailDistributorModel.js"; import RetailDistributor from "../RetailDistributor/RetailDistributorModel.js";
import { InvoiceRd } from "./invoiceModalRD.js";
import { RdOrder } from "./rdOrderModal.js"; import { RdOrder } from "./rdOrderModal.js";
// Controller to create a new order by RD // Controller to create a new order by RD
@ -45,6 +47,7 @@ export const createOrderRD = async (req, res) => {
description: item.description, description: item.description,
image: item.image, image: item.image,
quantity: item.count, quantity: item.count,
remainingQuantity: item.count,
})), })),
subtotal, subtotal,
gstTotal, gstTotal,
@ -62,6 +65,7 @@ export const createOrderRD = async (req, res) => {
res.status(500).json({ message: "Server error", error }); res.status(500).json({ message: "Server error", error });
} }
}; };
export const getPlacedOrdersForRD = async (req, res) => { export const getPlacedOrdersForRD = async (req, res) => {
try { try {
const rdId = req.user?._id; // Assuming the Retail Distributor's ID is obtained from the authenticated request const rdId = req.user?._id; // Assuming the Retail Distributor's ID is obtained from the authenticated request
@ -177,7 +181,9 @@ export const getSinglePlacedOrderForPD = async (req, res) => {
} }
// Fetch the specific order for the logged-in PD // Fetch the specific order for the logged-in PD
const order = await RdOrder.findOne({ _id: orderId, pd: pdId }); const order = await RdOrder.findOne({ _id: orderId, pd: pdId })
.populate({ path: "addedBy" })
.populate({ path: "invoices" });
if (!order) { if (!order) {
return res return res
@ -192,3 +198,637 @@ export const getSinglePlacedOrderForPD = async (req, res) => {
res.status(500).json({ message: "Server 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 = [];
// Check each item in invoiceItems for quantity limits
for (const item of invoiceItems) {
const orderItem = order.orderItem.find(
(i) => i.productId.toString() === item.productId.toString()
);
// If processquantity exceeds remainingQuantity, add the item name to exceededItems
if (orderItem && item.processquantity > orderItem.remainingQuantity) {
exceededItems.push(item.name);
}
}
// 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
// Generate unique invoice number
const existingInvoices = await InvoiceRd.find({ orderId });
const invoiceNumber = existingInvoices.length + 1;
const invoiceId = `ch/${order.uniqueId}/${invoiceItems.length}/${invoiceNumber}`;
// Calculate subtotal, gstTotal, and invoiceAmount for processed items
let subtotal = 0;
let gstTotal = 0;
let invoiceAmount = 0;
invoiceItems.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: invoiceItems,
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 = invoiceItems.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"; // All items are fully processed
} else {
order.status = "pending"; // 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 = invoiceItems
.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" });
}
};
// 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 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 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" });
}
};

View File

@ -49,18 +49,10 @@ const orderItemSchema = new Schema({
required: true, required: true,
default: 1, default: 1,
}, },
}); remainingQuantity: {
type: Number,
const StatusHistorySchema = new mongoose.Schema({
status: {
type: String,
enum: ["new", "dispatched", "cancelled", "processing", "delivered"], // Ensure this matches your status enum
required: true, required: true,
}, },
timestamp: {
type: Date,
default: Date.now,
},
}); });
const rdOrderSchema = new Schema( const rdOrderSchema = new Schema(
@ -93,9 +85,19 @@ const rdOrderSchema = new Schema(
}, },
status: { status: {
type: String, type: String,
enum: ["new", "dispatched", "cancelled", "processing", "delivered"], enum: [
"new",
"pending",
"processing",
"dispatched",
"cancelled",
"delivered",
],
default: "new", default: "new",
}, },
invoices: [
{ type: mongoose.Schema.Types.ObjectId, ref: "InvoiceRd" }, // Similar to PdOrder invoices
],
statusUpdatedAt: { statusUpdatedAt: {
type: Date, type: Date,
default: Date.now, default: Date.now,
@ -115,15 +117,16 @@ const rdOrderSchema = new Schema(
ref: "User", // Reference to the PD associated with the RD ref: "User", // Reference to the PD associated with the RD
required: true, required: true,
}, },
status_timeline: { // status_timeline: {
new: { type: Date }, // new: { type: Date },
paid: { type: Date }, // paid: { type: Date },
processing: { type: Date }, // processing: { type: Date },
dispatched: { type: Date }, // dispatched: { type: Date },
delivered: { type: Date }, // delivered: { type: Date },
cancelled: { type: Date }, // cancelled: { type: Date },
returned: { type: Date }, // returned: { type: Date },
}, // },
iscancelled: { iscancelled: {
type: Boolean, type: Boolean,
default: false, default: false,
@ -135,21 +138,21 @@ const rdOrderSchema = new Schema(
courier_tracking_id: { type: String }, courier_tracking_id: { type: String },
isDelivered: { type: Boolean, required: true, default: false }, isDelivered: { type: Boolean, required: true, default: false },
DeliveredDate: { type: String, default: "" }, DeliveredDate: { type: String, default: "" },
statusHistory: [StatusHistorySchema], // Add this field to store the status history // To store the status history
}, },
{ timestamps: true } { timestamps: true }
); );
// Middleware to update the statusUpdatedAt field whenever status changes // Middleware to generate uniqueId and update statusHistory
rdOrderSchema.pre("save", function (next) { rdOrderSchema.pre("save", function (next) {
if (this.isModified("status")) { if (this.isNew) {
this.statusUpdatedAt = Date.now(); const year = new Date().getFullYear().toString().slice(-2); // Get the last 2 digits of the year
// Add the new status and timestamp to statusHistory const orderItemCount = this.orderItem.length; // Count the number of order items
this.statusHistory.push({ const unique6CharId = nanoid(6); // Generate a 6-character unique ID
status: this.status,
timestamp: this.statusUpdatedAt, this.uniqueId = `${year}-${orderItemCount}-${unique6CharId}`;
});
} }
next(); next();
}); });

View File

@ -1,10 +1,15 @@
import express from "express"; import express from "express";
import { import {
cancelOrderController,
createOrderRD, createOrderRD,
getCancelledOrders,
getNewOrders,
getPendignOrders,
getPlacedOrdersForPD, getPlacedOrdersForPD,
getPlacedOrdersForRD, getPlacedOrdersForRD,
getSinglePlacedOrderForPD, getSinglePlacedOrderForPD,
getSinglePlacedOrderForRD, getSinglePlacedOrderForRD,
processOrder,
} from "./rdOrderController.js"; } from "./rdOrderController.js";
import { isAuthenticatedRD } from "../../middlewares/rdAuth.js"; import { isAuthenticatedRD } from "../../middlewares/rdAuth.js";
import { isAuthenticatedUser } from "../../middlewares/auth.js"; import { isAuthenticatedUser } from "../../middlewares/auth.js";
@ -22,7 +27,19 @@ router
.get(isAuthenticatedUser, getPlacedOrdersForPD); .get(isAuthenticatedUser, getPlacedOrdersForPD);
router router
.route("/pd-get-all-place-order/:id") .route("/pd-get-single-place-order/:id")
.get(isAuthenticatedUser, getSinglePlacedOrderForPD); .get(isAuthenticatedUser, getSinglePlacedOrderForPD);
router.route("/pd-process-order").post(isAuthenticatedUser, processOrder);
router.route("/pd-get-new-orders").get(isAuthenticatedUser, getNewOrders);
router
.route("/pd-get-pending-orders")
.get(isAuthenticatedUser, getPendignOrders);
router
.route("/pd-get-cancelled-orders")
.get(isAuthenticatedUser, getCancelledOrders);
router
.route("/pd-cancel-order/:id")
.put(isAuthenticatedUser, cancelOrderController);
export default router; export default router;