{
  "id": "vXQVvjilXxhAPzos5ZyiM",
  "name": "Automated QR Ticket Scanner & Validator (Google Workspace)",
  "tags": [],
  "nodes": [
    {
      "id": "93c914d6-1eb4-4848-ae52-733775baf12e",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "width": 480,
        "height": 688,
        "content": "## Automated QR Ticket Scanner & Validator (Google Workspace)\n\n### How it works\n\n1. Triggers on new data in Google Sheets.\n2. Processes the last added item via code execution.\n3. Edits fields for ticket verification purposes.\n4. Switches logic based on validation results.\n5. Appends the result back to Google Sheets.\n\n### Setup steps\n\n- [ ] Set up Google Sheets API credentials for n8n.\n- [ ] Configure the Google Sheets Trigger node with appropriate spreadsheet ID and trigger conditions.\n- [ ] Ensure code nodes are configured appropriately to handle data logic.\n\n### Customization\n\nUsers can customize the code logic nodes to fit different ticket validation criteria."
      },
      "typeVersion": 1
    },
    {
      "id": "eecee609-ad41-4e58-921e-04aedd597f36",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        560,
        192
      ],
      "parameters": {
        "color": 7,
        "width": 496,
        "height": 304,
        "content": "## Trigger and initial processing\n\nHandles the trigger from Google Sheets and initial processing of data."
      },
      "typeVersion": 1
    },
    {
      "id": "9abcd7af-f668-4aef-a086-4ad8b7620cab",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1136,
        208
      ],
      "parameters": {
        "color": 7,
        "width": 816,
        "height": 272,
        "content": "## Edit fields and validation\n\nEdits fields for verification and retrieves rows for processing."
      },
      "typeVersion": 1
    },
    {
      "id": "dad7b561-2af3-480f-9a8f-eb7b237aee52",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2032,
        0
      ],
      "parameters": {
        "color": 7,
        "height": 336,
        "content": "## Append results to sheet\n\nProcesses data after switching logic and appends results back to Google Sheets."
      },
      "typeVersion": 1
    },
    {
      "id": "8df63b34-0d81-4eb5-a538-2b9b21cd4058",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2032,
        384
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 304,
        "content": "## Alternative processing and result appending\n\nHandles alternative logic flows and appends different results based on secondary criteria."
      },
      "typeVersion": 1
    },
    {
      "id": "53f3565a-9c09-466d-92ee-91e23b67e05a",
      "name": "Sheets Update Trigger",
      "type": "n8n-nodes-base.googleSheetsTrigger",
      "position": [
        608,
        320
      ],
      "parameters": {
        "event": "rowAdded",
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SHEET_NAME_HERE"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SPREADSHEET_ID_HERE"
        }
      },
      "credentials": {
        "googleSheetsTriggerOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5708359e-e981-41d0-9b16-086144253331",
      "name": "Read Trigger Sheet Rows",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1456,
        320
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{ $json.kode_tiket }}",
              "lookupColumn": "TIKET"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SHEET_NAME_HERE"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SPREADSHEET_ID_HERE"
        }
      },
      "typeVersion": 4.6,
      "alwaysOutputData": true
    },
    {
      "id": "5856b6da-5738-402b-bd6c-d10081a0d149",
      "name": "Append Scan Results",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2080,
        176
      ],
      "parameters": {
        "columns": {
          "value": {
            "ID": "={{ $json.ID }}",
            "NAMA": "={{ $json.NAMA }}",
            "EMAIL": "={{ $json.EMAIL }}",
            "NO HP": "={{ $json['NO HP'] }}",
            "TIKET": "={{ $json.TIKET }}",
            "STATUS": "VALID",
            "UKURAN JERSEY": "={{ $json['UKURAN JERSEY'] }}",
            "GOLONGAN DARAH": "={{ $json['GOLONGAN DARAH'] }}"
          },
          "schema": [],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SHEET_NAME_HERE"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SPREADSHEET_ID_HERE"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "ff1ef0bc-30af-4b9d-8d7c-5485511c153a",
      "name": "Append to Scan Results Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2512,
        512
      ],
      "parameters": {
        "columns": {
          "value": {
            "ID": "-",
            "NAMA": "-",
            "EMAIL": "-",
            "NO HP": "-",
            "TIKET": "={{ $json['QR code'] }}",
            "STATUS": "TIDAK VALID",
            "UKURAN JERSEY": "-",
            "GOLONGAN DARAH": "-"
          },
          "schema": [],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SHEET_NAME_HERE"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SPREADSHEET_ID_HERE"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "dc5de5de-9f6e-488b-84ca-67b96aabcbb0",
      "name": "Route by Conditional Rules",
      "type": "n8n-nodes-base.switch",
      "onError": "continueRegularOutput",
      "position": [
        1808,
        320
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "VALID",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "b8830042-b369-4f4e-a5e1-e8737674e753",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('Set Ticket Code Field').item.json.kode_tiket }}",
                    "rightValue": "={{ $json.TIKET }}"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "TIDAK VALID",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "6c17595d-df2e-497e-af29-6113741ce83e",
                    "operator": {
                      "type": "string",
                      "operation": "notEquals"
                    },
                    "leftValue": "={{ $('Set Ticket Code Field').item.json.kode_tiket }}",
                    "rightValue": "={{ $json.TIKET }}"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "executeOnce": false,
      "typeVersion": 3.2,
      "alwaysOutputData": true
    },
    {
      "id": "949136d9-3896-4a96-bf18-f02f49eb1080",
      "name": "Set Ticket Code Field",
      "type": "n8n-nodes-base.set",
      "position": [
        1184,
        320
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a01cbbcd-3b94-445a-89be-9310798d9019",
              "name": "kode_tiket",
              "type": "string",
              "value": "={{ $json['QR code'] }}"
            }
          ]
        }
      },
      "executeOnce": true,
      "typeVersion": 3.4
    },
    {
      "id": "9a6fea51-16c5-40f8-b81d-91d96344762a",
      "name": "Select Latest Item",
      "type": "n8n-nodes-base.code",
      "position": [
        912,
        320
      ],
      "parameters": {
        "jsCode": "// Ambil item terakhir (asumsi sudah disortir)\nconst rows = items;\nconst lastRow = rows[rows.length - 1]; \nreturn [lastRow];\nitems.sort((a, b) => new Date(a.json['Timestamp']) - new Date(b.json['Timestamp']));\nconst latest = items[items.length - 1];\nreturn [latest];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "7fbcd00e-98f2-435a-8469-35642a93a52f",
      "name": "Read Form Responses Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2080,
        512
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SHEET_NAME_HERE"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SPREADSHEET_ID_HERE"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "dda36884-25b5-402d-b8b3-3dec81b56918",
      "name": "Select Latest Form Response",
      "type": "n8n-nodes-base.code",
      "position": [
        2288,
        512
      ],
      "parameters": {
        "jsCode": "// Ambil item terakhir (asumsi sudah disortir)\nconst rows = items;\nconst lastRow = rows[rows.length - 1]; \nreturn [lastRow];\nitems.sort((a, b) => new Date(a.json['Timestamp']) - new Date(b.json['Timestamp']));\nconst latest = items[items.length - 1];\nreturn [latest];\n"
      },
      "typeVersion": 2
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "2538aaf5-4de4-4bc0-9fa2-19a3c2d27c80",
  "connections": {
    "Select Latest Item": {
      "main": [
        [
          {
            "node": "Set Ticket Code Field",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Ticket Code Field": {
      "main": [
        [
          {
            "node": "Read Trigger Sheet Rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sheets Update Trigger": {
      "main": [
        [
          {
            "node": "Select Latest Item",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Trigger Sheet Rows": {
      "main": [
        [
          {
            "node": "Route by Conditional Rules",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Form Responses Sheet": {
      "main": [
        [
          {
            "node": "Select Latest Form Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Conditional Rules": {
      "main": [
        [
          {
            "node": "Append Scan Results",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Read Form Responses Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Select Latest Form Response": {
      "main": [
        [
          {
            "node": "Append to Scan Results Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}