Leçons apprises : ETL avec Dolibarr sans casser l’existant

Guide pratique pour concevoir, intégrer et exploiter des flux de données tout en préservant la stabilité de votre système ERP/CRM open‑source


1. Introduction

Dolibarr est souvent perçu comme un simple logiciel de gestion d’entreprise ; en réalité, derrière son interface épurée se cache un moteur de bases de données riche (MySQL/PostgreSQL/MariaDB) et une architecture modulaire très adaptée aux projets d’ETL (Extraction‑Transformation‑Chargement).
Cependant, directement implémenter des pipelines de transformation de données « à chaud » peut rapidement mettre en danger la disponibilité du système de production.

Cet article compile les enseignements tirés de plusieurs projets d’envergure (intégration deware‑warehouse, migration vers le cloud, analyse marketing…) et propose une méthodologie détaillée afin de concevoir des flux ETL robustes tout en conservant le bon fonctionnement de l’existant.


2. Pourquoi Dolibarr peut être un bon choix pour l’ETL ?

Atout Description Impact sur le projet ETL
Architecture modulaire Plugins (ex. : htdocs/business, htdocs/product, htdocs/stock) Possibilité de créer des modules dédiés à l’ETL sans toucher le noyau.
API native get, set, refresh via le framework Symfony‑Lite intégré Accès direct aux objets métier (fournisseurs, articles, paiements) via des appels HTTP ou PHP.
Base de données relationnelle Schéma normalisé, clé étrangère solide Extraction fiable et possibilité de réutiliser les vues existantes.
Moteur de workflow (CRON) Scheduler intégré (tâches cron ou cronjobs via Plugins) Orchestration de jobs ETL simples (ex. : extraction quotidienne).
Interface admin Gestion des champs, des listes, des droits Création dynamique de champs supplémentaires pour les tables ciblées (ex. : identifiants ELT).
Open‑source & gratuit Aucun coût de licence ni de verrouillage Flexibilité totale pour tester, versionner et déployer vos propres scripts.

Ces points permettent d’élaborer des pipelines qui ne touchent jamais directement les tables de production, mais qui utilisent plutôt des interfaces publiques (API, menus, plugins) afin de laisser la couche fonctionnelle intacte.


3. Architecture recommandée

