{
  "name": "Corrigé 5 - Upsert & Dédoublonnage Capteurs AgroTech",
  "nodes": [
    {
      "parameters": {},
      "id": "81e87549-3590-4d08-86c9-793595ba4245",
      "name": "When clicking 'Test workflow'",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        112,
        512
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "out_source",
              "name": "out_source",
              "value": "Sonde Humidité API",
              "type": "string"
            },
            {
              "id": "out_subject",
              "name": "out_subject",
              "value": "Batterie faible sur le capteur",
              "type": "string"
            },
            {
              "id": "out_message",
              "name": "out_message",
              "value": "Niveau de charge inférieur à 10%",
              "type": "string"
            },
            {
              "id": "out_device_email",
              "name": "out_device_email",
              "value": "sensor-zone-nord@farm.local",
              "type": "string"
            },
            {
              "id": "out_priority",
              "name": "out_priority",
              "value": "medium",
              "type": "string"
            },
            {
              "id": "out_created_at",
              "name": "out_created_at",
              "value": "2026-03-15T08:00:00Z",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "69885899-6fb6-4663-9ff5-9345bfe219c1",
      "name": "Simuler relevé normalisé",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        400,
        512
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const subject = String($json.out_subject || 'no-subject').toLowerCase().replace(/[^a-z0-9]/g, '-');\nconst email = String($json.out_device_email || 'no-email').toLowerCase();\nconst uniquenessKey = `agri-alert_${subject}_${email}`;\n\nreturn {\n  ...$json,\n  uniqueness_key: uniquenessKey\n};"
      },
      "id": "e1757b56-af94-4ce1-a0d4-d56968d4fb0b",
      "name": "Générer Clé d'Idempotence",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        704,
        512
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.hubspot.com/crm/v3/objects/tickets/search",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ { \"query\": $json.uniqueness_key } }}",
        "options": {}
      },
      "id": "d830b1be-996a-41a1-83bf-c093721cf48e",
      "name": "Rechercher Alerte Existante",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        1008,
        512
      ],
      "credentials": {
        "httpBearerAuth": {
          "id": "LjxsgB79lWlVUyaR",
          "name": "n8n-test-api-hubspot"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "leftValue": "={{ $json.results.length }}",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "rightValue": 0
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "0777ea29-9b4a-42d5-b657-497adfda7dd0",
      "name": "Existe déjà ?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        1312,
        512
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.hubspot.com/crm/v3/objects/tickets",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ { \"properties\": { \"subject\": $(\"Simuler relevé normalisé\").item.json.out_subject, \"content\": $(\"Simuler relevé normalisé\").item.json.out_message + \"\\n\\nKey: \" + $(\"Générer Clé d'Idempotence\").item.json.uniqueness_key + \"\\nCompteur de répétition : 1\", \"hs_pipeline\": \"0\", \"hs_pipeline_stage\": \"1\", \"hs_ticket_priority\": \"MEDIUM\" } } }}",
        "options": {}
      },
      "id": "34d66228-9887-4bce-995d-4b8a8793502b",
      "name": "Créer Nouveau Ticket",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        1712,
        304
      ],
      "credentials": {
        "httpBearerAuth": {
          "id": "LjxsgB79lWlVUyaR",
          "name": "n8n-test-api-hubspot"
        }
      }
    },
    {
      "parameters": {
        "method": "PATCH",
        "url": "={{ \"https://api.hubspot.com/crm/v3/objects/tickets/\" + $json.results[0].id }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ { \"properties\": { \"content\": $('Simuler relevé normalisé').item.json.out_message + '\\n\\n[Alerte répétée reçue le ' + new Date().toISOString() + ']\\nKey: ' + $(\"Générer Clé d'Idempotence\").item.json.uniqueness_key } } }}",
        "options": {}
      },
      "id": "ba3bfd58-a5cd-417c-be19-a0b97237e312",
      "name": "Incrémenter Compteur & Update",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        1712,
        704
      ],
      "credentials": {
        "httpBearerAuth": {
          "id": "LjxsgB79lWlVUyaR",
          "name": "n8n-test-api-hubspot"
        }
      }
    },
    {
      "parameters": {
        "content": "### Corrigé 5 - Logique Upsert (Idempotence)\n\n**Principe**\nÉviter la création de doublons lorsqu'un capteur émet plusieurs fois la même alerte.\n\n**Fonctionnement**\n1. Génération d'une clé unique basée sur le sujet et l'identifiant du capteur.\n2. Recherche via l'API Search de HubSpot.\n3. Si 0 résultat -> `POST` (Création avec `duplicate_count = 1`).\n4. Si 1+ résultat -> `PATCH` (Incrémentation de `duplicate_count`).",
        "height": 702,
        "width": 1940,
        "color": 4
      },
      "id": "f216ba48-1f48-47cc-87ae-8425342a0b69",
      "name": "Sticky Note 8c0ea508",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        0,
        176
      ]
    }
  ],
  "pinData": {},
  "connections": {
    "When clicking 'Test workflow'": {
      "main": [
        [
          {
            "node": "Simuler relevé normalisé",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Simuler relevé normalisé": {
      "main": [
        [
          {
            "node": "Générer Clé d'Idempotence",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Générer Clé d'Idempotence": {
      "main": [
        [
          {
            "node": "Rechercher Alerte Existante",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Rechercher Alerte Existante": {
      "main": [
        [
          {
            "node": "Existe déjà ?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Existe déjà ?": {
      "main": [
        [
          {
            "node": "Créer Nouveau Ticket",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Incrémenter Compteur & Update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate",
    "availableInMCP": true
  },
  "versionId": "6eb21aca-11d9-4d45-a37d-e5ef27639e31",
  "meta": {
    "aiBuilderAssisted": true,
    "builderVariant": "mcp",
    "instanceId": "ee4605bad6c4b5003dc41d3ea7bedaa9c80198c8426442908a1e821a57858a1d"
  },
  "nodeGroups": [],
  "id": "br5W831AyQTQ2IDG",
  "tags": []
}