Agent gériatre B) le moteur de scoring > Où inscrire ça dans Odoo ?

1️⃣ Où inscrire ça dans Odoo ?

Je te conseille un modèle dédié “Entretien gériatrique” relié au patient.

🔹 Modèle principal

  • Nom modèle technique : x_synergia_geriatrie_entretien
  • Module de base : Contacts (et éventuellement CRM / Helpdesk si tu veux des tickets)
  • Relations clés :
    • patient_id → res.partner (le senior)
    • responsable_id → res.users ou res.partner (pharmacien / infirmier / coordinateur)
    • un entretien = un JSON “figé” + scores

Tu pourras ensuite voir :

  • onglet “Gériatrie” sur la fiche contact ODOO  (patient)
  • liste des entretiens gériatriques par patient
  • filtres : niveau de risque, alertes actives, etc.

2️⃣ Mapping JSON → Odoo (Odoo Studio)

a) JSON de départ

{ "profil": { "age": 82, "habitat": "seul", "aidant": true }, "scores": { "autonomie": 55, "cognitif": 40, "chute": 80, "nutrition": 60, "moral": 65 }, "fragilite_globale": 68, "niveau_risque": "élevé", "alertes": ["chute", "isolement", "oubli traitement"], "recommandations": [ "aménagement salle de bain", "visite infirmière", "bilan gériatrique", "appel de suivi hebdomadaire" ] }

b) Champs à créer dans x_synergia_geriatrie_entretien

JSON pathChamp OdooType OdooCommentaire
profil.agex_ageIntegerÂge au moment de l’entretien (snapshot)
profil.habitatx_habitatSelectionValeurs : seul, conjoint, famille, institution…
profil.aidantx_has_aidantBoolean“Aidant identifié (oui/non)”
(lié patient)x_patient_idMany2one res.partnerLe senior concerné
(évaluateur)x_responsable_idMany2one res.users ou res.partnerPharmacien / infirmier / coordinateur
scores.autonomiex_score_autonomieInteger0–100
scores.cognitifx_score_cognitifInteger0–100
scores.chutex_score_chuteInteger0–100
scores.nutritionx_score_nutritionInteger0–100
scores.moralx_score_moralInteger0–100
fragilite_globalex_fragilite_globaleIntegerScore global 0–100
niveau_risquex_niveau_risqueSelectionfaible / modéré / élevé
alertes (liste)x_alertes_jsonTextStocker la liste JSON brute (facile côté API)
recommandations (liste)x_recommandations_textText (multiligne)Reco lisibles pour humain
(trace brute entretien)x_raw_payload_jsonTextOptionnel : stocker tout le JSON d’origine
(date entretien)x_date_entretienDatetimePour l’historique / tri
(canal : voix / texte)x_canalSelectionvoix / texte / mixte

Simple & Odoo Online-friendly : on garde les listes (alertes, recommandations) en TEXT/JSON. Tu pourras les normaliser en modèles dédiés plus tard si besoin (tags, etc.).


c) Mise en forme dans l’interface

Avec Odoo Studio :

  • Vue formulaire “Entretien gériatrique”
    • En haut : patient, date, niveau de risque (badge coloré)
    • Bloc “Scores” avec jauges ou au moins champs numériques
    • Bloc “Alertes” (zone texte + tags visuels)
    • Bloc “Recommandations” (multi-ligne, lisible pour le pharmacien / infirmier)
  • Vue liste :
    • Colonnes : Patient, Date, Niveau_risque, Score global, Nb d’alertes
    • Filtre rapide : Risque élevé uniquement
  • Sur fiche Contact (patient) :
    • Onglet “Synergia Senior / Gériatrie”
    • Smart button : “Entretiens gériatriques (N)”

3️⃣ Organisation avec n8n : le bot dans la boucle

🧩 Idée générale


  1. Le bot / WebApp collecte l’entretien (voix/texte).
  2. Le moteur d’IA + scoring produit le JSON ci-dessus.
  3. n8n reçoit ce JSON → le transforme → l’injecte dans Odoo via API.
  4. n8n peut ensuite :
    • créer des activités / tâches,
    • déclencher notifications,
    • alimenter des dashboards.


🔁 Flow n8n type

Node 1 – Webhook “Entretien gériatrique terminé”

  • Type : Webhook
  • Méthode : POST
  • Reçoit un body ≈ ton JSON :

{ "patient_external_id": "PAT-000123", "entretien": { "profil": {...}, "scores": {...}, "fragilite_globale": 68, "niveau_risque": "élevé", "alertes": [...], "recommandations": [...] } }


Node 2 – Function (mapping vers Odoo)

En JS dans n8n, tu prépares le payload pour Odoo :

const body = items[0].json.entretien; const patientExtId = items[0].json.patient_external_id; // Exemple : on suppose que patient_external_id = ref dans res.partner return [{ json: { model: "x_synergia_geriatrie_entretien", values: { x_patient_id: { ref: patientExtId }, // ou un id numérique résolu avant x_age: body.profil.age, x_habitat: body.profil.habitat, x_has_aidant: body.profil.aidant, x_score_autonomie: body.scores.autonomie, x_score_cognitif: body.scores.cognitif, x_score_chute: body.scores.chute, x_score_nutrition: body.scores.nutrition, x_score_moral: body.scores.moral, x_fragilite_globale: body.fragilite_globale, x_niveau_risque: body.niveau_risque, x_alertes_json: JSON.stringify(body.alertes || []), x_recommandations_text: (body.recommandations || []).join("\n"), x_raw_payload_json: JSON.stringify(body), x_date_entretien: new Date().toISOString(), x_canal: items[0].json.canal || "texte" } } }];

(À adapter selon ta stratégie d’identification patient : id direct, ref, email, etc.)

Node 3 – HTTP Request → Odoo /web/dataset/call_kw

  • Méthode : POST
  • URL : https://ton_instance.odoo.com/web/dataset/call_kw
  • Body JSON (exemple) :

{ "jsonrpc": "2.0", "method": "call", "params": { "model": "x_synergia_geriatrie_entretien", "method": "create", "args": [ { "x_patient_id": 123, "x_age": 82, "x_habitat": "seul", "x_has_aidant": true, "x_score_autonomie": 55, "x_score_cognitif": 40, "x_score_chute": 80, "x_score_nutrition": 60, "x_score_moral": 65, "x_fragilite_globale": 68, "x_niveau_risque": "élevé", "x_alertes_json": "[\"chute\",\"isolement\"]", "x_recommandations_text": "aménagement salle de bain\nvisite infirmière", "x_raw_payload_json": "{...}", "x_date_entretien": "2025-11-27T14:00:00", "x_canal": "voix" } ], "kwargs": {} } }

Auth : session Odoo ou token API (selon ce que tu mets en place).

Dans n8n : soit en Basic Auth si reverse proxy, soit cookie de session, soit Bearer si tu as un module d’API.