┌─────────────────────┐          ┌─────────────────────┐
│ Source(s) external│ │ Destination │
│ (ERP, CRM, API, etc.)│ │ (Dolibarr tables) │
└─────────┬───────────┘ └─────────┬───────────┘
│ │
▼ ▼
Extraction Transformation → [Vues matérialisées / tables d'archive]
│ │
▼ ▼
Files CSV / API URL → Import‑Staging → Chargement → BI/Dashboards

3.1. Les zones « staging »

Zone Rôle Principaux contenus
Staging Area Réceptacle temporaire, isolé du schéma de production. Table etl_staging_* ou schéma dédié (dolibarr_etl).
Transform Layer Application des règles (nettoyage, agrégation, calculs). Scripts PHP / Python exécutés dans le conteneur d’application.
Target Layer Table(s) de destination finale lues uniquement par les écrans. Tables xx_archive ou vues vw_* qui ne sont jamais modifiées en écriture.

Bonne pratique : Ne jamais écrire directement dans les tables « core » (products, invoices, customers, …).
Utilisez toujours des tables d’archive ou des vues qui pointent vers elles.

3.2. Orchestration

Outil Pourquoi l’utiliser avec Dolibarr
CRON du serveur Simple à configurer, s’intègre dans le même environnement PHP.
CronJob plugin de Dolibarr Permet de déclencher un script PHP depuis l’interface admin et de le logger.
Airflow / Prefect / Luigi Pour des pipelines plus complexes (multi‑sources, dépendances).
Docker Compose Isolation des dépendances (Python + PostgreSQL) tout en partageant le même réseau.


4. Étapes de mise en œuvre pas à pas

4.1. Phase de pré‑audit

  1. Cartographier les tables métier

    • Liste des tables qui contiennent les données source (ex. : llx_product, llx_categorie, llx_supplier).
  2. Analyser les contraintes

    • Clés étrangères, triggers, relations avec le module de facturation.
  3. Identifier les points d’entrée autorisés

    • Menu Administration → Outils → Scripts PHP ou plugins etl.
  4. Définir les indicateurs de performance (KPI)

    • Volume de lignes, latence maximale, fréquence (quotidienne, horaire, en temps réel).

4.2. Phase de mise en place du sandbox

Action Détails
Créez un schéma dédié dolibarr_etl dans votre BD de test. Exemple : CREATE SCHEMA dolibarr_etl;
Implémentez un module “Staging” (ex. : htdocs/etl/staging.php). Ce fichier liste les tables de staging et les droits associés.
Déployez un conteneur Docker séparé contenant Python + Airflow. Le conteneur se connecte à la BD via réseau Docker, mais ne touche pas au serveur de production.
Activez la détection de changements (timestamp date_modif, rowid). Utilisez les colonnes tDate ou datec pour le incremental extraction.

4.3. Extraction (E)

Méthode Points forts / limites
SQL SELECT vers staging Simple, mais nécessite de ré‑écrire le script à chaque changement de schéma.
API REST interne (via get.php) Découplage complet, mais surcharge de requêtes HTTP.
Export CSV depuis le menu “Importer/Exporter” Rapide pour les besoins ponctuels, peu automatisable.
Webhooks (via le plugin Webservices) Permet d’écouter les changements en temps réel (ex : création d’un nouveau fournisseur).

Leçon clé : utilisez une vue matérialisée dans le schéma dolibarr_etl qui regroupe toutes les tables sources en une seule source de consistance. Ainsi, l’extraction ne dépend plus d’un schéma spécifique au moment de la transformation.

4.4. Transformation (T)

Opération Implémentation typique
Nettoyage (trim, normalisation) preg_replace('/\s+/', ' ', $value) dans un script PHP.
Enrichissement (lookup) Jointure avec des tables de référence (ex. : code pays) stockées dans le même staging.
Agrégation (KPI) GROUP BY supplier_id, month(date) dans un script SQL exécuté via PDO.
Déduplication SELECT DISTINCT ou ROW_NUMBER() OVER (PARTITION BY ...) en SQL.
Conversion de types Cast explicite (CAST(value AS DECIMAL(12,2))).
Application de règles métier Table de mapping (etl_rule) chargée dynamiquement via phpMyAdmin ou un fichier YAML.

Exemple de code (PHP) – Nettoyage d’un libellé

<?php
require_once '/var/www/html/dolibarr/core/setup.php'; // charge les classes Dolibarr
$object = new Product($db);
$object->fetch($row['id_product']);
$object->label = trim(preg_replace('/\s+/', ' ', $object->label));
$object->save(); // uniquement dans le staging, pas dans la table core
?>

Bonne pratique : placez toute la logique de transformation dans des classes réutilisables (ex. : ETL\Transformer\ProductCleaner). Ainsi, les scripts d’orchestration restent légers et testables en isolation.

4.5. Chargement (C)

  1. Insertion dans les tables d’archive
    INSERT INTO etl_archive_product
    SELECT *, NOW() AS load_dt FROM etl_staging_product;
  2. Création de vues de reporting
    CREATE OR REPLACE VIEW vw_product_sales AS
    SELECT p.label, SUM(i.amount) AS total_sales
    FROM etl_archive_product p
    JOIN etl_archive_invoice i ON p.rowid = i.product_id
    GROUP BY p.label;
  3. Gestion des droits

    • Créez des groupes d’utilisateurs dans Dolibarr (Administration → Users) qui ont uniquement le rôle Viewer sur les vues.
    • Bloquez l’accès en écriture sur les tables d’archive via le module de sécurité ($conf->global->sql_...).
  4. Nettoyage du staging

    • Après succès, vidangez etl_staging_* ou archivez-les avec une politique de rétention (DROP PARTITION).


5. Pièges les plus courants & comment les éviter

Piège Conséquence Solution préventive
Modification directe du schéma Brèche de la garantie “ne pas toucher l’existant”. Utilisez un schéma dédié (dolibarr_etl) et versionnez les migrations avec doctrine/dbal ou Laravel migrations.
Chargement massif sans contrôle Saturation du serveur de production (I/O/CPU). Schedulez les jobs hors des pics d’activité et limitez le nombre de lignes par batch (LIMIT 10000).
Mauvaise gestion des clés étrangères Violations de contrainte → crash du job. Désactivez temporairement les contraintes FK (SET FOREIGN_KEY_CHECKS=0) uniquement dans le schéma de staging, puis ré‑activez‑les.
Absence de journalisation Difficulté à diagnostiquer les erreurs. Ajoutez un log table (etl_log) et un fichier etl.log rotatif (logrotate).
Verrouiller les tables en écriture pendant la transformation Bloque les transactions métiers. Optez pour l’architecture “append‑only” : aucune mise à jour, seulement des inserts dans les tables d’archive.
Désynchronisation des dates de modification Extraction partielle → données incohérentes. Implémentez un chronologie row_version ou un champ last_update dans chaque table source et utilisez-le comme filtre.
Ne pas tester en environnement de pré‑production Bugs en production. Créez un environnement “ETL‑sandbox” identique à la prod (même version de Dolibarr, même version de MySQL).


6. Exemple complet : Migration quotidienne des fiches fournisseurs vers un data‑warehouse client

6.1. Hypothèses

Élément Valeur
Source Table llx_supplier (colonne status, country, creation_date).
Fréquence Tous les jours à 02 h00 (hors pic).
Destination Table stg_supplier_archive + vue vw_supplier_dw.
Contraintes supplier_id doit rester unique, country_code doit être ISO‑2.

6.2. Script d’extraction (SQL + PHP)

-- 1. Crée la table staging (si absent)
CREATE TABLE IF NOT EXISTS dolibarr_etl.stg_supplier_archive (
rowid INT NOT NULL,
suppliers_id INT NOT NULL,
status VARCHAR(50),
fk_country INT,
creation_date DATE,
load_datetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (rowid)
);

<?php
// file: /var/www/html/dolibarr/etl/run_supplier.php
require_once '/var/www/html/dolibarr/core/my_const.php';
require_once '/var/www/html/dolibarr/biz/thirdparty.class.php'; // class Supplier
global $db;
$sth = $db->prepare("
INSERT INTO dolibarr_etl.stg_supplier_archive
(rowid, suppliers_id, status, fk_country, creation_date)
SELECT rowid, id, status, fk_country, datec FROM llx_supplier
WHERE last_update < DATE_SUB(NOW(), INTERVAL 1 DAY) -- incrémental
ON DUPLICATE KEY UPDATE
status = VALUES(status),
fk_country = VALUES(fk_country),
creation_date = VALUES(creation_date);
");
$sth->execute();
echo "Extraction terminée.\n";
?>

6.3. Transformation – Normalisation du pays

<?php
// file: /var/www/html/dolibarr/etl/transform_supplier.php
require_once '/var/www/html/dolibarr/inc/error.inc.php';
require_once '/var/www/html/dolibarr/inc/common.inc.php';
require_once '/var/www/html/dolibarr/biz/thirdparty.class.php';
$countryMap = [
1 => 'FR',
2 => 'DE',
3 => 'ES',
// ... le mapping complet
];
$db = /* récupération du DB via $mysh->new(...) */;
$sth = $db->prepare("
SELECT DISTINCT fk_country FROM dolibarr_etl.stg_supplier_archive WHERE fk_country NOT IN (SELECT id FROM llx_country);
");
$sth->execute();
while ($row = $sth->fetch()) {
// Ajout d’un mapping dynamique si nécessaire…
}

(Le script complet inclut les vérifications de domaine, le formatage ISO‑2, etc.)

6.4. Chargement final (Création de la vue)

CREATE OR REPLACE VIEW vw_supplier_dw AS
SELECT
a.suppliers_id AS supplier_id,
a.status,
c.iso_code AS country_iso,
DATE_FORMAT(a.creation_date,'%Y-%m') AS month_created,
CURRENT_DATE() AS load_date
FROM dolibarr_etl.stg_supplier_archive a
JOIN llx_country c ON a.fk_country = c.id;

Condition d’accès : le groupe etl_viewer a le droit READ sur cette vue — il ne peut jamais écrire dessus.

6.5. Orchestration avec Cron

# /etc/cron.d/etl_supplier
0 2 * * * www-data /usr/bin/php /var/www/html/dolibarr/etl/run_supplier.php >> /var/log/etl_supplier.log 2>&1


7. Bonnes pratiques récapitulatives

Domaine Règle d’or
Séparation des responsabilités Extraction → Staging → Transformation → Chargement dans des tables d’archive ou vues.
Versionnage des scripts Utilisez Git + CI (GitHub Actions, GitLab CI) pour déployer les scripts ETL dans le conteneur de production.
Tests automatisés Créez des tests unitaires (PHPUnit) sur chaque Transformer et des tests d’intégration avec une DB de test replicate.
Monitoring Table etl_log + alertes (Prometheus + Alertmanager) sur les durées d’exécution, le nombre de lignes insérées, et les erreurs critiques.
Gestion des droits Aucun utilisateur de production n’a le droit “INSERT/UPDATE” sur les tables stg_*. Utilisez des comptes DB avec INSERT uniquement sur le schéma etl.
Documentation Maintenez un README par module ETL : source, fréquence, transformation appliquée, propriétaire.
Performance Batch de 5 000‑10 000 lignes maximum par batch ; indexez les colonnes de jointure dans le staging.
Rollback Conservez les sauvegardes de chaque batch (snapshot_YYYYMMDD.sql) avant le DROP ou TRUNCATE du staging.


8. Conclusion

Dolibarr, loin d’être seulement un ERP de gestion quotidienne, possède tout ce qu’il faut pour être le moteur fiable d’un pipeline ETL lorsqu’on l’utilise avec les bonnes limites : pas d’écriture directe sur les tables core, mais exploitation d’une couche staging isolée.

Les leçons tirées de nos projets montrent que :

  1. Délimiter strictement les zones de transformation évite toute rupture de l’intégrité du système de production.
  2. L’utilisation d’une vue matérialisée ou d’une table d’archive comme point d’entrée unique garantit à la fois la traçabilité et la possibilité de rollback.
  3. Un bon contrôle des droits et la journalisation sont indispensables pour détecter rapidement toute dérive.
  4. L’automatisation des tests et du déploiement (Git + CI/CD) assure la pérennité du flux ETL tout en conservant une configuration déclarative et reproductible.

En suivant la méthodologie décrite ci‑dessus, vous pourrez déployer sans crainte des flux d’intégration de données volumineux, tout en préservant la continuité de service de votre instance Dolibarr.


À votre disposition pour étudier un cas concret, créer un prototype ou affiner la configuration de votre pipeline ETL !


Article rédigé en novembre 2025, basé sur les retours d’expérience de plusieurs projets clients (SME, e‑commerce, gestion de la logistique). Les bonnes pratiques décrites sont compatibles avec les versions 18.x – 21.x de Dolibarr.

Publications similaires