{
  "nodes": [
    {
      "id": "63cf5c9c-4716-4df7-ae3b-78b842fb9790",
      "name": "QuickBooks Find Customer",
      "type": "n8n-nodes-base.quickbooks",
      "position": [
        800,
        560
      ],
      "parameters": {
        "filters": {
          "query": "=WHERE DisplayName = '{{ $json[\"Customer Name\"] }}'"
        },
        "operation": "getAll",
        "returnAll": "={{ $('Get row(s) in sheet').item.json[\"Customer Account Number\"] }}"
      },
      "credentials": {
        "quickBooksOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "824b8f79-2364-4ac9-9d5c-bc224643f887",
      "name": "If Customer Exists?",
      "type": "n8n-nodes-base.if",
      "position": [
        1040,
        560
      ],
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $('Get row(s) in sheet').item.json[\"Customer Account Number\"] }}",
              "operation": "isEmpty"
            }
          ],
          "boolean": []
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5631c100-ef88-403a-8377-05490a67bf20",
      "name": "QuickBooks Create Customer",
      "type": "n8n-nodes-base.quickbooks",
      "position": [
        1200,
        640
      ],
      "parameters": {
        "operation": "create",
        "displayName": "={{ $('Get row(s) in sheet').item.json[\"Customer Name\"] }}",
        "additionalFields": {
          "CompanyName": "={{ $('Get row(s) in sheet').item.json[\"Company Name\"] }}",
          "PrimaryEmailAddr": "={{ $('Get row(s) in sheet').item.json.Email }}"
        }
      },
      "credentials": {
        "quickBooksOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "9baef671-798f-4609-b449-6571e6475ab2",
      "name": "QuickBooks Create Invoice",
      "type": "n8n-nodes-base.quickbooks",
      "position": [
        1440,
        544
      ],
      "parameters": {
        "Line": [
          {
            "Amount": "={{ $('Get row(s) in sheet').item.json.Quantity }}",
            "itemId": "2",
            "DetailType": "SalesItemLineDetail",
            "Description": "={{ $('Get row(s) in sheet').item.json.Decription }}"
          }
        ],
        "resource": "invoice",
        "operation": "create",
        "CustomerRef": "66",
        "additionalFields": {
          "DueDate": "={{ $('Get row(s) in sheet').item.json[\"Due Date\"] }}",
          "TxnDate": "={{ $('Get row(s) in sheet').item.json[\"Invoice Date\"] }}",
          "TotalAmt": "={{ $('Get row(s) in sheet').item.json.Quantity }}",
          "CustomFields": {
            "Field": [
              {
                "StringValue": "={{ $('Get row(s) in sheet').item.json[\"Customer Account Number\"] }}",
                "DefinitionId": "=Customer Account Number"
              },
              {
                "StringValue": "={{ $('Get row(s) in sheet').item.json[\"PO Number\"] }}",
                "DefinitionId": "=PO Number"
              }
            ]
          }
        }
      },
      "credentials": {
        "quickBooksOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "af5746bc-4efe-41b6-a97b-88cd82bb4179",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        336,
        576
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "d26d1afe-2855-45d7-8a7f-b64a3bbdec59",
      "name": "Get row(s) in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        544,
        576
      ],
      "parameters": {
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultUrl": "",
          "cachedResultName": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "="
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "6f45dbb4-1214-406f-83b4-4b35deddd048",
      "name": "Google Sheets2",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -336,
        1008
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "Customer Account Number",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Customer Account Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Invoice Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Invoice Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Due Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Due Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "PO Number",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "PO Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Item Column Title",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Item Column Title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Quantity Column",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Quantity Column",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Item Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Item Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Quantity",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Quantity",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Unit Price",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Unit Price",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Decription",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Decription",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Google Sheets: Create Sheet').item.json.sheets[0].properties.sheetId }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Google Sheets: Create Sheet').item.json.spreadsheetId }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "executeOnce": true,
      "typeVersion": 4.5,
      "alwaysOutputData": false
    },
    {
      "id": "ddc3111d-d7d6-4584-aa5a-ca7dbbd8be43",
      "name": "Set: Spreadsheet  (ID & Name)",
      "type": "n8n-nodes-base.set",
      "position": [
        -176,
        1008
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "89af4fa2-04e9-4e86-90cd-805437cb96c4",
              "name": "id",
              "type": "string",
              "value": "={{ $('Google Sheets: Create Sheet').item.json.spreadsheetId }}"
            },
            {
              "id": "6625391b-df04-4775-976d-baeb91ff083c",
              "name": "name",
              "type": "string",
              "value": "={{ $('Google Sheets: Create Sheet').item.json.properties.title }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "6bed8bcb-6e1a-4beb-8cd1-789f2e9307d3",
      "name": "Split Binary Attachments",
      "type": "n8n-nodes-base.code",
      "position": [
        -6016,
        976
      ],
      "parameters": {
        "jsCode": "const newItems = [];\n\nconst binary = items[0].binary;\n\nfor (const key in binary) {\n  newItems.push({\n    json: {},\n    binary: {\n      [key]: binary[key]\n    }\n  });\n}\n\nreturn newItems;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "9eeae953-2664-4563-852f-79ef504e74be",
      "name": "Loop: Process Each Attachment",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -5824,
        976
      ],
      "parameters": {
        "options": {
          "reset": false
        }
      },
      "typeVersion": 3,
      "alwaysOutputData": false
    },
    {
      "id": "00bf8cd1-98b1-45df-be2a-d072b30e58ed",
      "name": "Wait1",
      "type": "n8n-nodes-base.wait",
      "position": [
        -3776,
        1104
      ],
      "parameters": {
        "amount": 2
      },
      "typeVersion": 1.1
    },
    {
      "id": "d550e8ef-80b3-45d1-a33a-da14d69bf7c6",
      "name": "Split Each Month",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        -4528,
        1008
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "months"
      },
      "typeVersion": 1
    },
    {
      "id": "f7fbe95e-06e7-4987-859e-7c50bdbc3044",
      "name": "Map Timesheet Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        -3552,
        976
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "44bad27c-2c1d-46c7-9c60-d3a32b494a14",
              "name": "Employee Name",
              "type": "string",
              "value": "={{$('AI Agent').item.json.output.parseJson()['Employee Name'] }}"
            },
            {
              "id": "d5a52d08-8226-45bd-904a-82e03d1d2dba",
              "name": "Month",
              "type": "string",
              "value": "={{ $json.month }}\n"
            },
            {
              "id": "d0210ffe-0b19-4d18-9209-06257c9ab373",
              "name": "Total Hours",
              "type": "string",
              "value": "={{ $json['Total Hours'] }}\n"
            },
            {
              "id": "b5a64a37-8d6a-4040-bd07-b51fd15ba95b",
              "name": "Week Starting Date",
              "type": "string",
              "value": "={{ $json['Week Starting Date'] }}"
            },
            {
              "id": "c2ad96d6-deea-4869-995a-f5c580dbff76",
              "name": "Week Ending Date",
              "type": "string",
              "value": "={{ $json['Week Ending Date'] }}"
            },
            {
              "id": "00c459ba-b762-4337-8258-63d6fe56e370",
              "name": "Year",
              "type": "string",
              "value": "={{ $json.year }}"
            },
            {
              "id": "79c4a9c7-c6b6-49bb-a0da-764b64ab11c7",
              "name": "Client Name",
              "type": "string",
              "value": "={{ $('AI Agent').item.json.output.parseJson().Client}}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "79340f4e-1b4c-4ef2-9ed8-43078f44cee9",
      "name": "Check for Duplicate Entry",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -848,
        656
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "=Week ending date {{ $('Map Timesheet Fields').all()[0].json['Week Ending Date'] }}",
              "lookupColumn": "Decription"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5,
      "alwaysOutputData": true
    },
    {
      "id": "ca4d60a4-0ac4-4c96-a90f-3cbf5416d9f5",
      "name": "Skip If Duplicate Found",
      "type": "n8n-nodes-base.if",
      "position": [
        -416,
        304
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "b04fdc75-0d03-41b8-be76-7ed057d2087e",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.Decription }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "c58f4511-32e8-4927-931c-d04dd3b13e0d",
      "name": "Create Sheet Name + Invoice Date",
      "type": "n8n-nodes-base.set",
      "position": [
        -3376,
        976
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "ec172078-ec0e-4c75-b7aa-945b0a6259d8",
              "name": "Sheet Name",
              "type": "string",
              "value": "={{$('Map Timesheet Fields').item.json['Employee Name'].trim().replace(/\\s/g, \"\") + \"_\" + $('Map Timesheet Fields').item.json.Month.trim().replace(/\\s/g, \"\") + \"_\" + new Date().getFullYear() }}\n\n\n"
            },
            {
              "id": "525e1d85-c316-4cee-90b8-21859c33633d",
              "name": "last date of current month",
              "type": "string",
              "value": "={{ \n  (() => {\n    const monthMap = {\n      January: 0, February: 1, March: 2, April: 3, May: 4, June: 5,\n      July: 6, August: 7, September: 8, October: 9, November: 10, December: 11,\n    };\n    const rawMonth = $json['month'] || $json['Month'] || '';\n    const monthStr = rawMonth.toString().trim().replace(/\\s+/g, ' ');\n    const rawYear = $json['year'] || $json['Year'] || '';\n    const year = Number(rawYear);\n    const monthIndex = monthMap[monthStr];\n\n    if (monthIndex === undefined || isNaN(year)) {\n      return `Invalid input: month='${monthStr}', year='${rawYear}'`;\n    }\n\n    // Use Date.UTC to calculate last day reliably\n    const lastDay = new Date(Date.UTC(year, monthIndex + 1, 0));\n    return lastDay.toISOString().split('T')[0];\n  })() \n}}\n"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "cf4dbbbc-da9e-4fb6-bf6c-fde9551cdd1a",
      "name": "Google Sheets: Create Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -912,
        1008
      ],
      "parameters": {
        "title": "={{ $('Create Sheet Name + Invoice Date').all()[0].json['Sheet Name'] }}",
        "options": {},
        "resource": "spreadsheet",
        "sheetsUi": {
          "sheetValues": [
            {
              "title": "=Sheet1"
            }
          ]
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5,
      "alwaysOutputData": true
    },
    {
      "id": "299e9fe2-4e19-4a2a-b5d5-27379df97ee3",
      "name": "Move Sheet to Invoice Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -752,
        1008
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.spreadsheetId }}"
        },
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive",
          "cachedResultUrl": "https://drive.google.com/drive/my-drive",
          "cachedResultName": "My Drive"
        },
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Check if Year Folder Exists').item.json.id || $('Create Current Year Folder').item.json.id }}"
        },
        "operation": "move"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "6ae2aa39-41bd-4cca-9ea6-2647e9457828",
      "name": "Prepare Default Invoice Row",
      "type": "n8n-nodes-base.set",
      "position": [
        -576,
        1008
      ],
      "parameters": {
        "mode": "raw",
        "options": {
          "dotNotation": false
        },
        "jsonOutput": "{\n  \"Customer Account Number\": \"\",\n   \"Invoice Date\": \"\",\n  \"Due Date\": \"\",\n   \"PO Number\": \"\",\n  \"Item Column Title\":\"\",\n  \"Quantity Column\":\"\",\n  \"Item Name\":\"\",\n  \"Quantity\" :\"\",\n  \"Unit Price\":\"\",\n  \"Decription\" :\"\"\n  \n  }\n"
      },
      "executeOnce": true,
      "typeVersion": 3.4
    },
    {
      "id": "545e30b1-4364-4b40-80fe-62b4c3ca1154",
      "name": "If- File is Exist",
      "type": "n8n-nodes-base.if",
      "position": [
        -1152,
        896
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "768e3b62-b460-4845-abce-3e2058826a7a",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.id }}",
              "rightValue": "=\n"
            }
          ]
        }
      },
      "executeOnce": false,
      "typeVersion": 2.2,
      "alwaysOutputData": false
    },
    {
      "id": "c45ee3be-8041-4bf0-b5d2-96a8d1c9c11b",
      "name": "If1",
      "type": "n8n-nodes-base.if",
      "position": [
        -4288,
        1008
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "aa59ebe3-e51a-45ae-a3e0-2dfee0fba40c",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json['Total Hours'] }}",
              "rightValue": "0"
            },
            {
              "id": "0a8ff7ab-4a71-4e83-b5e1-a99516b63846",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.month }}",
              "rightValue": ""
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "01043fa6-1302-4d27-81f3-47da4ce1b354",
      "name": "Search: Client Invoices Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -2816,
        976
      ],
      "parameters": {
        "filter": {
          "driveId": {
            "mode": "list",
            "value": "My Drive"
          }
        },
        "options": {},
        "resource": "fileFolder",
        "returnAll": true,
        "queryString": "=01-ClientInvoices"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "b49931f5-da60-4a6d-a30d-b745c90c58f3",
      "name": "Search: Employee Name Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -2624,
        976
      ],
      "parameters": {
        "filter": {
          "driveId": {
            "mode": "list",
            "value": "My Drive"
          },
          "folderId": {
            "__rl": true,
            "mode": "id",
            "value": "={{ $json.id }}"
          },
          "whatToSearch": "folders"
        },
        "options": {},
        "resource": "fileFolder",
        "returnAll": true,
        "queryString": "={{ $('Map Timesheet Fields').item.json['Employee Name'] }}"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "7c165cf2-e64e-4791-97be-d00f61b90865",
      "name": "Check Employee Name Folder",
      "type": "n8n-nodes-base.if",
      "position": [
        -2384,
        960
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "e4d2d3f6-4fff-473b-9dd6-27bb19e8ce67",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.id }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "578cd5d9-9076-4d24-9484-29a85ffc86ae",
      "name": "Search: Inside folders in Employee Name Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -2192,
        752
      ],
      "parameters": {
        "filter": {
          "driveId": {
            "mode": "list",
            "value": "My Drive"
          },
          "folderId": {
            "__rl": true,
            "mode": "id",
            "value": "={{ $json.id }}"
          },
          "whatToSearch": "folders"
        },
        "options": {},
        "resource": "fileFolder",
        "returnAll": true,
        "queryString": "="
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "881e94d5-7603-4760-bc81-267ceece9a0d",
      "name": "Search: Year Folder ",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -1856,
        752
      ],
      "parameters": {
        "filter": {
          "folderId": {
            "__rl": true,
            "mode": "id",
            "value": "={{ $('Search: Inside folders in Employee Name Folder').first().json.id }}"
          },
          "whatToSearch": "folders"
        },
        "options": {},
        "resource": "fileFolder",
        "returnAll": true,
        "queryString": "={{ $('Map Timesheet Fields').item.json.Year }}"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "c846f0de-015b-4326-88dc-b96a9da139d6",
      "name": "Search: folder name",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -2016,
        752
      ],
      "parameters": {
        "filter": {
          "folderId": {
            "__rl": true,
            "mode": "id",
            "value": "={{ $json.id }}"
          }
        },
        "options": {},
        "resource": "fileFolder",
        "returnAll": true,
        "queryString": "={{ $('Get Customer Info From PO Sheet').item.json['Folder Name'] }}"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "64a8e2e8-20ec-406c-8ec9-d656239be9a0",
      "name": "Check if Year Folder Exists",
      "type": "n8n-nodes-base.if",
      "position": [
        -1648,
        912
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "daebe4a7-edcf-4902-a5d7-6c6b4ad995c8",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.id }}",
              "rightValue": ""
            }
          ]
        },
        "looseTypeValidation": "={{ false }}"
      },
      "typeVersion": 2.2
    },
    {
      "id": "d61eefea-4d26-4e1f-b728-f497088fa9bb",
      "name": "Create Current Year Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -1488,
        1104
      ],
      "parameters": {
        "name": "={{ $('Map Timesheet Fields').item.json.Year }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Search: folder name').item.json.id  }}"
        },
        "resource": "folder"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "5ab2c35e-ee0c-41b7-9ed3-419e97eb9373",
      "name": "Create Employee Name Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -2192,
        1088
      ],
      "parameters": {
        "name": "={{ $('Map Timesheet Fields').item.json['Employee Name'] }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Search: Client Invoices Folder').item.json.id }}"
        },
        "resource": "folder"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "a061431a-a11f-4f4a-a4a1-30efbca9a210",
      "name": "Google Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -1328,
        896
      ],
      "parameters": {
        "filter": {
          "driveId": {
            "mode": "list",
            "value": "My Drive"
          },
          "folderId": {
            "__rl": true,
            "mode": "id",
            "value": "={{ $json.id }}"
          }
        },
        "options": {},
        "resource": "fileFolder",
        "returnAll": true,
        "queryString": "={{ $('Create Sheet Name + Invoice Date').all()[0].json['Sheet Name']}}"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "a41d897b-d740-4ab7-93c5-7b70670fe053",
      "name": "Get Customer Info From PO Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -3104,
        976
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{ $('Gmail Trigger').item.json.from.value[0].address }}",
              "lookupColumn": "Email"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/11iUiyjpjaz6pNtSSncU3hwPvBzI5y2Gp8Tvuamjkd98/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "="
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5,
      "alwaysOutputData": true
    },
    {
      "id": "98b4e74d-201a-4ef0-a3fd-04cfb33dc04f",
      "name": "Create  Folder Name",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -2000,
        1088
      ],
      "parameters": {
        "name": "={{ $('Get Customer Info From PO Sheet').item.json['Folder Name']}}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "resource": "folder"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "ccaf9ebe-7669-4e85-b6f7-aa71f80e2f04",
      "name": "Create: Year Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -1808,
        1088
      ],
      "parameters": {
        "name": "={{ $('Map Timesheet Fields').item.json.Year }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "resource": "folder"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "5247b9d6-2020-43cc-8aab-2841b46959ac",
      "name": "Prepare Month array",
      "type": "n8n-nodes-base.set",
      "position": [
        -4720,
        1008
      ],
      "parameters": {
        "options": {
          "ignoreConversionErrors": true
        },
        "assignments": {
          "assignments": [
            {
              "id": "6a337e56-3cd4-46c4-aeb9-a9273bd34a3e",
              "name": "months",
              "type": "array",
              "value": "={{ JSON.stringify([ $json.output.parseJson().month1, $json.output.parseJson().month2 ]) }}"
            },
            {
              "id": "3d2cb537-6a4c-4ed1-b8cc-8b1d02af794d",
              "name": "Target month1",
              "type": "string",
              "value": "={{ $json.output.parseJson().month1['Week Starting Date'].split(\"/\")[0] }}\n"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "96f8a4a0-74f0-4560-8715-ca8e65d24cee",
      "name": "Gmail Trigger",
      "type": "n8n-nodes-base.gmailTrigger",
      "position": [
        -6208,
        976
      ],
      "parameters": {
        "simple": false,
        "filters": {
          "q": "=has:attachment (subject:\"Casper timesheet\" OR subject:\"Timesheets\")\n\n",
          "readStatus": "read"
        },
        "options": {
          "downloadAttachments": true
        },
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        }
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "d37d5a91-7b2d-4413-93f2-40d38ebb1ea7",
      "name": "Wait",
      "type": "n8n-nodes-base.wait",
      "position": [
        -5600,
        992
      ],
      "parameters": {
        "amount": 3
      },
      "typeVersion": 1.1
    },
    {
      "id": "086786c5-2c56-4825-b13d-ec21e1bfe27f",
      "name": "Extract Text ",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -5408,
        992
      ],
      "parameters": {
        "url": "https://universal-file-to-text-extractor.vercel.app/extract",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "multipart-form-data",
        "bodyParameters": {
          "parameters": [
            {
              "name": "mode",
              "value": "single"
            },
            {
              "name": "output_type",
              "value": "text"
            },
            {
              "name": "files",
              "parameterType": "formBinaryData",
              "inputDataFieldName": "={{ Object.keys($binary)[0] }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "fbc92283-dbe1-41bb-8b2f-3425269c21c9",
      "name": "Skip January First Time",
      "type": "n8n-nodes-base.if",
      "position": [
        -640,
        656
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "e01b225a-7c1a-499d-9fbd-ad7e61de8af1",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{ parseInt($json[\"Invoice Date\"].split(\"-\")[0].trim()) }}\n",
              "rightValue": "=1"
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "f937eb18-5d75-4eab-82b3-234a9e3e4191",
      "name": "Delete Exiting Row",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -448,
        640
      ],
      "parameters": {
        "operation": "delete",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('If- File is Exist').item.json.id }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "2ae397aa-f08d-47f7-8a85-f4f3a5302f43",
      "name": "OpenAI Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -5408,
        1280
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4",
          "cachedResultName": "gpt-4"
        },
        "options": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "ef7c089b-bfc0-408d-b02a-9561c70c01c4",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -5120,
        1008
      ],
      "parameters": {
        "text": "=Extract data **only** from the BILLABLE HOURS or DAYS section.\n\nIgnore:\n- \u201cPeriod Ending\u201d, signature dates, headers, or footers\n- NON-BILLABLE, HOLIDAY, LEAVE, or any other unrelated sections\n\n- extract billable hours data and working hours **month by month**, with the following fields:\n\nFor each month found in the BILLABLE HOURS row, return:\n- \"month\": Full month name (e.g., July)\n- \"year\": 4-digit year\n- \"Week Starting Date\": First date in that month from the BILLABLE HOURS row (even if hours = 0), format: MM/DD/YYYY\n- \"Week Ending Date\": Last date in that month from the BILLABLE HOURS row (even if hours = 0), format: MM/DD/YYYY\n- \"Total Hours\": Sum of billable hours for that month (use only the \u201cTotal Billable hours/days\u201d row)\n\nSpecial Handling for Split Weeks:\n- If a week includes dates across two months (e.g., Jun-30 to Jul-6), split them by month.\n- Each month should contain **only its own dates and billable hours**.\n\n Do not skip a month just because hours are 0 \u2014 still include the correct week start/end dates and `\"Total Hours\": 0`.\n\n Do not guess or assume any dates not clearly listed in the BILLABLE HOURS section.\n\n---\n\nExample:\nIf the BILLABLE HOURS row shows:  \n`Jun-30 Jul-1 Jul-2 Jul-3 Jul-4 Jul-5 Jul-6`  \nAnd only Jun-30 has hours:\n\nReturn:\n\n{\n  \"Employee Name\": \"Ravi Katta\",\n \"Manager Name\": \"\",\n \"Client\": \"\",\n  \"month1\": {\n    \"month\": \"June\",\n    \"year\": 2025,\n    \"Week Starting Date\": \"06/30/2025\",\n    \"Week Ending Date\": \"06/30/2025\",\n    \"Total Hours\": \n  },\n  \"month2\": {\n    \"month\": \"July\",\n    \"year\": 2025,\n    \"Week Starting Date\": \"07/01/2025\",\n    \"Week Ending Date\": \"07/06/2025\",\n    \"Total Hours\": \n  }\n}\n\nRemember this most importantly, Return only valid JSON. Do not wrap the JSON in markdown code fences (no ```json) or no use of ``` in the output.\n\n{{ $json.data[0].text }}",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 1.9
    },
    {
      "id": "7c696a0c-e31d-4531-b9c4-3d02d2127d3c",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        -5136,
        1264
      ],
      "parameters": {
        "options": {
          "temperature": 0.2
        }
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0e4a28e4-5647-4aaf-b361-45378123a7a5",
      "name": " Sheets: Append Row1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        96,
        96
      ],
      "parameters": {
        "columns": {
          "value": {
            "Due Date": "={{ $('Create Sheet Name + Invoice Date').all()[0].json['last date of current month'].trim().toDateTime().plus($('Get Customer Info From PO Sheet').all()[0].json['Due Date Calculation'],'days').format('MM-dd-yyyy') }}",
            "Quantity": "={{ $('Loop Over Items').item.json['Total Hours']}}",
            "Item Name": "={{ $('Get Customer Info From PO Sheet').item.json.Item }}",
            "PO Number": "={{ $('Get Customer Info From PO Sheet').item.json['PO Number'] }}",
            "Invoice Date": "={{ $('Create Sheet Name + Invoice Date').all()[0].json['last date of current month'].toDateTime().format('MM-dd-yyyy') }}",
            "Quantity Column": "Hours",
            "Item Column Title": "Items",
            "Customer Account Number": "={{ $('Get Customer Info From PO Sheet').item.json['Customer Account Number'] }}"
          },
          "schema": [
            {
              "id": "Customer Account Number",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Customer Account Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Invoice Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Invoice Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Due Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Due Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "PO Number",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "PO Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Item Column Title",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Item Column Title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Quantity Column",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Quantity Column",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Item Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Item Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Quantity",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Quantity",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Unit Price",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Unit Price",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Decription",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Decription",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id ||$('If- File is Exist').item.json.id }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5,
      "alwaysOutputData": false
    },
    {
      "id": "667a45ae-b9c7-40f5-8521-524267e29ccd",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -5488,
        848
      ],
      "parameters": {
        "color": 7,
        "width": 272,
        "height": 304,
        "content": "## OCR extraction\nSends each attachment to the OCR API and returns plain text. This turns PDFs and images into machine readable text before AI parsing.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "2b5a9a12-f3c4-4215-8eb2-040b60735ad6",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -960,
        880
      ],
      "parameters": {
        "color": 7,
        "width": 512,
        "height": 320,
        "content": "## Build invoice dates\nCalculates the invoice date and due date using the timesheet's week end date and PO due date rules. Outputs clean fields used to name and populate the invoice sheet.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "4c4eb027-fc39-4092-88f9-127a70dc1a35",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1584,
        1040
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 224,
        "content": "## create new year folder"
      },
      "typeVersion": 1
    },
    {
      "id": "96c97c10-93c6-40ad-95a2-8577fad99708",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4752,
        864
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 336,
        "content": "## normalize and extract timesheet month\nPrepare Month array and extract month number and split based on month\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "8b01a523-8db2-423c-9552-2db9864b0f75",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -6256,
        864
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 320,
        "content": "## Email intake and loop\nListens to Gmail for unread timesheet emails, splits all attachments, and processes each one in a loop so multiple timesheets in the same email are handled independently.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "659bc6b3-b974-422b-9da3-db6b9bb1cfda",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -7408,
        304
      ],
      "parameters": {
        "width": 976,
        "height": 992,
        "content": "## How it works\n\nThe workflow automates extracting timesheet data, organizing files, and syncing invoices to QuickBooks.\n\n1. Text extraction\nSplits attachments and sends them to an OCR API to convert PDFs or images into raw text.\n\n2. AI parsing\nGoogle Gemini analyzes the text to extract:\nEmployee and Client names\nTotal billable hours\nWeek start and end dates\nLogic to split weeks spanning two months\n\n3. Data lookup\nReferences your Customer POs Sheet to retrieve:\nPO and Account numbers\nItem details\nInvoice due date rules\n\n4. Drive folder logic\nLocates or creates a strict hierarchy inside 01-ClientInvoices:\nClient folder\nEmployee folder\nYear folder\n\n5. Sheet handling\nValidates data against existing records to prevent duplicates.\nAppends rows to existing monthly sheets, or\nCreates, names, and moves new sheets if necessary.\n\n6. QuickBooks sync\nFinalizes the process by:\nFinding or creating the Customer profile\nGenerating the Invoice with mapped fields\n\n## Setup steps\n\nConnect Drive, Sheets, Gmail, QuickBooks, and Gemini.\n\nUpdate the Master Sheet ID.\n\nCreate the 01-ClientInvoices root folder.\n\nVerify the OCR API URL.\n\nTest the duplicate check logic.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "5e8281df-c3d9-4b6e-8ae2-ce62a29494a7",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3200,
        784
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 352,
        "content": "## Customer and PO lookup\nLooks up the sender in the Customer POs sheet and pulls account number, PO number, item name, folder name, invoice range, and due date offset that drive the invoice logic.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "1dba7598-ddb3-4042-9ac1-8aceacb63082",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -5184,
        848
      ],
      "parameters": {
        "color": 7,
        "width": 352,
        "height": 304,
        "content": "## AI timesheet parsing\nOpenAI reads the timesheet text and extracts employee name, client name, week start and end dates, total hours, and current year into clean JSON fields for later use.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "42f7105c-2a3c-45d8-8c5c-5ba5f65715b9",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2864,
        800
      ],
      "parameters": {
        "color": 7,
        "width": 384,
        "height": 336,
        "content": "## Client folder discovery\nSearch Client Invoices folder, finds or creates the client level folder based on the timesheet client name and PO configuration.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "df6ef1e4-208d-405c-a24e-a23ef85bddfd",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2256,
        656
      ],
      "parameters": {
        "color": 7,
        "width": 592,
        "height": 272,
        "content": "## ## File naming and search\n searches Drive for existing sheets with the employee and if it exist get that year's folder"
      },
      "typeVersion": 1
    },
    {
      "id": "8fb091c3-7411-46a9-a8c8-d224868e0626",
      "name": "Sticky Note12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2224,
        1008
      ],
      "parameters": {
        "color": 7,
        "width": 528,
        "height": 224,
        "content": "## Create new \ncreate new client name, employee and year named folder\n"
      },
      "typeVersion": 1
    },
    {
      "id": "fc930765-6cc7-4f8b-b765-4bd6bff0c615",
      "name": "Sticky Note14",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -912,
        512
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 304,
        "content": "## check for duplicate and  Skip January First Time  (first week of the year)\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "30152731-a8f7-4e47-a20a-f137292d4b1e",
      "name": "Sticky Note15",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -496,
        176
      ],
      "parameters": {
        "color": 7,
        "width": 272,
        "height": 288,
        "content": "## skip if duplicate is found \n"
      },
      "typeVersion": 1
    },
    {
      "id": "b49aa34b-7bfb-485b-9a27-804fcf2df6ba",
      "name": "Sticky Note16",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 272,
        "height": 288,
        "content": "## add extracted data to sheets\n"
      },
      "typeVersion": 1
    },
    {
      "id": "de96bd29-001c-4246-9de0-582591cbdc05",
      "name": "Sticky Note17",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -368,
        880
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 288,
        "content": "## add extracted data to sheets\n"
      },
      "typeVersion": 1
    },
    {
      "id": "4be99b7f-8240-4bfd-b8dc-123a02acf23e",
      "name": "Sticky Note19",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        480,
        400
      ],
      "parameters": {
        "color": 7,
        "height": 336,
        "content": "## get data from sheets\nextracted data  from sheets\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b0438dc1-aff9-41ba-b5bb-2109eddbade9",
      "name": "Sticky Note20",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        736,
        400
      ],
      "parameters": {
        "color": 7,
        "height": 368,
        "content": "## quickbooks customer info \nfrom quickbooks find customer info that match customer name in sheets\n"
      },
      "typeVersion": 1
    },
    {
      "id": "e372d633-d563-49b2-b3d5-1e3124d47ff1",
      "name": "Sticky Note21",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1024,
        400
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 384,
        "content": "## check if customer exists\n\nif exists continue else add new customer  info\n"
      },
      "typeVersion": 1
    },
    {
      "id": "3999e083-c5aa-4137-9de9-548600dccd8b",
      "name": "Sticky Note22",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1360,
        400
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 384,
        "content": "## add data into Quickbooks\nadd data from sheets into Quickbooks invoice "
      },
      "typeVersion": 1
    },
    {
      "id": "886452e2-7474-43ff-9ae4-dedaffd60096",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4032,
        832
      ],
      "parameters": {
        "color": 7,
        "width": 784,
        "height": 384,
        "content": "## check occurrence than map the data\ncheck  If: First Time This Month? and than map the extracted data   and create sheet +invoice date\n"
      },
      "typeVersion": 1
    },
    {
      "id": "4f92a871-716d-4247-be9f-d30f1f80c56f",
      "name": "If: First Time This Month?",
      "type": "n8n-nodes-base.if",
      "position": [
        -4000,
        992
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "54fd631e-bb84-4d4d-a59f-325325d99a5a",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json['Week Starting Date'].split(\"/\")[0] }}\n",
              "rightValue": "={{ $('Prepare Month array').item.json['Target month1'] }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    }
  ],
  "connections": {
    "If1": {
      "main": [
        [
          {
            "node": "If: First Time This Month?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait": {
      "main": [
        [
          {
            "node": "Extract Text ",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait1": {
      "main": [
        [
          {
            "node": "Map Timesheet Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Prepare Month array",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Drive": {
      "main": [
        [
          {
            "node": "If- File is Exist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Text ": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail Trigger": {
      "main": [
        [
          {
            "node": "Split Binary Attachments",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets2": {
      "main": [
        [
          {
            "node": "Set: Spreadsheet  (ID & Name)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Each Month": {
      "main": [
        [
          {
            "node": "If1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If- File is Exist": {
      "main": [
        [
          {
            "node": "Check for Duplicate Entry",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Google Sheets: Create Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Delete Exiting Row": {
      "main": [
        [
          {
            "node": " Sheets: Append Row1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create  Folder Name": {
      "main": [
        [
          {
            "node": "Create: Year Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create: Year Folder": {
      "main": [
        [
          {
            "node": "Check if Year Folder Exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get row(s) in sheet": {
      "main": [
        [
          {
            "node": "QuickBooks Find Customer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Customer Exists?": {
      "main": [
        [
          {
            "node": "QuickBooks Create Invoice",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "QuickBooks Create Customer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Month array": {
      "main": [
        [
          {
            "node": "Split Each Month",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search: folder name": {
      "main": [
        [
          {
            "node": "Search: Year Folder ",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    " Sheets: Append Row1": {
      "main": [
        [
          {
            "node": "Loop: Process Each Attachment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Map Timesheet Fields": {
      "main": [
        [
          {
            "node": "Create Sheet Name + Invoice Date",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search: Year Folder ": {
      "main": [
        [
          {
            "node": "Check if Year Folder Exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Skip If Duplicate Found": {
      "main": [
        [
          {
            "node": "Loop: Process Each Attachment",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": " Sheets: Append Row1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Skip January First Time": {
      "main": [
        [
          {
            "node": "Delete Exiting Row",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Skip If Duplicate Found",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "QuickBooks Find Customer": {
      "main": [
        [
          {
            "node": "If Customer Exists?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Binary Attachments": {
      "main": [
        [
          {
            "node": "Loop: Process Each Attachment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check for Duplicate Entry": {
      "main": [
        [
          {
            "node": "Skip January First Time",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Employee Name Folder": {
      "main": [
        [
          {
            "node": "Search: Inside folders in Employee Name Folder",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create Employee Name Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Current Year Folder": {
      "main": [
        [
          {
            "node": "Google Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If: First Time This Month?": {
      "main": [
        [
          {
            "node": "Map Timesheet Fields",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "QuickBooks Create Customer": {
      "main": [
        [
          {
            "node": "QuickBooks Create Invoice",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if Year Folder Exists": {
      "main": [
        [
          {
            "node": "Google Drive",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create Current Year Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Employee Name Folder": {
      "main": [
        [
          {
            "node": "Create  Folder Name",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets: Create Sheet": {
      "main": [
        [
          {
            "node": "Move Sheet to Invoice Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Default Invoice Row": {
      "main": [
        [
          {
            "node": "Google Sheets2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Move Sheet to Invoice Folder": {
      "main": [
        [
          {
            "node": "Prepare Default Invoice Row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search: Employee Name Folder": {
      "main": [
        [
          {
            "node": "Check Employee Name Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop: Process Each Attachment": {
      "main": [
        [],
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set: Spreadsheet  (ID & Name)": {
      "main": [
        [
          {
            "node": " Sheets: Append Row1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search: Client Invoices Folder": {
      "main": [
        [
          {
            "node": "Search: Employee Name Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Customer Info From PO Sheet": {
      "main": [
        [
          {
            "node": "Search: Client Invoices Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Sheet Name + Invoice Date": {
      "main": [
        [
          {
            "node": "Get Customer Info From PO Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Get row(s) in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search: Inside folders in Employee Name Folder": {
      "main": [
        [
          {
            "node": "Search: folder name",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}