Rendre votre ERP "intelligent". Automatisation ODOO
C'est la touche finale qui va rendre votre ERP "intelligent".
Au lieu que vos gestionnaires fassent tout à la main, Odoo va travailler en arrière-plan pour maintenir la cohérence des données envoyées par l'app React.
Dans Odoo Studio, cela se passe dans le menu "Automatisations" (ou "Actions Automatisées").
Voici les 5 Automatisations Prioritaires à implémenter pour votre projet Synergia.
1. Le "Nettoyeur de Nom" (Data Quality)
Objectif : React envoie Prénom et Nom séparés. Odoo a besoin d'un champ name complet pour l'affichage.
- Modèle : Contact (res.partner)
- Déclencheur : À la création et à la mise à jour.
- Champs surveillés : x_firstname, x_lastname.
- Action à effectuer : Exécuter du code Python.
Code Python :
codePython
downloadcontent_copy
expand_lessfor record in records:
# On prend le prénom (ou vide si null) et le nom (ou vide si null)
prenom = record.x_firstname or ''
nom = record.x_lastname or ''
# On concatène et on retire les espaces inutiles (.strip)
record['name'] = f"{prenom} {nom}".strip()
2. Le "Calculateur d'Expérience" (Smart Data)
Objectif : Quand un candidat ajoute une expérience dans l'app, Odoo doit recalculer automatiquement son ancienneté totale sur sa fiche principale.
- Modèle : Expérience Candidat (x_candidate_experience)
- Déclencheur : À la création, mise à jour et suppression.
- Action à effectuer : Exécuter du code Python.
Code Python :
codePython
downloadcontent_copy
expand_less# On récupère le candidat lié à cette expérience
candidat = record.x_candidate_id
if candidat:
# On cherche toutes ses expériences
experiences = env['x_candidate_experience'].search([('x_candidate_id', '=', candidat.id)])
total_jours = 0
import datetime
for exp in experiences:
if exp.x_date_start:
# Si "En poste", on prend la date d'aujourd'hui comme fin
date_fin = datetime.date.today() if exp.x_is_current else exp.x_date_end
if date_fin:
delta = date_fin - exp.x_date_start
total_jours += delta.days
# On convertit en années (approximatif) et on écrit sur le candidat
# (Assurez-vous d'avoir créé un champ x_total_experience_years sur res.partner)
candidat['x_total_experience_years'] = round(total_jours / 365.25, 1)
3. Le "Validateur de Profil" (Workflow)
Objectif : Si un document passe au statut "Validé", vérifier si le dossier est complet. Si oui, passer le candidat en "Profil Vérifié" automatiquement.
- Modèle : Documents de Conformité (x_compliance_document)
- Déclencheur : À la mise à jour.
- Champs surveillés : x_validation_status.
- Domaine (Filtre) : Appliquer uniquement si x_validation_status = valid.
- Action à effectuer : Exécuter du code Python.
Code Python :
codePython
downloadcontent_copy
expand_lesscandidat = record.x_partner_id
# Liste des types de documents obligatoires pour Synergia
types_obligatoires = ['id_card', 'diploma', 'rpps', 'kbis']
# On cherche tous les docs validés de ce candidat
docs_valides = env['x_compliance_document'].search([
('x_partner_id', '=', candidat.id),
('x_validation_status', '=', 'valid')
])
# On récupère la liste des types qu'il a déjà validés
types_valides = [doc.x_document_type for doc in docs_valides]
# On vérifie si TOUS les obligatoires sont présents dans les valides
dossier_complet = all(type_doc in types_valides for type_doc in types_obligatoires)
if dossier_complet:
# On change le statut du candidat (créez ce champ sur res.partner)
candidat['x_onboarding_stage'] = 'validated'
# Optionnel : Envoyer un email de félicitations
4. L'Alerte "Document Expiré" (Compliance)
Objectif : Vérifier tous les jours si un document expire bientôt (ex: Assurance, CNI) et notifier l'infirmier.
- Modèle : Documents de Conformité (x_compliance_document)
- Déclencheur : Action Planifiée (Cron) - Fréquence : 1 jour.
- Action à effectuer : Envoyer un email.
Configuration sans code :
- Dans Studio, filtrez les enregistrements : Date expiration est dans 30 jours ET Statut = Validé.
- Action : "Envoyer un email".
- Choisissez un modèle d'email (Template) qui dit : "Bonjour, votre document {{object.x_document_type}} va expirer le {{object.x_expiration_date}}. Merci de le mettre à jour sur l'application."
5. Notification Admin "Nouveau Inscrit" (Réactivité)
Objectif : Alerter l'équipe Synergia quand quelqu'un finit son inscription via l'App.
- Modèle : Contact (res.partner)
- Déclencheur : À la mise à jour.
- Champs surveillés : x_onboarding_stage.
- Domaine : x_onboarding_stage = profile_filled (ou le statut qui correspond à la fin du wizard React).
- Action à effectuer : Ajouter un abonné ou Créer une activité.
Configuration sans code :
- Action : Créer une activité.
- Type d'activité : À faire.
- Résumé : Nouveau candidat à vérifier.
- Assigné à : Utilisateur spécifique (ex: Responsable Recrutement).
- Description : "Le candidat {{object.name}} vient de finaliser son inscription. Merci de vérifier ses documents."
Récapitulatif pour l'intégration
| Priorité | Nom | Type | Pourquoi ? |
| 🔥 Haute | Nettoyeur de Nom | Python | Évite d'avoir des factures sans nom. |
| 🔥 Haute | Validateur Profil | Python | Automatise le passage "En attente" -> "Validé". Gain de temps énorme. |
| ⚡ Moyenne | Notif Admin | Standard | Pour ne rater aucun nouveau lead. |
| ⚡ Moyenne | Calcul Expérience | Python | Pour pouvoir filtrer "Infirmiers > 5 ans exp". |
| 🛡️ Basse | Alerte Expiration | Cron | Pour la conformité légale sur le long terme. |
6- Validateur Profil
C'est une excellente décision. C'est l'automatisation qui a le plus fort retour sur investissement (ROI) car elle évite à votre équipe de vérifier manuellement chaque dossier 10 fois par jour.
Voici le code Python prêt à l'emploi et la procédure d'installation pas à pas.
Prérequis (Noms techniques)
Assurez-vous que vous avez bien ces noms de champs (ou adaptez le code) :
- Modèle Document : x_compliance_document
- Champ Type : x_document_type (valeurs: id_card, diploma, rpps, etc.)
- Champ Statut : x_validation_status (valeur validée : valid)
- Lien Candidat : x_partner_id
- Modèle Contact (res.partner) :
- Champ Étape : x_onboarding_stage (valeur cible : validated)
🛠️ Configuration dans Odoo Studio
- Allez sur le modèle Documents de Conformité (x_compliance_document).
- Cliquez sur le bouton Automatisations > Nouveau.
- Configurez comme suit :
- Nom : Validation Automatique Candidat
- Modèle : Documents de Conformité
- Déclencheur : À la mise à jour
- Champs surveillés : Statut (x_validation_status)
- Domaine (Filtre) : ["x_validation_status", "=", "valid"]
- (Cela signifie : ne lance ce code QUE si le document vient de passer à "Validé")
- Action à effectuer : Exécuter du code Python
🐍 Le Code Python
Copiez-collez ce bloc dans l'éditeur de code d'Odoo :
codePython
downloadcontent_copy
expand_less# 1. Récupérer le candidat lié au document qu'on vient de valider
candidat = record.x_partner_id
# Sécurité : Si le document n'est pas lié à un candidat, on ne fait rien
if not candidat:
action = {'type': 'ir.actions.act_window_close'} # Stop propre
# 2. LISTE DES DOCUMENTS OBLIGATOIRES
# Mettez ici les codes techniques exacts de votre champ Selection (x_document_type)
# Exemple : CNI, Diplôme et RPPS sont requis pour tout le monde.
docs_requis = ['id_card', 'diploma', 'rpps']
# (Optionnel) Ajout conditionnel : Si c'est une société, il faut le KBIS
# Adaptez 'societe' et 'kbis' selon vos vrais codes
# if candidat.x_freelance_status == 'societe':
# docs_requis.append('kbis')
# 3. Interroger la base de données
# On cherche TOUS les documents de ce candidat qui sont DÉJÀ validés
docs_valides_db = env['x_compliance_document'].search([
('x_partner_id', '=', candidat.id),
('x_validation_status', '=', 'valid')
])
# 4. Extraire les types qu'on a trouvés
# On crée une liste simple des types (ex: ['id_card', 'diploma'])
types_trouves = [doc.x_document_type for doc in docs_valides_db]
# 5. Vérification Logique
# On vérifie si CHAQUE document requis est présent dans les types trouvés
# La fonction all() renvoie True seulement si tout est présent
dossier_complet = all(requis in types_trouves for requis in docs_requis)
# 6. Action Finale
if dossier_complet:
# Si le candidat n'est pas déjà validé, on le valide
if candidat.x_onboarding_stage != 'validated':
candidat['x_onboarding_stage'] = 'validated'
# Le petit plus : On écrit un message dans le "Chatter" (l'historique) du candidat
candidat.message_post(
body="✅ <b>Automation System :</b> Tous les documents obligatoires sont validés. Profil activé."
)
🔍 Comment tester que ça marche ?
- Prenez un candidat de test (ex: "Jean Test").
- Mettez son statut à "Nouveau" ou "Profil rempli".
- Ajoutez-lui les 3 documents obligatoires (ex: CNI, Diplôme, RPPS).
- Laissez-les en brouillon.
- Passez les documents à "Validé" un par un.
- Au moment où vous validez le dernier document manquant :
- Allez voir la fiche de "Jean Test".
- Son statut doit être passé automatiquement à "Validé".
- Vous devriez voir le message de confirmation dans son historique de discussion.
.
7- Nettoyeur de Nom
C'est l'automatisation de base, indispensable pour que vos factures, emails et recherches dans Odoo soient propres. Sans cela, vous aurez des fiches contacts vides ou mal nommées.
Voici la procédure exacte et le code.
🛠️ Configuration dans Odoo Studio
- Allez sur l'application Contacts.
- Ouvrez Studio (l'icône clé à molette).
- Cliquez sur Automatisations (menu gauche ou haut) > Nouveau.
- Configurez comme suit :
- Nom : Calcul Automatique du Nom Complet
- Modèle : Contact (res.partner)
- Déclencheur : À la création et à la mise à jour
- Champs surveillés : Sélectionnez vos deux champs : x_firstname (Prénom) et x_lastname (Nom)
- Astuce : Il faut maintenir Ctrl ou Cmd pour en sélectionner plusieurs, ou les ajouter l'un après l'autre.
- Action à effectuer : Exécuter du code Python
🐍 Le Code Python
Copiez ce code. Il gère les majuscules automatiquement et évite les erreurs si un champ est vide.
codePython
downloadcontent_copy
expand_lessfor record in records:
# 1. Récupération sécurisée (évite le crash si le champ est vide)
# .strip() retire les espaces accidentels avant/après
prenom = (record.x_firstname or '').strip()
nom = (record.x_lastname or '').strip()
# 2. Mise en forme (Optionnel : Joli formatage)
# Met la première lettre en majuscule (Jean)
prenom_format = prenom.title()
# Met tout le nom en majuscule (DUPONT) - Standard administratif français
nom_format = nom.upper()
# 3. Concaténation
# On assemble. Si l'un est vide, .strip() à la fin nettoiera les espaces en trop.
nom_complet = f"{prenom_format} {nom_format}"
# 4. Écriture dans le champ standard Odoo
record['name'] = nom_complet.strip()🔎 Ce que fait ce code (Exemple)
| Saisie React (x_firstname) | Saisie React (x_lastname) | Résultat Odoo (name) |
| "jean" | "lauret" | Jean LAURET |
| "MARIE " | "curie" | Marie CURIE |
| "" (vide) | "Dupont" | DUPONT |
| "Thomas" | "" (vide) | Thomas |
⚠️ Point d'attention pour l'API React
Puisque Odoo calcule le nom automatiquement, votre développeur React ne doit pas envoyer le champ name lors de la création du contact.
Payload JSON correct à envoyer :
codeJSON
downloadcontent_copy
expand_less{
"x_firstname": "Jean",
"x_lastname": "Valjean",
"email": "jean@test.com"
// PAS de champ "name", Odoo s'en occupe !
}Si React envoie aussi le champ name, il risque d'écraser le calcul ou de créer un conflit. Laissez Odoo faire le travail.
8- Notif admin
C'est une excellente pratique. Plutôt que d'envoyer un email qui risque de se perdre, nous allons utiliser le système d'Activités Odoo (le petit réveil en haut à droite).
Cela créera une tâche "À faire" pour votre responsable recrutement dès qu'un candidat termine son inscription sur l'app React.
Voici comment configurer cela sans une seule ligne de code (Standard).
🛠️ Configuration dans Odoo Studio
- Allez sur l'application Contacts.
- Ouvrez Studio (l'icône clé à molette).
- Cliquez sur Automatisations > Nouveau.
- Configurez les paramètres généraux :
- Nom : Notif Nouveau Candidat Inscrit
- Modèle : Contact (res.partner)
- Déclencheur : À la mise à jour
- Champs surveillés : x_onboarding_stage (Étape d'inscription)
1. Le Filtre (Quand déclencher ?)
Nous ne voulons pas une alerte à chaque modification, mais uniquement quand l'inscription est finie.
- Dans la section "Appliquer sur" (ou Domaine), cliquez sur "Modifier le domaine".
- Ajoutez la règle suivante :
- Étape d'inscription est égal à Profil Rempli (ou la valeur technique que votre React envoie à la fin, ex: profile_filled).
- Optionnel mais conseillé : Ajoutez Est un candidat est vrai.
2. L'Action (Quoi faire ?)
- Type d'action : Créer une activité
- Type d'activité : À faire (ou Appel, ou Email selon votre process)
- Résumé : Nouveau candidat à valider
- Assigné à : Choisissez l'utilisateur responsable (ex: "Responsable RH" ou vous-même).
- Date d'échéance : Date de lancement + 0 jours (Pour que ce soit urgent/aujourd'hui).
- Note :
Vous pouvez écrire un petit texte qui apparaîtra dans la tâche, par exemple :
"Un nouveau candidat vient de finaliser son inscription via l'application mobile. Merci de vérifier ses documents et de valider son profil."
🔎 Résultat pour l'utilisateur Odoo
Dès que votre App React enverra la donnée :
{ "x_onboarding_stage": "profile_filled" }
- Une pastille verte/rouge apparaîtra sur l'icône "Horloge" en haut à droite de l'écran du recruteur.
- Dans la liste des activités, il verra : "Jean Dupont : Nouveau candidat à valider".
- Il pourra cliquer dessus pour ouvrir la fiche, vérifier les infos, et cliquer sur "Marquer comme fait".
C'est simple, standard, et rien ne passe à travers les mailles du filet !
9- Calcul d'expérience
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.
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.
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.