91 lines
4.0 KiB
JavaScript
91 lines
4.0 KiB
JavaScript
const PDFDocument = require('pdfkit');
|
|
|
|
/**
|
|
* Generates a PDF invoice based on Shopify order data.
|
|
* @param {Object} orderData - The Shopify order payload
|
|
* @returns {Promise<Buffer>} - A promise that resolves to a Buffer containing the PDF data
|
|
*/
|
|
const generateInvoicePDF = (orderData) => {
|
|
return new Promise((resolve, reject) => {
|
|
try {
|
|
const doc = new PDFDocument({ margin: 50 });
|
|
let buffers = [];
|
|
|
|
doc.on('data', buffers.push.bind(buffers));
|
|
doc.on('end', () => {
|
|
const pdfData = Buffer.concat(buffers);
|
|
resolve(pdfData);
|
|
});
|
|
|
|
// Invoice Header
|
|
doc.fontSize(20).text('Invoice', { align: 'right' });
|
|
doc.moveDown();
|
|
|
|
doc.fontSize(12)
|
|
.text(`Order Number: ${orderData.name || orderData.order_number}`)
|
|
.text(`Date: ${new Date(orderData.created_at).toLocaleDateString()}`)
|
|
.moveDown();
|
|
|
|
// Store Info (You can customize this)
|
|
const shopName = process.env.SHOP_NAME || 'Your Store Name';
|
|
doc.fontSize(14).text(shopName);
|
|
doc.moveDown();
|
|
|
|
// Customer Info
|
|
doc.fontSize(14).text('Billed To:');
|
|
doc.fontSize(12).text(`${orderData.billing_address?.first_name || ''} ${orderData.billing_address?.last_name || ''}`);
|
|
doc.text(`${orderData.billing_address?.address1 || ''}`);
|
|
if (orderData.billing_address?.address2) {
|
|
doc.text(`${orderData.billing_address.address2}`);
|
|
}
|
|
doc.text(`${orderData.billing_address?.city || ''}, ${orderData.billing_address?.province || ''} ${orderData.billing_address?.zip || ''}`);
|
|
doc.text(`${orderData.billing_address?.country || ''}`);
|
|
doc.moveDown(2);
|
|
|
|
// Line Items Table Header
|
|
doc.fontSize(12).font('Helvetica-Bold');
|
|
doc.text('Item', 50, doc.y, { continued: true });
|
|
doc.text('Qty', 300, doc.y, { continued: true, width: 50, align: 'right' });
|
|
doc.text('Price', 350, doc.y, { continued: true, width: 100, align: 'right' });
|
|
doc.text('Total', 450, doc.y, { width: 100, align: 'right' });
|
|
|
|
doc.moveTo(50, doc.y).lineTo(550, doc.y).stroke();
|
|
doc.moveDown(0.5);
|
|
|
|
// Line Items Table Rows
|
|
doc.font('Helvetica');
|
|
let currentY = doc.y;
|
|
|
|
if (orderData.line_items && orderData.line_items.length > 0) {
|
|
orderData.line_items.forEach(item => {
|
|
doc.text(item.name, 50, currentY, { width: 250 });
|
|
doc.text(item.quantity.toString(), 300, currentY, { width: 50, align: 'right' });
|
|
doc.text(`${orderData.currency} ${parseFloat(item.price).toFixed(2)}`, 350, currentY, { width: 100, align: 'right' });
|
|
const total = parseFloat(item.price) * item.quantity;
|
|
doc.text(`${orderData.currency} ${total.toFixed(2)}`, 450, currentY, { width: 100, align: 'right' });
|
|
|
|
doc.moveDown(0.5);
|
|
currentY = doc.y;
|
|
});
|
|
}
|
|
|
|
doc.moveTo(50, currentY).lineTo(550, currentY).stroke();
|
|
doc.moveDown(1);
|
|
|
|
// Totals
|
|
doc.text(`Subtotal: ${orderData.currency} ${orderData.subtotal_price}`, { align: 'right' });
|
|
if (orderData.total_tax > 0) {
|
|
doc.text(`Tax: ${orderData.currency} ${orderData.total_tax}`, { align: 'right' });
|
|
}
|
|
doc.text(`Shipping: ${orderData.currency} ${orderData.total_shipping_price_set?.shop_money?.amount || '0.00'}`, { align: 'right' });
|
|
doc.font('Helvetica-Bold').text(`Total: ${orderData.currency} ${orderData.total_price}`, { align: 'right' });
|
|
|
|
doc.end();
|
|
} catch (error) {
|
|
reject(error);
|
|
}
|
|
});
|
|
};
|
|
|
|
module.exports = { generateInvoicePDF };
|