Generación y envío automatizados de facturas PDF con Gmail y almacenamiento en Google Drive
Este es unMiscellaneous, Multimodal AIflujo de automatización del dominio deautomatización que contiene 13 nodos.Utiliza principalmente nodos como Code, Webhook, EmailSend, GoogleDrive, HttpRequest. Automatizar la generación y envío de facturas PDF con Gmail y Google Drive
- •Punto final de HTTP Webhook (n8n generará automáticamente)
- •Credenciales de API de Google Drive
- •Pueden requerirse credenciales de autenticación para la API de destino
Nodos utilizados (13)
Categoría
{
"meta": {
"instanceId": "6d51f49bab6b0dffc9b87e9dabbeb0e9b71c14bdaab2b96ec32b663d472dacc3",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "3060dd2d-bf5b-404e-8f85-c0bc78a3075e",
"name": "Nota adhesiva",
"type": "n8n-nodes-base.stickyNote",
"position": [
320,
-192
],
"parameters": {
"width": 214,
"height": 272,
"content": "✅ **SUCCESS RESPONSE**\n\n- Confirms invoice generated\n- Returns invoice number & total\n- Email delivery confirmation\n- Google Drive storage status\n- Complete operation summary"
},
"typeVersion": 1
},
{
"id": "353da029-1514-40d0-969b-bcd2816bdbcc",
"name": "Webhook Trigger",
"type": "n8n-nodes-base.webhook",
"position": [
-800,
112
],
"webhookId": "56df3812-2f30-4148-9223-a6474390fe15",
"parameters": {
"path": "generate-invoice",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "d3c566ba-582b-4e17-b30d-580c5e617630",
"name": "Procesar Datos de Factura",
"type": "n8n-nodes-base.code",
"position": [
-576,
112
],
"parameters": {
"jsCode": "// Process and validate invoice data\nconst data = $input.item.json.body;\n\n// Generate invoice number if not provided\nconst invoiceNumber = data.invoiceNumber || `INV-${new Date().getFullYear()}-${String(Date.now()).slice(-6)}`;\n\n// Process items and calculate totals\nconst items = data.items || [];\nlet subtotal = 0;\n\nconst processedItems = items.map(item => {\n const qty = parseFloat(item.quantity || item.qty || 1);\n const price = parseFloat(item.price || 0);\n const total = qty * price;\n subtotal += total;\n \n return {\n description: item.description || 'Service',\n quantity: qty,\n price: price,\n total: total.toFixed(2)\n };\n});\n\n// Calculate tax and total\nconst taxRate = parseFloat(data.taxRate || 0.1);\nconst taxAmount = subtotal * taxRate;\nconst totalAmount = subtotal + taxAmount;\n\n// Format dates\nconst currentDate = new Date().toISOString().split('T')[0];\nconst dueDate = data.dueDate || new Date(Date.now() + 30*24*60*60*1000).toISOString().split('T')[0];\n\nreturn {\n customerName: data.customerName || 'Customer',\n customerEmail: data.customerEmail,\n customerAddress: data.customerAddress || '',\n invoiceNumber: invoiceNumber,\n invoiceDate: currentDate,\n dueDate: dueDate,\n companyName: data.companyName || $env.COMPANY_NAME || 'Your Company Ltd',\n companyAddress: data.companyAddress || $env.COMPANY_ADDRESS || '123 Business Street',\n companyEmail: data.companyEmail || $env.COMPANY_EMAIL || 'billing@company.com',\n companyPhone: data.companyPhone || $env.COMPANY_PHONE || '+1-555-0123',\n items: processedItems,\n subtotal: subtotal.toFixed(2),\n taxRate: (taxRate * 100).toFixed(1),\n taxAmount: taxAmount.toFixed(2),\n totalAmount: totalAmount.toFixed(2),\n notes: data.notes || 'Thank you for your business!',\n paymentTerms: data.paymentTerms || 'Payment due within 30 days',\n timestamp: new Date().toISOString()\n};"
},
"typeVersion": 2
},
{
"id": "659c77de-7c5c-4a49-9525-07b0106460da",
"name": "Generar Plantilla HTML",
"type": "n8n-nodes-base.code",
"position": [
-352,
112
],
"parameters": {
"jsCode": "// Generate HTML for PDF invoice\nconst data = $input.item.json;\n\n// Create items table rows\nconst itemRows = data.items.map(item => `\n <tr>\n <td style=\"padding: 8px; border-bottom: 1px solid #eee;\">${item.description}</td>\n <td style=\"padding: 8px; border-bottom: 1px solid #eee; text-align: center;\">${item.quantity}</td>\n <td style=\"padding: 8px; border-bottom: 1px solid #eee; text-align: right;\">$${item.price.toFixed(2)}</td>\n <td style=\"padding: 8px; border-bottom: 1px solid #eee; text-align: right;\">$${item.total}</td>\n </tr>\n`).join('');\n\nconst htmlContent = `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <style>\n body { font-family: Arial, sans-serif; margin: 0; padding: 20px; color: #333; }\n .header { display: flex; justify-content: space-between; margin-bottom: 30px; border-bottom: 2px solid #007bff; padding-bottom: 20px; }\n .company-info h1 { color: #007bff; margin: 0; font-size: 28px; }\n .company-info p { margin: 5px 0; color: #666; }\n .invoice-info { text-align: right; }\n .invoice-info h2 { color: #333; margin: 0; font-size: 24px; }\n .customer-section { margin: 30px 0; }\n .customer-section h3 { color: #333; margin-bottom: 10px; }\n .items-table { width: 100%; border-collapse: collapse; margin: 30px 0; }\n .items-table th { background: #007bff; color: white; padding: 12px 8px; }\n .totals { margin-top: 20px; }\n .totals table { margin-left: auto; width: 300px; }\n .totals td { padding: 5px 10px; }\n .totals .total-row { font-weight: bold; border-top: 2px solid #333; }\n .footer { margin-top: 40px; padding-top: 20px; border-top: 1px solid #eee; color: #666; }\n .payment-terms { background: #f8f9fa; padding: 15px; border-radius: 5px; margin-top: 20px; }\n </style>\n</head>\n<body>\n <div class=\"header\">\n <div class=\"company-info\">\n <h1>${data.companyName}</h1>\n <p>${data.companyAddress}</p>\n <p>Email: ${data.companyEmail}</p>\n <p>Phone: ${data.companyPhone}</p>\n </div>\n <div class=\"invoice-info\">\n <h2>INVOICE</h2>\n <p><strong>Invoice #:</strong> ${data.invoiceNumber}</p>\n <p><strong>Date:</strong> ${data.invoiceDate}</p>\n <p><strong>Due Date:</strong> ${data.dueDate}</p>\n </div>\n </div>\n \n <div class=\"customer-section\">\n <h3>Bill To:</h3>\n <p><strong>${data.customerName}</strong></p>\n <p>${data.customerEmail}</p>\n </div>\n \n <table class=\"items-table\">\n <thead>\n <tr>\n <th>Description</th>\n <th>Quantity</th>\n <th>Unit Price</th>\n <th>Total</th>\n </tr>\n </thead>\n <tbody>\n ${itemRows}\n </tbody>\n </table>\n \n <div class=\"totals\">\n <table>\n <tr>\n <td>Subtotal:</td>\n <td style=\"text-align: right;\">$${data.subtotal}</td>\n </tr>\n <tr>\n <td>Tax (${data.taxRate}%):</td>\n <td style=\"text-align: right;\">$${data.taxAmount}</td>\n </tr>\n <tr class=\"total-row\">\n <td><strong>Total Amount:</strong></td>\n <td style=\"text-align: right;\"><strong>$${data.totalAmount}</strong></td>\n </tr>\n </table>\n </div>\n \n <div class=\"payment-terms\">\n <h4>Payment Terms:</h4>\n <p>${data.paymentTerms}</p>\n </div>\n \n <div class=\"footer\">\n <p>${data.notes}</p>\n <p><em>Generated automatically on ${new Date().toLocaleDateString()}</em></p>\n </div>\n</body>\n</html>\n`;\n\nreturn {\n ...data,\n htmlContent: htmlContent,\n filename: `invoice-${data.invoiceNumber}.pdf`\n};"
},
"typeVersion": 2
},
{
"id": "7fe430f5-e516-4f3f-9ffd-d82e3a3db05a",
"name": "Generar PDF",
"type": "n8n-nodes-base.httpRequest",
"position": [
-112,
112
],
"parameters": {
"url": "={{ $env.PDF_API_URL || 'https://api.pdfshift.io/v3/convert/pdf' }}",
"method": "POST",
"options": {
"response": {}
},
"sendBody": true,
"sendHeaders": true,
"bodyParameters": {
"parameters": [
{}
]
},
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Authorization",
"value": "Basic {{ $env.PDF_API_KEY }}"
}
]
}
},
"typeVersion": 4
},
{
"id": "9b88a23b-b415-4f2c-b818-a12a6e5c2bf6",
"name": "Enviar Correo al Cliente",
"type": "n8n-nodes-base.emailSend",
"position": [
128,
48
],
"webhookId": "f33ab465-57d0-48db-ae94-3f6d2b37c930",
"parameters": {
"html": "=Dear {{ $json.customerName }},<br><br>Thank you for your business! Please find your invoice attached.<br><br><strong>Invoice Details:</strong><br>• Invoice Number: {{ $json.invoiceNumber }}<br>• Date: {{ $json.invoiceDate }}<br>• Due Date: {{ $json.dueDate }}<br>• Amount Due: ${{ $json.totalAmount }}<br><br><strong>Payment Terms:</strong><br>{{ $json.paymentTerms }}<br><br>If you have questions, contact us at {{ $json.companyEmail }}<br><br>Best regards,<br>{{ $json.companyName }}",
"options": {},
"subject": "Invoice {{ $json.invoiceNumber }} from {{ $json.companyName }}",
"toEmail": "={{ $json.customerEmail }}",
"fromEmail": "={{ $env.COMPANY_EMAIL }}",
"emailFormat": "html"
},
"typeVersion": 2
},
{
"id": "5279d3ca-eff7-45dc-bcc6-41f85bbe2bb6",
"name": "Guardar en Google Drive",
"type": "n8n-nodes-base.googleDrive",
"position": [
128,
176
],
"parameters": {
"name": "={{ $json.filename }}",
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "list",
"value": "root",
"cachedResultName": "/ (Root folder)"
}
},
"typeVersion": 3
},
{
"id": "629c75bd-88a2-4ea7-a3dc-5450387d6378",
"name": "Respuesta de Éxito",
"type": "n8n-nodes-base.code",
"position": [
352,
112
],
"parameters": {
"jsCode": "return {\n success: true,\n message: 'Invoice generated and sent successfully',\n invoiceNumber: $json.invoiceNumber,\n customerEmail: $json.customerEmail,\n totalAmount: $json.totalAmount,\n filename: $json.filename,\n timestamp: new Date().toISOString(),\n emailSent: true,\n savedToDrive: true\n};"
},
"typeVersion": 2
},
{
"id": "921ff838-cd75-4f5b-9b29-9d96fbcac947",
"name": "Responder Webhook",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
576,
112
],
"parameters": {
"options": {
"responseCode": 200
},
"respondWith": "json",
"responseBody": "={{ $json }}"
},
"typeVersion": 1
},
{
"id": "0c4bb277-7fe4-419c-bee0-69dede34a59e",
"name": "Nota adhesiva1",
"type": "n8n-nodes-base.stickyNote",
"position": [
96,
320
],
"parameters": {
"width": 214,
"height": 224,
"content": "☁️ **SAVE TO DRIVE**\n\n- Uploads PDF to Google Drive\n- Organized folder structure\n- Automated file naming\n- Backup for accounting records\n- Secure cloud storage"
},
"typeVersion": 1
},
{
"id": "be43dfc4-8068-44db-bbcb-f81dc86d2162",
"name": "Nota adhesiva2",
"type": "n8n-nodes-base.stickyNote",
"position": [
32,
-208
],
"parameters": {
"width": 214,
"height": 240,
"content": "📧 **SENDS TO CUSTOMER**\n\n- Emails PDF invoice to customer\n- Professional email template\n- Includes payment instructions\n- Attachment with generated PDF\n- Confirms delivery status"
},
"typeVersion": 1
},
{
"id": "84e365dd-a54a-4ce0-a273-ae8cbfb9bf93",
"name": "Nota adhesiva3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-208,
-160
],
"parameters": {
"width": 214,
"height": 256,
"content": "📄 **INVOICE GENERATION**\n\n- Creates professional HTML template\n- Applies company branding & colors\n- Builds itemized table with pricing\n- Adds payment terms and due dates\n- Includes company contact details"
},
"typeVersion": 1
},
{
"id": "3673840a-5ac8-48ec-af6a-c30db464e73d",
"name": "Nota adhesiva4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-448,
-144
],
"parameters": {
"width": 214,
"height": 256,
"content": "⚙️ **PREPARING INVOICE**\n\n- Extracts customer data from webhook\n- Validates required fields (email, items)\n- Calculates line totals and subtotals\n- Applies tax rates (default 10%)\n- Formats dates and invoice numbers"
},
"typeVersion": 1
}
],
"pinData": {},
"connections": {
"7fe430f5-e516-4f3f-9ffd-d82e3a3db05a": {
"main": [
[
{
"node": "9b88a23b-b415-4f2c-b818-a12a6e5c2bf6",
"type": "main",
"index": 0
},
{
"node": "5279d3ca-eff7-45dc-bcc6-41f85bbe2bb6",
"type": "main",
"index": 0
}
]
]
},
"353da029-1514-40d0-969b-bcd2816bdbcc": {
"main": [
[
{
"node": "d3c566ba-582b-4e17-b30d-580c5e617630",
"type": "main",
"index": 0
}
]
]
},
"629c75bd-88a2-4ea7-a3dc-5450387d6378": {
"main": [
[
{
"node": "921ff838-cd75-4f5b-9b29-9d96fbcac947",
"type": "main",
"index": 0
}
]
]
},
"d3c566ba-582b-4e17-b30d-580c5e617630": {
"main": [
[
{
"node": "659c77de-7c5c-4a49-9525-07b0106460da",
"type": "main",
"index": 0
}
]
]
},
"5279d3ca-eff7-45dc-bcc6-41f85bbe2bb6": {
"main": [
[
{
"node": "629c75bd-88a2-4ea7-a3dc-5450387d6378",
"type": "main",
"index": 0
}
]
]
},
"659c77de-7c5c-4a49-9525-07b0106460da": {
"main": [
[
{
"node": "7fe430f5-e516-4f3f-9ffd-d82e3a3db05a",
"type": "main",
"index": 0
}
]
]
},
"9b88a23b-b415-4f2c-b818-a12a6e5c2bf6": {
"main": [
[
{
"node": "629c75bd-88a2-4ea7-a3dc-5450387d6378",
"type": "main",
"index": 0
}
]
]
}
}
}¿Cómo usar este flujo de trabajo?
Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.
¿En qué escenarios es adecuado este flujo de trabajo?
Intermedio - Varios, IA Multimodal
¿Es de pago?
Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.
Flujos de trabajo relacionados recomendados
Ibrahim Emre POLAT
@epolatSenior Software Developer specializing in automation and integrations with n8n. Experienced in .NET, PostgreSQL, and cloud-native systems. Continuously learning new tools and technologies to deliver efficient, scalable workflows.
Compartir este flujo de trabajo