{
  "name": "Generation et mise a jour des fiches RNCP",
  "nodes": [
    {
      "id": "bc1cd16a-6fce-4f8a-af92-54ddb3fdb7ad",
      "name": "Note source",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -460,
        -340
      ],
      "parameters": {
        "color": 4,
        "width": 520,
        "height": 300,
        "content": "## 1. Source des donnees\n\nLe node **Parametres** centralise les URL. Par defaut il pointe vers l'open data France Competences, mais toute source fait l'affaire : API interne, export CSV, base metier.\n\nOnglet **Certifications** attendu :\n`code_rncp` | `intitule` | `url_fiche_site` | `hash_precedent` | `derniere_maj`"
      },
      "typeVersion": 1
    },
    {
      "id": "33d4d400-b98d-4497-a5f9-b5cd0ee78534",
      "name": "Note diff",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        420,
        -340
      ],
      "parameters": {
        "color": 3,
        "width": 460,
        "height": 300,
        "content": "## 2. Detection de changement\n\nLe node Code calcule une empreinte des champs surveilles (intitule, niveau, blocs de competences, date d'echeance, certificateur).\n\nSi l'empreinte differe de `hash_precedent`, la fiche du site est regeneree et l'equipe pedagogique est notifiee avec le detail des ecarts."
      },
      "typeVersion": 1
    },
    {
      "id": "0623d427-7e9e-45a6-a38e-704e78233ce6",
      "name": "Note publication",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -460,
        240
      ],
      "parameters": {
        "color": 5,
        "width": 460,
        "height": 220,
        "content": "## 3. Publication\n\nLe node HTTP Request `Publier la fiche` pousse le contenu vers votre CMS (WordPress REST, Strapi, Directus, Next.js API...).\n\nGeneration a la demande : `POST /fiche-rncp` avec `{ code_rncp }`."
      },
      "typeVersion": 1
    },
    {
      "id": "391ee4c7-ea3e-4285-a66b-bcccbe0ead81",
      "name": "Chaque lundi a 6h",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -420,
        -20
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 6 * * 1"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "a4d2b91b-d7a2-4cba-a378-dfa4a1170406",
      "name": "Parametres",
      "type": "n8n-nodes-base.set",
      "position": [
        -200,
        -20
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "55bbb306-62fc-4f4e-a603-b389ef836fc0",
              "name": "api_fiche_url",
              "type": "string",
              "value": "https://api.francecompetences.fr/opendata/v1/certifications"
            },
            {
              "id": "ce527ada-a766-4cad-acc7-e63af30b2645",
              "name": "api_publication_url",
              "type": "string",
              "value": "https://votre-site.fr/api/fiches-rncp"
            },
            {
              "id": "7f46ae01-8f52-4fbb-a44d-e8f02c194cf3",
              "name": "email_equipe",
              "type": "string",
              "value": "pedagogie@votre-of.fr"
            }
          ]
        },
        "includeOtherFields": false
      },
      "typeVersion": 3.4
    },
    {
      "id": "db8a86e6-dcd2-4d94-a261-62bf4ae0b06a",
      "name": "Lire les certifications suivies",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        20,
        -20
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Certifications"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "REMPLACER_PAR_ID_DU_GOOGLE_SHEET"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "5ef87b58-5ad1-49d9-a16c-0da77a7e9d05",
      "name": "Recuperer la fiche officielle",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        240,
        -20
      ],
      "parameters": {
        "url": "={{ $('Parametres').first().json.api_fiche_url }}/{{ $json.code_rncp }}",
        "method": "GET",
        "options": {},
        "sendQuery": false
      },
      "typeVersion": 4.2,
      "onError": "continueRegularOutput"
    },
    {
      "id": "218fbf41-4c6b-4869-ade6-227018cf25d8",
      "name": "Comparer avec la fiche publiee",
      "type": "n8n-nodes-base.code",
      "position": [
        460,
        -20
      ],
      "parameters": {
        "jsCode": "// Compare la fiche officielle avec la version publiee sur le site.\nconst crypto = require('crypto');\n\n// Champs surveilles : adaptez-les a la structure de votre source.\nconst CHAMPS = [\n  'intitule',\n  'niveau',\n  'certificateur',\n  'date_echeance',\n  'blocs_competences',\n  'modalites_acces',\n];\n\nconst lignes = $('Lire les certifications suivies').all();\nconst sortie = [];\n\n$input.all().forEach((item, index) => {\n  const source = item.json || {};\n  const fiche = source.data || source.certification || source;\n  const ligne = (lignes[index] && lignes[index].json) || {};\n\n  const surveille = {};\n  for (const champ of CHAMPS) {\n    if (fiche[champ] !== undefined) surveille[champ] = fiche[champ];\n  }\n\n  const empreinte = crypto\n    .createHash('sha1')\n    .update(JSON.stringify(surveille))\n    .digest('hex');\n\n  const changement = empreinte !== String(ligne.hash_precedent || '');\n\n  const ecarts = [];\n  for (const champ of CHAMPS) {\n    if (ligne[champ] !== undefined && String(ligne[champ]) !== String(surveille[champ])) {\n      ecarts.push(champ + ' : ' + ligne[champ] + ' -> ' + surveille[champ]);\n    }\n  }\n\n  sortie.push({\n    json: {\n      code_rncp: ligne.code_rncp || fiche.code_rncp || source.code_rncp,\n      intitule: surveille.intitule || ligne.intitule || '',\n      url_fiche_site: ligne.url_fiche_site || '',\n      fiche: surveille,\n      empreinte,\n      changement,\n      ecarts,\n      controle_le: new Date().toISOString(),\n    },\n  });\n});\n\nreturn sortie;"
      },
      "typeVersion": 2
    },
    {
      "id": "9aa0857d-4504-406c-a0ea-8ae7185f67ed",
      "name": "Des changements ?",
      "type": "n8n-nodes-base.if",
      "position": [
        680,
        -20
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "7f50fab3-7b4b-4f0e-a8dc-55291197f170",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.changement }}",
              "rightValue": ""
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "19ba581f-5bcd-4bae-aab7-34dbac488cff",
      "name": "Fiche deja a jour",
      "type": "n8n-nodes-base.noOp",
      "position": [
        900,
        140
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "fed95d9f-da43-41b7-a25c-3b01396ab8bd",
      "name": "Generer le contenu de la fiche RNCP",
      "type": "n8n-nodes-base.code",
      "position": [
        900,
        -160
      ],
      "parameters": {
        "jsCode": "// Genere le contenu publiable (HTML + metadonnees SEO) de la fiche RNCP.\nreturn $input.all().map((item) => {\n  const l = item.json;\n  const f = l.fiche || {};\n  const h = [];\n\n  h.push('<h1>' + (f.intitule || l.intitule) + ' - RNCP ' + l.code_rncp + '</h1>');\n  h.push('<p><strong>Niveau :</strong> ' + (f.niveau || 'non renseigne') + '</p>');\n  h.push('<p><strong>Certificateur :</strong> ' + (f.certificateur || 'non renseigne') + '</p>');\n  h.push('<p><strong>Date d echeance de l enregistrement :</strong> ' + (f.date_echeance || 'non renseignee') + '</p>');\n\n  const blocs = Array.isArray(f.blocs_competences) ? f.blocs_competences : [];\n  if (blocs.length) {\n    h.push('<h2>Blocs de competences</h2><ul>');\n    for (const b of blocs) {\n      h.push('<li>' + (typeof b === 'string' ? b : (b.code || '') + ' - ' + (b.libelle || '')) + '</li>');\n    }\n    h.push('</ul>');\n  }\n\n  if (f.modalites_acces) {\n    h.push('<h2>Modalites d acces</h2><p>' + f.modalites_acces + '</p>');\n  }\n\n  h.push('<p><em>Fiche mise a jour automatiquement le ' + new Date().toLocaleDateString('fr-FR') + ' a partir du repertoire national.</em></p>');\n\n  return {\n    json: {\n      ...l,\n      titre_seo: (f.intitule || l.intitule) + ' (RNCP ' + l.code_rncp + ')',\n      slug: 'rncp-' + String(l.code_rncp).toLowerCase(),\n      contenu_html: h.join(''),\n      resume_ecarts: (l.ecarts || []).join(' | ') || 'Premiere publication',\n    },\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "4176edb7-bf3c-458f-a2eb-4155fe343874",
      "name": "Publier la fiche sur le site",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1120,
        -160
      ],
      "parameters": {
        "url": "={{ $('Parametres').first().json.api_publication_url }}",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ code_rncp: $json.code_rncp, slug: $json.slug, titre: $json.titre_seo, contenu: $json.contenu_html }) }}"
      },
      "typeVersion": 4.2,
      "onError": "continueRegularOutput"
    },
    {
      "id": "321d8e4e-d4f6-472f-a8d4-5353706698ab",
      "name": "Journaliser la mise a jour",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1340,
        -160
      ],
      "parameters": {
        "columns": {
          "value": {
            "code_rncp": "={{ $('Generer le contenu de la fiche RNCP').item.json.code_rncp }}",
            "hash_precedent": "={{ $('Generer le contenu de la fiche RNCP').item.json.empreinte }}",
            "derniere_maj": "={{ $('Generer le contenu de la fiche RNCP').item.json.controle_le }}",
            "derniers_ecarts": "={{ $('Generer le contenu de la fiche RNCP').item.json.resume_ecarts }}"
          },
          "schema": [
            {
              "id": "code_rncp",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "code_rncp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "hash_precedent",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "hash_precedent",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "derniere_maj",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "derniere_maj",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "derniers_ecarts",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "derniers_ecarts",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "code_rncp"
          ]
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Certifications"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "REMPLACER_PAR_ID_DU_GOOGLE_SHEET"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "b0b794aa-33fd-4f07-ab61-258ffc415218",
      "name": "Notifier l'equipe pedagogique",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1560,
        -160
      ],
      "parameters": {
        "sendTo": "={{ $('Parametres').first().json.email_equipe }}",
        "subject": "=Fiche RNCP mise a jour - {{ $('Generer le contenu de la fiche RNCP').item.json.code_rncp }}",
        "message": "=<p>La fiche <strong>{{ $('Generer le contenu de la fiche RNCP').item.json.titre_seo }}</strong> a &eacute;t&eacute; mise &agrave; jour automatiquement.</p><p><strong>&Eacute;carts d&eacute;tect&eacute;s :</strong> {{ $('Generer le contenu de la fiche RNCP').item.json.resume_ecarts }}</p><p>Pensez &agrave; v&eacute;rifier les supports p&eacute;dagogiques et les programmes associ&eacute;s.</p>",
        "options": {
          "appendAttribution": false
        },
        "emailType": "html",
        "resource": "message",
        "operation": "send"
      },
      "typeVersion": 2.1,
      "webhookId": "2b4f2247-d583-4198-aaaa-a6a01ae0c04c"
    },
    {
      "id": "e88a0921-f01f-4ff7-a8c9-67646b8f0c5c",
      "name": "Generation a la demande",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -420,
        340
      ],
      "parameters": {
        "path": "fiche-rncp",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2,
      "webhookId": "5e1f678e-1300-4c3e-a896-5fc3c7c07bd7",
      "onError": "continueRegularOutput"
    },
    {
      "id": "e0777fcc-0913-4f05-adf4-9690d219afac",
      "name": "Normaliser la demande",
      "type": "n8n-nodes-base.set",
      "position": [
        -200,
        340
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "64b0ac72-a58c-45d0-ad38-94b178cdf384",
              "name": "code_rncp",
              "type": "string",
              "value": "={{ $json.body.code_rncp }}"
            }
          ]
        },
        "includeOtherFields": false
      },
      "typeVersion": 3.4
    }
  ],
  "pinData": {},
  "connections": {
    "Chaque lundi a 6h": {
      "main": [
        [
          {
            "node": "Parametres",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parametres": {
      "main": [
        [
          {
            "node": "Lire les certifications suivies",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lire les certifications suivies": {
      "main": [
        [
          {
            "node": "Recuperer la fiche officielle",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Recuperer la fiche officielle": {
      "main": [
        [
          {
            "node": "Comparer avec la fiche publiee",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Comparer avec la fiche publiee": {
      "main": [
        [
          {
            "node": "Des changements ?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Des changements ?": {
      "main": [
        [
          {
            "node": "Generer le contenu de la fiche RNCP",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Fiche deja a jour",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generer le contenu de la fiche RNCP": {
      "main": [
        [
          {
            "node": "Publier la fiche sur le site",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Publier la fiche sur le site": {
      "main": [
        [
          {
            "node": "Journaliser la mise a jour",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Journaliser la mise a jour": {
      "main": [
        [
          {
            "node": "Notifier l'equipe pedagogique",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generation a la demande": {
      "main": [
        [
          {
            "node": "Normaliser la demande",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normaliser la demande": {
      "main": [
        [
          {
            "node": "Recuperer la fiche officielle",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "314268b3-b875-4987-a2bf-1ff5e6206dce",
  "meta": {
    "instanceId": "5f7c1a2b9d3e4f60a8b7c6d5e4f3021998af77bc12de34ff56aa7788bb99ccdd",
    "templateCredsSetupCompleted": true
  },
  "tags": []
}
