8
n8n 한국어amn8n.com

GPT-4o-mini를 사용하여 Gmail에서 Google Sheets로 호텔 예약 요청 자동화

고급

이것은Document Extraction, AI Summarization분야의자동화 워크플로우로, 29개의 노드를 포함합니다.주로 If, Set, Code, Gmail, Filter 등의 노드를 사용하며. GPT-4o-mini를 통해 Gmail의 호텔 예약 요청을 Google Sheets에 자동 입력

사전 요구사항
  • Google 계정 및 Gmail API 인증 정보
  • Google Sheets API 인증 정보
  • OpenAI API Key
워크플로우 미리보기
노드 연결 관계를 시각적으로 표시하며, 확대/축소 및 이동을 지원합니다
워크플로우 내보내기
다음 JSON 구성을 복사하여 n8n에 가져오면 이 워크플로우를 사용할 수 있습니다
{
  "meta": {
    "instanceId": "9229062b09b690c4ccf0cfe4e3838e59180e8646ff632ec42c3b984a473da8ae"
  },
  "nodes": [
    {
      "id": "13cf7be4-2d3e-4e58-b4d7-409f107197c1",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        80,
        1056
      ],
      "parameters": {
        "color": 2,
        "width": 528,
        "height": 976,
        "content": "## Error Notification\n\n![Data Flow Diagram](https://i.postimg.cc/tRvgMXT2/Screenshot-2025-11-07-at-00-54-22.png#full-width)"
      },
      "typeVersion": 1
    },
    {
      "id": "bc3df21f-0a08-49dd-aab6-4f1b0452c252",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "color": 3,
        "width": 464,
        "height": 592,
        "content": "## Confirmation Email\n\n![Data Flow Diagram](https://i.postimg.cc/X7yn1dtV/Screenshot-2025-11-07-at-00-36-19.png#full-width)"
      },
      "typeVersion": 1
    },
    {
      "id": "1d59ebc0-245d-4b58-b8a1-ec396761f5c5",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1344,
        336
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 304,
        "content": "### 3. Workflow configuration\n- Add your **google sheet ID*\n- Add the **email address** you want error notifications sent to."
      },
      "typeVersion": 1
    },
    {
      "id": "16372fd9-9526-454e-8c86-e8e2156e9aea",
      "name": "이메일 텍스트용 OpenAI 모델",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -1504,
        1200
      ],
      "parameters": {
        "text": "={{ $('Get many messages (1)').item.json.text }}",
        "options": {
          "systemMessage": "You are a hotel booking specialist AI. Extract booking information from emails and return ONLY a valid JSON object.\n\nCRITICAL INSTRUCTIONS:\n1. Look for booking details anywhere in the email text\n2. Extract numbers from phrases like \"55 rooms\" or \"Number of Rooms: 55\"\n3. Parse dates in any format and convert to YYYY-MM-DD\n4. If a field is not found, use null\n5. Return ONLY the JSON object - no explanations\n\nREQUIRED JSON STRUCTURE:\n{\n  \"travel_agency_name\": \"string or null\",\n  \"contact_person\": \"string or null\",\n  \"contact_email\": \"string or null\",\n  \"contact_phone\": \"string or null\",\n  \"number_of_rooms\": number,\n  \"check_in_date\": \"YYYY-MM-DD or null\",\n  \"check_out_date\": \"YYYY-MM-DD or null\",\n  \"room_type\": \"string or null\",\n  \"special_requests\": \"string or null\",\n  \"total_guests\": number,\n  \"booking_reference\": \"string or null\",\n  \"urgency\": \"urgent or normal or low\"\n}"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.9,
      "continueOnFail": true
    },
    {
      "id": "64a15364-f803-41bf-a4db-88fdda710e60",
      "name": "PDF용 OpenAI 모델",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -1504,
        848
      ],
      "parameters": {
        "text": "={{ $json.text }}",
        "options": {
          "systemMessage": "You are a hotel booking specialist AI. Extract booking information from the PDF attachment and return ONLY a valid JSON object.\n\nCRITICAL INSTRUCTIONS:\n1. Look for booking details anywhere in the document\n2. Extract numbers from phrases like \"55 rooms\" or \"Number of Rooms: 55\"\n3. Parse dates in any format and convert to YYYY-MM-DD\n4. If a field is not found, use null\n5. Return ONLY the JSON object - no explanations\n\nREQUIRED JSON STRUCTURE:\n{\n  \"travel_agency_name\": \"string or null\",\n  \"contact_person\": \"string or null\",\n  \"contact_email\": \"string or null\",\n  \"contact_phone\": \"string or null\",\n  \"number_of_rooms\": number,\n  \"check_in_date\": \"YYYY-MM-DD or null\",\n  \"check_out_date\": \"YYYY-MM-DD or null\",\n  \"room_type\": \"string or null\",\n  \"special_requests\": \"string or null\",\n  \"total_guests\": number,\n  \"booking_reference\": \"string or null\",\n  \"urgency\": \"urgent or normal or low\"\n}"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.9,
      "continueOnFail": true
    },
    {
      "id": "dae2d85e-4b36-4520-a89d-d2509688dcb1",
      "name": "OpenAI GPT 모델 (이메일)",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -1504,
        1344
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {
          "temperature": 0.3,
          "responseFormat": "json_object"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "43353dbd-5112-44e4-ac85-331f7612e359",
      "name": "OpenAI GPT 모델 (첨부파일)",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -1504,
        976
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {
          "temperature": 0.3,
          "responseFormat": "json_object"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "6ebca2d8-b73d-4ec8-8546-f48083fbc135",
      "name": "성공 메트릭 로깅",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        608,
        672
      ],
      "parameters": {
        "columns": {
          "value": {
            "case_id": "={{ $('Apply Business Rules').item.json.case_id }}",
            "priority": "={{ $('Apply Business Rules').item.json.priority }}",
            "timestamp": "={{ $today }}",
            "email_sent": "={{ $('Send Confirmation Email').item.json.error ? 'No' : 'Yes' }}",
            "assigned_team": "={{ $('Apply Business Rules').item.json.assigned_team }}",
            "sheets_updated": "Yes",
            "number_of_rooms": "={{ $('Apply Business Rules').item.json.number_of_rooms }}",
            "processing_time_seconds": "={{ Math.round(($execution.startedAt ? (Date.now() - new Date($execution.startedAt).getTime()) / 1000 : 0)) }}"
          },
          "schema": [
            {
              "id": "timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "case_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "case_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "processing_time_seconds",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "processing_time_seconds",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "assigned_team",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "assigned_team",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "priority",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "priority",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "number_of_rooms",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "number_of_rooms",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email_sent",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email_sent",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "sheets_updated",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "sheets_updated",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Success Metrics"
        },
        "documentId": {
          "__rl": true,
          "mode": "expression",
          "value": "={{ $('Configuration: User Settings').item.json.gSheetID }}"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "b395a72e-e78d-4200-9e72-130a8e885e41",
      "name": "확인 이메일 전송",
      "type": "n8n-nodes-base.gmail",
      "position": [
        240,
        672
      ],
      "webhookId": "ad57867a-a7b8-4c06-a446-cb47bc70da57",
      "parameters": {
        "sendTo": "={{ $json.contact_email }}",
        "message": "=<html>\n<body style=\"font-family: Arial, sans-serif; line-height: 1.6; color: #333;\">\n\t<div style=\"max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #ddd;\">\n\t\t<h2 style=\"color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 10px;\">Booking Request Confirmation</h2>\n\t\t\n\t\t<p>Dear {{ $json.contact_person }},</p>\n\t\t\n\t\t<p>Thank yourself for your booking request. Your reservation has been received and is being processed by our <strong>{{ $json.assigned_team }}</strong>.</p>\n\t\t\n\t\t<div style=\"background-color: #f8f9fa; padding: 15px; border-radius: 5px; margin: 20px 0;\">\n\t\t\t<h3 style=\"color: #2c3e50; margin-top: 0;\">Booking Details</h3>\n\t\t\t<table style=\"width: 100%; border-collapse: collapse;\">\n\t\t\t\t<tr>\n\t\t\t\t\t<td style=\"padding: 5px 0;\"><strong>Case Reference:</strong></td>\n\t\t\t\t\t<td style=\"padding: 5px 0;\">{{ $json.case_id }}</td>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<td style=\"padding: 5px 0;\"><strong>Priority:</strong></td>\n\t\t\t\t\t<td style=\"padding: 5px 0;\"><span style=\"background-color: #{{ $json.priority === 'High' ? 'e74c3c' : $json.priority === 'Medium' ? 'f39c12' : '27ae60' }}; color: white; padding: 2px 8px; border-radius: 3px;\">{{ $json.priority }}</span></td>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<td style=\"padding: 5px 0;\"><strong>Number of Rooms:</strong></td>\n\t\t\t\t\t<td style=\"padding: 5px 0;\">{{ $json.number_of_rooms }}</td>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<td style=\"padding: 5px 0;\"><strong>Check-in Date:</strong></td>\n\t\t\t\t\t<td style=\"padding: 5px 0;\">{{ $json.check_in_date }}</td>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<td style=\"padding: 5px 0;\"><strong>Check-out Date:</strong></td>\n\t\t\t\t\t<td style=\"padding: 5px 0;\">{{ $json.check_out_date }}</td>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<td style=\"padding: 5px 0;\"><strong>Total Nights:</strong></td>\n\t\t\t\t\t<td style=\"padding: 5px 0;\">{{ $json.total_nights }}</td>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<td style=\"padding: 5px 0;\"><strong>Total Guests:</strong></td>\n\t\t\t\t\t<td style=\"padding: 5px 0;\">{{ $json.total_guests }}</td>\n\t\t\t\t</tr>\n\t\t\t</table>\n\t\t</div>\n\t\t\n\t\t<p><strong>Status:</strong> {{ $json.status }}</p>\n\t\t<p><strong>Booking Reference:</strong> {{ $json.booking_reference }}</p>\n\t\t\n\t\t<p style=\"margin-top: 20px;\">Our team will review your request and respond within <strong>24 hours</strong>.</p>\n\t\t\n\t\t<p>If you have any questions, please contact us at {{ $json.team_email }}</p>\n\t\t\n\t\t<p style=\"margin-top: 30px;\">Best regards,<br>\n\t\t<strong>Hotel Booking Team</strong></p>\n\t</div>\n</body>\n</html>",
        "options": {
          "appendAttribution": false
        },
        "subject": "=Booking Request Received - Ref #{{ $json.case_id }}"
      },
      "typeVersion": 2.1,
      "continueOnFail": true
    },
    {
      "id": "b3f06fe6-b8db-4828-a6b9-a7b8cc13ea02",
      "name": "팀 할당 로깅",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -16,
        864
      ],
      "parameters": {
        "columns": {
          "value": {
            "case_id": "={{ $json.case_id }}",
            "priority": "={{ $json.priority }}",
            "timestamp": "={{ $json.processed_date }}",
            "team_email": "={{ $json.team_email }}",
            "assigned_team": "={{ $json.assigned_team }}",
            "check_in_date": "={{ $json.check_in_date }}",
            "travel_agency": "={{ $json.travel_agency_name }}",
            "number_of_rooms": "={{ $json.number_of_rooms }}"
          },
          "schema": [
            {
              "id": "timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "case_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "case_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "assigned_team",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "assigned_team",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "team_email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "team_email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "priority",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "priority",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "number_of_rooms",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "number_of_rooms",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "travel_agency",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "travel_agency",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "check_in_date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "check_in_date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1858323773,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1qhUoE4baN5TyO51mD2caYU789XizhXl3UDCCT0v83So/edit#gid=1858323773",
          "cachedResultName": "Team Assignments"
        },
        "documentId": {
          "__rl": true,
          "mode": "expression",
          "value": "={{ $('Configuration: User Settings').item.json.gSheetID }}"
        }
      },
      "typeVersion": 4.5,
      "continueOnFail": true
    },
    {
      "id": "c49c023b-71b2-474f-a2ab-2444a3d4cc63",
      "name": "Cases 시트에 추가",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -16,
        672
      ],
      "parameters": {
        "columns": {
          "value": {
            "status": "={{ $json.status }}",
            "case_id": "={{ $json.case_id }}",
            "urgency": "={{ $json.urgency }}",
            "priority": "={{ $json.priority }}",
            "room_type": "={{ $json.room_type }}",
            "team_email": "={{ $json.team_email }}",
            "total_guests": "={{ $json.total_guests }}",
            "total_nights": "={{ $json.total_nights }}",
            "assigned_team": "={{ $json.assigned_team }}",
            "check_in_date": "={{ $json.check_in_date }}",
            "contact_email": "={{ $json.contact_email }}",
            "contact_phone": "={{ $json.contact_phone }}",
            "check_out_date": "={{ $json.check_out_date }}",
            "contact_person": "={{ $json.contact_person }}",
            "processed_date": "={{ $json.processed_date }}",
            "number_of_rooms": "={{ $json.number_of_rooms }}",
            "original_sender": "={{ $('Get many messages (1)').item.json.from.value[0].address }}",
            "original_subject": "={{ $('Look for incoming emails').item.json.Subject }}",
            "special_requests": "={{ $json.special_requests }}",
            "booking_reference": "={{ $json.booking_reference }}",
            "days_until_checkin": "={{ $json.days_until_checkin }}",
            "travel_agency_name": "={{ $json.travel_agency_name }}"
          },
          "schema": [
            {
              "id": "case_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "case_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "processed_date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "processed_date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "travel_agency_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "travel_agency_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "contact_person",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "contact_person",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "contact_email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "contact_email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "contact_phone",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "contact_phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "number_of_rooms",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "number_of_rooms",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "check_in_date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "check_in_date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "check_out_date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "check_out_date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "total_nights",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "total_nights",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "room_type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "room_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "total_guests",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "total_guests",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "special_requests",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "special_requests",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "booking_reference",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "booking_reference",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "urgency",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "urgency",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "assigned_team",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "assigned_team",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "team_email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "team_email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "priority",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "priority",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "days_until_checkin",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "days_until_checkin",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "original_sender",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "original_sender",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "original_subject",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "original_subject",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1qhUoE4baN5TyO51mD2caYU789XizhXl3UDCCT0v83So/edit#gid=0",
          "cachedResultName": "Cases"
        },
        "documentId": {
          "__rl": true,
          "mode": "expression",
          "value": "={{ $('Configuration: User Settings').item.json.gSheetID }}"
        }
      },
      "typeVersion": 4.5,
      "continueOnFail": true
    },
    {
      "id": "e756d1fe-fb7a-4731-8106-2d58a7141f13",
      "name": "비즈니스 규칙 적용",
      "type": "n8n-nodes-base.code",
      "position": [
        -480,
        752
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const bookingData = $json.validated_data;\n\nlet assignedTeam = \"\";\nlet teamEmail = \"\";\nlet priority = \"Normal\";\nlet status = \"New\";\n\nconst numRooms = parseInt(bookingData.number_of_rooms) || 0;\n\n// Rule 1: Assignment based on number of rooms\nif (numRooms >= 50) {\n\tassignedTeam = \"Large Bookings Team\";\n\tteamEmail = \"large-bookings@hotel.com\";\n\tpriority = \"High\";\n} else if (numRooms >= 20) {\n\tassignedTeam = \"Group Bookings Team\";\n\tteamEmail = \"group-bookings@hotel.com\";\n\tpriority = \"Medium\";\n} else {\n\tassignedTeam = \"Regular Bookings Team\";\n\tteamEmail = \"regular-bookings@hotel.com\";\n\tpriority = \"Normal\";\n}\n\n// Rule 2: Urgency override\nif (bookingData.urgency === \"urgent\") {\n\tpriority = \"High\";\n\tassignedTeam = \"Urgent Bookings Team\";\n\tteamEmail = \"urgent-bookings@hotel.com\";\n}\n\n// Rule 3: Check-in date proximity\nconst checkInDate = new Date(bookingData.check_in_date);\nconst today = new Date();\nconst daysUntilCheckIn = Math.ceil((checkInDate - today) / (1000 * 60 * 60 * 24));\n\nif (daysUntilCheckIn <= 7 && daysUntilCheckIn >= 0) {\n\tpriority = \"High\";\n\tstatus = \"Urgent - Near Check-in\";\n}\n\n// Rule 4: VIP Agencies\nconst vipAgencies = [\"Premium Travel Co\", \"Elite Bookings\", \"Luxury Tours\"];\nif (vipAgencies.some(agency => bookingData.travel_agency_name?.includes(agency))) {\n\tpriority = \"High\";\n\tassignedTeam = \"VIP Relations Team\";\n\tteamEmail = \"vip-relations@hotel.com\";\n}\n\n// Calculate total nights\nconst checkOutDate = new Date(bookingData.check_out_date);\nconst totalNights = Math.ceil((checkOutDate - checkInDate) / (1000 * 60 * 60 * 24));\n\n// Get original email info - FIXED LINE BELOW\nconst originalEmail = $('Look for incoming emails').item.json;\n\nreturn {\n\tjson: {\n\t\t// Extracted booking data\n\t\ttravel_agency_name: bookingData.travel_agency_name || \"N/A\",\n\t\tcontact_person: bookingData.contact_person || \"N/A\",\n\t\tcontact_email: bookingData.contact_email || \"N/A\",\n\t\tcontact_phone: bookingData.contact_phone || \"N/A\",\n\t\tnumber_of_rooms: numRooms,\n\t\tcheck_in_date: bookingData.check_in_date || \"N/A\",\n\t\tcheck_out_date: bookingData.check_out_date || \"N/A\",\n\t\ttotal_nights: totalNights || 0,\n\t\troom_type: bookingData.room_type || \"Standard\",\n\t\tspecial_requests: bookingData.special_requests || \"None\",\n\t\ttotal_guests: bookingData.total_guests || numRooms * 2,\n\t\tbooking_reference: bookingData.booking_reference || `BK${Date.now()}`,\n\t\turgency: bookingData.urgency || \"normal\",\n\t\t\n\t\t// Business rules output\n\t\tassigned_team: assignedTeam,\n\t\tteam_email: teamEmail,\n\t\tpriority: priority,\n\t\tstatus: status,\n\t\tdays_until_checkin: daysUntilCheckIn,\n\t\t\n\t\t// Metadata\n\t\tprocessed_date: new Date().toISOString(),\n\t\toriginal_subject: originalEmail.subject,\n\t\toriginal_sender: originalEmail.from,\n\t\tcase_id: `CASE-${Date.now()}`,\n\t\tprocessing_status: \"SUCCESS\"\n\t}\n};"
      },
      "typeVersion": 2,
      "continueOnFail": true
    },
    {
      "id": "a76e69e5-2df0-48c1-9cce-522a191e62da",
      "name": "오류 알림 전송",
      "type": "n8n-nodes-base.gmail",
      "position": [
        -144,
        1296
      ],
      "webhookId": "814ad124-75bd-4a92-8686-0b3729d263e5",
      "parameters": {
        "sendTo": "={{ $('Configuration: User Settings').item.json.adminEmailForErrors }}",
        "message": "=<html>\n<body style=\"font-family: Arial, sans-serif; line-height: 1.6; color: #333;\">\n\t<div style=\"max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #dc3545; border-radius: 5px;\">\n\t\t<h2 style=\"color: #dc3545; border-bottom: 2px solid #dc3545; padding-bottom: 10px;\">⚠️ Booking Processing Error</h2>\n\t\t\n\t\t<div style=\"background-color: #f8d7da; padding: 15px; border-radius: 5px; margin: 20px 0; border-left: 4px solid #dc3545;\">\n\t\t\t<h3 style=\"color: #721c24; margin-top: 0;\">Error Details</h3>\n\t\t\t<p><strong>Error Type:</strong> {{ $json.error_type }}</p>\n\t\t\t<p><strong>Error Message:</strong> {{ $json.error_message }}</p>\n\t\t\t<p><strong>Timestamp:</strong> {{ $json.timestamp }}</p>\n\t\t</div>\n\t\t\n\t\t<div style=\"background-color: #fff3cd; padding: 15px; border-radius: 5px; margin: 20px 0; border-left: 4px solid #ffc107;\">\n\t\t\t<h3 style=\"color: #856404; margin-top: 0;\">Original Email Information</h3>\n\t\t\t<p><strong>From:</strong> {{ $('Get many messages (1)').item.json.from.value[0].address|| 'N/A' }}</p>\n\t\t\t<p><strong>Subject:</strong> {{ $('Get many messages (1)').item.json.subject|| 'N/A' }}</p>\n\t\t\t<p><strong>Date:</strong> {{ $('Get many messages (1)').item.json.headers.date || 'N/A' }}</p>\n\t\t\t<p><strong>Snippet:</strong> {{ $('Look for incoming emails').item.json.snippet|| 'N/A' }}</p>\n\t\t</div>\n\t\t\n\t\t<div style=\"background-color: #d1ecf1; padding: 15px; border-radius: 5px; margin: 20px 0; border-left: 4px solid #17a2b8;\">\n\t\t\t<h3 style=\"color: #0c5460; margin-top: 0;\">Extracted Data (if any)</h3>\n\t\t\t<pre style=\"background-color: white; padding: 10px; border-radius: 3px; overflow-x: auto;\">{{ JSON.stringify($json.extracted_data, null, 2) }}</pre>\n\t\t</div>\n\t\t\n\t\t<div style=\"margin-top: 20px; padding: 15px; background-color: #e7f3ff; border-radius: 5px;\">\n\t\t\t<h3 style=\"color: #004085; margin-top: 0;\">Action Required</h3>\n\t\t\t<p>Please review this email manually and process the booking request.</p>\n\t\t\t<p><strong>Workflow Execution ID:</strong> {{ $execution.id }}</p>\n\t\t</div>\n\t\t\n\t\t<p style=\"margin-top: 30px; font-size: 12px; color: #666;\">This is an automated alert from the Hotel Booking Workflow System.</p>\n\t</div>\n</body>\n</html>",
        "options": {
          "appendAttribution": false
        },
        "subject": "=⚠️ Booking Processing Error - {{ $json.error_type }}"
      },
      "typeVersion": 2.1
    },
    {
      "id": "a47aa97a-decd-4219-9642-c2d6c0e4ef29",
      "name": "시트에 오류 로깅",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -480,
        1296
      ],
      "parameters": {
        "columns": {
          "value": {
            "timestamp": "={{ $json.timestamp }}",
            "Error Type": "={{ $json.error_type }}",
            "error_type": "={{ $json.error_type }}",
            "email_snippet": "={{ $('Look for incoming emails').item.json.snippet }}",
            "error_message": "={{ $json.error_message }}",
            "extracted_data": "={{ $json.extracted_data }}",
            "original_sender": "={{ $('Look for incoming emails').item.json.From }}",
            "original_subject": "={{ $('Look for incoming emails').item.json.Subject }}",
            "workflow_execution_id": "={{ $workflow.id }}"
          },
          "schema": [
            {
              "id": "timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "error_type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "error_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "error_message",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "error_message",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "original_subject",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "original_subject",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "original_sender",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "original_sender",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email_snippet",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email_snippet",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "extracted_data",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "extracted_data",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "workflow_execution_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "workflow_execution_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Error Type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Error Type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Meaning",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Meaning",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Action Needed",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Action Needed",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 325369644,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1qhUoE4baN5TyO51mD2caYU789XizhXl3UDCCT0v83So/edit#gid=325369644",
          "cachedResultName": "Error Logs"
        },
        "documentId": {
          "__rl": true,
          "mode": "expression",
          "value": "={{ $('Configuration: User Settings').item.json.gSheetID }}"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "4516f99d-9d38-4bb8-8f42-cd1123a0724a",
      "name": "오류 확인",
      "type": "n8n-nodes-base.if",
      "position": [
        -880,
        1024
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "check-error",
              "operator": {
                "type": "boolean",
                "operation": "false"
              },
              "leftValue": "={{ $json.error_occurred }}",
              "rightValue": ""
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "48268a8c-9a75-45fb-afbb-c5782d6c8e7b",
      "name": "추출 검증",
      "type": "n8n-nodes-base.code",
      "position": [
        -1120,
        1024
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Check if AI extraction succeeded\nif ($json.error) {\n\treturn {\n\t\tjson: {\n\t\t\terror_occurred: true,\n\t\t\terror_type: \"AI_EXTRACTION_FAILED\",\n\t\t\terror_message: $json.error.message || \"AI extraction failed\",\n\t\t\toriginal_email: $('Get many messages (1)').item.json,\n\t\t\ttimestamp: new Date().toISOString()\n\t\t}\n\t};\n}\n\nif (!$json.output) {\n\treturn {\n\t\tjson: {\n\t\t\terror_occurred: true,\n\t\t\terror_type: \"NO_OUTPUT\",\n\t\t\terror_message: \"AI did not return any output\",\n\t\t\toriginal_email: $('Get many messages (1)').item.json,\n\t\t\ttimestamp: new Date().toISOString()\n\t\t}\n\t};\n}\n\ntry {\n\tlet bookingData;\n\t\n\tif (typeof $json.output === 'string') {\n\t\tbookingData = JSON.parse($json.output);\n\t} else {\n\t\tbookingData = $json.output;\n\t}\n\t\n\tconsole.log(\"Parsed booking data:\", JSON.stringify(bookingData, null, 2));\n\t\n\tconst requiredFields = ['travel_agency_name', 'number_of_rooms', 'check_in_date', 'check_out_date'];\n\tconst missingFields = [];\n\t\n\tfor (const field of requiredFields) {\n\t\tif (!bookingData[field] || bookingData[field] === null || bookingData[field] === \"null\" || bookingData[field] === \"\") {\n\t\t\tmissingFields.push(field);\n\t\t}\n\t}\n\t\n\tif (missingFields.length > 0) {\n\t\tconsole.log(\"Missing fields detected:\", missingFields);\n\t\treturn {\n\t\t\tjson: {\n\t\t\t\terror_occurred: true,\n\t\t\t\terror_type: \"MISSING_REQUIRED_FIELDS\",\n\t\t\t\terror_message: `Missing required fields: ${missingFields.join(', ')}`,\n\t\t\t\textracted_data: bookingData,\n\t\t\t\toriginal_email: $('Get many messages (1)').item.json,\n\t\t\t\ttimestamp: new Date().toISOString()\n\t\t\t}\n\t\t};\n\t}\n\t\n\tconst checkInDate = new Date(bookingData.check_in_date);\n\tconst checkOutDate = new Date(bookingData.check_out_date);\n\t\n\tif (isNaN(checkInDate.getTime()) || isNaN(checkOutDate.getTime())) {\n\t\tconsole.log(\"Invalid date format detected\");\n\t\treturn {\n\t\t\tjson: {\n\t\t\t\terror_occurred: true,\n\t\t\t\terror_type: \"INVALID_DATE_FORMAT\",\n\t\t\t\terror_message: \"Check-in or check-out date is invalid\",\n\t\t\t\textracted_data: bookingData,\n\t\t\t\toriginal_email: $('Get many messages (1)').item.json,\n\t\t\t\ttimestamp: new Date().toISOString()\n\t\t\t}\n\t\t};\n\t}\n\t\n\tif (checkOutDate <= checkInDate) {\n\t\tconsole.log(\"Date logic error detected\");\n\t\treturn {\n\t\t\tjson: {\n\t\t\t\terror_occurred: true,\n\t\t\t\terror_type: \"INVALID_DATE_LOGIC\",\n\t\t\t\terror_message: \"Check-out date must be after check-in date\",\n\t\t\t\textracted_data: bookingData,\n\t\t\t\toriginal_email: $('Get many messages (1)').item.json,\n\t\t\t\ttimestamp: new Date().toISOString()\n\t\t\t}\n\t\t};\n\t}\n\t\n\tconsole.log(\"Validation successful!\");\n\treturn {\n\t\tjson: {\n\t\t\terror_occurred: false,\n\t\t\tvalidated_data: bookingData\n\t\t}\n\t};\n\t\n} catch (error) {\n\tconsole.log(\"JSON parse error:\", error.message);\n\treturn {\n\t\tjson: {\n\t\t\terror_occurred: true,\n\t\t\terror_type: \"JSON_PARSE_ERROR\",\n\t\t\terror_message: error.message,\n\t\t\traw_output: $json.output,\n\t\t\toriginal_email: $('Get many messages (1)').item.json,\n\t\t\ttimestamp: new Date().toISOString()\n\t\t}\n\t};\n}"
      },
      "typeVersion": 2
    },
    {
      "id": "6af4f7e8-e23b-4ce5-9f08-5545f192af4e",
      "name": "첨부파일 데이터 추출",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -1920,
        976
      ],
      "parameters": {
        "options": {},
        "operation": "pdf",
        "binaryPropertyName": "={{ Object.keys($json.binary || {})[0] || 'attachment_0' }}"
      },
      "typeVersion": 1
    },
    {
      "id": "0c7b7738-c233-4c71-b02c-f8b0331aa0f0",
      "name": "첨부파일 확인",
      "type": "n8n-nodes-base.if",
      "position": [
        -1040,
        464
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "check-attachment",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ Object.keys($binary || {}).length }}",
              "rightValue": 0
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "61ea223c-c6b9-4e0f-a30c-d9bb33620a79",
      "name": "구성: 사용자 설정",
      "type": "n8n-nodes-base.set",
      "position": [
        -1264,
        464
      ],
      "parameters": {
        "values": {
          "string": [
            {
              "name": "gSheetID",
              "value": "1qhUoE4baN5TyO51mD2caYU789XizhXl3UDCCT0v83So"
            },
            {
              "name": "adminEmailForErrors",
              "value": "admin@hotel.com"
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "8aa4991f-6300-418d-b442-3540b8b48308",
      "name": "예약 이메일 필터링",
      "type": "n8n-nodes-base.filter",
      "position": [
        -1504,
        528
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "filter-booking-subject",
              "operator": {
                "type": "string",
                "operation": "contains",
                "caseSensitive": false
              },
              "leftValue": "={{ $json.subject }}",
              "rightValue": "Booking Request"
            },
            {
              "id": "107664b3-31f6-4df6-89ef-33fc5af78cce",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json.subject }}",
              "rightValue": "reservation"
            },
            {
              "id": "4de37c49-313a-4477-80cd-9553fde62f53",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.subject }}",
              "rightValue": "room request"
            },
            {
              "id": "839bc665-ad8b-469c-862c-d911418d66ae",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.subject }}",
              "rightValue": "accommondation"
            },
            {
              "id": "ec0fc23d-1083-4dac-a9ea-4c2a6eedb740",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.subject }}",
              "rightValue": "check-in"
            },
            {
              "id": "4e923cdb-6127-4068-80cf-6b5cd4ebc98c",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.subject }}",
              "rightValue": "boking"
            },
            {
              "id": "f6b9bf16-ad15-4e02-a78e-7e0b6a3adaf0",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.subject }}",
              "rightValue": "reserv"
            },
            {
              "id": "77152b7b-6e55-494f-9e12-3e99c77570a6",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.subject }}",
              "rightValue": "booking"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "22027bbe-8ecf-4632-a856-3a5b23b8476c",
      "name": "여러 메시지 가져오기 (1)",
      "type": "n8n-nodes-base.gmail",
      "position": [
        -1712,
        528
      ],
      "webhookId": "2b7ef828-6a6d-4930-ab92-9670869a1f75",
      "parameters": {
        "limit": 1,
        "simple": false,
        "filters": {},
        "options": {
          "downloadAttachments": true
        },
        "operation": "getAll"
      },
      "typeVersion": 2.1
    },
    {
      "id": "69b7cb59-f2d9-4f7e-badc-19ac6555437d",
      "name": "수신 이메일 확인",
      "type": "n8n-nodes-base.gmailTrigger",
      "position": [
        -1936,
        528
      ],
      "parameters": {
        "filters": {
          "labelIds": [
            "INBOX"
          ]
        },
        "pollTimes": {
          "item": [
            {
              "mode": "everyHour"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "c1258b0a-561d-46f6-84f8-f5cc549382d5",
      "name": "Sticky Note24",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1168,
        752
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 400,
        "content": "## Validate the data and check for missing values\nChecks for:\n✓ Required fields present (agency, rooms, dates)\n✓ Valid date format (YYYY-MM-DD)\n✓ Check-out after check-in\n✓ No null/empty critical values\nErrors are caught and routed to error handler. "
      },
      "typeVersion": 1
    },
    {
      "id": "f469b629-e26a-44c9-aa2b-bc66f5bc2215",
      "name": "Sticky Note21",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -592,
        1184
      ],
      "parameters": {
        "color": 2,
        "width": 640,
        "height": 304,
        "content": "## ⚠️ Error Handling Flow\n### Any failures are logged and admins are notified"
      },
      "typeVersion": 1
    },
    {
      "id": "e13d1fb4-9d47-4aeb-a4d4-7f7a0383b0a9",
      "name": "Sticky Note20",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1968,
        752
      ],
      "parameters": {
        "color": 4,
        "width": 736,
        "height": 736,
        "content": "## Extract *data from PDF*\n### The Agent extracts the data from the attachment in mail and processes them. \nUses OpenAI GPT-4o-mini with JSON mode to extract:\n- Travel agency name, contact details\n- Room count, dates, guest count\n- Special requests, urgency level\nTemperature set to 0.3 for consistent extraction\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Extract *email body* \n"
      },
      "typeVersion": 1
    },
    {
      "id": "ec304ef1-5e6b-409c-a07a-e83c81efd08d",
      "name": "Sticky Note19",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1968,
        336
      ],
      "parameters": {
        "color": 5,
        "width": 608,
        "height": 352,
        "content": "## Mail extraction\n### Extract the mails thats have to do with booking or reservations.\n Filters emails by checking subject line for keywords:\n- \"Booking Request\", \"reservation\", \"room request\", \"accommodation\", \"check-in\", \"booking\"\nUses OR logic - any match proceeds to next step"
      },
      "typeVersion": 1
    },
    {
      "id": "56eb53d5-2cc4-4bc7-8706-c7645a167dce",
      "name": "Sticky Note18",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -592,
        576
      ],
      "parameters": {
        "color": 3,
        "width": 1056,
        "height": 432,
        "content": "## Log to *Case* and *Team Assignment* tables\n**- Make a copy of this sheet:**\nhttps://docs.google.com/spreadsheets/d/1qhUoE4baN5TyO51mD2caYU789XizhXl3UDCCT0v83So/edit?usp=sharing\n"
      },
      "typeVersion": 1
    },
    {
      "id": "8becac6c-0937-4c0c-b0b2-9f7c72267818",
      "name": "Sticky Note17",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        480,
        592
      ],
      "parameters": {
        "color": 6,
        "width": 352,
        "height": 248,
        "content": "## 📊 Success Metrics Logger"
      },
      "typeVersion": 1
    },
    {
      "id": "6c05a64f-0a42-4731-9c60-477695a52dbc",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2560,
        320
      ],
      "parameters": {
        "width": 496,
        "height": 1168,
        "content": "# 🏨 Automate hotel booking requests from Gmail to Google Sheets using AI\n\nThis workflow automates *hotel booking requests that come in through Gmail by instantly extracting data, intelligently routing it to a team, and tracking performance reliably*. it can be useful for hotels, travel agencies, or operations teams that want to avoid data entry. \n\n## How it Works (Core Flow)\n\nThe workflow runs hourly and scans your Gmail inbox for booking-related emails. It then utilizes the **OpenAI (GPT-4o-mini)** to extract key details from either the email body or attached PDFs and validates the fields and dates. Then comes the application of business rules for priority and team allocation based on room count or urgency.\n\n## Benefits of Automating\n\nThe process logs all successful bookings and assignments to Google Sheets across Cases, Team Assignments, and Success Metrics tabs. In the event of any failed extraction, strong error handling ensures the request is logged in the Error Log tab and an administrator is notified, hence ensuring that no request is ever lost.\n\n## ⚙️ Setup Requirements\n**3 Steps Credentials:** \n1) Add your Gmail, Google Sheets, and OpenAI (GPT-4o-mini) account credentials to n8n. \n\n2) Google Sheet: Duplicate the following template (link is available in the workflow description) within your Google Drive account. \n\n3) Configuration: **Update** the central \"Configuration: User Settings\" node with your copied Google Sheet ID and dedicated admin email address where error alerts should be sent.\n\n## 📋 Quick Setup Checklist\n1. ✅ Connect Gmail OAuth2 (Settings → Credentials)\n2. ✅ Connect Google Sheets OAuth2\n3. ✅ Add OpenAI API key\n4. ✅ Create Google Sheet with 4 tabs: Cases, Team Assignments, Error Logs, Success Metrics\n5. ✅ Update Configuration node with your settings\n6. ✅ Test with a sample booking email\n7. ✅ Adjust trigger frequency (default: hourly)"
      },
      "typeVersion": 1
    }
  ],
  "pinData": {},
  "connections": {
    "4516f99d-9d38-4bb8-8f42-cd1123a0724a": {
      "main": [
        [
          {
            "node": "e756d1fe-fb7a-4731-8106-2d58a7141f13",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "a47aa97a-decd-4219-9642-c2d6c0e4ef29",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a47aa97a-decd-4219-9642-c2d6c0e4ef29": {
      "main": [
        [
          {
            "node": "a76e69e5-2df0-48c1-9cce-522a191e62da",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "48268a8c-9a75-45fb-afbb-c5782d6c8e7b": {
      "main": [
        [
          {
            "node": "4516f99d-9d38-4bb8-8f42-cd1123a0724a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "e756d1fe-fb7a-4731-8106-2d58a7141f13": {
      "main": [
        [
          {
            "node": "b3f06fe6-b8db-4828-a6b9-a7b8cc13ea02",
            "type": "main",
            "index": 0
          },
          {
            "node": "c49c023b-71b2-474f-a2ab-2444a3d4cc63",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "0c7b7738-c233-4c71-b02c-f8b0331aa0f0": {
      "main": [
        [
          {
            "node": "6af4f7e8-e23b-4ce5-9f08-5545f192af4e",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "16372fd9-9526-454e-8c86-e8e2156e9aea",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "64a15364-f803-41bf-a4db-88fdda710e60": {
      "main": [
        [
          {
            "node": "48268a8c-9a75-45fb-afbb-c5782d6c8e7b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "c49c023b-71b2-474f-a2ab-2444a3d4cc63": {
      "main": [
        [
          {
            "node": "b395a72e-e78d-4200-9e72-130a8e885e41",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8aa4991f-6300-418d-b442-3540b8b48308": {
      "main": [
        [
          {
            "node": "61ea223c-c6b9-4e0f-a30c-d9bb33620a79",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "22027bbe-8ecf-4632-a856-3a5b23b8476c": {
      "main": [
        [
          {
            "node": "8aa4991f-6300-418d-b442-3540b8b48308",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6af4f7e8-e23b-4ce5-9f08-5545f192af4e": {
      "main": [
        [
          {
            "node": "64a15364-f803-41bf-a4db-88fdda710e60",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "b395a72e-e78d-4200-9e72-130a8e885e41": {
      "main": [
        [
          {
            "node": "6ebca2d8-b73d-4ec8-8546-f48083fbc135",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "69b7cb59-f2d9-4f7e-badc-19ac6555437d": {
      "main": [
        [
          {
            "node": "22027bbe-8ecf-4632-a856-3a5b23b8476c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "dae2d85e-4b36-4520-a89d-d2509688dcb1": {
      "ai_languageModel": [
        [
          {
            "node": "16372fd9-9526-454e-8c86-e8e2156e9aea",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "16372fd9-9526-454e-8c86-e8e2156e9aea": {
      "main": [
        [
          {
            "node": "48268a8c-9a75-45fb-afbb-c5782d6c8e7b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "61ea223c-c6b9-4e0f-a30c-d9bb33620a79": {
      "main": [
        [
          {
            "node": "0c7b7738-c233-4c71-b02c-f8b0331aa0f0",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "43353dbd-5112-44e4-ac85-331f7612e359": {
      "ai_languageModel": [
        [
          {
            "node": "64a15364-f803-41bf-a4db-88fdda710e60",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  }
}
자주 묻는 질문

이 워크플로우를 어떻게 사용하나요?

위의 JSON 구성 코드를 복사하여 n8n 인스턴스에서 새 워크플로우를 생성하고 "JSON에서 가져오기"를 선택한 후, 구성을 붙여넣고 필요에 따라 인증 설정을 수정하세요.

이 워크플로우는 어떤 시나리오에 적합한가요?

고급 - 문서 추출, AI 요약

유료인가요?

이 워크플로우는 완전히 무료이며 직접 가져와 사용할 수 있습니다. 다만, 워크플로우에서 사용하는 타사 서비스(예: OpenAI API)는 사용자 직접 비용을 지불해야 할 수 있습니다.

워크플로우 정보
난이도
고급
노드 수29
카테고리2
노드 유형11
난이도 설명

고급 사용자를 위한 16+개 노드의 복잡한 워크플로우

외부 링크
n8n.io에서 보기

이 워크플로우 공유

카테고리

카테고리: 34