fetch product images from Shopify API and add to order data for invoice generation

This commit is contained in:
Alaguraj0361 2026-06-03 10:52:46 +05:30
parent 46713fc66b
commit 8281f95c71
2 changed files with 64 additions and 11 deletions

View File

@ -222,9 +222,9 @@ const generateInvoicePDF = async (orderData) => {
for (let i = 0; i < orderData.line_items.length; i++) {
const item = orderData.line_items[i];
// Background color for alternating rows
// Background color for alternating rows (slightly taller: 46 height)
if (i % 2 === 1) {
doc.rect(40, tableY - 4, 515, 38).fill(rowAltColor);
doc.rect(40, tableY - 6, 515, 46).fill(rowAltColor);
}
doc.fontSize(9)
@ -232,41 +232,57 @@ const generateInvoicePDF = async (orderData) => {
.fillColor(textColor);
// S.No
doc.text((i + 1).toString(), 40, tableY);
doc.text((i + 1).toString(), 40, tableY + 10);
// Handle product image
let textX = 85;
let textWidth = 270;
if (item.image_url) {
const imgBuffer = await fetchImageBuffer(item.image_url);
if (imgBuffer) {
try {
doc.image(imgBuffer, 85, tableY - 2, { fit: [35, 35] });
textX = 130;
textWidth = 225;
} catch (e) {
console.error('Error rendering line item image:', e);
}
}
}
// Product Name and Variant/Quantity details
const productText = item.title || item.name;
doc.text(productText, 85, tableY, { width: 270, height: 15, ellipsis: true });
doc.text(productText, textX, tableY, { width: textWidth, height: 15, ellipsis: true });
// Display quantity/variant info if available
if (item.variant_title) {
doc.fontSize(8)
.fillColor('#64748b')
.text(item.variant_title, 85, tableY + 12, { width: 270 });
.text(item.variant_title, textX, tableY + 14, { width: textWidth });
}
// Reset font size
doc.fontSize(9).fillColor(textColor);
// Quantity
doc.text(item.quantity.toString(), 365, tableY, { width: 50, align: 'right' });
doc.text(item.quantity.toString(), 365, tableY + 10, { width: 50, align: 'right' });
// Unit Price
const unitPrice = parseFloat(item.price).toFixed(2);
doc.text(`${currencySymbol}${unitPrice}`, 425, tableY, { width: 60, align: 'right' });
doc.text(`${currencySymbol}${unitPrice}`, 425, tableY + 10, { width: 60, align: 'right' });
// Total Price
const totalPrice = (parseFloat(item.price) * item.quantity).toFixed(2);
doc.text(`${currencySymbol}${totalPrice}`, 495, tableY, { width: 60, align: 'right' });
doc.text(`${currencySymbol}${totalPrice}`, 495, tableY + 10, { width: 60, align: 'right' });
// Divider Line
doc.moveTo(40, tableY + 28)
.lineTo(555, tableY + 28)
doc.moveTo(40, tableY + 38)
.lineTo(555, tableY + 38)
.lineWidth(0.5)
.strokeColor('#f1f5f9')
.stroke();
tableY += 34;
tableY += 44;
}
}

View File

@ -52,6 +52,43 @@ app.post('/webhooks/orders/create', verifyShopifyWebhook, async (req, res) => {
const processMessage = `[${new Date().toISOString()}] Processing Order ${orderData.order_number}\n`;
fs.appendFileSync('webhook.log', processMessage);
// Fetch product images from Shopify Admin API (requires read_products scope)
if (orderData.line_items && orderData.line_items.length > 0) {
await Promise.all(orderData.line_items.map(async (item) => {
if (!item.product_id) return;
try {
const shopifyUrl = `https://${process.env.SHOPIFY_STORE_DOMAIN}/admin/api/2024-01/products/${item.product_id}.json`;
const response = await fetch(shopifyUrl, {
headers: {
'X-Shopify-Access-Token': process.env.SHOPIFY_ADMIN_API_TOKEN
}
});
if (response.ok) {
const data = await response.json();
const product = data.product;
if (product) {
// Find variant-specific image
let imgUrl = null;
if (item.variant_id && product.variants) {
const variant = product.variants.find(v => v.id === item.variant_id);
if (variant && variant.image_id && product.images) {
const variantImg = product.images.find(img => img.id === variant.image_id);
if (variantImg) imgUrl = variantImg.src;
}
}
// Fallback to main product image
item.image_url = imgUrl || product.image?.src || (product.images && product.images[0]?.src) || null;
}
} else {
const errText = await response.text();
console.error(`Shopify API error fetching product ${item.product_id}: Status ${response.status} - ${errText}`);
}
} catch (err) {
console.error(`Failed to fetch image for product ${item.product_id}:`, err);
}
}));
}
// 1. Generate the PDF invoice
const pdfBuffer = await generateInvoicePDF(orderData);