{
  "name": "Lead Qualified → Mietvertrag PDF",
  "nodes": [
    {
      "parameters": {
        "triggerOnNotify": true,
        "channel": "lead_qualified",
        "additionalFields": {}
      },
      "id": "pg-trigger-mv",
      "name": "Postgres Trigger",
      "type": "n8n-nodes-base.postgresTrigger",
      "typeVersion": 1,
      "position": [250, 300],
      "credentials": {
        "postgres": {
          "id": "1",
          "name": "MC Cars Postgres"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT value FROM public.site_settings WHERE key = 'mietvertrag_template_path'",
        "additionalFields": {}
      },
      "id": "check-template",
      "name": "Check Template Exists",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [470, 300],
      "credentials": {
        "postgres": {
          "id": "1",
          "name": "MC Cars Postgres"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "cond1",
              "leftValue": "={{ $json.value }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "if-template-exists",
      "name": "Template Exists?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [670, 300]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT c.name, c.email, c.phone,\n       so.order_number, so.total_eur, so.deposit_eur,\n       so.date_from, so.date_to, so.vehicle_label,\n       so.daily_subtotal, so.weekend_subtotal,\n       so.subtotal_eur, so.vat_eur,\n       so.total_days, so.weekday_count, so.weekend_day_count,\n       to_char(so.date_from, 'DD.MM.YYYY') as date_from_de,\n       to_char(so.date_to, 'DD.MM.YYYY') as date_to_de,\n       to_char(now(), 'DD.MM.YYYY') as today_de\nFROM public.customers c\nJOIN public.sales_orders so ON so.customer_id = c.id\nWHERE so.id = '{{ $('Postgres Trigger').item.json.sales_order_id }}'::uuid",
        "additionalFields": {}
      },
      "id": "fetch-full-data",
      "name": "Fetch Full Order+Customer",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [890, 200],
      "credentials": {
        "postgres": {
          "id": "1",
          "name": "MC Cars Postgres"
        }
      }
    },
    {
      "parameters": {
        "url": "=http://kong:8000/storage/v1/object/document-templates/{{ $('Check Template Exists').item.json.value }}",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "={{ $env.SERVICE_ROLE_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU' }}"
            },
            {
              "name": "Authorization",
              "value": "=Bearer {{ $env.SERVICE_ROLE_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU' }}"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "id": "download-template",
      "name": "Download DOCX Template",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1110, 200]
    },
    {
      "parameters": {
        "jsCode": "// Fill DOCX template placeholders using simple text replacement.\n// The DOCX is a ZIP containing XML. We replace {{placeholder}} markers\n// in the document.xml with actual values from the order data.\n\nconst JSZip = require('jszip');\n\nconst binaryData = await this.helpers.getBinaryDataBuffer(0, 'data');\nconst orderData = $('Fetch Full Order+Customer').first().json;\n\n// Placeholders map\nconst placeholders = {\n  '{{KUNDE_NAME}}': orderData.name || '',\n  '{{KUNDE_EMAIL}}': orderData.email || '',\n  '{{KUNDE_TELEFON}}': orderData.phone || '',\n  '{{BESTELLNUMMER}}': orderData.order_number || '',\n  '{{FAHRZEUG}}': orderData.vehicle_label || '',\n  '{{DATUM_VON}}': orderData.date_from_de || '',\n  '{{DATUM_BIS}}': orderData.date_to_de || '',\n  '{{TAGE_GESAMT}}': String(orderData.total_days || 0),\n  '{{WOCHENTAGE}}': String(orderData.weekday_count || 0),\n  '{{WOCHENENDTAGE}}': String(orderData.weekend_day_count || 0),\n  '{{NETTO}}': String(orderData.subtotal_eur || 0),\n  '{{MWST}}': String(orderData.vat_eur || 0),\n  '{{GESAMT}}': String(orderData.total_eur || 0),\n  '{{KAUTION}}': String(orderData.deposit_eur || 0),\n  '{{TAGESSATZ}}': String(orderData.daily_subtotal || 0),\n  '{{WOCHENENDZUSCHLAG}}': String(orderData.weekend_subtotal || 0),\n  '{{DATUM_HEUTE}}': orderData.today_de || '',\n};\n\nconst zip = await JSZip.loadAsync(binaryData);\n\n// Process all XML files in the docx\nconst xmlFiles = Object.keys(zip.files).filter(f => f.endsWith('.xml'));\n\nfor (const xmlFile of xmlFiles) {\n  let content = await zip.file(xmlFile).async('string');\n  for (const [placeholder, value] of Object.entries(placeholders)) {\n    // Handle split placeholders in XML (Word splits text into runs)\n    // Simple approach: replace in the raw XML\n    const escaped = placeholder.replace(/[{}]/g, c => `\\\\${c}`);\n    content = content.split(placeholder).join(value);\n  }\n  zip.file(xmlFile, content);\n}\n\nconst filledDocx = await zip.generateAsync({ type: 'nodebuffer' });\n\nreturn [{\n  json: { filename: `Mietvertrag_${orderData.order_number}.docx` },\n  binary: {\n    data: await this.helpers.prepareBinaryData(filledDocx, `Mietvertrag_${orderData.order_number}.docx`, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document')\n  }\n}];"
      },
      "id": "fill-template",
      "name": "Fill DOCX Template",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [1330, 200]
    },
    {
      "parameters": {
        "url": "http://gotenberg:3000/forms/libreoffice/convert",
        "method": "POST",
        "sendBody": true,
        "contentType": "multipart-form-data",
        "bodyParameters": {
          "parameters": [
            {
              "parameterType": "formBinaryData",
              "name": "files",
              "inputDataFieldName": "data"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "id": "convert-to-pdf",
      "name": "Convert to PDF (Gotenberg)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1550, 200]
    },
    {
      "parameters": {
        "jsCode": "// Rename the binary output to have the correct PDF filename\nconst orderData = $('Fetch Full Order+Customer').first().json;\nconst binaryData = await this.helpers.getBinaryDataBuffer(0, 'data');\n\nreturn [{\n  json: { filename: `Mietvertrag_${orderData.order_number}.pdf`, email: orderData.email, name: orderData.name, order_number: orderData.order_number },\n  binary: {\n    data: await this.helpers.prepareBinaryData(binaryData, `Mietvertrag_${orderData.order_number}.pdf`, 'application/pdf')\n  }\n}];"
      },
      "id": "prepare-pdf",
      "name": "Prepare PDF Attachment",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [1770, 200]
    },
    {
      "parameters": {
        "fromEmail": "info@mc-cars.at",
        "toEmail": "={{ $json.email }}",
        "subject": "MC Cars – Ihr Mietvertrag {{ $json.order_number }}",
        "emailType": "html",
        "html": "<div style=\"font-family:Arial,sans-serif;max-width:600px;margin:0 auto;\">\n  <div style=\"background:#1a1a1a;padding:20px;text-align:center;\">\n    <h1 style=\"color:#c87941;margin:0;\">MC Cars</h1>\n  </div>\n  <div style=\"padding:30px;background:#f9f9f9;\">\n    <p>Sehr geehrte/r <strong>{{ $json.name }}</strong>,</p>\n    <p>anbei finden Sie Ihren Mietvertrag für die Bestellung <strong>{{ $json.order_number }}</strong>.</p>\n    <p>Bitte prüfen Sie die Angaben und bringen Sie den unterschriebenen Vertrag zur Fahrzeugübergabe mit.</p>\n    <hr style=\"border:none;border-top:1px solid #ddd;margin:25px 0;\" />\n    <p>Bei Fragen stehen wir Ihnen jederzeit zur Verfügung.</p>\n    <p>Mit freundlichen Grüßen,<br/><strong>MC Cars GmbH</strong><br/>info@mc-cars.at<br/>mc-cars.at</p>\n  </div>\n</div>",
        "options": {
          "attachments": "data"
        }
      },
      "id": "send-mietvertrag",
      "name": "Send Mietvertrag Email",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 2.1,
      "position": [1990, 200],
      "credentials": {
        "smtp": {
          "id": "2",
          "name": "MC Cars SMTP"
        }
      }
    }
  ],
  "connections": {
    "Postgres Trigger": {
      "main": [
        [
          {
            "node": "Check Template Exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Template Exists": {
      "main": [
        [
          {
            "node": "Template Exists?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Template Exists?": {
      "main": [
        [
          {
            "node": "Fetch Full Order+Customer",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Fetch Full Order+Customer": {
      "main": [
        [
          {
            "node": "Download DOCX Template",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download DOCX Template": {
      "main": [
        [
          {
            "node": "Fill DOCX Template",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fill DOCX Template": {
      "main": [
        [
          {
            "node": "Convert to PDF (Gotenberg)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert to PDF (Gotenberg)": {
      "main": [
        [
          {
            "node": "Prepare PDF Attachment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare PDF Attachment": {
      "main": [
        [
          {
            "node": "Send Mietvertrag Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [
    {
      "name": "mc-cars"
    }
  ],
  "triggerCount": 1
}
