order partial and fully processing with sending mail
This commit is contained in:
parent
e53a503ffa
commit
839f942f08
@ -34,7 +34,7 @@ const orderItemSchema = new Schema({
|
|||||||
type: Number,
|
type: Number,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
quantity: {
|
processquantity: { //updated quantity
|
||||||
type: Number,
|
type: Number,
|
||||||
required: true,
|
required: true,
|
||||||
default: 1,
|
default: 1,
|
||||||
|
@ -79,7 +79,7 @@ export const processOrder = async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find the order by ID
|
// Find the order by ID
|
||||||
const order = await PdOrder.findById(orderId);
|
const order = await PdOrder.findById(orderId).populate('addedBy');
|
||||||
|
|
||||||
if (!order) {
|
if (!order) {
|
||||||
return res.status(404).json({ error: 'Order not found' });
|
return res.status(404).json({ error: 'Order not found' });
|
||||||
@ -88,25 +88,25 @@ export const processOrder = async (req, res) => {
|
|||||||
// Validate quantities
|
// Validate quantities
|
||||||
for (const item of invoiceItems) {
|
for (const item of invoiceItems) {
|
||||||
const orderItem = order.orderItem.find(i => i.productId.toString() === item.productId.toString());
|
const orderItem = order.orderItem.find(i => i.productId.toString() === item.productId.toString());
|
||||||
if (orderItem && item.quantity > orderItem.remainingQuantity) {
|
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.` });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate unique invoice number
|
// Generate unique invoice number
|
||||||
const existingInvoices = await Invoice.find({ orderId });
|
const existingInvoices = await Invoice.find({ orderId });
|
||||||
const invoiceNumber = existingInvoices.length + 1;
|
const invoiceNumber = existingInvoices.length + 1;
|
||||||
const invoiceId = `ch/${order.uniqueId}/${invoiceItems.length}/${invoiceNumber}`;
|
const invoiceId = `ch/${order.uniqueId}/${invoiceItems.length}/${invoiceNumber}`;
|
||||||
|
|
||||||
// Calculate subtotal, gstTotal, and invoiceAmount
|
// Calculate subtotal, gstTotal, and invoiceAmount for processed items
|
||||||
let subtotal = 0;
|
let subtotal = 0;
|
||||||
let gstTotal = 0;
|
let gstTotal = 0;
|
||||||
let invoiceAmount = 0;
|
let invoiceAmount = 0;
|
||||||
|
|
||||||
invoiceItems.forEach(item => {
|
invoiceItems.forEach(item => {
|
||||||
const itemSubtotal = item.price * item.quantity;
|
const itemSubtotal = item.price * item.processquantity;
|
||||||
const itemGST = (item.price * item.GST) / 100 * item.quantity;
|
const itemGST = (item.price * item.GST / 100) * item.processquantity;
|
||||||
|
|
||||||
subtotal += itemSubtotal;
|
subtotal += itemSubtotal;
|
||||||
gstTotal += itemGST;
|
gstTotal += itemGST;
|
||||||
invoiceAmount += itemSubtotal + itemGST;
|
invoiceAmount += itemSubtotal + itemGST;
|
||||||
@ -130,7 +130,7 @@ export const processOrder = async (req, res) => {
|
|||||||
order.orderItem.forEach(item => {
|
order.orderItem.forEach(item => {
|
||||||
const invoicedItem = invoiceItems.find(i => i.productId.toString() === item.productId.toString());
|
const invoicedItem = invoiceItems.find(i => i.productId.toString() === item.productId.toString());
|
||||||
if (invoicedItem) {
|
if (invoicedItem) {
|
||||||
item.remainingQuantity -= invoicedItem.quantity;
|
item.remainingQuantity -= invoicedItem.processquantity;
|
||||||
if (item.remainingQuantity < 0) {
|
if (item.remainingQuantity < 0) {
|
||||||
item.remainingQuantity = 0; // Ensure it does not go negative
|
item.remainingQuantity = 0; // Ensure it does not go negative
|
||||||
}
|
}
|
||||||
@ -140,20 +140,130 @@ export const processOrder = async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Update the order status
|
// Update the order status
|
||||||
order.status = allItemsProcessed ? 'processing' : 'pending';
|
order.status = allItemsProcessed ? 'processing' : 'pending';
|
||||||
|
|
||||||
// Save the updated order
|
// Save the updated order
|
||||||
await order.save();
|
await order.save();
|
||||||
|
|
||||||
return res.status(201).json({
|
// Prepare the email content
|
||||||
message: 'Invoice created and order processed successfully',
|
const processedItems = invoiceItems.map((item, index) => `
|
||||||
invoice: savedInvoice,
|
<tr>
|
||||||
order: order,
|
<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>
|
||||||
|
` : ''}
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
res.status(200).json({ message: 'Order processed and invoice created successfully', invoiceId: savedInvoice.invoiceId });
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error('Error processing order:', error);
|
||||||
return res.status(500).json({ error: 'Internal server error' });
|
res.status(500).json({ error: 'An error occurred while processing the order' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user