# DataFirefly Odoo Connector — guide d'installation et de configuration

> Ce guide couvre l'installation, la configuration et l'exploitation du plugin DataFirefly Odoo Connector pour Shopware 6.6 et 6.7. À la fin, votre boutique synchronisera produits, stock, clients et commandes avec…

- Page: <https://www.datafirefly.com/documentation/df-odoo-connector/>
- Langue: fr
- Mis à jour le: 2026-06-29
- Autres langues: [en](https://www.datafirefly.com/en/documentation/df-odoo-connector/index.md), [es](https://www.datafirefly.com/es/documentation/df-odoo-connector/index.md), [de](https://www.datafirefly.com/de/documentation/df-odoo-connector/index.md), [it](https://www.datafirefly.com/it/documentation/df-odoo-connector/index.md), [pl](https://www.datafirefly.com/pl/documentation/df-odoo-connector/index.md), [nl](https://www.datafirefly.com/nl/documentation/df-odoo-connector/index.md), [pt](https://www.datafirefly.com/pt/documentation/df-odoo-connector/index.md)
- Index: <https://www.datafirefly.com/documentation/llms.txt>

Ce guide couvre l'installation, la configuration et l'exploitation du plugin **DataFirefly Odoo Connector** pour Shopware 6.6 et 6.7. À la fin, votre boutique synchronisera produits, stock, clients et commandes avec votre instance Odoo via XML-RPC natif, sans aucune dépendance externe ni surcoût d'API tierce.

## Présentation

Le plugin établit un pont bidirectionnel entre Shopware et Odoo en parlant directement le protocole XML-RPC d'Odoo (stable depuis la version 8). Aucun module à installer côté Odoo, aucun middleware payant, aucun SaaS intermédiaire.

| Entité | Odoo → Shopware (pull) | Shopware → Odoo (push) |
| --- | --- | --- |
| Produits (product.template) | ✅ | ✅ |
| Stock (qty_available / free_qty) | ✅ | — |
| Catégories (product.category) | ✅ | ✅ |
| Clients (res.partner) | — | ✅ avec adresses enfants |
| Commandes (sale.order) | — | ✅ avec confirmation et facture optionnelles |

## Prérequis

- **Shopware** 6.6.x ou 6.7.x (toutes versions mineures).
- **PHP** 8.2, 8.3 ou 8.4.
- **Extensions PHP** : curl, xml, simplexml (présentes par défaut sur la quasi-totalité des hébergeurs).
- **Odoo** 12, 13, 14, 15, 16, 17 ou 18, en Community ou Enterprise. Odoo.sh, Odoo Online (SaaS) et instances auto-hébergées fonctionnent identiquement.
- Un utilisateur Odoo dédié à l'API (recommandé) avec droits de lecture/écriture sur les modèles utilisés (product.template, product.product, res.partner, sale.order, stock.warehouse, product.category, res.country, account.tax).

## Installation

### Via téléversement dans l'administration

1. Téléchargez l'archive `DfOdooConnector-v1.0.0.zip` depuis votre compte client.
2. Dans l'administration Shopware : _Extensions → Mes extensions → Téléverser une extension_.
3. Sélectionnez le ZIP puis cliquez sur _Installer_.
4. Activez l'extension en cliquant sur l'interrupteur.

### Via console SSH

```
cd /chemin/vers/shopware
cp DfOdooConnector-v1.0.0.zip custom/plugins/
cd custom/plugins && unzip DfOdooConnector-v1.0.0.zip
sudo -u www-data setsid php bin/console plugin:refresh
sudo -u www-data setsid php bin/console plugin:install --activate DfOdooConnector
sudo -u www-data setsid php bin/console cache:clear
```

Recompilation de l'administration pour charger le module Vue 3 :

```
sudo -u www-data setsid php bin/build-administration.sh
```

**Note** — L'installation crée deux tables : `df_odoo_mapping` (correspondances persistantes Shopware ↔ Odoo) et `df_odoo_log` (journal des opérations). Aucune table existante n'est modifiée.

## Configuration côté Odoo

### Créer un utilisateur dédié

Il est fortement recommandé de créer un utilisateur Odoo dédié à l'intégration plutôt que d'utiliser un compte administrateur personnel. Cela permet d'auditer précisément les actions du connecteur et de révoquer son accès indépendamment.

1. Dans Odoo : _Paramètres → Utilisateurs et sociétés → Utilisateurs_.
2. Créez un utilisateur nommé par exemple `Shopware Bridge`.
3. Donnez-lui les droits requis : Inventaire (utilisateur), Ventes (administrateur des documents), Facturation (utilisateur si vous activez la création de facture), Contacts (utilisateur).

### Générer une clé API

1. Connectez-vous à Odoo avec ce nouvel utilisateur.
2. Cliquez sur l'avatar en haut à droite → _Préférences_.
3. Onglet _Compte_ → _Clés API_ → _Nouvelle clé API_.
4. Donnez un nom descriptif (par exemple `Shopware Connector`) et copiez la valeur générée.

**Important** — La clé API ne s'affiche qu'une seule fois. Si vous la perdez, il faudra en générer une nouvelle. Stockez-la dans un gestionnaire de mots de passe avant de fermer la modale.

## Configuration côté Shopware

### Renseigner la connexion

Dans l'administration Shopware : _Paramètres → Système → Plugins → Df Odoo → Paramètres_, ou directement via le menu latéral _Paramètres → Df Odoo → Paramètres_.

- **URL Odoo** : URL complète de votre instance sans slash final, par exemple `https://moncompte.odoo.com`.
- **Nom de la base** : visible dans l'URL Odoo après `?db=`, ou dans _Paramètres → Technique → Base de données_.
- **Utilisateur** : login de l'utilisateur dédié, généralement son adresse email.
- **Clé API Odoo** : valeur copiée à l'étape précédente.
- **Délai d'attente** : 30 secondes par défaut, suffisant dans la majorité des cas.

### Tester la connexion

Cliquez sur le bouton _Tester la connexion_ en haut à droite. Si tout est correct, une notification verte affiche la version d'Odoo et l'identifiant utilisateur (uid). Si la connexion échoue, le message d'erreur retourné par Odoo est affiché tel quel.

**Conseil** — Le test de connexion peut aussi être appelé depuis la console pour scripter une vérification :
`curl -X POST -H "Authorization: Bearer ADMIN_TOKEN" https://votreshopware.com/api/_action/df-odoo/test-connection`

## Directions de synchronisation

Chaque entité dispose d'un sélecteur indépendant : _désactivé_, _Odoo → Shopware_ (pull), _Shopware → Odoo_ (push), ou _bidirectionnel_. Les valeurs par défaut sont :

- **Produits** : bidirectionnel
- **Stock** : Odoo → Shopware (Odoo est la source de vérité)
- **Clients** : Shopware → Odoo
- **Commandes** : Shopware → Odoo
- **Catégories** : désactivé (à activer manuellement selon votre organisation)

## Synchronisation des produits

### Stratégies de correspondance

Trois stratégies sont configurables :

- **SKU** (recommandé) : Shopware `productNumber` ↔ Odoo `default_code`.
- **ID Odoo** : repose uniquement sur la table de mapping persistante. Utile si vos SKU sont volatiles.
- **Code-barres** (EAN) : Shopware `ean` ↔ Odoo `barcode`. Exige des EAN renseignés des deux côtés.

Une fois liés, deux produits restent appariés via la table `df_odoo_mapping`, même si la SKU change ensuite.

### Pull depuis Odoo

La tâche planifiée lit les `product.template` modifiés depuis la dernière exécution (champ `write_date`) et crée ou met à jour les produits correspondants côté Shopware. Les champs synchronisés sont : nom, SKU, prix de vente, prix de revient, description courte, description longue, poids, volume, état actif, catégorie, taxes.

### Push vers Odoo

Les produits maîtres Shopware (avec `parentId = null`) actifs sont envoyés vers Odoo en tant que `product.template` de type _product_ (article stockable). Les variantes Shopware sont remontées sous leur produit parent.

**Détection des changements** — Avant chaque écriture, un hash SHA-1 du contenu est comparé à celui mémorisé dans le mapping. Si rien n'a changé, l'écriture est ignorée et l'opération est journalisée comme `skipped`. Cela évite de saturer Odoo lors des cron successifs.

## Synchronisation du stock

Le stock est toujours tiré depuis Odoo (jamais l'inverse). Toutes les 15 minutes, la tâche planifiée lit les variantes `product.product` par lots de 100 par identifiant de template parent, agrège `qty_available` ou `free_qty` (configurable globalement) puis met à jour le champ `stock` de chaque produit Shopware en une seule requête DAL.

**qty_available vs free_qty** — `qty_available` reflète le stock physique présent en entrepôt. `free_qty` retire les quantités déjà réservées sur des commandes non livrées. _free_qty_ est généralement préférable pour un site marchand car il évite la survente.

## Synchronisation des catégories

Désactivée par défaut. Activez-la si votre arborescence de catégories doit rester synchrone avec celle d'Odoo. La hiérarchie `parent_id` est préservée des deux côtés. Comme pour les produits, un hash de contenu évite les écritures inutiles.

## Synchronisation des clients

Les clients Shopware sont poussés comme `res.partner` Odoo avec :

- **Déduplication par email** : avant toute création, un partenaire existant avec le même email et `parent_id = false` est cherché. S'il existe, il est mis à jour au lieu d'être dupliqué.
- **company_type** : _company_ si le champ société de l'adresse de facturation est renseigné, _person_ sinon.
- **Adresses enfants** : l'adresse de facturation par défaut est créée comme partenaire enfant avec `type='invoice'`, l'adresse de livraison comme partenaire enfant avec `type='delivery'`.
- **TVA intracommunautaire** : reportée sur le champ `vat` du partenaire principal.
- **Pays et région** : résolus par code ISO avec cache mémoire intra-requête.

## Synchronisation des commandes

### En temps réel au checkout

Si l'option _Pousser chaque commande dès validation_ est activée, un event subscriber écoute `CheckoutOrderPlacedEvent` et envoie immédiatement la commande vers Odoo après la finalisation du checkout. Le client est créé dans Odoo si nécessaire (via la synchronisation client), puis la commande est créée comme `sale.order` avec :

- `partner_id` résolu via le mapping client.
- `order_line` en syntaxe tuple Odoo : `[0, 0, {name, product_uom_qty, price_unit, product_id}]`.
- Une ligne supplémentaire pour les frais de transport si `totalPrice` du shipping est supérieur à zéro.
- `company_id`, `warehouse_id`, `pricelist_id` selon les valeurs par défaut configurées.

**Le checkout n'est jamais bloqué** — Si Odoo est inaccessible, l'erreur est tracée dans `df_odoo_log` et la commande sera reprise dans les 10 minutes par la tâche planifiée `df_odoo.order_sync`, qui scanne les commandes des 7 derniers jours non encore mappées.

### Filtre d'état

Le filtre _État des commandes_ permet de restreindre les commandes poussées :

- **Toutes** : toute commande validée est envoyée (recommandé en B2C avec paiement immédiat).
- **Payées uniquement** : seules les commandes dont l'état de paiement est _paid_ sont poussées. Évite de remonter des paniers abandonnés à paiement manuel.
- **Payées ou expédiées** : ajoute aux précédentes les commandes expédiées avant paiement (B2B avec délais).

### Confirmation et facture automatiques

Deux options pilotent ce qui se passe côté Odoo une fois la commande créée :

- **Confirmer la commande** : appelle `action_confirm` sur la `sale.order`, qui passe alors directement à l'état _commande confirmée_ au lieu de rester _devis_.
- **Créer la facture** : appelle `_create_invoices` pour générer immédiatement une facture validée. L'identifiant de la facture créée est mémorisé comme mapping de type `invoice`.

## Multi sales channel

Tous les paramètres du plugin peuvent être surchargés par canal de vente. En haut de la page _Paramètres_, le sélecteur natif Shopware permet de basculer entre _Tous les canaux_ et un canal spécifique.

Cas d'usage typiques :

- Un canal B2C qui pousse vers un Odoo principal et un canal B2B qui pousse vers un Odoo distinct.
- Un canal de production avec direction _push_ et un canal staging avec direction _désactivée_.
- Différents identifiants Odoo (warehouse, sales team, pricelist) selon le canal.

## Tâches planifiées

| Nom interne | Fréquence | Action |
| --- | --- | --- |
| `df_odoo.product_sync` | 1 heure | Pull puis push produits selon la direction configurée. Le pull n'examine que les fiches modifiées depuis -2 h. |
| `df_odoo.stock_sync` | 15 minutes | Pull du stock depuis Odoo pour tous les produits déjà mappés. |
| `df_odoo.customer_sync` | 1 heure | Push des clients actifs non encore mappés (100 max par exécution). |
| `df_odoo.order_sync` | 10 minutes | Push des commandes des 7 derniers jours non encore mappées (50 max par exécution). |

Forcer l'exécution d'une tâche depuis la console :

```
sudo -u www-data setsid php bin/console scheduled-task:run-single df_odoo.product_sync
```

**Worker Shopware** — Pour que les tâches planifiées se déclenchent automatiquement, le worker messenger Shopware doit tourner (cron `messenger:consume` ou tâche systemd). Vérifiez dans _Paramètres → Système → File d'attente_ que _scheduled_task_ est consommée régulièrement.

## Module d'administration

Une section **Df Odoo** apparaît dans _Paramètres → Plugins_ avec quatre pages.

### Dashboard

Compteurs en direct (mappings actifs par entité, activité des dernières 24 h par statut), boutons de synchronisation manuelle par entité (pull et push), bandeau d'état de la connexion, liste des erreurs récentes et raccourcis vers les autres pages.

### Paramètres

Formulaire complet avec sélecteur de canal de vente. Bouton _Tester la connexion_ et _Enregistrer_ dans la barre d'actions.

### Journal

Toutes les opérations sont tracées dans `df_odoo_log` avec leur statut (_success_, _error_, _warning_, _skipped_), leur direction, l'entité concernée, la durée en millisecondes et le message complet. Filtres combinables par statut, type d'entité et direction. Pagination serveur.

**Mode debug** — Les opérations _skipped_ ne sont écrites dans le journal que si le mode debug est activé dans les paramètres. À utiliser ponctuellement pour diagnostiquer un comportement, à désactiver en production pour éviter de saturer la table.

### Correspondances

Vue lecture sur la table `df_odoo_mapping` avec recherche, filtre par type d'entité et tri par date de dernière synchronisation. Pratique pour vérifier qu'un produit donné est bien mappé à l'ID Odoo attendu.

## API REST admin

Tous les endpoints requièrent une authentification admin standard (Bearer token).

| Méthode | Endpoint | Paramètres |
| --- | --- | --- |
| POST | `/api/_action/df-odoo/test-connection` | `salesChannelId` (optionnel) |
| POST | `/api/_action/df-odoo/sync/products` | `direction=pull\|push`, `salesChannelId` |
| POST | `/api/_action/df-odoo/sync/stock` | `salesChannelId` |
| POST | `/api/_action/df-odoo/sync/customers` | `salesChannelId` |
| POST | `/api/_action/df-odoo/sync/orders` | `salesChannelId`, `limit` (1-500) |
| POST | `/api/_action/df-odoo/sync/categories` | `direction=pull\|push` |
| GET | `/api/_action/df-odoo/stats` | — |
| GET | `/api/_action/df-odoo/logs` | `status`, `entityType`, `direction`, `page`, `perPage` |

Exemple d'appel pour forcer un push produit :

```
curl -X POST
  -H "Authorization: Bearer ADMIN_TOKEN"
  -d "direction=push"
  https://votreshopware.com/api/_action/df-odoo/sync/products
```

## Tables et données stockées

Le plugin crée deux tables MySQL :

- `df_odoo_mapping` — correspondances persistantes (identifiant Shopware ↔ identifiant Odoo) avec hash de synchronisation et payload optionnel. Une ligne est unique sur le couple (type d'entité, identifiant Shopware) et sur (type d'entité, identifiant Odoo).
- `df_odoo_log` — journal des opérations avec statut, durée, message, payload, identifiant du canal de vente.

Aucune table Shopware standard n'est modifiée.

## Désinstallation

Depuis l'administration : _Extensions → Mes extensions → Df Odoo → Désinstaller_.

Une boîte de dialogue propose deux options :

- **Conserver les données utilisateur** coché : les tables `df_odoo_mapping` et `df_odoo_log` sont préservées, ainsi que les paramètres système. Pratique en cas de réinstallation ultérieure.
- **Conserver les données utilisateur** décoché : les deux tables sont supprimées (DROP TABLE) à la désinstallation. L'instance Odoo n'est jamais touchée.

## Dépannage

### « Configuration Odoo incomplète » au test de connexion

L'un des quatre champs obligatoires (URL, base, utilisateur, clé API) est vide. Vérifiez que vous avez bien sélectionné le bon canal de vente avant d'enregistrer.

### « 401 Unauthorized » ou « access denied »

La clé API a été révoquée côté Odoo, ou l'utilisateur n'a pas les droits requis sur le modèle ciblé. Régénérez une clé API et vérifiez les droits Odoo de l'utilisateur (notamment _Inventaire → Utilisateur_ et _Ventes → Administrateur des documents_).

### « Connexion refusée » ou timeout

L'URL Odoo n'est pas accessible depuis le serveur Shopware. Vérifiez que le pare-feu autorise les connexions sortantes HTTPS vers le domaine Odoo. Augmentez le délai d'attente si votre instance Odoo est lente à répondre.

### Les produits ne se synchronisent pas

Vérifiez le journal (page _Journal_) pour des entrées en erreur. Activez le mode debug pour tracer également les opérations _skipped_ et identifier si le hash de contenu fait que rien ne change réellement.

### Les commandes ne partent pas au checkout

Vérifiez que l'option _Pousser chaque commande dès validation_ est cochée et que la direction _Commandes_ est sur _Shopware → Odoo_. Si le filtre d'état est sur _Payées uniquement_ et que le paiement est asynchrone, c'est la tâche planifiée qui pousse la commande quelques minutes après l'encaissement.

## Limites connues

- Les attributs de variantes Odoo (`product.attribute`) ne sont pas encore mappés automatiquement. Les variantes Shopware sont remontées comme produits parents Odoo (`product.template`). Les variantes Odoo créées manuellement restent correctement liées via leur template parent. Une gestion native est prévue en version 1.1.
- Les remises de ligne de commande sont reportées comme `price_unit` ajusté, pas comme `discount` Odoo.
- Les modes de paiement et expédition Shopware ne sont pas mappés vers les `journal_id` Odoo — les valeurs par défaut Odoo sont utilisées.

## Support

Pour toute question, contactez l'équipe DataFirefly via le formulaire de contact sur [datafirefly.com](https://www.datafirefly.com/contact/). Pensez à joindre l'export du journal (page _Journal_ → bouton d'export à venir) ou à minima une capture de la ligne en erreur ainsi que la version exacte de Shopware, PHP et Odoo.
