Version Dolibarr ≥ 19 – 2025
1. Introduction
Dolibarr est un ERP/CRM open‑source particulièrement apprécié des PME pour sa simplicité d’utilisation et son extensibilité via modules et hooks. L’un des points de friction les plus récurrents concerne la gestion des coûts : achats, frais de déplacement, commissions, ou encore coûts indirects liés aux projets.
Ce guide vous propose : 1. Une méthodologie pour concevoir un framework d’automatisation des coûts, basé sur les capacités de Dolibarr mais en s’appuyant sur des intégrations modernes (API, services cloud, framework PHP).
- Un exemple de structure de projet (architecture, dépendances, tests).
- Des extraits de code pour mettre en place les automatisations les plus courantes (calcul automatique du prix de vente, affectation de coûts indirects, synchronisation avec des outils comptables). 4. Des bonnes pratiques pour garantir la maintenabilité, la scalabilité et la conformité RGPD.
Objectif : permettre à un développeur ou à une équipe technique de bâtir un moteur de calcul de coûts qui s’exécute automatiquement lors de la création ou de la mise à jour d’un tiers (fournisseur, client) ou d’une ligne de commande, tout en profitant des API tierces (ex. Stripe, Twilio, services de conversion de devises).
2. Pourquoi automatiser les coûts avec Dolibarr ?
| Problématique | Solution manuelle | Solution automatisée |
|---|---|---|
| Mise à jour des prix d’achat | Modification manuelle dans chaque ligne de commande. | Règles métier centralisées (ex. % de marge, seuils de réapprovisionnement). |
| Calcul du prix de vente | Tableur externe, risque d’incohérence. | Algorithme intégré dans le module “Produit” qui tire les coûts d’achat, de main‑d’œuvre et d’indirects. |
| Intégration de frais externes (courrier, énergie, taxes) | Saisie au moment de la facture. | API tierce (ex. rapport de dépenses) qui alimente automatiquement les comptes de charge. |
| Reporting multi‑devise | Consolidation fastidieuse. | Consommation d’une API de change en temps réel pour recalculer les coûts en fonction du taux du jour. |
En résumé, l’automatisation réduit les erreurs, améliore la visibilité et permet de déclencher de nouveaux workflows (notifications Slack, mise à jour de tableaux de bord, synchronisation avec un ERP tiers).
3. Architecture du cadre d’automatisation
┌───────────────────────┐ ┌─────────────────────┐
│ Dolibarr Core │ │ API externes │
│ (Modules, Hooks) │◀──────▶│ (Devise, Paiement, ││ │ │ Comptes Cloud) │
└─────────────▲─────────┘ └─────────────▲─────────┘ │ │
┌───────────┴─────────────┐ ┌─────────────┴─────────────┐
│ Framework “CostEngine”│ │ Services Tierces │
│ • Listener (Hook) │ │ • Paiement (Stripe) │
│ • Event Dispatcher │ │ • Devise (ex. exchangerate)│ │ • Business Rules │ │ • Reporting (PowerBI) │ └───────────▲─────────────┘ └─────────────▲─────────────┘
│ │
┌────────┴─────────┐ ┌───────────┴───────────┐
│ Domain Model │ │ Repository / Cache │
│ CoûtProduit │ │ (Doctrine, Redis) │
│ CoûtCommande() │ │ │
└──────────────────┘ └───────────────────────┘
3.1. Les briques clés
| Brique | Rôle | Technologies conseillées |
|---|---|---|
| Listeners / Hooks | Intercepter les événements Dolibarr (creation d’un produit, validation d’une commande) et déclencher le calcul du coût. | symfony/event-dispatcher ou hook natif de Dolibarr ($this->event->...). |
| Business Rules | Définir les formules (coût de production = matière + main‑d’œuvre + charges indirectes, marge cible). | PHP classes Rule\* avec injection de dépendances. |
| Domain Model | Objet métier CoûtProduit, CoûtCommande, CoûtIndirect qui encapsulent les calculs. |
Doctrine ORM (ou Simple POPO si vous préférez). |
| Service Layer | Accès aux API externes (devise, paiement, CRM), calcul de frais additionnels. | Guzzle HTTP client, Symfony HttpClient, ou APIs spécifiques. |
| Cache / Persistence | Stocker les résultats intermédiaires (taux de change du jour, frais de transaction) afin d’éviter des appels redondants. | Redis, APCu, ou table de Dolibarr llx_price. |
| Scheduler | Exécuter des tâches périodiques (recalcul des marges, import de données de coûts). | cron interne à Dolibarr ou Symfony Console Command. |
4. Mise en place concrète (exemple « Coût d’un produit »)
4.1. Étape 1 – Créer le module de base
# Structure du module
modules/
└─ costumecost/
├─ costumecost.class.php
├─ manifest.json
└─ inc/
└─ class/...
manifest.json (déclaration du plugin)
{
"name": "Cost Automation",
"author": "Your Company",
"version": "1.0.0",
"description": "Automation des coûts et prix de vente",
"requirements": ["php>=7.4","dolibarr>=19.0"]
}
4.2. Étape 2 – Intercepter l’événement de création de produit
Dolibarr possède un système d’hooks. Dans le fichier inc/class/hookform.class.php du module, on ajoute :
class HookFormExample extends HookForm {
public function init(*) {
$this->substitute SubmitAction = 'SubmitWithCostAutomation';
}
}
Ensuite, on implémente le listener dans le module principal :
//CostAutomationPlugin.php
class CostAutomationPlugin {
public function __construct() {
// Hook à l'événement "afterInsert" du formulaire produit
$this->hook = new HookForm($this);
$this->hook->registerHook('FormulaireProduit::save');
}
public function triggerAfterInsertProduct($formparams) {
// $formparams contient les champs du produit (price buy, supplier, etc.)
$costService = new CostService();
$cost = $costService->calculateProductCost($formparams['id']);
// On met à jour le champ 'price' (coût réel) du produit
$product = new Product($this->db);
$product->fetch($formparams['id']);
$product->price = $cost['total_cost'];
$product->update();
}
}
Remarque : l’API de hook de Dolibarr se déclenche après l’enregistrement en base, ce qui garantit que toutes les contraintes sont déjà validées.
4.3. Étape 3 – Définir la logique de calcul (Business Rule)
« `php// src/Service/CostService.php
namespace CostAutomation\Service;
use Doctrine\ORM\EntityManagerInterface;
use CostAutomation\Domain\CostProduit;
class CostService {
private EntityManagerInterface $em;
public function __construct(EntityManagerInterface $em) {
$this->em = $em;
}
public function calculateProductCost(int $productId): array {
$product = $this->em->getRepository(Product::class)->find($productId);
$supplier = $this->em->getRepository(Supplier::class)->find($product->soc_id);
// 1️⃣ Coût d’achat (unit price * qty_stock)
$purchaseCost = $product->price * $product->qty_stock;
// 2️⃣ Frais indirects (exemple: énergie = 0.05 € / unité)
$indirectCost = $purchaseCost * 0.05;
// 3️⃣ Conversion éventuelle si le fournisseur est en devises différente
if ($supplier->currency !== $this->defaultCurrency) {
$rate = CurrencyService::fetchRate($supplier->currency, $this->defaultCurrency);
$purchaseCost = $purchaseCost * $rate;
$indirectCost = $indirectCost * $rate;
}
// 4️⃣ Marge souhaitée (ex. 30 %)
$marginRate = 0.30;
$sellingPrice = ($purchaseCost + $indirectCost) * (1 + $marginRate);
return [
'purchase_cost' => $purchaseCost,
'indirect_cost' => $indirectCost,
'total_cost' => $purchaseCost + $indirectCost,
'selling_price' => $sellingPrice,
];
}
}
> **Tip** : utilisez le **Service Container** de Symfony (ou l’équivalent Dolibarr) pour injecter les dépendances (DB, API clients) afin de garder le code testable.
### 4.4. Étape 4 – Persister le coût calculé dans Dolibarr
```php
// Return to the Hook listener
public function triggerAfterInsertProduct($formparams) {
$cost = $costService->calculateProductCost($formparams['id']);
$product = new Product($this->db);
$product->fetch($formparams['id']);
// On stocke le coût total dans le champ 'cost' (ou un champ custom)
$product->cost = $cost['total_cost'] ?? $product->cost;
$product->update();
// Optionnel : mise à jour du champ "price" (prix de vente calculé)
$product->price = $cost['selling_price'];
$product->update();
}
5. Intégrations modernes : API & Cloud
5.1. Conversion de devises en temps réel
// src/Service/CurrencyService.php
namespace CostAutomation\Service;
use GuzzleHttp\Client;
class CurrencyService {
private Client $client;
private string $apiUrl = 'https://api.exchangerate.host/';
public function __construct() {
$this->client = new Client([
'base_uri' => $this->apiUrl,
'timeout' => 5,
]);
}
public function fetchRate(string $from, string $to): float {
$response = $this->client->request('get', "$from/$to");
$data = json_decode($response->getBody()->getContents(), true);
return $data['rates'][$to] ?? 1.0;
}
}
Pourquoi ?
- La conversion se fait à la volée lorsqu’un achat est enregistré dans une devise différente.
- Le taux est тогда mis en cache (ex. 24 h) via Redis pour éviter les dépassements de quotas.
5.2. Reporting comptable vers un ERP ou BI
Dolibarr expose les tables comptables (llx_accounting, llx_price). Vous pouvez publier les événements via Kafka ou RabbitMQ pour que des plateformes comme Power BI, Tableau ou Metabase consomment les nouvelles lignes de coût.
« `php// PublishEvent.php
namespace CostAutomation\Event;
class CostRecalculated {
public int $productId;
public float $totalCost;
public float $sellingPrice;
public function __construct(int $productId, float $totalCost, float $sellingPrice) {
$this->productId = $productId;
$this->totalCost = $totalCost;
$this->sellingPrice= $sellingPrice;
}
}
// Dispatch via Symfony Messenger (or custom queue)
$bus->dispatch(new CostRecalculated($productId, $totalCost, $sellingPrice));
### 5.3. Paiement en ligne & frais de transaction Si vous facturez directement depuis Dolibarr (module **Facture**), vous pouvez ajouter :
```php
// After generating the invoice
$fee = $this->paymentGateway->applyFee($invoice->total, 0.025); // 2,5 % frais Stripe
$invoice->total += $fee;
$invoice->save();
6. Bonnes pratiques & conformité
| Aspect | Recommandation |
|---|---|
| Modularité | Séparez les règles de calcul (ex : marge, seuils de réapprovisionnement) dans des services séparés pour faciliter les tests unitaires. |
| Tests | Créez des tests PHPUnit qui simulent des produits, fournisseurs et taux de change. Exemple : assertEquals(120.00, $cost['total_cost']). |
| Sécurité | Ne stockez jamais les clés API en clair dans le code : utilisez le système de configuration Dolibarr ($conf->global->...) ou le Secret Manager de votre cloud. |
| Performance | Cachez les résultats de conversion de devises pendant 12–24 h. Utilisez un worker CRON qui met à jour une table currency_rates. |
| Audit | Conservez un journal des calculs (table llx_custom_cost_log) contenant les étapes (purchase, indirect, conversion, margin). |
| Internationalisation | Si vous gérez plusieurs langues, externalisez les libellés et les paramètres de marge dans un fichier lang/fr.php. |
| Documentation | Rédigez un README technique détaillé pour vos équipes (déploiement, configuration des variables d’environnement). |
7. Exemple de tableau de bord « Coûts automatisés » (Power BI)
| KPI | Source | Fréquence | Visualisation |
|---|---|---|---|
| Coût moyen par produit | Table llx_product (champ cost) |
Quotidienne | Carte thermique |
| Marge brute moyenne | $selling_price - $total_cost |
Hebdomadaire | Gauge |
| Taux de change appliqué | Table currency_rates (cache Redis) |
En temps réel | Ligne de tendance |
| Transactions à risque de frais | Faktures avec frais Stripe > 5 % | Mensuelle | Bar chart |
| Évolution des frais indirects | llx_price → lignes « indirect » |
Mensuelle | Histogramme |
Ces indicateurs peuvent être connectés via API REST du plugin costautomation ou via un view SQL que vous exposez dans votre base.
8. Deployment & maintenance
-
Installation du plugin
« `bash cd dolibarr/htdocs/custom git clone https://github.com/yourorg/dolibarr-cost-automation.git costumecost
php -r "require ‘vendor/autoload.php’;" # composer install
Puis activez le module depuis l’interface d’administration (Extensions → Modules → Réglages avancés). -
Variables d’environnement (
.env) : « `dotenv
DB_DATABASE=dolibarr
DB_USER=root
CURRENCY_API_KEY=xxxxxxx # si vous utilisez un service payant DEFAULT_CURRENCY=EUR
MARGE_PAR_DEFECTU=0.30 # 30 % -
Scheduler interne (cron) dans
cron/dolibarr:
« `cron /15 * php /path/to/dolibarr/cron.php –dispatcher -
Versionning :
- Git tags pour chaque version majeure (v1.0.0, v1.1.0).
- Utilisez GitHub Actions pour exécuter les tests et pousser les images Docker du service
costservice.
- Mise à jour de Dolibarr :
- Les hooks sont généralement compatibles entre versions majeures (ex. 18 → 19).
- Vérifiez les changements de nom de tables (
llx_→ nouveau préfixe) et mettez à jour les migrations Doctrine.
9. Conclusion
Automatiser les coûts dans Dolibarr n’est pas seulement une question de saisie manuelle : c’est un projet d’ingénierie où l’on combine :
- Les hooks natifs de Dolibarr pour déclencher les calculs au bon moment.
- Un framework externe (Symfony/Doctrine ou léger POPO) afin de séparer la logique métier des dépendances.
- Des API tierces modernes (devise, paiement, BI) pour enrichir le calcul avec des flux de données en temps réel.
- Des bonnes pratiques de test, de sécurité et de documentation pour garantir la pérennité du moteur.
En suivant l’architecture présentée — Listener → Service Layer → Domain Model → Cache/Repository — vous obtenez un système extensible, capable d’évoluer avec vos besoins (nouveau type de coût, règle de marge dynamique, intégration ERP).
À retenir : commencez par un MVP (exemple : calcul du prix de vente à partir du prix d’achat + 30 % de marge). Puis itérez : ajoutez la conversion de devises, les frais de paiement, la publication d’évènements pour le reporting. Chaque itération vous avvicinera d’un pas d’une automatisation complète et fiable des coûts dans Dolibarr.
Bonne implémentation ! 🚀
Ce document a été rédigé à destination des équipes IT et de la comptabilité opérationnelle souhaitant tirer parti des capacités d’extension de Dolibarr tout en adoptant les standards du développement logiciel moderne.