Dynamischer Sitzplatz- und Veranstaltungsort-Planer
Dies ist ein Miscellaneous-Bereich Automatisierungsworkflow mit 18 Nodes. Hauptsächlich werden Code, Webhook, GoogleSheets, RespondToWebhook und andere Nodes verwendet. Dynamische Sitz- und Raumplanung mit Google Sheets erstellen
- •HTTP Webhook-Endpunkt (wird von n8n automatisch generiert)
- •Google Sheets API-Anmeldedaten
Verwendete Nodes (18)
Kategorie
{
"id": "XOs7YXaXmcGasosl",
"meta": {
"instanceId": "dd69efaf8212c74ad206700d104739d3329588a6f3f8381a46a481f34c9cc281",
"templateCredsSetupCompleted": true
},
"name": "Dynamic Seating & Venue Layout Planner",
"tags": [],
"nodes": [
{
"id": "6ebed595-6ce0-4738-9350-639fe6eaa8dc",
"name": "Webhook-Trigger Trigger",
"type": "n8n-nodes-base.webhook",
"position": [
-1584,
336
],
"webhookId": "seating-planner-webhook",
"parameters": {
"path": "seating-planner",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2
},
{
"id": "f9099584-6f17-4392-ba9f-4819eefc857c",
"name": "Notiz - Trigger",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1648,
-112
],
"parameters": {
"color": 4,
"width": 208,
"height": 696,
"content": "## Trigger Seating Request\n\nReceives venue requirements and attendee data via webhook.\n\nExpected payload:\n{\n \"eventType\": \"Conference/Wedding/Banquet\",\n \"venueCapacity\": 500,\n \"attendeeCount\": 350,\n \"layoutPreference\": \"Theater/Classroom/Banquet\"\n}"
},
"typeVersion": 1
},
{
"id": "c7e2cfc4-5c30-4a37-9481-b08a7c338759",
"name": "Anfragedaten validieren",
"type": "n8n-nodes-base.code",
"position": [
-1360,
336
],
"parameters": {
"jsCode": "// Validate and parse incoming request\nconst payload = $input.first().json.body || $input.first().json;\n\nconst requestData = {\n eventType: payload.eventType || \"Conference\",\n venueCapacity: parseInt(payload.venueCapacity) || 500,\n attendeeCount: parseInt(payload.attendeeCount) || 350,\n layoutPreference: payload.layoutPreference || \"Theater\",\n venueDimensions: payload.venueDimensions || { width: 30, length: 40 }, // in meters\n specialRequirements: payload.specialRequirements || [],\n accessibilityNeeds: parseInt(payload.accessibilityNeeds) || 10,\n vipCount: parseInt(payload.vipCount) || 0,\n requestId: payload.requestId || `seat-${Date.now()}`,\n timestamp: new Date().toISOString()\n};\n\n// Validate capacity\nif (requestData.attendeeCount > requestData.venueCapacity) {\n return {\n json: {\n error: true,\n message: \"Attendee count exceeds venue capacity\",\n requestData\n }\n };\n}\n\nreturn { json: requestData };"
},
"typeVersion": 2
},
{
"id": "493e8a46-496a-4169-a6bf-6527169feba3",
"name": "Teilnehmerdaten abrufen",
"type": "n8n-nodes-base.googleSheets",
"position": [
-1136,
192
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultName": "Attendees"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_SPREADSHEET_ID",
"cachedResultName": "Venue Data"
},
"authentication": "serviceAccount"
},
"credentials": {
"googleApi": {
"id": "ScSS2KxGQULuPtdy",
"name": "Google Sheets- test"
}
},
"typeVersion": 4
},
{
"id": "b93eb9e9-f6fa-451c-aec8-c510b30fc57f",
"name": "Notiz - Daten abrufen",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1408,
-112
],
"parameters": {
"color": 3,
"width": 176,
"height": 688,
"content": "## Fetch Attendee Data\n\nRetrieve attendee information including names, groups, accessibility needs, and VIP status from Google Sheets."
},
"typeVersion": 1
},
{
"id": "afa08e18-f492-4d0a-a818-91c914180cf3",
"name": "Veranstaltungsort-Vorlagen abrufen",
"type": "n8n-nodes-base.googleSheets",
"position": [
-1136,
480
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=1",
"cachedResultName": "Venue Layouts"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_SPREADSHEET_ID",
"cachedResultName": "Venue Data"
},
"authentication": "serviceAccount"
},
"credentials": {
"googleApi": {
"id": "ScSS2KxGQULuPtdy",
"name": "Google Sheets- test"
}
},
"typeVersion": 4
},
{
"id": "3134f27d-2601-4599-a4d7-4627c06833a3",
"name": "Alle Daten kombinieren",
"type": "n8n-nodes-base.code",
"position": [
-912,
336
],
"parameters": {
"jsCode": "// Combine all data for processing\nconst requestData = $input.all()[0].json;\nconst attendees = $input.all()[1].json;\nconst venueTemplates = $input.all()[2].json;\n\n// Structure combined data\nconst combinedData = {\n request: requestData,\n attendees: Array.isArray(attendees) ? attendees : [attendees],\n venueTemplates: Array.isArray(venueTemplates) ? venueTemplates : [venueTemplates],\n processingTimestamp: new Date().toISOString()\n};\n\nreturn { json: combinedData };"
},
"typeVersion": 2
},
{
"id": "fcc3ef45-7cea-4b8f-976d-34a945785bdb",
"name": "Notiz - Berechnen",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1168,
-192
],
"parameters": {
"color": 5,
"width": 192,
"height": 864,
"content": "## Calculate Totals\n\nAggregate attendee data, venue constraints, and layout requirements for optimal planning."
},
"typeVersion": 1
},
{
"id": "55f73cc6-3003-4ff9-b202-e333b86afdcb",
"name": "Sitzplatzlayout optimieren",
"type": "n8n-nodes-base.code",
"position": [
-688,
336
],
"parameters": {
"jsCode": "const data = $input.first().json;\nconst request = data.request;\nconst attendees = data.attendees;\nconst templates = data.venueTemplates;\n\n// Select appropriate layout template\nfunction selectLayoutTemplate(eventType, layoutPref, templates) {\n const template = templates.find(t => \n t.eventType === eventType && t.layoutType === layoutPref\n ) || templates[0] || {\n layoutType: layoutPref,\n seatsPerRow: 20,\n rowSpacing: 1.2,\n aisleWidth: 1.5,\n stageDepth: 5\n };\n \n return template;\n}\n\n// Calculate optimal layout dimensions\nfunction calculateLayout(attendeeCount, venueSize, template) {\n const seatsPerRow = template.seatsPerRow || 20;\n const totalRows = Math.ceil(attendeeCount / seatsPerRow);\n const rowSpacing = template.rowSpacing || 1.2;\n const aisleWidth = template.aisleWidth || 1.5;\n \n // Calculate number of aisles needed\n const aislesNeeded = Math.floor(seatsPerRow / 10);\n \n // Calculate actual width needed\n const seatWidth = 0.6; // meters\n const widthNeeded = (seatsPerRow * seatWidth) + (aislesNeeded * aisleWidth);\n const lengthNeeded = (totalRows * rowSpacing) + (template.stageDepth || 5);\n \n return {\n totalRows,\n seatsPerRow,\n aislesNeeded,\n dimensions: {\n width: widthNeeded,\n length: lengthNeeded\n },\n feasible: widthNeeded <= venueSize.width && lengthNeeded <= venueSize.length\n };\n}\n\n// Group attendees by type\nfunction categorizeAttendees(attendees) {\n const vips = attendees.filter(a => a.vipStatus === true || a.type === 'VIP');\n const accessibility = attendees.filter(a => a.accessibility === true || a.accessibilityNeeds);\n const groups = {};\n \n attendees.forEach(a => {\n const group = a.group || a.company || 'General';\n if (!groups[group]) groups[group] = [];\n groups[group].push(a);\n });\n \n return { vips, accessibility, groups };\n}\n\n// Generate seating assignments\nfunction generateSeatingPlan(layout, categorized, totalAttendees) {\n const seatingPlan = [];\n let currentRow = 1;\n let currentSeat = 1;\n \n // Assign VIPs to front rows\n categorized.vips.forEach((vip, index) => {\n seatingPlan.push({\n attendeeId: vip.id || vip.name,\n attendeeName: vip.name,\n section: 'VIP',\n row: Math.floor(index / layout.seatsPerRow) + 1,\n seat: (index % layout.seatsPerRow) + 1,\n type: 'VIP',\n notes: vip.notes || ''\n });\n });\n \n // Reserve accessible seating near aisles\n let accessibleSeatsAssigned = 0;\n categorized.accessibility.forEach((person, index) => {\n const rowNum = Math.floor(layout.totalRows / 2) + Math.floor(index / 2);\n seatingPlan.push({\n attendeeId: person.id || person.name,\n attendeeName: person.name,\n section: 'Accessible',\n row: rowNum,\n seat: index % 2 === 0 ? 1 : layout.seatsPerRow, // Aisle seats\n type: 'Accessible',\n notes: person.accessibilityNeeds || 'Wheelchair accessible'\n });\n accessibleSeatsAssigned++;\n });\n \n // Assign groups together\n let generalSeatCounter = categorized.vips.length;\n Object.keys(categorized.groups).forEach(groupName => {\n const groupMembers = categorized.groups[groupName];\n \n groupMembers.forEach((member, index) => {\n // Skip if already assigned (VIP or accessible)\n if (seatingPlan.find(s => s.attendeeId === (member.id || member.name))) {\n return;\n }\n \n const rowNum = Math.floor(generalSeatCounter / layout.seatsPerRow) + 1;\n const seatNum = (generalSeatCounter % layout.seatsPerRow) + 1;\n \n seatingPlan.push({\n attendeeId: member.id || member.name,\n attendeeName: member.name,\n section: 'General',\n row: rowNum,\n seat: seatNum,\n type: 'Group',\n group: groupName,\n notes: member.notes || ''\n });\n \n generalSeatCounter++;\n });\n });\n \n return seatingPlan;\n}\n\n// Main processing\nconst template = selectLayoutTemplate(\n request.eventType,\n request.layoutPreference,\n templates\n);\n\nconst layout = calculateLayout(\n request.attendeeCount,\n request.venueDimensions,\n template\n);\n\nconst categorized = categorizeAttendees(attendees);\nconst seatingPlan = generateSeatingPlan(layout, categorized, request.attendeeCount);\n\n// Calculate statistics\nconst stats = {\n totalSeats: layout.totalRows * layout.seatsPerRow,\n assignedSeats: seatingPlan.length,\n availableSeats: (layout.totalRows * layout.seatsPerRow) - seatingPlan.length,\n utilizationRate: ((seatingPlan.length / (layout.totalRows * layout.seatsPerRow)) * 100).toFixed(2),\n vipSeats: categorized.vips.length,\n accessibleSeats: categorized.accessibility.length,\n groupCount: Object.keys(categorized.groups).length\n};\n\n// Generate output\nconst result = {\n requestId: request.requestId,\n timestamp: new Date().toISOString(),\n eventType: request.eventType,\n layoutType: request.layoutPreference,\n venue: {\n capacity: request.venueCapacity,\n dimensions: request.venueDimensions,\n feasible: layout.feasible\n },\n layout: {\n totalRows: layout.totalRows,\n seatsPerRow: layout.seatsPerRow,\n aisles: layout.aislesNeeded,\n calculatedDimensions: layout.dimensions\n },\n seatingPlan: seatingPlan,\n statistics: stats,\n visualMap: generateVisualMap(layout, seatingPlan)\n};\n\n// Generate ASCII visual map\nfunction generateVisualMap(layout, seating) {\n const map = [];\n map.push('\\n=== VENUE LAYOUT MAP ===\\n');\n map.push('[STAGE]'.padStart(layout.seatsPerRow * 2, ' '));\n map.push('\\n');\n \n for (let row = 1; row <= layout.totalRows; row++) {\n let rowStr = `R${row.toString().padStart(2, '0')} `;\n \n for (let seat = 1; seat <= layout.seatsPerRow; seat++) {\n const assignment = seating.find(s => s.row === row && s.seat === seat);\n \n if (assignment) {\n if (assignment.type === 'VIP') rowStr += 'V ';\n else if (assignment.type === 'Accessible') rowStr += 'A ';\n else rowStr += 'X ';\n } else {\n rowStr += '○ ';\n }\n \n // Add aisle\n if (seat % 10 === 0 && seat !== layout.seatsPerRow) {\n rowStr += '| ';\n }\n }\n \n map.push(rowStr);\n }\n \n map.push('\\n\\nLegend: V=VIP | A=Accessible | X=Assigned | ○=Available\\n');\n \n return map.join('\\n');\n}\n\nreturn { json: result };"
},
"typeVersion": 2
},
{
"id": "241cbdaf-4e19-4243-8bff-000f8543ed52",
"name": "Notiz - Optimieren",
"type": "n8n-nodes-base.stickyNote",
"position": [
-928,
-112
],
"parameters": {
"width": 352,
"height": 752,
"content": "## AI Optimization\n\nUse algorithms to calculate optimal seating based on:\n- Venue dimensions\n- Attendee groups\n- Accessibility needs\n- VIP placement\n- Aisle placement"
},
"typeVersion": 1
},
{
"id": "cd660d9f-7d3c-4593-8ae9-d854f6cbc514",
"name": "Empfehlungen formatieren",
"type": "n8n-nodes-base.code",
"position": [
-464,
336
],
"parameters": {
"jsCode": "const layoutData = $input.first().json;\n\n// Format recommendations in natural language\nconst recommendations = [];\n\nif (!layoutData.venue.feasible) {\n recommendations.push('⚠️ WARNING: Current layout exceeds venue dimensions. Consider reducing seats per row or attendee count.');\n}\n\nif (layoutData.statistics.utilizationRate > 95) {\n recommendations.push('⚠️ High capacity utilization. Consider adding buffer space for comfort.');\n}\n\nif (layoutData.statistics.utilizationRate < 70) {\n recommendations.push('✓ Good space utilization with room for comfort and movement.');\n}\n\nif (layoutData.layout.aisles < 2) {\n recommendations.push('💡 Consider adding more aisles for better traffic flow.');\n}\n\nif (layoutData.statistics.accessibleSeats > 0) {\n recommendations.push(`✓ ${layoutData.statistics.accessibleSeats} accessible seats reserved near aisles.`);\n}\n\nif (layoutData.statistics.vipSeats > 0) {\n recommendations.push(`✓ ${layoutData.statistics.vipSeats} VIP seats assigned in front rows.`);\n}\n\nrecommendations.push(`✓ ${layoutData.statistics.groupCount} groups seated together for better networking.`);\n\n// Create formatted output\nconst formattedOutput = {\n ...layoutData,\n recommendations: recommendations,\n summary: `Successfully generated seating plan for ${layoutData.statistics.assignedSeats} attendees in ${layoutData.layout.totalRows} rows with ${layoutData.statistics.availableSeats} buffer seats.`,\n exportReady: true\n};\n\nreturn { json: formattedOutput };"
},
"typeVersion": 2
},
{
"id": "2e43af7a-7d3c-4077-b15d-b86a0b83a962",
"name": "Notiz - Formatieren",
"type": "n8n-nodes-base.stickyNote",
"position": [
-560,
32
],
"parameters": {
"color": 3,
"height": 528,
"content": "## Format Recommendations\n\nStructure seating plan with:\n- Visual layout map\n- Seat assignments\n- Statistics & metrics\n- Optimization tips"
},
"typeVersion": 1
},
{
"id": "3b5e5ec2-317b-4977-bdbf-0b3536e20b3e",
"name": "Masterplan speichern",
"type": "n8n-nodes-base.googleSheets",
"position": [
-224,
96
],
"parameters": {
"columns": {
"value": {},
"schema": [],
"mappingMode": "autoMapInputData",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=2",
"cachedResultName": "Seating Plans"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_SPREADSHEET_ID",
"cachedResultName": "Venue Data"
},
"authentication": "serviceAccount"
},
"credentials": {
"googleApi": {
"id": "ScSS2KxGQULuPtdy",
"name": "Google Sheets- test"
}
},
"typeVersion": 4
},
{
"id": "acfda3e7-b8ab-4d29-aba4-a616f3fb2cdb",
"name": "Einzelne Zuordnungen speichern",
"type": "n8n-nodes-base.googleSheets",
"position": [
-16,
528
],
"parameters": {
"columns": {
"mappingMode": "autoMapInputData"
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=3",
"cachedResultName": "Seat Assignments"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_SPREADSHEET_ID",
"cachedResultName": "Venue Data"
},
"authentication": "serviceAccount"
},
"credentials": {
"googleApi": {
"id": "ScSS2KxGQULuPtdy",
"name": "Google Sheets- test"
}
},
"typeVersion": 4
},
{
"id": "6cdcdd87-3938-46f7-856e-47da5213884d",
"name": "Notiz - Speichern",
"type": "n8n-nodes-base.stickyNote",
"position": [
-256,
288
],
"parameters": {
"color": 2,
"width": 368,
"height": 436,
"content": "## Update Sheets\n\nSave seating plan to Google Sheets:\n- Master plan summary\n- Individual seat assignments\n- Layout specifications"
},
"typeVersion": 1
},
{
"id": "9f0f8821-d72a-440b-958d-2cf4ee20f553",
"name": "Antwort senden",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
-224,
-80
],
"parameters": {
"options": {
"responseCode": 200,
"responseHeaders": {
"entries": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json, null, 2) }}"
},
"typeVersion": 1
},
{
"id": "126e21b6-1913-452d-bd8e-c65c4109aab5",
"name": "Notiz - Antwort",
"type": "n8n-nodes-base.stickyNote",
"position": [
-288,
-304
],
"parameters": {
"color": 5,
"width": 272,
"height": 576,
"content": "## Send Alert\n\nReturn complete seating plan with:\n- Visual layout map\n- Seat assignments list\n- Statistics & recommendations\n- Export-ready format"
},
"typeVersion": 1
},
{
"id": "7ae9a9d9-a170-4a1f-aca5-37d393ba9938",
"name": "Sitzplatzzuordnungen aufteilen",
"type": "n8n-nodes-base.code",
"position": [
-240,
528
],
"parameters": {
"jsCode": "const layoutData = $input.first().json;\n\n// Split seating plan into individual seat records\nconst seatAssignments = layoutData.seatingPlan.map(seat => ({\n requestId: layoutData.requestId,\n timestamp: layoutData.timestamp,\n attendeeId: seat.attendeeId,\n attendeeName: seat.attendeeName,\n section: seat.section,\n row: seat.row,\n seat: seat.seat,\n type: seat.type,\n group: seat.group || '',\n notes: seat.notes || ''\n}));\n\nreturn seatAssignments.map(seat => ({ json: seat }));"
},
"typeVersion": 2
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "d1d5db44-9513-485d-8c2b-4a480fe4190e",
"connections": {
"Webhook Trigger": {
"main": [
[
{
"node": "c7e2cfc4-5c30-4a37-9481-b08a7c338759",
"type": "main",
"index": 0
}
]
]
},
"3134f27d-2601-4599-a4d7-4627c06833a3": {
"main": [
[
{
"node": "55f73cc6-3003-4ff9-b202-e333b86afdcb",
"type": "main",
"index": 0
}
]
]
},
"493e8a46-496a-4169-a6bf-6527169feba3": {
"main": [
[
{
"node": "3134f27d-2601-4599-a4d7-4627c06833a3",
"type": "main",
"index": 0
}
]
]
},
"afa08e18-f492-4d0a-a818-91c914180cf3": {
"main": [
[
{
"node": "3134f27d-2601-4599-a4d7-4627c06833a3",
"type": "main",
"index": 0
}
]
]
},
"c7e2cfc4-5c30-4a37-9481-b08a7c338759": {
"main": [
[
{
"node": "493e8a46-496a-4169-a6bf-6527169feba3",
"type": "main",
"index": 0
},
{
"node": "afa08e18-f492-4d0a-a818-91c914180cf3",
"type": "main",
"index": 0
},
{
"node": "3134f27d-2601-4599-a4d7-4627c06833a3",
"type": "main",
"index": 0
}
]
]
},
"cd660d9f-7d3c-4593-8ae9-d854f6cbc514": {
"main": [
[
{
"node": "9f0f8821-d72a-440b-958d-2cf4ee20f553",
"type": "main",
"index": 0
},
{
"node": "3b5e5ec2-317b-4977-bdbf-0b3536e20b3e",
"type": "main",
"index": 0
},
{
"node": "7ae9a9d9-a170-4a1f-aca5-37d393ba9938",
"type": "main",
"index": 0
}
]
]
},
"7ae9a9d9-a170-4a1f-aca5-37d393ba9938": {
"main": [
[
{
"node": "acfda3e7-b8ab-4d29-aba4-a616f3fb2cdb",
"type": "main",
"index": 0
}
]
]
},
"55f73cc6-3003-4ff9-b202-e333b86afdcb": {
"main": [
[
{
"node": "cd660d9f-7d3c-4593-8ae9-d854f6cbc514",
"type": "main",
"index": 0
}
]
]
}
}
}Wie verwende ich diesen Workflow?
Kopieren Sie den obigen JSON-Code, erstellen Sie einen neuen Workflow in Ihrer n8n-Instanz und wählen Sie "Aus JSON importieren". Fügen Sie die Konfiguration ein und passen Sie die Anmeldedaten nach Bedarf an.
Für welche Szenarien ist dieser Workflow geeignet?
Experte - Verschiedenes
Ist es kostenpflichtig?
Dieser Workflow ist völlig kostenlos. Beachten Sie jedoch, dass Drittanbieterdienste (wie OpenAI API), die im Workflow verwendet werden, möglicherweise kostenpflichtig sind.
Verwandte Workflows
Oneclick AI Squad
@oneclick-aiThe AI Squad Initiative is a pioneering effort to build, automate and scale AI-powered workflows using n8n.io. Our mission is to help individuals and businesses integrate AI agents seamlessly into their daily operations from automating tasks and enhancing productivity to creating innovative, intelligent solutions. We design modular, reusable AI workflow templates that empower creators, developers and teams to supercharge their automation with minimal effort and maximum impact.
Diesen Workflow teilen