{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "ab1b7d2d-7eac-45eb-9e0a-36f14c56df14",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -560,
        384
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "c8e4edfe-cdb8-49ce-a2f8-fc1b96fb72ac",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1088,
        -416
      ],
      "parameters": {
        "width": 400,
        "height": 1056,
        "content": "\n## \u2699\ufe0f Setup Instructions\n\n### 1\ufe0f\u20e3 Connect Google Sheets\n1. Copy this [Invoice Template Sheet](https://docs.google.com/spreadsheets/d/1a6QBIQkr7RsZtUZBi87NwhwgTbnr5hQl4J_ZOkr3F1U/edit?usp=drivesdk) into your own Drive  \n2. In **n8n \u2192 Credentials \u2192 New \u2192 Google Sheets (OAuth2)**  \n   - Log in with your Google account and save  \n3. In the workflow, select your **Spreadsheet ID** and **Worksheet (Sheet1)** in the **Google Sheets node**  \n\n---\n\n### 2\ufe0f\u20e3 Connect PDF.co\n1. Create a free account at [PDF.co](https://pdf.co/)  \n2. Copy your **API Key** from the dashboard  \n3. In **n8n \u2192 Credentials \u2192 New \u2192 PDF.co API**  \n   - Paste your API Key \u2192 **Save**  \n4. In the **PDF.co node**, select your credential and choose the **HTML Template to PDF** operation  \n\n---\n\n### 3\ufe0f\u20e3 Create Your PDF.co HTML Template\n1. In your [PDF.co dashboard](https://app.pdf.co/), go to **Templates \u2192 New Template**  \n2. Paste in the HTML from the template section below  \n3. Save the template and copy its **Template ID**  \n4. Replace the `templateId` in the workflow with your new ID  \n\n---\n\n## \ud83d\udcec Contact\nNeed help customizing this (e.g., filter by sender, auto-reply, or Slack notifications)?  \n\n\ud83d\udce7 **robert@ynteractive.com**  \n\ud83d\udd17 **[Robert Breen](https://www.linkedin.com/in/robert-breen-29429625/)**  \n\ud83c\udf10 **[ynteractive.com](https://ynteractive.com)**\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "13bf89d7-6c1d-4859-b1f2-78eb49ea3d80",
      "name": "Sticky Note51",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -640,
        -416
      ],
      "parameters": {
        "color": 7,
        "width": 1376,
        "height": 1056,
        "content": "# \ud83d\udccb Generate PDF Invoices from Google Sheets with PDF.co\n\nThis workflow automatically **pulls invoice rows from Google Sheets** and generates a **PDF invoice** using a PDF.co template.  \nPerfect for small businesses that manage invoices in Sheets but need professional, ready-to-send PDFs.\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "34da303a-56f4-46c8-867b-f4d8e26ccbc3",
      "name": "Get Invoice Rows",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -320,
        384
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1a6QBIQkr7RsZtUZBi87NwhwgTbnr5hQl4J_ZOkr3F1U/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1a6QBIQkr7RsZtUZBi87NwhwgTbnr5hQl4J_ZOkr3F1U",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1a6QBIQkr7RsZtUZBi87NwhwgTbnr5hQl4J_ZOkr3F1U/edit?usp=drivesdk",
          "cachedResultName": "Invoice Template"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "c824838a-3512-44c9-bc8d-06b5ceae13ab",
      "name": "Convert to html import",
      "type": "n8n-nodes-base.code",
      "position": [
        0,
        -16
      ],
      "parameters": {
        "jsCode": "// n8n Code node (JavaScript)\n// Input: Google Sheets rows (each row as an item) OR one item whose .json is an array of rows.\n// Output: ONE item with root-level fields ready for PDF.co Mustache template.\n\nconst INVOICE_PREFIX = 'INV-2025-';\nconst TAX_RATE = 0.00;          // set >0 if you want tax (e.g., 0.07 for 7%)\nconst DISCOUNT = 0.00;          // flat discount amount\nconst TERMS = 'Net 14. Thank you for your business!';\nconst NOTES = 'Please reference the invoice number on payment.';\n\n// ---- Helpers\nconst fmtUSD = (n) => {\n  const v = Number(n || 0);\n  return v.toLocaleString('en-US', { style: 'currency', currency: 'USD' });\n};\nconst toNum = (v) => {\n  if (v === null || v === undefined || v === '') return 0;\n  const n = Number(String(v).replace(/[^0-9.\\-]/g, ''));\n  return Number.isFinite(n) ? n : 0;\n};\n\n// ---- Get rows from input (supports both shapes)\nconst items = $input.all();\nlet rows = [];\nif (items.length === 1 && Array.isArray(items[0].json)) {\n  rows = items[0].json;\n} else {\n  rows = items.map(i => i.json);\n}\n\n// ---- Normalize & filter valid rows\nconst clean = rows\n  .map((r) => ({\n    Description: r.Description ?? r.description ?? '',\n    Qty: toNum(r.Qty ?? r.qty),\n    Price: toNum(r.Price ?? r.price),\n    Total: toNum(r.Total ?? r.total), // will recompute if missing\n    Company: r.Company ?? r.company ?? '',\n    Address: r.Address ?? r.address ?? '',\n    Email: r.Email ?? r.email ?? ''\n  }))\n  .filter(r => r.Description && (r.Qty > 0) && (r.Price > 0 || r.Total > 0));\n\n// ---- Bill-to (use first non-empty)\nconst first = clean.find(r => r.Company || r.Address || r.Email) || {};\nconst billTo = {\n  name: first.Company || 'Customer',\n  address: first.Address || '',\n  email: first.Email || ''\n};\n\n// ---- Build line items & totals\nlet subTotal = 0;\nconst itemsOut = clean.map((r, idx) => {\n  const lineTotal = r.Total > 0 ? r.Total : (r.Qty * r.Price);\n  subTotal += lineTotal;\n  return {\n    line: idx + 1,\n    description: r.Description,\n    qty: r.Qty,\n    unitPriceFmt: fmtUSD(r.Price),\n    lineTotalFmt: fmtUSD(lineTotal)\n  };\n});\n\nconst taxAmount = subTotal * TAX_RATE;\nconst grandTotal = subTotal + taxAmount - DISCOUNT;\n\n// ---- Dates & invoice number\nconst today = new Date();\nconst invoiceDate = today.toISOString().slice(0, 10);\nconst due = new Date(today.getTime() + 14 * 24 * 60 * 60 * 1000).toISOString().slice(0, 10);\nconst invoiceNumber = INVOICE_PREFIX + String(Math.floor(10000 + Math.random() * 90000));\n\n// ---- Final payload (root-level keys for your Mustache template)\nconst out = {\n  invoiceNumber,\n  invoiceDate,\n  dueDate: due,\n  company: {\n    name: 'Ynteractive, LLC',\n    address: '123 Main Street, Palmyra, PA 17078',\n    phone: '111-111-1111',\n    email: 'user@example.com',\n    logoUrl: 'https://via.placeholder.com/160x50?text=Ynteractive'\n  },\n  billTo,\n  items: itemsOut,\n  subTotalFmt: fmtUSD(subTotal),\n  taxRatePct: (TAX_RATE * 100).toFixed(2) + '%',\n  taxAmountFmt: fmtUSD(taxAmount),\n  discountFmt: fmtUSD(DISCOUNT),\n  totalFmt: fmtUSD(grandTotal),\n  notes: NOTES,\n  terms: TERMS\n};\n\nreturn [out];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "bf3fef3e-7dea-4444-8892-8ad2f64f0a55",
      "name": "Create  PDF",
      "type": "n8n-nodes-pdfco.PDFco Api",
      "position": [
        352,
        256
      ],
      "parameters": {
        "operation": "URL/HTML to PDF",
        "templateId": "12010",
        "convertType": "htmlTemplateToPDF",
        "templateData": "={{ JSON.stringify($json) }}\n",
        "advancedOptions": {}
      },
      "credentials": {
        "pdfcoApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "14ce82c1-8abd-420a-bb8b-27d10fd7131d",
      "name": "Sticky Note57",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -384,
        64
      ],
      "parameters": {
        "color": 3,
        "width": 224,
        "height": 464,
        "content": "### 2\ufe0f\u20e3 Connect PDF.co\n1. Create a free account at [PDF.co](https://pdf.co/)  \n2. Copy your **API Key** from the dashboard  \n3. In **n8n \u2192 Credentials \u2192 New \u2192 PDF.co API**  \n   - Paste your API Key \u2192 **Save**  \n4. In the **PDF.co node**, select your credential and choose the **HTML Template to PDF** operation  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "e2a7370a-34f2-488e-84e8-94ae7fb4663a",
      "name": "Sticky Note58",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        256,
        -256
      ],
      "parameters": {
        "color": 3,
        "width": 288,
        "height": 624,
        "content": "### 2\ufe0f\u20e3 Connect PDF.co\n1. Create a free account at [PDF.co](https://pdf.co/)  \n2. Copy your **API Key** from the dashboard  \n3. In **n8n \u2192 Credentials \u2192 New \u2192 PDF.co API**  \n   - Paste your API Key \u2192 **Save**  \n4. In the **PDF.co node**, select your credential and choose the **HTML Template to PDF** operation  \n\n---\n\n### 3\ufe0f\u20e3 Create Your PDF.co HTML Template\n1. In your [PDF.co dashboard](https://app.pdf.co/), go to **Templates \u2192 New Template**  \n2. Paste in the HTML from the template section below  \n3. Save the template and copy its **Template ID**  \n4. Replace the `templateId` in the workflow with your new ID  \n\n---\n"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Get Invoice Rows": {
      "main": [
        [
          {
            "node": "Convert to html import",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert to html import": {
      "main": [
        [
          {
            "node": "Create  PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Get Invoice Rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}