{
  "nodes": [
    {
      "id": "sticky-overview",
      "name": "Sticky Note - Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1100,
        -180
      ],
      "parameters": {
        "color": 6,
        "width": 380,
        "height": 340,
        "content": "## Google Sheets to Odoo Syncer\n\n### How it works\n1. Triggers when a new row is added to Google Sheets.\n2. Checks if the product already exists in Odoo via Barcode.\n3. If missing, it fetches the appropriate category.\n4. Checks if an image URL is provided. If yes, it downloads and converts it to base64.\n5. Creates the product in Odoo (with or without the image).\n6. Updates the Google Sheet status to 'Done'.\n\n*Includes an error-handling loop that waits 1 minute and retries if the Google Sheet update fails.*"
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-phase-1",
      "name": "Sticky Note - Phase 1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1050,
        200
      ],
      "parameters": {
        "color": 7,
        "width": 1000,
        "height": 280,
        "content": "## Phase 1: Fetch & Verify\nTriggered by new rows. Loops through them and checks Odoo for existing barcodes."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-phase-2",
      "name": "Sticky Note - Phase 2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        50,
        20
      ],
      "parameters": {
        "color": 7,
        "width": 1250,
        "height": 450,
        "content": "## Phase 2: Category, Image Processing & Creation\nRetrieves category, checks for image URL, downloads if present, and creates the product in Odoo."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-phase-3",
      "name": "Sticky Note - Phase 3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1350,
        20
      ],
      "parameters": {
        "color": 7,
        "width": 320,
        "height": 450,
        "content": "## Phase 3: Status & Error Recovery\nUpdates Sheet to 'Done'. If error occurs, waits 1 minute and returns to the loop."
      },
      "typeVersion": 1
    },
    {
      "id": "183ef33f-9a5c-457e-a5b1-c848728d6695",
      "name": "On New Row in Sheets",
      "type": "n8n-nodes-base.googleSheetsTrigger",
      "position": [
        -1000,
        280
      ],
      "parameters": {
        "event": "rowAdded",
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1xY4o1gv2lvglcIlxNPbM-vuNC6tIysO9rwkse-cnRH8/edit#gid=0",
          "cachedResultName": "\u0627\u0644\u0648\u0631\u0642\u06291"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1xY4o1gv2lvglcIlxNPbM-vuNC6tIysO9rwkse-cnRH8",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1xY4o1gv2lvglcIlxNPbM-vuNC6tIysO9rwkse-cnRH8/edit?usp=drivesdk",
          "cachedResultName": "khaled"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a69ff7df-c37e-416a-b0e5-eb2614d3d0c9",
      "name": "Process Row Batch",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -750,
        280
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "3a469a4c-7aff-4cd8-b5d6-55da653e6d80",
      "name": "Check Odoo for Barcode",
      "type": "n8n-nodes-base.odoo",
      "position": [
        -500,
        280
      ],
      "parameters": {
        "limit": 1,
        "options": {
          "fieldsList": []
        },
        "resource": "custom",
        "operation": "getAll",
        "filterRequest": {
          "filter": [
            {
              "value": "={{ $json.Barcode }}",
              "fieldName": "barcode"
            }
          ]
        },
        "customResource": "product.product"
      },
      "credentials": {
        "odooApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "85d563e9-9878-4f68-9031-f87b10788179",
      "name": "If Product Missing",
      "type": "n8n-nodes-base.if",
      "position": [
        -250,
        280
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "213647d7-d6dc-4d55-99c1-9107052c97cb",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json.id }}",
              "rightValue": ""
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.3
    },
    {
      "id": "acddd5e0-4dce-46ca-946e-98dbca0e25cd",
      "name": "Get Odoo Category",
      "type": "n8n-nodes-base.odoo",
      "position": [
        100,
        260
      ],
      "parameters": {
        "limit": 1,
        "options": {},
        "resource": "custom",
        "operation": "getAll",
        "filterRequest": {
          "filter": [
            {
              "value": "={{ $('Process Row Batch').item.json.category }}",
              "fieldName": "name"
            }
          ]
        },
        "customResource": "product.category"
      },
      "credentials": {
        "odooApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "383d89b8-ad0b-4dc1-93b2-4d5d58c074ae",
      "name": "Has Image URL?",
      "type": "n8n-nodes-base.if",
      "position": [
        350,
        260
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "25a10f95-d8a2-4479-9109-0ddca965493f",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $('On New Row in Sheets').item.json['\u0627\u0644\u0635\u0648\u0631\u0647'] }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "07d6f7a7-4641-462f-8bf2-1d5828c451f2",
      "name": "Download Image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        600,
        140
      ],
      "parameters": {
        "url": "={{ $('On New Row in Sheets').item.json['\u0627\u0644\u0635\u0648\u0631\u0647'] }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "typeVersion": 4.3,
      "alwaysOutputData": true
    },
    {
      "id": "0251b632-eb98-4a63-aab0-98ff9113d306",
      "name": "Convert Image to Base64",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        850,
        140
      ],
      "parameters": {
        "options": {},
        "operation": "binaryToPropery",
        "destinationKey": "final_image"
      },
      "typeVersion": 1.1,
      "alwaysOutputData": true
    },
    {
      "id": "f61d1efc-47ed-46ca-b81c-6d05b70daea6",
      "name": "Create Product (With Image)",
      "type": "n8n-nodes-base.odoo",
      "position": [
        1100,
        140
      ],
      "parameters": {
        "resource": "custom",
        "customResource": "product.template",
        "fieldsToCreateOrUpdate": {
          "fields": [
            {
              "fieldName": "=name",
              "fieldValue": "={{ $('Process Row Batch').item.json.Name }}"
            },
            {
              "fieldName": "barcode",
              "fieldValue": "={{ $('Process Row Batch').item.json.Barcode }}"
            },
            {
              "fieldName": "list_price",
              "fieldValue": "={{ $('Process Row Batch').item.json['Sales Price'] }}"
            },
            {
              "fieldName": "standard_price",
              "fieldValue": "={{ $('Process Row Batch').item.json.Cost }}"
            },
            {
              "fieldName": "categ_id",
              "fieldValue": "={{ $('Get Odoo Category').item.json.id }}"
            },
            {
              "fieldName": "taxes_id",
              "fieldValue": "={{ [] }}"
            },
            {
              "fieldName": "supplier_taxes_id",
              "fieldValue": "={{ [] }}"
            },
            {
              "fieldName": "image_1920",
              "fieldValue": "={{ $json.final_image }}"
            }
          ]
        }
      },
      "credentials": {
        "odooApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "16ca4dff-41d1-42d9-af17-25a7118c2cb5",
      "name": "Create Product (No Image)",
      "type": "n8n-nodes-base.odoo",
      "position": [
        1100,
        340
      ],
      "parameters": {
        "resource": "custom",
        "customResource": "product.template",
        "fieldsToCreateOrUpdate": {
          "fields": [
            {
              "fieldName": "=name",
              "fieldValue": "={{ $('Process Row Batch').item.json.Name }}"
            },
            {
              "fieldName": "barcode",
              "fieldValue": "={{ $('Process Row Batch').item.json.Barcode }}"
            },
            {
              "fieldName": "list_price",
              "fieldValue": "={{ $('Process Row Batch').item.json['Sales Price'] }}"
            },
            {
              "fieldName": "standard_price",
              "fieldValue": "={{ $('Process Row Batch').item.json.Cost }}"
            },
            {
              "fieldName": "categ_id",
              "fieldValue": "={{ $('Get Odoo Category').item.json.id }}"
            },
            {
              "fieldName": "taxes_id",
              "fieldValue": "={{ [] }}"
            },
            {
              "fieldName": "supplier_taxes_id",
              "fieldValue": "={{ [] }}"
            }
          ]
        }
      },
      "credentials": {
        "odooApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5d552216-2f48-45cf-8431-da5c1f4875cb",
      "name": "Mark as Done in Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "onError": "continueErrorOutput",
      "position": [
        1400,
        240
      ],
      "parameters": {
        "columns": {
          "value": {
            "Cost": "={{ $('On New Row in Sheets').item.json.Cost }}",
            "Name": "={{ $('On New Row in Sheets').item.json.Name }}",
            "Weight": "={{ $('On New Row in Sheets').item.json.Weight }}",
            "Barcode": "={{ $('On New Row in Sheets').item.json.Barcode }}",
            "category": "={{ $('On New Row in Sheets').item.json.category }}",
            "row_number": 0,
            "External ID": "={{ $('On New Row in Sheets').item.json['External ID'] }}",
            "Sales Price": "={{ $('On New Row in Sheets').item.json['Sales Price'] }}",
            "Sales Taxes": "={{ $('On New Row in Sheets').item.json['Sales Taxes'] }}",
            "Product Type": "={{ $('On New Row in Sheets').item.json['Product Type'] }}",
            "\u0627\u0644\u062d\u0627\u0644\u0647": "Done",
            "Purchase Taxes": "={{ $('On New Row in Sheets').item.json['Purchase Taxes'] }}",
            "Internal Reference": "={{ $('On New Row in Sheets').item.json['Internal Reference'] }}"
          },
          "schema": [
            {
              "id": "External ID",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "External ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Product Type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Product Type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "category",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "category",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Internal Reference",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Internal Reference",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Barcode",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Barcode",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Sales Price",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Sales Price",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Cost",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Cost",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Sales Taxes",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Sales Taxes",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Purchase Taxes",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Purchase Taxes",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Weight",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Weight",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "\u0627\u0644\u062d\u0627\u0644\u0647",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "\u0627\u0644\u062d\u0627\u0644\u0647",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Name"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1xY4o1gv2lvglcIlxNPbM-vuNC6tIysO9rwkse-cnRH8/edit#gid=0",
          "cachedResultName": "DATA"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/1xY4o1gv2lvglcIlxNPbM-vuNC6tIysO9rwkse-cnRH8/edit?gid=0#gid=0"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "82c2a98f-c8c8-426e-8974-3daef7e64c8b",
      "name": "Wait on Error",
      "type": "n8n-nodes-base.wait",
      "position": [
        1400,
        400
      ],
      "parameters": {
        "unit": "minutes"
      },
      "typeVersion": 1.1
    }
  ],
  "connections": {
    "Wait on Error": {
      "main": [
        [
          {
            "node": "Process Row Batch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Image": {
      "main": [
        [
          {
            "node": "Convert Image to Base64",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Image URL?": {
      "main": [
        [
          {
            "node": "Download Image",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create Product (No Image)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Odoo Category": {
      "main": [
        [
          {
            "node": "Has Image URL?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Row Batch": {
      "main": [
        [],
        [
          {
            "node": "Check Odoo for Barcode",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Product Missing": {
      "main": [
        [
          {
            "node": "Get Odoo Category",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Process Row Batch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On New Row in Sheets": {
      "main": [
        [
          {
            "node": "Process Row Batch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark as Done in Sheet": {
      "main": [
        [
          {
            "node": "Process Row Batch",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait on Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Odoo for Barcode": {
      "main": [
        [
          {
            "node": "If Product Missing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert Image to Base64": {
      "main": [
        [
          {
            "node": "Create Product (With Image)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Product (No Image)": {
      "main": [
        [
          {
            "node": "Mark as Done in Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Product (With Image)": {
      "main": [
        [
          {
            "node": "Mark as Done in Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}