Node 4 – Règles et notifications

Tu peux enchaîner avec :

  • IF node : si fragilite_globale >= 67 ou niveau_risque == "élevé"
    • Node : envoyer un email au pharmacien
    • Node : créer une Activité sur le patient dans Odoo (modèle mail.activity)
    • Node : ping sur un canal Slack / Teams “Risque élevé détecté”

4️⃣ En résumé (stratégie)

  1. Odoo Studio
    • Créer x_synergia_geriatrie_entretien
    • Ajouter tous les champs du JSON (profil, scores, fragilité, alertes, recos, raw JSON)
    • Lier au patient (Many2one res.partner)
    • Ajouter un onglet “Gériatrie” sur la fiche patient
  2. n8n
    • Webhook ← reçoit le JSON de ton agent IA
    • Function → mappe vers values Odoo
    • HTTP Request → create dans x_synergia_geriatrie_entretien
    • IF → déclenche des actions (email, activité, etc.)
  3. Bot
    • Continue à faire la conversation, scoring, etc.
    • n8n devient la colonne vertébrale d’intégration entre ton bot et Odoo.

ANNEXES

A1- tableau complet des champs Odoo Studio “prêt à créer” (nom technique, label FR, type, aide),

Parfait, on passe en mode Odoo Studio ready 🧩

Voici le tableau complet des champs à créer pour le modèle x_synergia_geriatrie_entretien, couvrant tout ton JSON + ce qu’il faut pour travailler confortablement dans Odoo.

💡 Tu pourras regrouper ces champs en onglets “Profil”, “Scores”, “Alertes & recommandations”, “Technique” dans la vue formulaire.

🧱 Modèle Odoo

  • Nom technique du modèle : x_synergia_geriatrie_entretien
  • Nom affiché : Entretien gériatrique
  • Base : module Contacts (lié à res.partner)

📋 Tableau des champs Odoo Studio

SectionLabel FRNom techniqueType OdooRequisValeurs / DomaineAide (tooltip)
🔗 Identification / liensIntitulé de l’entretienx_nameTexte (Char)NonTitre court de l’entretien (ex. “Entretien gériatrique de novembre 2025”).
🔗 Identification / liensPatientx_patient_idMany2one → res.partnerOuiDomain : contact de type “personne”Patient concerné par cet entretien.
🔗 Identification / liensResponsable Synergiax_responsable_idMany2one → res.users ou res.partnerNonProfessionnel ayant conduit ou validé l’entretien (pharmacien, infirmier, coordinateur…).
🔗 Identification / liensDate de l’entretienx_date_entretienDatetimeOuiDate et heure de réalisation de l’entretien.
🔗 Identification / liensCanal d’entréex_canalSélectionNonvoix, texte, mixteCanal principal utilisé par le patient (voix / texte).
👤 ProfilÂge au moment de l’entretienx_ageEntier (Integer)NonÂge du patient au moment de l’entretien (photo instantanée).
👤 ProfilHabitatx_habitatSélectionNonseul, conjoint, famille, institution, autreSituation de vie principale du patient.
👤 ProfilAidant identifiéx_has_aidantBooléenNonCocher si un aidant (proche, voisin, professionnel) est identifié.
📊 ScoresScore autonomiex_score_autonomieEntierNon0–100Score 0–100 calculé à partir des réponses sur les activités de la vie quotidienne.
📊 ScoresScore cognitifx_score_cognitifEntierNon0–100Score 0–100 estimant le risque de troubles cognitifs.
📊 ScoresScore risque de chutex_score_chuteEntierNon0–100Score 0–100 pour le risque de chute (chutes, peur de tomber, blessures…).
📊 ScoresScore nutritionx_score_nutritionEntierNon0–100Score 0–100 relatif au risque de dénutrition / hydratation insuffisante.
📊 ScoresScore moral / psycho-socialx_score_moralEntierNon0–100Score 0–100 sur l’isolement, le moral, la perte d’intérêt.
📊 ScoresScore global de fragilitéx_fragilite_globaleEntierNon0–100Score global agrégé de fragilité gériatrique.
📊 ScoresNiveau de risque globalx_niveau_risqueSélectionNonfaible, modere, eleveCatégorie globale : faible / modéré / élevé (dérivée du score global).
🚨 Alertes & recommandationsAlertes (JSON brut)x_alertes_jsonTexte (Text)NonListe JSON des alertes générées par l’IA (ex. ["chute","isolement","oubli traitement"]).
🚨 Alertes & recommandationsAlertes (lecture humaine)x_alertes_labelTexte (Text) ou CharNonVersion lisible des alertes (ex. “Risque de chute ; Isolement ; Oubli de traitement”).
🚨 Alertes & recommandationsRecommandations (texte)x_recommandations_textTexte (Text, multi-ligne)NonSynthèse des recommandations : aménagement, visites, bilans, appels de suivi…
🛠 Technique / auditPayload JSON brutx_raw_payload_jsonTexte (Text)NonJSON complet renvoyé par le moteur d’IA (pour audit ou recalcul).
🛠 Technique / auditRéférence externe (entretien bot)x_external_refTexte (Char)NonIdentifiant de l’entretien côté WebApp / bot / n8n (trace technique, corrélation).

🧭 Comment les utiliser dans Odoo Studio (concrètement)

  1. Créer le modèle
    • Ouvrir Contacts → Studio → Nouveau modèle → “Entretien gériatrique”
    • Nom technique : x_synergia_geriatrie_entretien
  2. Créer les champs selon le tableau
    • Respecter les noms techniques (colonne Nom technique)
    • Utiliser les types indiqués
    • Pour les sélections, saisir exactement les valeurs proposées (clé technique en minuscules, sans accent de préférence).
  3. Lier au patient
    • Champ x_patient_id (Many2one → Contact)
    • Dans la fiche Contact : ajouter un smart button “Entretiens gériatriques” et/ou un onglet “Gériatrie” qui liste les enregistrements de x_synergia_geriatrie_entretien.
  4. Préparer l’injection via n8n / API
    • Ton flow n8n fera un create sur x_synergia_geriatrie_entretien en mappant le JSON :
      • profil.age → x_age
      • scores.autonomie → x_score_autonomie
      • etc. (champ par champ, le mapping est 1:1 grâce à ce tableau).

A2- exemple de flow n8n écrit “node par node” que tu peux reconstituer.

Parfait, on passe en mode n8n architecte 🧠⚙️

Je te propose un flow complet ultra simple :

  • le bot envoie le JSON d’entretien →
  • n8n le reçoit →
  • crée l’enregistrement x_synergia_geriatrie_entretien dans Odoo →
  • envoie une alerte si risque élevé.

Je pars sur le cas le plus simple et robuste :

👉 le front / bot envoie déjà patient_id (id Odoo) dans le POST.

🔁 Flow n8n : “Synergia – Enregistrement entretien gériatrique dans Odoo”

