From a15558d565f56829553c2991c516ac93d4428ff5 Mon Sep 17 00:00:00 2001 From: Alaguraj0361 Date: Wed, 3 Jun 2026 17:03:17 +0530 Subject: [PATCH] add shipping label generation and email functionality --- mailer.js | 74 ++++++++--- send-label-test.js | 80 ++++++++++++ server.js | 13 +- shipping-label-test.pdf | Bin 0 -> 57597 bytes shippingLabelGenerator.js | 254 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 400 insertions(+), 21 deletions(-) create mode 100644 send-label-test.js create mode 100644 shipping-label-test.pdf create mode 100644 shippingLabelGenerator.js diff --git a/mailer.js b/mailer.js index 9a7ae55..0bff353 100644 --- a/mailer.js +++ b/mailer.js @@ -7,9 +7,10 @@ const path = require('path'); * Sends a premium custom email with the PDF attachment. * @param {string} toEmail - The recipient's email address * @param {Object} orderData - The Shopify order payload - * @param {Buffer} pdfBuffer - The PDF data buffer + * @param {Buffer} pdfBuffer - The invoice PDF data buffer + * @param {Buffer} [shippingLabelBuffer] - Optional shipping label PDF buffer */ -const sendEmailWithAttachment = async (toEmail, orderData, pdfBuffer) => { +const sendEmailWithAttachment = async (toEmail, orderData, pdfBuffer, shippingLabelBuffer = null) => { const transporter = nodemailer.createTransport({ host: process.env.SMTP_HOST, port: Number(process.env.SMTP_PORT) || 465, @@ -209,8 +210,8 @@ const sendEmailWithAttachment = async (toEmail, orderData, pdfBuffer) => { `; - // Build attachments array - always include PDF, add logo as CID inline if it exists - const attachments = [ + // --- Customer attachments: Invoice PDF only --- + const customerAttachments = [ { filename: `Invoice_${orderNumber}.pdf`, content: pdfBuffer, @@ -219,26 +220,65 @@ const sendEmailWithAttachment = async (toEmail, orderData, pdfBuffer) => { ]; if (logoExists) { - attachments.push({ + customerAttachments.push({ filename: 'logo.png', path: localLogoPath, - cid: 'store_logo' // Referenced in HTML as src="cid:store_logo" + cid: 'store_logo' }); } - const mailOptions = { - from: `"${process.env.SHOP_NAME || 'Your Store'}" <${process.env.SMTP_FROM_EMAIL}>`, - to: toEmail, - subject: `Invoice for your order #${orderNumber}`, - text: `Thank you for your order! Attached is the invoice for order #${orderNumber}.`, - html: htmlTemplate, - attachments - }; + // --- Seller attachments: Invoice PDF + Shipping Label PDF --- + const sellerAttachments = [ + { + filename: `Invoice_${orderNumber}.pdf`, + content: pdfBuffer, + contentType: 'application/pdf' + } + ]; + + if (shippingLabelBuffer) { + sellerAttachments.push({ + filename: `ShippingLabel_${orderNumber}.pdf`, + content: shippingLabelBuffer, + contentType: 'application/pdf' + }); + } + + if (logoExists) { + sellerAttachments.push({ + filename: 'logo.png', + path: localLogoPath, + cid: 'store_logo' + }); + } try { - const info = await transporter.sendMail(mailOptions); - console.log(`Email sent: ${info.messageId}`); - return info; + // 1. Send to customer (Invoice only) + const customerMail = await transporter.sendMail({ + from: `"${process.env.SHOP_NAME || 'Your Store'}" <${process.env.SMTP_FROM_EMAIL}>`, + to: toEmail, + subject: `Invoice for your order #${orderNumber}`, + text: `Thank you for your order! Attached is the invoice for order #${orderNumber}.`, + html: htmlTemplate, + attachments: customerAttachments + }); + console.log(`Customer email sent: ${customerMail.messageId}`); + + // 2. Send to seller (Invoice + Shipping Label) + const sellerEmail = process.env.SELLER_EMAIL; + if (sellerEmail) { + const sellerMail = await transporter.sendMail({ + from: `"${process.env.SHOP_NAME || 'Your Store'}" <${process.env.SMTP_FROM_EMAIL}>`, + to: sellerEmail, + subject: `[NEW ORDER] #${orderNumber} - Invoice & Shipping Label`, + text: `New order #${orderNumber} received. Invoice and Shipping Label attached.`, + html: htmlTemplate, + attachments: sellerAttachments + }); + console.log(`Seller email sent: ${sellerMail.messageId}`); + } + + return customerMail; } catch (error) { console.error('Error sending email:', error); throw error; diff --git a/send-label-test.js b/send-label-test.js new file mode 100644 index 0000000..ea46d8a --- /dev/null +++ b/send-label-test.js @@ -0,0 +1,80 @@ +require('dotenv').config({ override: true }); +const nodemailer = require('nodemailer'); +const { generateShippingLabelPDF } = require('./shippingLabelGenerator'); + +async function sendTestShippingLabelEmail() { + try { + console.log('Generating dummy Shipping Label...'); + const dummyOrder = { + name: '#9999', + order_number: 9999, + created_at: new Date().toISOString(), + currency: 'INR', + subtotal_price: '660.00', + total_tax: '0.00', + total_price: '660.00', + gateway: 'Request Quote', + shipping_lines: [{ title: 'Delhivery Courier' }], + billing_address: { + first_name: 'Alagu', last_name: 'Raj', + address1: 'South Street', address2: 'Near Temple', + city: 'Tuticorin', province: 'Tamil Nadu', zip: '628304', + country: 'India', phone: '7871207631' + }, + shipping_address: { + first_name: 'Alagu', last_name: 'Raj', + address1: 'South Street', address2: 'Near Temple', + city: 'Tuticorin', province: 'Tamil Nadu', zip: '628304', + country: 'India', phone: '7871207631' + }, + email: process.env.SMTP_USER, + line_items: [ + { name: 'Flat Bangle 4 Cut - Each Box', quantity: 1, price: '130.00', image_url: 'https://picsum.photos/200' }, + { name: 'Glue Stick pencil - 1 piece', quantity: 3, price: '35.00', image_url: 'https://picsum.photos/200' }, + { name: 'E-8000 - 50ML - 1 Piece', quantity: 2, price: '60.00', image_url: 'https://picsum.photos/200' } + ] + }; + + const shippingLabelBuffer = await generateShippingLabelPDF(dummyOrder); + console.log('Shipping Label PDF generated successfully.'); + const fs = require('fs'); + fs.writeFileSync('shipping-label-test.pdf', shippingLabelBuffer); + console.log('Saved shipping-label-test.pdf to disk.'); + + const transporter = nodemailer.createTransport({ + host: process.env.SMTP_HOST, + port: Number(process.env.SMTP_PORT) || 465, + secure: process.env.SMTP_SECURE === 'true', + auth: { + user: process.env.SMTP_USER, + pass: process.env.SMTP_PASS, + }, + tls: { + rejectUnauthorized: false + } + }); + + const targetEmail = process.env.SMTP_USER; + console.log(`Sending email with shipping label attached to ${targetEmail}...`); + + const mailInfo = await transporter.sendMail({ + from: `"${process.env.SHOP_NAME || 'Your Store'}" <${process.env.SMTP_FROM_EMAIL}>`, + to: targetEmail, + subject: `Test Shipping Label - Order #9999`, + text: `Hello, this is a test email with the generated Shipping Label PDF attached.`, + attachments: [ + { + filename: `ShippingLabel_9999.pdf`, + content: shippingLabelBuffer, + contentType: 'application/pdf' + } + ] + }); + + console.log(`Success! Test email sent: ${mailInfo.messageId}`); + } catch (error) { + console.error('Error sending test shipping label email:', error); + } +} + +sendTestShippingLabelEmail(); diff --git a/server.js b/server.js index c7a0012..7646c54 100644 --- a/server.js +++ b/server.js @@ -3,6 +3,7 @@ const express = require('express'); const cors = require('cors'); const crypto = require('crypto'); const { generateInvoicePDF } = require('./pdfGenerator'); +const { generateShippingLabelPDF } = require('./shippingLabelGenerator'); const { sendEmailWithAttachment } = require('./mailer'); const app = express(); @@ -105,10 +106,13 @@ app.post('/webhooks/orders/create', verifyShopifyWebhook, async (req, res) => { })); } - // 1. Generate the PDF invoice - const pdfBuffer = await generateInvoicePDF(orderData); + // 1. Generate the PDF invoice and shipping label in parallel + const [pdfBuffer, shippingLabelBuffer] = await Promise.all([ + generateInvoicePDF(orderData), + generateShippingLabelPDF(orderData) + ]); - // 2. Send the email with the attached PDF + // 2. Send the email with the attached PDFs const customerEmail = orderData.email || orderData.contact_email; if (!customerEmail) { const errorMsg = `[${new Date().toISOString()}] Order ${orderData.order_number} has no email address associated.\n`; @@ -119,7 +123,8 @@ app.post('/webhooks/orders/create', verifyShopifyWebhook, async (req, res) => { await sendEmailWithAttachment( customerEmail, orderData, - pdfBuffer + pdfBuffer, + shippingLabelBuffer ); const successMsg = `[${new Date().toISOString()}] Successfully processed and sent email for Order ${orderData.order_number}\n`; diff --git a/shipping-label-test.pdf b/shipping-label-test.pdf new file mode 100644 index 0000000000000000000000000000000000000000..91eb0286fc1aba436c3141e91b202400107b3956 GIT binary patch literal 57597 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 biirW8oZmV+|7R#6P%tkT$iyVADg*pKyBDkc literal 0 HcmV?d00001 diff --git a/shippingLabelGenerator.js b/shippingLabelGenerator.js new file mode 100644 index 0000000..553edaa --- /dev/null +++ b/shippingLabelGenerator.js @@ -0,0 +1,254 @@ +const PDFDocument = require('pdfkit'); +const fs = require('fs'); +const path = require('path'); + +/** + * Helper to draw a clean, structured mock barcode + */ +function drawBarcode(doc, x, y, width, height, text) { + doc.save(); + let currentX = x; + const endX = x + width; + + // Draw barcode bars + while (currentX < endX) { + // Vary the bar width and spacing to make it look like a real barcode + const isWide = Math.random() > 0.6; + const lineWidth = isWide ? 2.2 : 0.9; + const spacing = Math.random() > 0.4 ? 1.5 : 2.5; + + if (currentX + lineWidth > endX) break; + + doc.rect(currentX, y, lineWidth, height - 16).fill('#000000'); + currentX += lineWidth + spacing; + } + + // Barcode number text below bars (with extra vertical gap and letter spacing) + doc.fontSize(8.5) + .font('Helvetica-Bold') + .fillColor('#000000') + .text(text, x, y + height - 11, { width: width, align: 'center', characterSpacing: 1.5 }); + + doc.restore(); +} + +/** + * Helper to adjust order number using ORDER_NUMBER_OFFSET + */ +const getAdjustedOrderNumber = (orderNumberOrName) => { + if (!orderNumberOrName) return ''; + const offset = parseInt(process.env.ORDER_NUMBER_OFFSET, 10) || 0; + const str = orderNumberOrName.toString(); + const matches = str.match(/\d+/); + if (!matches) return str; + const num = parseInt(matches[0], 10); + return (num + offset).toString(); +}; + +/** + * Generates a professional 4x6 inch shipping label PDF. + * @param {Object} orderData - The Shopify order payload + * @returns {Promise} - A promise that resolves to a Buffer containing the PDF data + */ +const generateShippingLabelPDF = async (orderData) => { + return new Promise(async (resolve, reject) => { + try { + // 4x6 inch = 288 x 432 points (1 inch = 72 points) + const doc = new PDFDocument({ + margin: 0, + size: [288, 432] + }); + + let buffers = []; + doc.on('data', buffers.push.bind(buffers)); + doc.on('end', () => resolve(Buffer.concat(buffers))); + + const W = 288; + const H = 432; + const PAD = 16; + + // --- BACKGROUND --- + doc.rect(0, 0, W, H).fill('#ffffff'); + + // --- OUTER BORDER (Thicker, professional frame) --- + doc.rect(6, 6, W - 12, H - 12) + .lineWidth(2) + .strokeColor('#1e293b') + .stroke(); + + // ============================================================ + // SECTION 1: HEADER STRIP (FROM shop info) + // ============================================================ + const headerY = 6; + const headerH = 58; + doc.rect(6, headerY, W - 12, headerH).fill('#1e293b'); + + // Load local logo if it exists + const localLogoPath = path.join(__dirname, 'logo.png'); + let logoLoaded = false; + if (fs.existsSync(localLogoPath)) { + try { + doc.image(localLogoPath, PAD, headerY + 9, { height: 40 }); + logoLoaded = true; + } catch (e) { /* silent fail */ } + } + + // Shop name text (right side of header) + doc.fontSize(12.5) + .font('Helvetica-Bold') + .fillColor('#ffffff') + .text('RAY AARI SHOP', logoLoaded ? 95 : PAD, headerY + 13, { width: W - (logoLoaded ? 111 : PAD * 2) }); + + doc.fontSize(7.5) + .font('Helvetica') + .fillColor('#cbd5e1') + .text('Sivanatham Salai, Arappalayam Cross Rd,', logoLoaded ? 95 : PAD, headerY + 28, { width: W - (logoLoaded ? 111 : PAD * 2) }) + .text('Madurai 625016, Tamil Nadu, India | Ph: 9994333548', logoLoaded ? 95 : PAD, headerY + 38, { width: W - (logoLoaded ? 111 : PAD * 2) }); + + // ============================================================ + // SECTION 2: ORDER INFO STRIP (Left-Right Aligned) + // ============================================================ + const orderStripY = headerY + headerH; + const orderStripH = 30; + doc.rect(6, orderStripY, W - 12, orderStripH).fill('#f1f5f9'); + + const orderNumber = getAdjustedOrderNumber(orderData.order_number || orderData.name); + const orderDate = new Date(orderData.created_at || Date.now()).toLocaleDateString('en-GB'); + const shippingMethod = orderData.shipping_lines?.[0]?.title || 'Standard Courier'; + + // Order Number on Left + doc.fontSize(9.5) + .font('Helvetica-Bold') + .fillColor('#0f172a') + .text(`ORDER: #${orderNumber}`, PAD, orderStripY + 10); + + // Date | Courier Method on Right + doc.fontSize(8) + .font('Helvetica-Bold') + .fillColor('#475569') + .text(`${orderDate} | ${shippingMethod}`, PAD, orderStripY + 11, { width: W - PAD * 2, align: 'right' }); + + // ============================================================ + // SECTION 3: SHIP TO SECTION + // ============================================================ + const shipToLabelY = orderStripY + orderStripH; + const shipToLabelH = 18; + doc.rect(6, shipToLabelY, W - 12, shipToLabelH).fill('#0f172a'); + + doc.fontSize(8.5) + .font('Helvetica-Bold') + .fillColor('#ffffff') + .text('SHIP TO', PAD, shipToLabelY + 5, { width: W - PAD * 2, align: 'center' }); + + // ============================================================ + // SECTION 4: CUSTOMER ADDRESS (Clean typesetting) + // ============================================================ + const addressStartY = shipToLabelY + shipToLabelH + 12; + const shipping = orderData.shipping_address || orderData.billing_address || {}; + + const toName = `${shipping.first_name || ''} ${shipping.last_name || ''}`.trim() || 'Customer'; + const toPhone = shipping.phone || orderData.phone || orderData.billing_address?.phone || ''; + const toAddr1 = shipping.address1 || ''; + const toAddr2 = shipping.address2 || ''; + const toCity = shipping.city || ''; + const toProvince = shipping.province || ''; + const toZip = shipping.zip || ''; + const toCountry = shipping.country || 'India'; + + // Customer Name + doc.fontSize(14) + .font('Helvetica-Bold') + .fillColor('#0f172a') + .text(toName, PAD, addressStartY, { width: W - PAD * 2 }); + + let currentY = addressStartY + 18; + + // Customer Phone (Clean phone icon fallback) + if (toPhone) { + doc.fontSize(9.5) + .font('Helvetica-Bold') + .fillColor('#0f172a') + .text(`Phone: ${toPhone}`, PAD, currentY, { width: W - PAD * 2 }); + currentY += 14; + } + + // Customer Address lines combined with consistent spacing + const addressParts = []; + if (toAddr1) addressParts.push(toAddr1); + if (toAddr2) addressParts.push(toAddr2); + + if (toCity || toProvince || toZip) { + const parts = []; + if (toCity) parts.push(toCity); + if (toProvince) parts.push(toProvince); + const cityState = parts.join(', '); + addressParts.push(cityState + (toZip ? ' - ' + toZip : '')); + } + addressParts.push(toCountry); + + const addressText = addressParts.join('\n'); + + doc.fontSize(9.5) + .font('Helvetica') + .fillColor('#334155') + .text(addressText, PAD, currentY, { width: W - PAD * 2, lineGap: 3.5 }); + + // Calculate height of the address block to dynamically place the separator + const addressHeight = doc.heightOfString(addressText, { width: W - PAD * 2, lineGap: 3.5 }); + currentY += addressHeight + 10; + + // Ensure the separator doesn't overflow if address is short or long + const minSeparatorY = 250; + const sepY = Math.max(currentY, minSeparatorY); + + // ============================================================ + // SECTION 5: HORIZONTAL SEPARATOR + // ============================================================ + doc.moveTo(PAD, sepY) + .lineTo(W - PAD, sepY) + .lineWidth(1) + .strokeColor('#cbd5e1') + .stroke(); + + // ============================================================ + // SECTION 6: FROM ADDRESS (Ray Aari Shop - Return address) + // ============================================================ + const fromY = sepY + 10; + + doc.fontSize(7.5) + .font('Helvetica-Bold') + .fillColor('#64748b') + .text('FROM / SENDER:', PAD, fromY); + + doc.fontSize(9) + .font('Helvetica-Bold') + .fillColor('#1e293b') + .text('Ray Aari Shop', PAD, fromY + 12); + + const shopAddressText = [ + 'Sivanatham Salai, Arappalayam Cross Rd, Near Madura Coats pvt', + 'Madurai 625016, Tamil Nadu, India | Ph: 9994333548' + ].join('\n'); + + doc.fontSize(7.5) + .font('Helvetica') + .fillColor('#475569') + .text(shopAddressText, PAD, fromY + 24, { width: W - PAD * 2, lineGap: 2 }); + + // ============================================================ + // SECTION 7: BARCODE STRIP (Locked to Bottom) + // ============================================================ + const barcodeAreaY = H - 75; + doc.rect(6, barcodeAreaY, W - 12, 1).fill('#cbd5e1'); + + const barcodeText = `RA${orderNumber}IN`; + drawBarcode(doc, PAD + 15, barcodeAreaY + 12, W - PAD * 2 - 30, 52, barcodeText); + + doc.end(); + } catch (error) { + reject(error); + } + }); +}; + +module.exports = { generateShippingLabelPDF };