Files
mc_cars_gmbh_infraestructure/n8n/workflows/01-qualification-payment-email.json
T
Lago f46ba8cadc feat(i18n): add VAT labels and email sent messages in German and English
style(admin): increase max-width of admin page and adjust table styles

fix(n8n): enhance workflow import and publishing process

fix(workflows): update SQL queries for fetching and updating sales orders

feat(migrations): normalize rental types and enhance email guard for individuell rentals

feat(migrations): add RPC for updating deposit in sales orders

fix(migrations): ensure individuell orders persist net/vat components and backfill existing records

test: update last run status to failed
2026-05-17 22:35:11 +02:00

230 lines
11 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"name": "Lead Qualified -> Payment Email",
"nodes": [
{
"parameters": {
"schema": {
"__rl": true,
"mode": "list",
"value": "public"
},
"tableName": {
"__rl": true,
"value": "sales_orders",
"mode": "list",
"cachedResultName": "sales_orders"
},
"additionalFields": {},
"options": {}
},
"id": "4337dcb2-b962-4bdb-8517-20e570016c05",
"name": "Postgres Trigger",
"type": "n8n-nodes-base.postgresTrigger",
"typeVersion": 1,
"position": [0, 0],
"credentials": {
"postgres": {
"id": "__POSTGRES_CREDENTIAL_ID__",
"name": "Postgres account"
}
}
},
{
"parameters": {
"operation": "executeQuery",
"query": "SELECT so.id, 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 so.rental_type\nFROM public.customers c\nJOIN public.sales_orders so ON so.customer_id = c.id\nWHERE so.id = '{{ $json.payload.id }}'::uuid\n AND coalesce(lower(trim(so.rental_type)), 'weekend') NOT IN ('individuell','individual','custom')",
"options": {}
},
"id": "ca4ca61e-fea9-4044-9586-216af016cb2e",
"name": "Fetch Order Data",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [224, 0],
"credentials": {
"postgres": {
"id": "__POSTGRES_CREDENTIAL_ID__",
"name": "Postgres account"
}
}
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const item = $json;\n\nconst formatEur = (value) => {\n const n = Number(value || 0);\n return new Intl.NumberFormat(\"de-AT\", { style: \"currency\", currency: \"EUR\" }).format(n);\n};\n\nconst formatDate = (value) => {\n if (!value) return \"-\";\n const d = new Date(value);\n if (Number.isNaN(d.getTime())) return String(value);\n return new Intl.DateTimeFormat(\"de-AT\", { day: \"2-digit\", month: \"2-digit\", year: \"numeric\" }).format(d);\n};\n\nconst orderNumber = item.order_number || \"\";\nconst dateFrom = formatDate(item.date_from);\nconst dateTo = formatDate(item.date_to);\nconst rentalRange = `${dateFrom} bis ${dateTo}`;\n\nconst depositEur = formatEur(item.deposit_eur);\nconst rentalEur = formatEur(item.total_eur);\nconst subtotalEur = formatEur(item.subtotal_eur);\nconst vatEur = formatEur(item.vat_eur);\n\nconst safeName = item.name || \"Kundin/Kunde\";\nconst vehicle = item.vehicle_label || \"-\";\n\nconst subject = `MC Cars Buchung bestätigt (${orderNumber}) Zahlungsinformationen`;\n\nconst paypalButton = (url, alt) => `\n <a href=\"${url}\" style=\"display:inline-block;text-decoration:none;\" target=\"_blank\" rel=\"noopener noreferrer\">\n <img src=\"https://www.paypalobjects.com/webstatic/en_US/i/buttons/checkout-logo-large.png\" alt=\"${alt}\" style=\"display:block;border:0;max-width:290px;width:100%;height:auto;\">\n </a>\n`;\n\nconst html = `\n<div style=\"margin:0;padding:24px;background:#f3f1ed;font-family:Arial,sans-serif;color:#151515;\">\n <table role=\"presentation\" style=\"width:100%;max-width:680px;margin:0 auto;border-collapse:collapse;background:#ffffff;border-radius:14px;overflow:hidden;\">\n <tr>\n <td style=\"background:#101010;padding:24px 28px;\">\n <div style=\"font-size:13px;letter-spacing:0.18em;text-transform:uppercase;color:#caa06a;\">MC Cars</div>\n <h1 style=\"margin:10px 0 0 0;font-size:24px;line-height:1.2;color:#ffffff;\">Ihre Miete wurde freigegeben</h1>\n </td>\n </tr>\n <tr>\n <td style=\"padding:28px;\">\n <p style=\"margin:0 0 14px 0;font-size:16px;\">Guten Tag <strong>${safeName}</strong>,</p>\n <p style=\"margin:0 0 18px 0;font-size:15px;line-height:1.6;\">\n Ihre Buchung wurde auf Basis der von Ihnen bereitgestellten Informationen geprüft und freigegeben.\n Nachfolgend finden Sie die Zahlungsanweisungen für Kaution und Mietbetrag.\n </p>\n\n <table role=\"presentation\" style=\"width:100%;border-collapse:collapse;background:#f8f8f8;border:1px solid #e8e8e8;border-radius:10px;overflow:hidden;margin:0 0 22px 0;\">\n <tr>\n <td style=\"padding:12px 14px;border-bottom:1px solid #e8e8e8;width:44%;color:#666;\">Bestellnummer</td>\n <td style=\"padding:12px 14px;border-bottom:1px solid #e8e8e8;\"><strong>${orderNumber}</strong></td>\n </tr>\n <tr>\n <td style=\"padding:12px 14px;border-bottom:1px solid #e8e8e8;width:44%;color:#666;\">Fahrzeug</td>\n <td style=\"padding:12px 14px;border-bottom:1px solid #e8e8e8;\">${vehicle}</td>\n </tr>\n <tr>\n <td style=\"padding:12px 14px;border-bottom:1px solid #e8e8e8;width:44%;color:#666;\">Mietzeitraum</td>\n <td style=\"padding:12px 14px;border-bottom:1px solid #e8e8e8;\">${rentalRange}</td>\n </tr>\n <tr>\n <td style=\"padding:12px 14px;border-bottom:1px solid #e8e8e8;width:44%;color:#666;\">Zwischensumme</td>\n <td style=\"padding:12px 14px;border-bottom:1px solid #e8e8e8;\">${subtotalEur}</td>\n </tr>\n <tr>\n <td style=\"padding:12px 14px;border-bottom:1px solid #e8e8e8;width:44%;color:#666;\">MwSt.</td>\n <td style=\"padding:12px 14px;border-bottom:1px solid #e8e8e8;\">${vatEur}</td>\n </tr>\n <tr>\n <td style=\"padding:12px 14px;border-bottom:1px solid #e8e8e8;width:44%;color:#666;\">Mietbetrag</td>\n <td style=\"padding:12px 14px;border-bottom:1px solid #e8e8e8;\"><strong>${rentalEur}</strong></td>\n </tr>\n <tr>\n <td style=\"padding:12px 14px;width:44%;color:#666;\">Kaution</td>\n <td style=\"padding:12px 14px;\"><strong>${depositEur}</strong></td>\n </tr>\n </table>\n\n <h2 style=\"margin:0 0 10px 0;font-size:18px;color:#101010;\">1) Kaution bezahlen</h2>\n <p style=\"margin:0 0 12px 0;font-size:14px;line-height:1.6;\">Sie können die Kaution in Höhe von <strong>${depositEur}</strong> per PayPal bezahlen:</p>\n ${paypalButton('__PAYPAL_KAUTION_LINK__', 'PayPal Kaution bezahlen')}\n <p style=\"margin:12px 0 0 0;font-size:14px;line-height:1.6;\">Alternativ ist Barzahlung möglich. In diesem Fall antworten Sie bitte so schnell wie möglich auf diese E-Mail, damit wir die Übergabe bestätigen können.</p>\n\n <h2 style=\"margin:22px 0 10px 0;font-size:18px;color:#101010;\">2) Mietbetrag bezahlen</h2>\n <p style=\"margin:0 0 12px 0;font-size:14px;line-height:1.6;\">Den Mietbetrag von <strong>${rentalEur}</strong> können Sie über folgenden PayPal-Button bezahlen:</p>\n ${paypalButton('__PAYPAL_MIETE_LINK__', 'PayPal Mietbetrag bezahlen')}\n\n <p style=\"margin:20px 0 6px 0;font-size:14px;line-height:1.6;\">Falls Sie Fragen haben, antworten Sie einfach auf diese E-Mail.</p>\n <p style=\"margin:0;font-size:14px;line-height:1.6;\">Freundliche Grüße<br><strong>MC Cars Team</strong></p>\n </td>\n </tr>\n </table>\n</div>`;\n\nreturn {\n toEmail: item.email,\n subject,\n html,\n};\n"
},
"id": "a39ba066-d093-4444-bd45-6a295d599637",
"name": "Build Payment Email",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [448, 0]
},
{
"parameters": {
"fromEmail": "office@mc-cars.at",
"toEmail": "={{ $json.toEmail }}",
"subject": "={{ $json.subject }}",
"html": "={{ $json.html }}",
"options": {
"appendAttribution": false
},
"continueOnFail": true
},
"id": "c537fb83-bc97-4015-b9fe-5ff3ca8b2c97",
"name": "Send Payment Email",
"type": "n8n-nodes-base.emailSend",
"typeVersion": 2.1,
"position": [672, 0],
"credentials": {
"smtp": {
"id": "__SMTP_CREDENTIAL_ID__",
"name": "SMTP account"
}
}
},
{
"parameters": {
"operation": "executeQuery",
"query": "UPDATE public.sales_orders SET email_sent = 1, updated_at = now() WHERE id = '{{ $('Fetch Order Data').item.json.id }}'::uuid",
"options": {}
},
"id": "update-email-sent-1",
"name": "Update email_sent = 1",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [1024, -100],
"credentials": {
"postgres": {
"id": "__POSTGRES_CREDENTIAL_ID__",
"name": "Postgres account"
}
}
},
{
"parameters": {
"operation": "executeQuery",
"query": "UPDATE public.sales_orders SET email_sent = 2, updated_at = now() WHERE id = '{{ $('Fetch Order Data').item.json.id }}'::uuid",
"options": {}
},
"id": "update-email-sent-2",
"name": "Update email_sent = 2",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [1024, 100],
"credentials": {
"postgres": {
"id": "__POSTGRES_CREDENTIAL_ID__",
"name": "Postgres account"
}
}
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "cond-email-error",
"leftValue": "={{ $json.error }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "notExists"
}
}
],
"combinator": "and"
}
},
"id": "check-email-error",
"name": "IF",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [896, 0]
}
],
"pinData": {},
"connections": {
"Postgres Trigger": {
"main": [
[
{
"node": "Fetch Order Data",
"type": "main",
"index": 0
}
]
]
},
"Fetch Order Data": {
"main": [
[
{
"node": "Build Payment Email",
"type": "main",
"index": 0
}
]
]
},
"Build Payment Email": {
"main": [
[
{
"node": "Send Payment Email",
"type": "main",
"index": 0
}
]
]
},
"Send Payment Email": {
"main": [
[
{
"node": "IF",
"type": "main",
"index": 0
}
]
]
},
"IF": {
"main": [
[
{
"node": "Update email_sent = 1",
"type": "main",
"index": 0
}
],
[
{
"node": "Update email_sent = 2",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {
"executionOrder": "v1",
"binaryMode": "separate"
},
"versionId": "814e8f72-95dc-4097-bc94-76fe437448ef",
"meta": {
"templateCredsSetupCompleted": true
},
"id": "rI1gUpcRXSikxWhi",
"tags": [
{
"name": "mc-cars"
}
]
}