🌐 Node 1 – Webhook “Entretien gériatrique terminé”

  • Type : Webhook
  • Nom : Webhook – Entretien gériatrique
  • Méthode : POST
  • Path : /synergia/geriatrie/entretien
  • Response :
    • Mode : On Received
    • Body : application/json
    • Réponse basique : { "status": "received" }

Body attendu (exemple) côté bot

{ "patient_id": 123, // ID Odoo du patient (res.partner) "canal": "voix", // "voix" | "texte" | "mixte" "entretien": { "profil": { "age": 82, "habitat": "seul", "aidant": true }, "scores": { "autonomie": 55, "cognitif": 40, "chute": 80, "nutrition": 60, "moral": 65 }, "fragilite_globale": 68, "niveau_risque": "élevé", "alertes": ["chute", "isolement", "oubli traitement"], "recommandations": [ "aménagement salle de bain", "visite infirmière", "bilan gériatrique", "appel de suivi hebdomadaire" ] } }

🧮 Node 2 – Function “Build Odoo Payload”

  • Type : Function
  • Nom : Build Odoo Payload

Ce node transforme le JSON d’entrée en un payload Odoo propre pour call_kw.

Code

const input = items[0].json; const patientId = input.patient_id; const canal = input.canal || "texte"; const body = input.entretien || {}; const profil = body.profil || {}; const scores = body.scores || {}; const alertes = body.alertes || []; const recommandations = body.recommandations || []; return [ { json: { jsonrpc: "2.0", method: "call", params: { model: "x_synergia_geriatrie_entretien", method: "create", args: [ { x_patient_id: patientId, x_age: profil.age || null, x_habitat: profil.habitat || null, x_has_aidant: !!profil.aidant, x_score_autonomie: scores.autonomie ?? null, x_score_cognitif: scores.cognitif ?? null, x_score_chute: scores.chute ?? null, x_score_nutrition: scores.nutrition ?? null, x_score_moral: scores.moral ?? null, x_fragilite_globale: body.fragilite_globale ?? null, x_niveau_risque: body.niveau_risque || null, x_alertes_json: JSON.stringify(alertes), x_alertes_label: alertes.join(" ; "), x_recommandations_text: recommandations.join("\n"), x_raw_payload_json: JSON.stringify(body), x_date_entretien: new Date().toISOString(), x_canal: canal, // Optionnel : titre lisible x_name: `Entretien gériatrique – patient #${patientId}` } ], kwargs: {} } } } ];

👉 Après ce node, items[0].json est directement le body JSON à envoyer à Odoo sur /web/dataset/call_kw.

🧷 Node 3 – HTTP Request “Odoo – Create Entretien”

🧷 Node 3 – HTTP Request “Odoo – Create Entretien”

  • Type : HTTP Request
  • Nom : Odoo – Create Entretien
  • Méthode : POST
  • URL : https://TON_INSTANCE.odoo.com/web/dataset/call_kw

Authentification

Selon ton setup :

  • soit Basic Auth (proxy devant Odoo),
  • soit API Key / Bearer en Header,
  • soit cookie de session si tu sais le gérer dans n8n.

Exemple simple (Headers) :

  • Header : Content-Type: application/json
  • Header : X-Api-Key: TON_TOKEN (si tu as un module API)

Body

  • Content Type : JSON
  • Body : {{ JSON.stringify($json) }}

Le $json ici est exactement celui généré dans le node précédent.

Réponse Odoo

En général :

{ "jsonrpc": "2.0", "id": null, "result": 456 // ID de l'entretien créé }

Tu peux récupérer entretien_id = $json.result dans le node suivant.

🚨 Node 4 – IF “High Risk ?”

🚨 Node 4 – IF “High Risk ?”

  • Type : IF
  • Nom : IF – Risque élevé ?

On veut déclencher des actions si risque fort.

Comme le JSON original est sur le Webhook, on a deux options :

  • soit on rebranche le Webhook sur l’IF via un second output,
  • soit on passe les infos utiles via meta (simplifions).

Le plus simple : on branche l’IF juste après le Webhook, en parallèle du Flow “Odoo”.

Configuration de l’IF

  • Condition 1 :
    • Value 1 : {{$json.entretien.fragilite_globale}}
    • Operation : larger
    • Value 2 : 66
  • OU
  • Condition 2 :
    • Value 1 : {{$json.entretien.niveau_risque}}
    • Operation : equal
    • Value 2 : élevé

Tu peux cocher “Combine” → Any (au moins une des conditions vraie).

✉️ Node 5 (branche TRUE) – Notification (ex: Email)

5a – Email “Alerte gériatrique”

  • Type : Email
  • Nom : Email – Alerte risque élevé
  • Config :
    • To : adresse du pharmacien / coordinateur, ou liste.
    • Subject : Alerte Synergia – Risque gériatrique élevé
    • Body (HTML ou texte) :

Un entretien gériatrique signale un niveau de risque élevé. Patient ID Odoo : {{ $json.patient_id }} Score global de fragilité : {{ $json.entretien.fragilite_globale }} Niveau de risque : {{ $json.entretien.niveau_risque }} Alertes : {{ $json.entretien.alertes.join(", ") }} Recommandations proposées : {{ $json.entretien.recommandations.join("\n") }}

5b – (option) HTTP Request “Odoo – Créer activité”

Si tu veux aussi créer une activité de suivi sur le patient :

  • Type : HTTP Request
  • Nom : Odoo – Create Activity
  • URL : https://TON_INSTANCE.odoo.com/web/dataset/call_kw
  • Body (exemple, modèle mail.activity) :

{ "jsonrpc": "2.0", "method": "call", "params": { "model": "mail.activity", "method": "create", "args": [ { "res_model": "res.partner", "res_id": {{ $json.patient_id }}, "activity_type_id": 1, "summary": "Suivi gériatrique – risque élevé", "note": "Un entretien gériatrique a détecté un risque élevé.\nScore global : " + {{ $json.entretien.fragilite_globale }} + "\nAlertes : " + {{ $json.entretien.alertes.join(", ") }} } ], "kwargs": {} } }

(tu adapteras activity_type_id en fonction de ta config Odoo)

🧱 Vue d’ensemble du flow


  1. Webhook – Entretien gériatrique
    ↳ reçoit le JSON depuis ton bot.
  2. [Branche A]
    2.1. Build Odoo Payload
    2.2. Odoo – Create Entretien
  3. [Branche B] (en parallèle)
    3.1. IF – Risque élevé ?
    3.2. Si vrai → Email – Alerte risque élevé (+ optionnel Odoo – Create Activity)


flow mais dans le cas où tu ne connais PAS patient_id et tu dois d’abord faire un search_read sur res.partner à partir d’un external_ref ou d’un email.

Parfait, on passe à la version “réaliste” : tu ne connais pas patient_id, tu as juste une référence externe (ex. external_ref) ou un email.

On va faire :

  1. Webhook reçoit le JSON (avec patient_external_ref ou patient_email)
  2. n8n fait un search_read sur res.partner pour trouver le patient
  3. récupère id
  4. crée l’x_synergia_geriatrie_entretien dans Odoo
  5. en parallèle : IF risque élevé → alertes

🧩 0. Payload côté bot (entrante)

On suppose que ton bot envoie un truc du genre :

{ "patient_external_ref": "PAT-000123", // ou null "patient_email": "jeanne.dupont@example.com", // fallback "canal": "voix", "entretien": { "profil": { "age": 82, "habitat": "seul", "aidant": true }, "scores": { "autonomie": 55, "cognitif": 40, "chute": 80, "nutrition": 60, "moral": 65 }, "fragilite_globale": 68, "niveau_risque": "élevé", "alertes": ["chute", "isolement", "oubli traitement"], "recommandations": [ "aménagement salle de bain", "visite infirmière", "bilan gériatrique", "appel de suivi hebdomadaire" ] } }

👉 Pas de patient_id ici.

🌐 Node 1 – Webhook “Entretien gériatrique”

Identique au flow précédent, sauf que le body n’a plus patient_id.

On garde le même path : /synergia/geriatrie/entretien.

🔍 Node 2 – Function “Build Search Patient Query”

On prépare le domain pour search_read Odoo sur res.partner.

  • Type : Function
  • Nom : Build Patient Search Query

Code

const input = items[0].json; const externalRef = input.patient_external_ref || null; const email = input.patient_email || null; if (!externalRef && !email) { throw new Error("Aucun identifiant patient fourni (external_ref ou email manquant)."); } // On prépare le domain pour Odoo let domain; if (externalRef) { // Suppose qu'on utilise un champ x_external_ref sur res.partner domain = [["x_external_ref", "=", externalRef]]; } else { domain = [["email", "=", email]]; } return [ { json: { domain, original: input // on garde le payload original pour la suite } } ];

🧵 Node 3 – HTTP Request “Odoo – search_read Patient”

  • Type : HTTP Request
  • Nom : Odoo – search_read Patient
  • Méthode : POST
  • URL : https://TON_INSTANCE.odoo.com/web/dataset/call_kw
  • Headers : Content-Type: application/json (+ auth comme d’habitude)

Body (JSON)

{ "jsonrpc": "2.0", "method": "call", "params": { "model": "res.partner", "method": "search_read", "args": [ {{ $json.domain }}, ["id", "name", "email", "x_external_ref"] ], "kwargs": { "limit": 2 } } }

Dans n8n, tu écris le body comme :

return JSON.stringify({ jsonrpc: "2.0", method: "call", params: { model: "res.partner", method: "search_read", args: [ $json.domain, ["id", "name", "email", "x_external_ref"] ], kwargs: { limit: 2 } } });

⚠️ limit: 2 permet de détecter les doublons (0, 1 ou >1 résultats).

✅ Node 4 – Function “Extract Patient ID”


On récupère le résultat de search_read et on gère les cas :

  • 0 résultat → erreur / log / pas d’insertion
  • 1 résultat → ok
  • 1 résultat → au choix : prendre le 1er ou lever une alerte

  • Type : Function
  • Nom : Extract Patient ID

Code

// items[0].json contient la réponse d'Odoo const res = items[0].json; const result = res.result || []; if (!Array.isArray(result)) { throw new Error("Réponse Odoo inattendue sur search_read"); } if (result.length === 0) { throw new Error("Aucun patient trouvé pour ce critère (external_ref / email)."); } if (result.length > 1) { // Selon stratégie : ici on prend le premier, mais tu peux aussi throw // throw new Error("Plusieurs patients trouvés, ambiguïté."); console.warn("Plusieurs patients trouvés, premier utilisé."); } const patient = result[0]; const patientId = patient.id; // On récupère aussi le payload original du Webhook. // Astuce : on le passait dans "original" depuis le node 2. // Donc on doit l’avoir dans un autre branchement… // Simplifions : on va supposer que tu rebranches le Webhook sur ce node // via un Merge node. Je te donne la version “après Merge” : // Ici, on va supposer que tu merges "search_read" avec "originalPayload" plus loin. // Donc ce node ne garde que patientId pour l'instant. return [ { json: { patient_id: patientId, patient_name: patient.name, patient_email: patient.email, patient_external_ref: patient.x_external_ref || null } } ];

👉 Pour être propre, on va utiliser un Merge Node ensuite pour fusionner :

  • le patient_id trouvé
  • le payload original d’entretien reçu au Webhook

🔗 Node 5 – Merge “Patient + Entretien”


On a 2 branches qui remontent ici :

  1. Branche A : depuis le Webhook (payload original)
  2. Branche B : depuis Extract Patient ID (patient info)
  • Type : Merge
  • Mode : Merge by Index (simple, un seul item dans chaque branche)
  • Nom : Merge – Patient + Entretien

Résultat attendu :

{ "patient_id": 123, "patient_name": "Jeanne Dupont", "patient_email": "jeanne.dupont@example.com", "patient_external_ref": "PAT-000123", "entretien": { ... }, "canal": "voix" }

Tu peux y arriver en branchant :

  • Sortie du Webhook → Input 1 du Merge
  • Sortie du node “Extract Patient ID” → Input 2 du Merge

🧮 Node 6 – Function “Build Odoo Entretien Payload”


C’est l’équivalent du Build Odoo Payload d’avant, mais sur la base du JSON fusionné.

  • Type : Function
  • Nom : Build Odoo Entretien Payload

Code

const input = items[0].json; const patientId = input.patient_id; const canal = input.canal || "texte"; const body = input.entretien || {}; const profil = body.profil || {}; const scores = body.scores || {}; const alertes = body.alertes || []; const recommandations = body.recommandations || []; return [ { json: { jsonrpc: "2.0", method: "call", params: { model: "x_synergia_geriatrie_entretien", method: "create", args: [ { x_patient_id: patientId, x_age: profil.age || null, x_habitat: profil.habitat || null, x_has_aidant: !!profil.aidant, x_score_autonomie: scores.autonomie ?? null, x_score_cognitif: scores.cognitif ?? null, x_score_chute: scores.chute ?? null, x_score_nutrition: scores.nutrition ?? null, x_score_moral: scores.moral ?? null, x_fragilite_globale: body.fragilite_globale ?? null, x_niveau_risque: body.niveau_risque || null, x_alertes_json: JSON.stringify(alertes), x_alertes_label: alertes.join(" ; "), x_recommandations_text: recommandations.join("\n"), x_raw_payload_json: JSON.stringify(body), x_date_entretien: new Date().toISOString(), x_canal: canal, x_name: `Entretien gériatrique – ${input.patient_name || ("patient #" + patientId)}` } ], kwargs: {} } } } ];


🧷 Node 7 – HTTP Request “Odoo – Create Entretien”

Identique à avant :

  • Type : HTTP Request
  • Nom : Odoo – Create Entretien
  • Méthode : POST
  • URL : https://TON_INSTANCE.odoo.com/web/dataset/call_kw
  • Body : {{ JSON.stringify($json) }}
  • Headers : Content-Type: application/json + auth

🚨 Branche risque élevé : IF + Email (en parallèle)

Comme précédemment, tu peux faire :

  • Sortie du Merge ou du Webhook → IF – Risque élevé ?
  • Puis Email – Alerte gériatrique + éventuellement Odoo – Create Activity

Node IF – “Risque élevé ?”

  • Type : IF
  • Nom : IF – Risque élevé ?

Conditions :

  • {{$json.entretien.fragilite_globale}} > 66
    OU
  • {{$json.entretien.niveau_risque}} equal élevé

Node Email – “Alerte risque élevé”

Exemple de corps :

Alerte Synergia : risque gériatrique élevé détecté. Patient externe : {{ $json.patient_external_ref || 'N/A' }} Email patient : {{ $json.patient_email || 'N/A' }} Score global de fragilité : {{ $json.entretien.fragilite_globale }} Niveau de risque : {{ $json.entretien.niveau_risque }} Alertes : {{ $json.entretien.alertes.join(", ") }} Merci de vérifier la situation et de planifier un suivi.

🧱 Résumé des nodes dans l’ordre logique

  1. Webhook – Entretien gériatrique
  2. Function – Build Patient Search Query
  3. HTTP – Odoo search_read Patient
  4. Function – Extract Patient ID
  5. Merge – Patient + Entretien
  6. Function – Build Odoo Entretien Payload
  7. HTTP – Odoo Create Entretien

En parallèle depuis le Webhook ou le Merge :

  1. IF – Risque élevé ?
  2. Email – Alerte (+ optionnel : HTTP – Odoo Create Activity)

ANNEXE

Décrire les champs res.partner à prévoir (ex. x_external_ref, “type patient”, etc.),

Excellent choix — la qualité de votre modèle res.partner conditionne toute la robustesse du système (reconnaissance patient, historique, IA, RGPD, interopérabilité).

Voici donc le modèle patient Odoo idéal pour Synergia Senior : minimal mais structurant.

🧩 res.partner — Champs à prévoir dans Odoo Studio

(Fiche patient enrichie — base de tout le système gériatrique)

🎯 Objectifs du modèle

Votre fiche Contact devient :

  • une identité patient stable,
  • une clé d’interopérabilité avec vos apps (bot, web, téléphone),
  • un point d’ancrage pour les entretiens, scores, alertes,
  • une base RGPD propre.

✅ Champs obligatoires (fondation technique)

Label FRNom techniqueType OdooRequisUtilité
Identifiant externe patientx_external_refCharID unique venant du bot / mobile / système externe
Type de contactx_contact_typeSelectionpatient, aidant, professionnel, etablissement
Consentement entretien IAx_consent_aiBooleanAutorisation légale entretien IA
Autorisation stockage donnéesx_consent_dataBooleanRGPD : accord stockage
Date consentementx_consent_dateDatetimeTrace légale
Canal préféréx_preferred_channelSelectionNonvoix, sms, email, whatsapp, app
Langue préféréex_languageSelectionNonfr, mg, en, etc.

🧬 Identity & démographie

Label FRNom techniqueType OdooCommentaire
Date de naissancebirthdate_dateDateChamp standard Odoo
Sexex_genderSelectionhomme, femme, autre
Situation familialex_family_statusSelectionseul, couple, famille, institution
Nationalitéx_nationalityCharOptionnel
Langue maternellex_native_languageCharUtile pour API voix

🏠 Habitat & contexte de vie

Label FRNom techniqueType
Type d’habitatx_housing_typeSelection
Présence d’escaliersx_has_stairsBoolean
Type de logementx_home_typeSelection
Vit seulx_living_aloneBoolean
Vit en zone isoléex_geo_isolatedBoolean

❤️ Santé & dépendance (haut niveau)

Label FRNom techniqueType
Affection de longue durée (ALD)x_has_aldBoolean
Niveau de dépendancex_dependency_levelSelection (autonome, fragile, dependent)
Mobilitéx_mobility_levelSelection
Troubles cognitifs connusx_known_cognitive_issueBoolean
Chutes récentesx_recent_fallsBoolean

⚠️ Ces champs sont déclaratifs, pas médicaux (conformité réglementaire).

👪 Aidants & entourage

Label FRNom techniqueType
Aidant principalx_main_caregiver_idMany2one → res.partner
Type de relationx_caregiver_relationSelection
Présence d’aidantx_has_caregiverBoolean
Aidant épuisé (signalé)x_caregiver_burnoutBoolean

🔗 Interopérabilité & systèmes

Label FRNom techniqueType
Compte bot liéx_bot_account_idChar
ID téléphone systèmex_telephony_idChar
Origine des donnéesx_data_sourceSelection (bot, pharmacie, infirmier, web, import)
Dernier entretien IAx_last_ai_interviewDatetime
Score dernière fragilitéx_last_fragility_scoreInteger
Niveau dernier risquex_last_risk_levelSelection

🔐 Conformité RGPD & audit

Label FRNom techniqueType
Traitement autoriséx_data_processing_okBoolean
ACL niveaux_access_levelSelection
Date dernière mise à jour donnéesx_last_data_updateDatetime
Source du dernier consentementx_consent_sourceSelection

✅ Champs minimum viables (MVP)

Si tu veux démarrer vite et propre, crée d’abord ces 10 champs essentiels :

ChampNom technique
ID externex_external_ref
Type contactx_contact_type
Consentement IAx_consent_ai
Consentement datax_consent_data
Date consentementx_consent_date
Canal préféréx_preferred_channel
Languex_language
Aidant présentx_has_caregiver
Dernier scorex_last_fragility_score
Dernier risquex_last_risk_level

🔁 Chauffage automatique via n8n

Après chaque entretien gériatrique, n8n pourra :

Mettre à jour res.partner automatiquement :

write res.partner: x_last_ai_interview = now() x_last_fragility_score = fragilite_globale x_last_risk_level = niveau_risque

Et éventuellement :

si risque élevé: x_dependency_level = "fragile"

✅ Vision cible

Avec ces champs :

  • Odoo devient votre DMP patient senior (mini dossier médico-social),
  • n8n devient votre orchestrateur,
  • l’IA devient votre capteur humain.

Si vous voulez, je peux maintenant vous livrer :

✅ le mapping JSON → res.partner write prêt pour n8n

✅ les vues Odoo Studio recommandées (onglet “Synergia Senior”)

✅ le schéma global architecture Synergia Senior (bot → n8n → Odoo)

✅ un module prédictif basé sur l’évolution des scores

Dis-moi ce que tu veux prendre ensuite 👇

Faire un “mini schéma JSON-RPC Odoo global” pour toute la chaîne (bot → n8n → Odoo),

Parfait, on va faire un “mini schéma contractuel” de tout le pipeline, côté JSON & JSON-RPC Odoo.

Je te le découpe en 4 blocs :

  1. Contrat bot → n8n (Webhook)
  2. Appels JSON-RPC Odoo : res.partner.search_read
  3. Appels JSON-RPC Odoo : x_synergia_geriatrie_entretien.create
  4. Appels JSON-RPC Odoo : res.partner.write (mise à jour patient)

1️⃣ Contrat bot → n8n (Webhook)

1.1. URL Webhook n8n

POST https://ton-n8n.com/webhook/synergia/geriatrie/entretien Content-Type: application/json

1.2. Body JSON attendu

{ "patient_external_ref": "PAT-000123", // option 1 (préférée) "patient_email": "jeanne.dupont@example.com", // option 2 (fallback) "canal": "voix", // "voix" | "texte" | "mixte" "entretien": { "profil": { "age": 82, "habitat": "seul", "aidant": true }, "scores": { "autonomie": 55, "cognitif": 40, "chute": 80, "nutrition": 60, "moral": 65 }, "fragilite_globale": 68, "niveau_risque": "élevé", "alertes": ["chute", "isolement", "oubli traitement"], "recommandations": [ "aménagement salle de bain", "visite infirmière", "bilan gériatrique", "appel de suivi hebdomadaire" ] } }

👉 n8n reçoit toujours ce format.

Ensuite il décide :

  1. trouver le patient dans Odoo
  2. créer l’entretien
  3. éventuellement mettre à jour res.partner.

2️⃣ JSON-RPC Odoo – res.partner.search_read

Objectif : retrouver patient_id à partir de x_external_ref ou email.

2.1. URL & headers

POST https://ton-instance.odoo.com/web/dataset/call_kw Content-Type: application/json ( + Auth : selon ton setup )

2.2. search_read par x_external_ref

{ "jsonrpc": "2.0", "method": "call", "params": { "model": "res.partner", "method": "search_read", "args": [ [["x_external_ref", "=", "PAT-000123"]], ["id", "name", "email", "x_external_ref"] ], "kwargs": { "limit": 2 } } }

2.3. search_read par email (fallback)

{ "jsonrpc": "2.0", "method": "call", "params": { "model": "res.partner", "method": "search_read", "args": [ [["email", "=", "jeanne.dupont@example.com"]], ["id", "name", "email", "x_external_ref"] ], "kwargs": { "limit": 2 } } }

2.4. Réponse attendue

{ "jsonrpc": "2.0", "id": null, "result": [ { "id": 123, "name": "Jeanne Dupont", "email": "jeanne.dupont@example.com", "x_external_ref": "PAT-000123" } ] }

👉 n8n extrait patient_id = result[0].id.

3️⃣ JSON-RPC Odoo – x_synergia_geriatrie_entretien.create

Objectif : créer un enregistrement d’entretien avec les champs Studio que tu as définis.

3.1. URL & headers

Toujours :

POST https://ton-instance.odoo.com/web/dataset/call_kw Content-Type: application/json

3.2. Payload type (après mapping n8n)

{ "jsonrpc": "2.0", "method": "call", "params": { "model": "x_synergia_geriatrie_entretien", "method": "create", "args": [ { "x_patient_id": 123, "x_age": 82, "x_habitat": "seul", "x_has_aidant": true, "x_score_autonomie": 55, "x_score_cognitif": 40, "x_score_chute": 80, "x_score_nutrition": 60, "x_score_moral": 65, "x_fragilite_globale": 68, "x_niveau_risque": "élevé", "x_alertes_json": "[\"chute\",\"isolement\",\"oubli traitement\"]", "x_alertes_label": "chute ; isolement ; oubli traitement", "x_recommandations_text": "aménagement salle de bain\nvisite infirmière\nbilan gériatrique\nappel de suivi hebdomadaire", "x_raw_payload_json": "{... JSON complet de entretien ...}", "x_date_entretien": "2025-11-27T14:25:00", "x_canal": "voix", "x_name": "Entretien gériatrique – Jeanne Dupont" } ], "kwargs": {} } }

3.3. Réponse attendue

{ "jsonrpc": "2.0", "id": null, "result": 456 }

👉 456 = id de l’entretien créé (utile si tu veux le réutiliser juste après).

4️⃣ JSON-RPC Odoo – res.partner.write (mise à jour du patient)

Objectif : garder sur la fiche patient une vue synthétique du dernier entretien.

Exemple : mettre à jour :

  • x_last_ai_interview
  • x_last_fragility_score
  • x_last_risk_level

4.1. Payload write

{ "jsonrpc": "2.0", "method": "call", "params": { "model": "res.partner", "method": "write", "args": [ [123], { "x_last_ai_interview": "2025-11-27T14:25:00", "x_last_fragility_score": 68, "x_last_risk_level": "élevé" } ], "kwargs": {} } }

4.2. Réponse attendue

{ "jsonrpc": "2.0", "id": null, "result": true }

5️⃣ Vue synthétique de la chaîne (contrat global)

5.1. Résumé “du point de vue de chaque acteur”

ActeurEnvoieReçoit
BotJSON “Entretien” → Webhook n8n200 OK simple ({"status":"received"})
n8nJSON-RPC search_read / create / write → OdooJSON-RPC result
OdooN/Areçoit les call_kw et retourne les result

5.2. Pipeline complet (texte)

  1. Bot → n8n
    • POST /webhook/synergia/geriatrie/entretien
    • Body = JSON d’entretien (profil + scores + alertes + recommandations)
  2. n8n → Odoo #1 (res.partner.search_read)
    • JSON-RPC model: "res.partner", method: "search_read"
    • Domain = par x_external_ref puis fallback par email
  3. n8n
    • extrait patient_id
    • fusionne avec l’entretien
    • construit args[0] pour le create du modèle x_synergia_geriatrie_entretien
  4. n8n → Odoo #2 (x_synergia_geriatrie_entretien.create)
    • JSON-RPC model: "x_synergia_geriatrie_entretien", method: "create"
  5. n8n → Odoo #3 (optionnel)
    • res.partner.write pour mettre à jour x_last_ai_interview, x_last_fragility_score, x_last_risk_level
  6. Branche alerte
    • si fragilite_globale >= 67 ou niveau_risque = "élevé"
      → Email / Slack / activité Odoo (autres call_kw possibles).

tableau récap des 3 appels JSON-RPC (colonnes : Use Case / model / method / args / kwargs),

Voici le tableau récapitulatif clair et prêt à l’emploi des 3 appels JSON-RPC Odoo utilisés dans votre chaîne bot → n8n → Odoo.

Format volontairement simple pour être collé dans Notion / Excel / documentation projet.

📋 Tableau récapitulatif — Appels JSON-RPC Odoo (Synergia Senior)

Use caseModelMethodArgsKwargs
🔍 Rechercher le patient par identifiant externeres.partnersearch_read[[["x_external_ref","=","PAT-000123"]], ["id","name","email","x_external_ref"]]{"limit":2}
🔍 Rechercher le patient par email (fallback)res.partnersearch_read[[["email","=","jeanne.dupont@example.com"]], ["id","name","email","x_external_ref"]]{"limit":2}
📝 Créer l’entretien gériatriquex_synergia_geriatrie_entretiencreate[{"x_patient_id":123,"x_age":82,"x_habitat":"seul","x_has_aidant":true,"x_score_autonomie":55,"x_score_cognitif":40,"x_score_chute":80,"x_score_nutrition":60,"x_score_moral":65,"x_fragilite_globale":68,"x_niveau_risque":"élevé","x_alertes_json":"[\"chute\",\"isolement\"]","x_alertes_label":"chute ; isolement","x_recommandations_text":"aménagement salle de bain\nvisite infirmière","x_raw_payload_json":"{...}","x_date_entretien":"2025-11-27T14:25:00","x_canal":"voix","x_name":"Entretien gériatrique – Jeanne Dupont"}]{}
🔄 Mettre à jour la synthèse sur le patientres.partnerwrite[[123], {"x_last_ai_interview":"2025-11-27T14:25:00","x_last_fragility_score":68,"x_last_risk_level":"élevé"}]{}

✅ Comment lire le tableau

🔹 Use Case

Le scénario métier : chercher un patient, créer un entretien, mettre à jour son profil.

🔹 Model

Le modèle Odoo impacté :

  • res.partner → fiche patient
  • x_synergia_geriatrie_entretien → table personnalisée Odoo Studio

🔹 Method

Méthodes standard JSON-RPC Odoo :

  • search_read → lire
  • create → créer
  • write → modifier

🔹 Args

Transmis tel quel dans params.args :

"args": [ ...arguments... ]

🔹 Kwargs

Options supplémentaires (limit, context, etc.) :

"kwargs": { "limit": 2 }

✅ Utilisation directe dans n8n

Dans chaque node HTTP Request :

URL Odoo

https://TON_INSTANCE.odoo.com/web/dataset/call_kw

Body générique

{ "jsonrpc": "2.0", "method": "call", "params": { "model": "...", "method": "...", "args": [...], "kwargs": {...} } }

Tu adaptes simplement les blocs model, method, args, kwargs à partir du tableau.

✅ un flow n8n export JSON prêt à importer

Les grandes histoires ont une personnalité. Envisagez de raconter une belle histoire qui donne de la personnalité. Écrire une histoire avec de la personnalité pour des clients potentiels aidera à établir un lien relationnel. Cela se traduit par de petites spécificités comme le choix des mots ou des phrases. Écrivez de votre point de vue, pas de l'expérience de quelqu'un d'autre.

Les grandes histoires sont pour tout le monde, même lorsqu'elles ne sont écrites que pour une seule personne. Si vous essayez d'écrire en pensant à un public large et général, votre histoire sonnera fausse et manquera d'émotion. Personne ne sera intéressé. Ecrire pour une personne en particulier signifie que si c'est authentique pour l'un, c'est authentique pour le reste.

voici un workflow n8n export JSON prêt à coller dans n8n (Menu → Import from file / clipboardPaste JSON).

✅ À adapter :

  • ODDO_BASE_URL (URL de ton Odoo Online)
  • Auth des deux nodes HTTP (ajouter tes credentials dans n8n)
  • Adresses email dans le node Email

{ "name": "Synergia – Entretien gériatrique → Odoo", "nodes": [ { "id": "WebhookGeriatrie", "name": "Webhook – Entretien gériatrique", "type": "n8n-nodes-base.webhook", "typeVersion": 1, "position": [260, 300], "parameters": { "path": "synergia/geriatrie/entretien", "httpMethod": "POST", "responseMode": "onReceived", "responseData": "custom", "responseBody": "{\"status\":\"received\"}", "options": { "rawBody": false } }, "webhookId": "synergia-geriatrie-entretien" }, { "id": "BuildSearchQuery", "name": "Build Patient Search Query", "type": "n8n-nodes-base.function", "typeVersion": 1, "position": [540, 180], "parameters": { "functionCode": "const input = items[0].json;\n\nconst externalRef = input.patient_external_ref || null;\nconst email = input.patient_email || null;\n\nif (!externalRef && !email) {\n throw new Error(\"Aucun identifiant patient fourni (external_ref ou email manquant).\");\n}\n\nlet domain;\nif (externalRef) {\n domain = [[\"x_external_ref\", \"=\", externalRef]];\n} else {\n domain = [[\"email\", \"=\", email]];\n}\n\nreturn [{ json: { domain } }];" } }, { "id": "OdooSearchPatient", "name": "Odoo – search_read Patient", "type": "n8n-nodes-base.httpRequest", "typeVersion": 1, "position": [820, 180], "parameters": { "url": "https://ODDO_BASE_URL/web/dataset/call_kw", "method": "POST", "authentication": "none", "jsonParameters": true, "options": {}, "bodyParametersJson": "={\n \"jsonrpc\": \"2.0\",\n \"method\": \"call\",\n \"params\": {\n \"model\": \"res.partner\",\n \"method\": \"search_read\",\n \"args\": [\n $json.domain,\n [\"id\", \"name\", \"email\", \"x_external_ref\"]\n ],\n \"kwargs\": {\n \"limit\": 2\n }\n }\n}" } }, { "id": "ExtractPatientId", "name": "Extract Patient ID", "type": "n8n-nodes-base.function", "typeVersion": 1, "position": [1100, 180], "parameters": { "functionCode": "const res = items[0].json;\nconst result = res.result || [];\n\nif (!Array.isArray(result)) {\n throw new Error(\"Réponse Odoo inattendue sur search_read\");\n}\n\nif (result.length === 0) {\n throw new Error(\"Aucun patient trouvé pour ce critère (external_ref / email).\");\n}\n\nif (result.length > 1) {\n // selon ta politique, tu peux throw ici\n console.warn(\"Plusieurs patients trouvés, premier utilisé.\");\n}\n\nconst patient = result[0];\n\nreturn [{\n json: {\n patient_id: patient.id,\n patient_name: patient.name,\n patient_email: patient.email,\n patient_external_ref: patient.x_external_ref || null\n }\n}];" } }, { "id": "MergePatientEntretien", "name": "Merge – Patient + Entretien", "type": "n8n-nodes-base.merge", "typeVersion": 1, "position": [1380, 300], "parameters": { "mode": "mergeByIndex", "join": "inner" } }, { "id": "BuildEntretienPayload", "name": "Build Odoo Entretien Payload", "type": "n8n-nodes-base.function", "typeVersion": 1, "position": [1660, 300], "parameters": { "functionCode": "const input = items[0].json;\n\nconst patientId = input.patient_id;\nconst canal = input.canal || \"texte\";\nconst body = input.entretien || {};\n\nconst profil = body.profil || {};\nconst scores = body.scores || {};\n\nconst alertes = body.alertes || [];\nconst recommandations = body.recommandations || [];\n\nreturn [{\n json: {\n jsonrpc: \"2.0\",\n method: \"call\",\n params: {\n model: \"x_synergia_geriatrie_entretien\",\n method: \"create\",\n args: [\n {\n x_patient_id: patientId,\n x_age: profil.age || null,\n x_habitat: profil.habitat || null,\n x_has_aidant: !!profil.aidant,\n\n x_score_autonomie: scores.autonomie ?? null,\n x_score_cognitif: scores.cognitif ?? null,\n x_score_chute: scores.chute ?? null,\n x_score_nutrition: scores.nutrition ?? null,\n x_score_moral: scores.moral ?? null,\n\n x_fragilite_globale: body.fragilite_globale ?? null,\n x_niveau_risque: body.niveau_risque || null,\n\n x_alertes_json: JSON.stringify(alertes),\n x_alertes_label: alertes.join(\" ; \"),\n x_recommandations_text: recommandations.join(\"\\n\"),\n\n x_raw_payload_json: JSON.stringify(body),\n x_date_entretien: new Date().toISOString(),\n x_canal: canal,\n\n x_name: `Entretien gériatrique – ${input.patient_name || (\"patient #\" + patientId)}`\n }\n ],\n kwargs: {}\n }\n }\n}];" } }, { "id": "OdooCreateEntretien", "name": "Odoo – Create Entretien", "type": "n8n-nodes-base.httpRequest", "typeVersion": 1, "position": [1940, 300], "parameters": { "url": "https://ODDO_BASE_URL/web/dataset/call_kw", "method": "POST", "authentication": "none", "jsonParameters": true, "bodyParametersJson": "={{$json}}", "options": {} } }, { "id": "BuildPartnerWrite", "name": "Build Partner Write Payload", "type": "n8n-nodes-base.function", "typeVersion": 1, "position": [1660, 520], "parameters": { "functionCode": "const input = items[0].json;\n\nconst patientId = input.patient_id;\nconst body = input.entretien || {};\n\nreturn [{\n json: {\n jsonrpc: \"2.0\",\n method: \"call\",\n params: {\n model: \"res.partner\",\n method: \"write\",\n args: [\n [patientId],\n {\n x_last_ai_interview: new Date().toISOString(),\n x_last_fragility_score: body.fragilite_globale ?? null,\n x_last_risk_level: body.niveau_risque || null\n }\n ],\n kwargs: {}\n }\n }\n}];" } }, { "id": "OdooUpdatePartner", "name": "Odoo – Update Patient", "type": "n8n-nodes-base.httpRequest", "typeVersion": 1, "position": [1940, 520], "parameters": { "url": "https://ODDO_BASE_URL/web/dataset/call_kw", "method": "POST", "authentication": "none", "jsonParameters": true, "bodyParametersJson": "={{$json}}", "options": {} } }, { "id": "IFRiskHigh", "name": "IF – Risque élevé ?", "type": "n8n-nodes-base.if", "typeVersion": 1, "position": [540, 460], "parameters": { "conditions": { "number": [ { "value1": "={{$json.entretien.fragilite_globale}}", "operation": "larger", "value2": 66 } ], "string": [ { "value1": "={{$json.entretien.niveau_risque}}", "operation": "equal", "value2": "élevé" } ] }, "combineOperation": "any" } }, { "id": "EmailAlert", "name": "Email – Alerte gériatrique", "type": "n8n-nodes-base.emailSend", "typeVersion": 1, "position": [820, 460], "parameters": { "fromEmail": "", "toEmail": "pharmacien@example.com", "subject": "Synergia – Alerte risque gériatrique élevé", "text": "Alerte Synergia : risque gériatrique élevé détecté.\n\nPatient externe : {{$json.patient_external_ref || 'N/A'}}\nEmail patient : {{$json.patient_email || 'N/A'}}\n\nScore global de fragilité : {{$json.entretien.fragilite_globale}}\nNiveau de risque : {{$json.entretien.niveau_risque}}\nAlertes : {{($json.entretien.alertes || []).join(', ')}}\n\nMerci de vérifier la situation et de planifier un suivi." } } ], "connections": { "Webhook – Entretien gériatrique": { "main": [ [ { "node": "Build Patient Search Query", "type": "main", "index": 0 }, { "node": "IF – Risque élevé ?", "type": "main", "index": 0 }, { "node": "Merge – Patient + Entretien", "type": "main", "index": 0 } ] ] }, "Build Patient Search Query": { "main": [ [ { "node": "Odoo – search_read Patient", "type": "main", "index": 0 } ] ] }, "Odoo – search_read Patient": { "main": [ [ { "node": "Extract Patient ID", "type": "main", "index": 0 } ] ] }, "Extract Patient ID": { "main": [ [ { "node": "Merge – Patient + Entretien", "type": "main", "index": 1 } ] ] }, "Merge – Patient + Entretien": { "main": [ [ { "node": "Build Odoo Entretien Payload", "type": "main", "index": 0 }, { "node": "Build Partner Write Payload", "type": "main", "index": 0 } ] ] }, "Build Odoo Entretien Payload": { "main": [ [ { "node": "Odoo – Create Entretien", "type": "main", "index": 0 } ] ] }, "Build Partner Write Payload": { "main": [ [ { "node": "Odoo – Update Patient", "type": "main", "index": 0 } ] ] }, "IF – Risque élevé ?": { "main": [ [ { "node": "Email – Alerte gériatrique", "type": "main", "index": 0 } ], [] ] } }, "active": false, "versionId": "synergia-geriatrie-v1", "settings": {}, "tags": [] }

Pour l’utiliser

  1. Dans n8n : Workflows → ImportPaste JSON → colle tout.
  2. Remplace https://ODDO_BASE_URL par l’URL réelle de ton Odoo Online.
  3. Sur les nodes HTTP, ajoute tes credentials (API key / Basic Auth / cookie, selon ton setup).
  4. Mets un vrai email dans le node Email – Alerte gériatrique.

Les grandes histoires ont une personnalité. Envisagez de raconter une belle histoire qui donne de la personnalité. Écrire une histoire avec de la personnalité pour des clients potentiels aidera à établir un lien relationnel. Cela se traduit par de petites spécificités comme le choix des mots ou des phrases. Écrivez de votre point de vue, pas de l'expérience de quelqu'un d'autre.

Les grandes histoires sont pour tout le monde, même lorsqu'elles ne sont écrites que pour une seule personne. Si vous essayez d'écrire en pensant à un public large et général, votre histoire sonnera fausse et manquera d'émotion. Personne ne sera intéressé. Ecrire pour une personne en particulier signifie que si c'est authentique pour l'un, c'est authentique pour le reste.