1. Contexte du problème
Dolibarr permet l'envoi d'un devis (proposition commerciale) par email au client, avec un lien de signature en ligne. Le client ouvre le lien, signe dans son navigateur, et le devis passe automatiquement au statut « Signé ».
Ce qui fonctionne :
- L'envoi initial du devis avec le lien de signature (tracé dans
dolibarr_mail.log) - La signature elle-même (changement de statut, stockage de la signature PNG, génération du PDF signé)
- Le déclenchement du trigger
PROPAL_CLOSE_SIGNED(vérifié dans les logs)
Ce qui ne fonctionne pas : l'étape d'envoi de l'email de notification après le trigger.
2. Analyse technique
2.1 Flux de la signature en ligne
core/ajax/onlineSign.phpPROPAL_CLOSE_SIGNED déclenchéinterface_50_modNotification_Notification.class.php appelle Notify::send()Notify::send() cherche les destinataires → aucun trouvé → pas d'email2.2 Trois mécanismes de notification dans Dolibarr
La méthode Notify::send() dans core/class/notify.class.php gère trois types de destinataires :
| Mécanisme | Comment le configurer | Fonctionne ? |
|---|---|---|
| Par contact tiers | Onglet « Notifications » d'un tiers → ajouter un contact + événement | OUI |
| Par utilisateur Dolibarr | Onglet « Notifications » d'un utilisateur → ajouter un événement | OUI |
| Par email fixe global | Page d'administration du module Notification | NON (voir ci-dessous) |
3. Cause racine
L'interface d'administration (
/admin/notification.php) permet de saisir un email fixe
dans la grille « E-mails des destinataires globaux ». Cette saisie insère une ligne dans la table
llx_notify_def avec fk_user = NULL et fk_contact = NULL.
Le code PHP ne lit jamais cette entrée. La requête SQL dans
Notify::send()
fait un JOIN sur fk_contact ou fk_user, qui sont NULL,
donc aucun résultat n'est retourné.
Le code source contient un commentaire explicite (ligne 1080 de
notify.class.php) :
// TODO Move vars NOTIFICATION_FIXEDEMAIL into table llx_notify_def
Ce « TODO » n'est pas implémenté — l'interface laisse croire que la fonctionnalité existe, mais le backend n'est pas câblé.
3.1 Comment Dolibarr gère réellement les emails fixes
Pour les emails fixes globaux, le code ne cherche pas dans llx_notify_def mais dans les
constantes de la table llx_const, avec un format précis :
NOTIFICATION_FIXEDEMAIL_{CODE_TRIGGER}_THRESHOLD_HIGHER_{SEUIL}
Le code parcourt toutes les constantes $conf->global et cherche celles qui matchent
le pattern NOTIFICATION_FIXEDEMAIL_PROPAL_CLOSE_SIGNED_THRESHOLD_HIGHER_*.
La valeur de la constante contient l'adresse email du destinataire. Le suffixe numérique représente le seuil minimum de montant HT du devis pour déclencher la notification.
4. Solution
4.1 Prérequis
Module Notifications activé
Vérifier dans Accueil > Configuration > Modules que le module « Notifications » est actif. En SQL :
SELECT value FROM llx_const WHERE name = 'MAIN_MODULE_NOTIFICATION';
La valeur doit être 1.
4.2 Notification quand un devis est signé
Créer la constante
Exécuter la requête SQL suivante sur la base de production :
INSERT IGNORE INTO llx_const (name, value, type, visible, entity)
VALUES (
'NOTIFICATION_FIXEDEMAIL_PROPAL_CLOSE_SIGNED_THRESHOLD_HIGHER_0',
'destinataire@example.com',
'chaine', 0, 1
);
Remplacer destinataire@example.com par l'adresse email souhaitée.
4.3 Notification quand un devis est refusé
Créer la constante pour le refus (optionnel)
INSERT IGNORE INTO llx_const (name, value, type, visible, entity)
VALUES (
'NOTIFICATION_FIXEDEMAIL_PROPAL_CLOSE_REFUSED_THRESHOLD_HIGHER_0',
'destinataire@example.com',
'chaine', 0, 1
);
4.4 Plusieurs destinataires
Pour envoyer la notification à plusieurs adresses, les séparer par une virgule dans la valeur :
UPDATE llx_const
SET value = 'secretariat@example.com, direction@example.com'
WHERE name = 'NOTIFICATION_FIXEDEMAIL_PROPAL_CLOSE_SIGNED_THRESHOLD_HIGHER_0'
AND entity = 1;
4.5 Seuil de montant
Le chiffre à la fin du nom de la constante définit le seuil minimum de montant HT.
_0 signifie « tous les devis avec un montant HT supérieur à 0 ».
Exemples de seuils :
| Constante | Comportement |
|---|---|
..._THRESHOLD_HIGHER_0 | Tous les devis (montant > 0) |
..._THRESHOLD_HIGHER_1000 | Devis dont le montant HT > 1 000 € |
..._THRESHOLD_HIGHER_5000 | Devis dont le montant HT > 5 000 € |
5. Configuration Multicompany
Dans un environnement Multicompany, chaque entité (société) a ses propres constantes
dans llx_const différenciées par le champ entity.
Lors de la signature en ligne, Dolibarr charge les constantes de l'entité associée au devis. Il suffit donc d'insérer une constante par entité avec l'email correspondant.
5.1 Identifier les entités
SELECT rowid, label, active FROM llx_entity ORDER BY rowid;
Résultat type :
| rowid | label | active |
|---|---|---|
| 1 | Société A | 1 |
| 2 | Société B | 1 |
| 3 | Société C | 0 (désactivée) |
5.2 Insérer une constante par entité
-- Entité 1 : Société A
INSERT IGNORE INTO llx_const (name, value, type, visible, entity)
VALUES ('NOTIFICATION_FIXEDEMAIL_PROPAL_CLOSE_SIGNED_THRESHOLD_HIGHER_0',
'secretariat@societe-a.com', 'chaine', 0, 1);
-- Entité 2 : Société B
INSERT IGNORE INTO llx_const (name, value, type, visible, entity)
VALUES ('NOTIFICATION_FIXEDEMAIL_PROPAL_CLOSE_SIGNED_THRESHOLD_HIGHER_0',
'admin@societe-b.com', 'chaine', 0, 2);
-- Répéter pour chaque entité active
entity = 2. La notification sera donc envoyée
à l'adresse de l'entité 2, et non à celle de l'entité 1.
Chaque entité reçoit uniquement les notifications de ses propres devis.
5.3 Même logique pour les devis refusés
-- Entité 1
INSERT IGNORE INTO llx_const (name, value, type, visible, entity)
VALUES ('NOTIFICATION_FIXEDEMAIL_PROPAL_CLOSE_REFUSED_THRESHOLD_HIGHER_0',
'secretariat@societe-a.com', 'chaine', 0, 1);
-- Entité 2
INSERT IGNORE INTO llx_const (name, value, type, visible, entity)
VALUES ('NOTIFICATION_FIXEDEMAIL_PROPAL_CLOSE_REFUSED_THRESHOLD_HIGHER_0',
'admin@societe-b.com', 'chaine', 0, 2);
6. Vérification post-déploiement
Vérifier les constantes
SELECT name, value, entity
FROM llx_const
WHERE name LIKE 'NOTIFICATION_FIXEDEMAIL_PROPAL%'
ORDER BY entity, name;
Vérifier le module Notification
SELECT name, value FROM llx_const
WHERE name = 'MAIN_MODULE_NOTIFICATION';
Doit retourner value = 1.
Tester avec un devis
Créer un devis de test avec un montant > 0 €, le valider, puis le signer via le lien en ligne ou manuellement via le bouton « Classer signé ».
Consulter l'historique des notifications
SELECT * FROM llx_notify ORDER BY rowid DESC LIMIT 10;
Une nouvelle entrée doit apparaître avec le code PROPAL_CLOSE_SIGNED et l'email du destinataire.
Consulter le log mail
Activer temporairement le log mail si ce n'est pas déjà fait :
-- Activer le log mail (niveau debug)
INSERT IGNORE INTO llx_const (name, value, type, visible, entity)
VALUES ('MAIN_MAIL_DEBUG', '1', 'chaine', 0, 0);
-- Désactiver après le test
UPDATE llx_const SET value = '0' WHERE name = 'MAIN_MAIL_DEBUG';
Ou via l'interface : Accueil > Configuration > Divers → paramètre MAIN_MAIL_DEBUG.
Vérifier ensuite le fichier documents/dolibarr_mail.log pour le détail de l'envoi SMTP.
7. Résumé
| Critère | Détail |
|---|---|
| Cause | L'interface admin insère dans llx_notify_def mais le code cherche dans llx_const (TODO non implémenté) |
| Correctif | Constante NOTIFICATION_FIXEDEMAIL_PROPAL_CLOSE_SIGNED_THRESHOLD_HIGHER_0 dans llx_const |
| Impact fichiers | Aucune modification de fichier (ni core, ni custom) |
| Compatibilité | 100% — les constantes llx_const sont préservées lors des mises à jour |
| Multicompany | Une constante par entité (champ entity) |
| Temps de déploiement | 2 minutes (requêtes SQL) |
| Contenu de l'email | Message natif Dolibarr avec lien vers le devis + PDF en pièce jointe |
| Rollback | DELETE FROM llx_const WHERE name LIKE 'NOTIFICATION_FIXEDEMAIL_PROPAL_CLOSE%'; |
NOTIFICATION_FIXEDEMAIL_PROPAL_VALIDATE_THRESHOLD_HIGHER_0 — Devis validéNOTIFICATION_FIXEDEMAIL_ORDER_VALIDATE_THRESHOLD_HIGHER_0 — Commande validéeNOTIFICATION_FIXEDEMAIL_BILL_VALIDATE_THRESHOLD_HIGHER_0 — Facture validéeNOTIFICATION_FIXEDEMAIL_BILL_PAYED_THRESHOLD_HIGHER_0 — Facture payée