DataFirefly Odoo Konnektor — Installations- und Konfigurationsanleitung
Verbinden Sie Shopware 6.6 / 6.7 mit Odoo 12 → 18 über natives XML-RPC. Installation, API-Schlüssel-Setup, Synchronisationsrichtungen, geplante Aufgaben und Fehlerbehebung.
Diese Anleitung deckt Installation, Konfiguration und tägliche Nutzung des Plugins DataFirefly Odoo Connector für Shopware 6.6 und 6.7 ab. Am Ende synchronisiert Ihr Shop Produkte, Lagerbestand, Kunden und Bestellungen mit Ihrer Odoo-Instanz über natives XML-RPC — ohne externe Abhängigkeit und ohne Drittanbieter-API-Aufpreis.
Überblick
Das Plugin baut eine bidirektionale Brücke zwischen Shopware und Odoo auf, indem es direkt das XML-RPC-Protokoll von Odoo (seit Version 8 stabil) spricht. Kein Modul auf der Odoo-Seite, keine kostenpflichtige Middleware, kein SaaS-Mittelsmann.
| Entität | Odoo → Shopware (pull) | Shopware → Odoo (push) |
|---|---|---|
| Produkte (product.template) | ✅ | ✅ |
| Lagerbestand (qty_available / free_qty) | ✅ | — |
| Kategorien (product.category) | ✅ | ✅ |
| Kunden (res.partner) | — | ✅ mit Unteradressen |
| Bestellungen (sale.order) | — | ✅ mit optionaler Bestätigung und Rechnung |
Voraussetzungen
- Shopware 6.6.x oder 6.7.x (alle Minor-Versionen).
- PHP 8.2, 8.3 oder 8.4.
- PHP-Erweiterungen: curl, xml, simplexml (auf praktisch allen Hostern standardmäßig vorhanden).
- Odoo 12, 13, 14, 15, 16, 17 oder 18, Community oder Enterprise. Odoo.sh, Odoo Online (SaaS) und selbstgehostete Instanzen funktionieren gleichermaßen.
- Ein dedizierter Odoo-Benutzer für die API (empfohlen) mit Lese-/Schreibrechten auf den verwendeten Modellen (product.template, product.product, res.partner, sale.order, stock.warehouse, product.category, res.country, account.tax).
Installation
Über das Admin-Upload
- Laden Sie
DfOdooConnector-v1.0.0.zipaus Ihrem Kundenkonto herunter. - In der Shopware-Administration: Erweiterungen → Meine Erweiterungen → Erweiterung hochladen.
- Wählen Sie das ZIP aus und klicken Sie auf Installieren.
- Aktivieren Sie die Erweiterung über den Schalter.
Per SSH-Konsole
cd /pfad/zu/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
Bauen Sie die Administration neu, um das Vue-3-Modul zu laden:
sudo -u www-data setsid php bin/build-administration.sh
df_odoo_mapping (persistente Shopware ↔ Odoo-Zuordnungen) und df_odoo_log (Operationsjournal). Es wird keine bestehende Tabelle verändert.
Konfiguration auf der Odoo-Seite
Dedizierten Benutzer anlegen
Wir empfehlen dringend, einen dedizierten Odoo-Benutzer für die Integration anzulegen, anstatt einen persönlichen Administratoraccount zu verwenden. So lassen sich die Aktionen des Konnektors leichter auditieren und sein Zugriff unabhängig widerrufen.
- In Odoo: Einstellungen → Benutzer und Unternehmen → Benutzer.
- Legen Sie einen Benutzer beispielsweise namens
Shopware Bridgean. - Vergeben Sie die nötigen Rechte: Lager (Benutzer), Verkauf (Administrator), Buchhaltung (Benutzer, falls Sie die Rechnungserstellung aktivieren), Kontakte (Benutzer).
API-Schlüssel generieren
- Melden Sie sich mit diesem neuen Benutzer in Odoo an.
- Klicken Sie oben rechts auf den Avatar → Präferenzen.
- Reiter Konto → API-Schlüssel → Neuer API-Schlüssel.
- Geben Sie einen aussagekräftigen Namen ein (z. B.
Shopware Connector) und kopieren Sie den generierten Wert.
Konfiguration auf der Shopware-Seite
Verbindungsdaten eintragen
In der Shopware-Administration: Einstellungen → System → Plugins → Df Odoo → Einstellungen oder über das Seitenmenü Einstellungen → Df Odoo → Einstellungen.
- Odoo URL: vollständige URL Ihrer Instanz ohne abschließenden Schrägstrich, z. B.
https://meinkonto.odoo.com. - Datenbankname: in der Odoo-URL nach
?db=sichtbar oder unter Einstellungen → Technisch → Datenbank. - Benutzer: Login des dedizierten Benutzers, meist die E-Mail-Adresse.
- Odoo API-Schlüssel: im vorherigen Schritt kopierter Wert.
- Timeout: standardmäßig 30 Sekunden, in den meisten Fällen ausreichend.
Verbindung testen
Klicken Sie oben rechts auf Verbindung testen. Wenn alles korrekt ist, zeigt eine grüne Benachrichtigung die Odoo-Version und die Benutzerkennung (uid) an. Schlägt die Verbindung fehl, wird die von Odoo zurückgegebene Fehlermeldung unverändert angezeigt.
curl -X POST -H "Authorization: Bearer ADMIN_TOKEN" https://ihrshopware.com/api/_action/df-odoo/test-connection
Synchronisationsrichtungen
Jede Entität hat ihren eigenen Selektor: deaktiviert, Odoo → Shopware (pull), Shopware → Odoo (push) oder bidirektional. Die Standardwerte sind:
- Produkte: bidirektional
- Lagerbestand: Odoo → Shopware (Odoo ist die Wahrheitsquelle)
- Kunden: Shopware → Odoo
- Bestellungen: Shopware → Odoo
- Kategorien: deaktiviert (je nach Organisation manuell aktivieren)
Produktsynchronisation
Zuordnungsstrategien
Drei Strategien sind konfigurierbar:
- SKU (empfohlen): Shopware
productNumber↔ Odoodefault_code. - Odoo-ID: stützt sich ausschließlich auf die persistente Zuordnungstabelle. Nützlich, wenn Ihre SKUs unbeständig sind.
- Barcode (EAN): Shopware
ean↔ Odoobarcode. Erfordert EANs auf beiden Seiten.
Einmal verknüpft, bleiben zwei Produkte über die Tabelle df_odoo_mapping verknüpft, selbst wenn sich die SKU später ändert.
Pull aus Odoo
Die geplante Aufgabe liest product.template-Datensätze, die seit dem letzten Lauf geändert wurden (Feld write_date), und legt die entsprechenden Shopware-Produkte an oder aktualisiert sie. Synchronisierte Felder: Name, SKU, Verkaufspreis, Einstandspreis, Kurzbeschreibung, Langbeschreibung, Gewicht, Volumen, Aktiv-Status, Kategorie, Steuern.
Push nach Odoo
Aktive Shopware-Hauptprodukte (mit parentId = null) werden als product.template vom Typ product (lagerbare Ware) an Odoo gesendet. Shopware-Varianten werden unter ihrem Hauptprodukt gebündelt.
skipped protokolliert. So wird Odoo bei aufeinanderfolgenden Cron-Läufen nicht überlastet.
Lagerbestandssynchronisation
Der Lagerbestand wird immer aus Odoo gezogen (nie umgekehrt). Alle 15 Minuten liest die geplante Aufgabe product.product-Varianten in Stapeln von 100 nach übergeordneter Template-ID, aggregiert qty_available oder free_qty (global konfigurierbar) und aktualisiert das Feld stock jedes Shopware-Produkts in einer einzigen DAL-Anfrage.
qty_available spiegelt den physischen Bestand im Lager wider. free_qty zieht bereits auf nicht ausgelieferten Bestellungen reservierte Mengen ab. free_qty ist für einen Online-Shop in der Regel vorzuziehen, da Überverkäufe vermieden werden.
Kategoriensynchronisation
Standardmäßig deaktiviert. Aktivieren Sie sie, wenn Ihr Kategoriebaum mit dem von Odoo synchron bleiben soll. Die Hierarchie parent_id wird auf beiden Seiten erhalten. Wie bei Produkten verhindert ein Inhalts-Hash unnötige Schreibvorgänge.
Kundensynchronisation
Shopware-Kunden werden als Odoo-res.partner mit Folgendem gepusht:
- Deduplizierung per E-Mail: Vor jeder Anlage wird ein bestehender Partner mit derselben E-Mail und
parent_id = falsegesucht. Wird einer gefunden, wird er aktualisiert statt dupliziert. - company_type: company, wenn das Feld Unternehmen der Rechnungsadresse ausgefüllt ist, sonst person.
- Unteradressen: Die Standardrechnungsadresse wird als Unterpartner mit
type='invoice'angelegt, die Standardlieferadresse als Unterpartner mittype='delivery'. - Innergemeinschaftliche USt-IdNr.: wird auf das Feld
vatdes Hauptpartners übernommen. - Land und Region: per ISO-Code mit In-Memory-Cache pro Anfrage aufgelöst.
Bestellsynchronisation
In Echtzeit beim Checkout
Ist die Option Jede Bestellung beim Auslösen pushen aktiviert, lauscht ein Event-Subscriber auf CheckoutOrderPlacedEvent und überträgt die Bestellung unmittelbar nach Checkout-Abschluss an Odoo. Der Kunde wird bei Bedarf in Odoo angelegt (über die Kundensynchronisation), anschließend wird die Bestellung als sale.order mit folgendem erzeugt:
partner_idüber die Kundenzuordnung aufgelöst.order_linein Odoo-Tuple-Syntax:[0, 0, {name, product_uom_qty, price_unit, product_id}].- Eine zusätzliche Position für Versandkosten, wenn die Versand-
totalPricegrößer null ist. company_id,warehouse_id,pricelist_idgemäß den konfigurierten Standardwerten.
df_odoo_log protokolliert und die Bestellung innerhalb von 10 Minuten von der geplanten Aufgabe df_odoo.order_sync erneut versucht, welche die nicht zugeordneten Bestellungen der letzten 7 Tage scannt.
Statusfilter
Die Einstellung Bestellstatus-Filter schränkt ein, welche Bestellungen gepusht werden:
- Alle: jede ausgelöste Bestellung wird gesendet (für B2C mit sofortiger Zahlung empfohlen).
- Nur bezahlt: Nur Bestellungen mit Zahlungsstatus paid werden gepusht. Verhindert, dass abgebrochene Warenkörbe mit manueller Zahlung Odoo verschmutzen.
- Bezahlt oder versendet: Pusht zusätzlich Bestellungen, die vor der Zahlung versendet wurden (B2B mit Zahlungsfristen).
Automatische Bestätigung und Rechnung
Zwei Optionen steuern, was auf der Odoo-Seite passiert, sobald die Bestellung angelegt ist:
- Bestellung bestätigen: ruft
action_confirmauf dersale.orderauf, die direkt in den Zustand bestätigte Bestellung wechselt, statt als Angebot stehen zu bleiben. - Rechnung erstellen: ruft
_create_invoicesauf, um sofort eine validierte Rechnung zu erzeugen. Die ID der erstellten Rechnung wird als Mapping vom Typinvoicegespeichert.
Multi Sales Channel
Alle Plugin-Einstellungen können pro Sales Channel überschrieben werden. Oben auf der Seite Einstellungen erlaubt der native Shopware-Selektor das Umschalten zwischen Alle Channels und einem bestimmten Channel.
Typische Anwendungsfälle:
- Ein B2C-Channel, der an ein Haupt-Odoo pusht, und ein B2B-Channel, der an ein separates Odoo pusht.
- Ein Produktions-Channel mit Richtung push und ein Staging-Channel mit Richtung deaktiviert.
- Unterschiedliche Odoo-IDs (Warehouse, Sales Team, Pricelist) je Channel.
Geplante Aufgaben
| Interner Name | Frequenz | Aktion |
|---|---|---|
df_odoo.product_sync |
1 Stunde | Pull und Push von Produkten gemäß der konfigurierten Richtung. Pull betrachtet nur seit -2h geänderte Datensätze. |
df_odoo.stock_sync |
15 Minuten | Pull des Lagerbestands aus Odoo für alle bereits zugeordneten Produkte. |
df_odoo.customer_sync |
1 Stunde | Push aktiver, noch nicht zugeordneter Kunden (max. 100 pro Lauf). |
df_odoo.order_sync |
10 Minuten | Push der nicht zugeordneten Bestellungen der letzten 7 Tage (max. 50 pro Lauf). |
Eine Aufgabe von der Konsole erzwingen:
sudo -u www-data setsid php bin/console scheduled-task:run-single df_odoo.product_sync
messenger:consume oder systemd-Unit). Prüfen Sie in Einstellungen → System → Warteschlange, dass scheduled_task regelmäßig konsumiert wird.
Admin-Modul
Ein Bereich Df Odoo erscheint unter Einstellungen → Plugins mit vier Seiten.
Dashboard
Live-Zähler (aktive Zuordnungen pro Entität, Aktivität der letzten 24h pro Status), manuelle Sync-Buttons pro Entität (Pull und Push), Verbindungsstatusbanner, Liste der letzten Fehler und Verknüpfungen zu den anderen Seiten.
Einstellungen
Vollständiges Formular mit Sales-Channel-Auswahl. Buttons Verbindung testen und Speichern in der Aktionsleiste.
Logs
Jede Operation wird in df_odoo_log mit ihrem Status (success, error, warning, skipped), Richtung, Entität, Dauer in Millisekunden und vollständiger Nachricht protokolliert. Kombinierbare Filter nach Status, Entitätstyp und Richtung. Serverseitige Paginierung.
Zuordnungen
Lesende Ansicht auf die Tabelle df_odoo_mapping mit Suche, Filter nach Entitätstyp und Sortierung nach letztem Synchronisationsdatum. Praktisch, um zu prüfen, ob ein bestimmtes Produkt der erwarteten Odoo-ID zugeordnet ist.
Admin REST-API
Alle Endpunkte erfordern eine Standard-Admin-Authentifizierung (Bearer-Token).
| Methode | Endpunkt | Parameter |
|---|---|---|
| POST | /api/_action/df-odoo/test-connection |
salesChannelId (optional) |
| 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 |
Beispielaufruf zum Erzwingen eines Produkt-Pushs:
curl -X POST
-H "Authorization: Bearer ADMIN_TOKEN"
-d "direction=push"
https://ihrshopware.com/api/_action/df-odoo/sync/products
Tabellen und gespeicherte Daten
Das Plugin erstellt zwei MySQL-Tabellen:
df_odoo_mapping— persistente Zuordnungen (Shopware-ID ↔ Odoo-ID) mit Synchronisations-Hash und optionalem Payload. Eine Zeile ist eindeutig auf (Entitätstyp, Shopware-ID) und auf (Entitätstyp, Odoo-ID).df_odoo_log— Operationsjournal mit Status, Dauer, Nachricht, Payload, Sales-Channel-ID.
Es wird keine Standardtabelle von Shopware verändert.
Deinstallation
Aus der Administration: Erweiterungen → Meine Erweiterungen → Df Odoo → Deinstallieren.
Ein Dialog bietet zwei Optionen:
- Benutzerdaten behalten aktiviert: Die Tabellen
df_odoo_mappingunddf_odoo_logsowie die Systemeinstellungen bleiben erhalten. Praktisch für eine spätere Neuinstallation. - Benutzerdaten behalten deaktiviert: Beide Tabellen werden bei der Deinstallation gelöscht (DROP TABLE). Die Odoo-Instanz wird nie angerührt.
Fehlerbehebung
„Odoo-Konfiguration unvollständig“ beim Verbindungstest
Eines der vier Pflichtfelder (URL, Datenbank, Benutzer, API-Schlüssel) ist leer. Vergewissern Sie sich, dass der richtige Sales Channel vor dem Speichern ausgewählt war.
„401 Unauthorized“ oder „access denied“
Der API-Schlüssel wurde auf der Odoo-Seite widerrufen oder der Benutzer hat nicht die erforderlichen Rechte auf das Zielmodell. Generieren Sie einen neuen API-Schlüssel und prüfen Sie die Odoo-Rechte des Benutzers (insbesondere Lager → Benutzer und Verkauf → Administrator).
„Verbindung verweigert“ oder Timeout
Die Odoo-URL ist vom Shopware-Server aus nicht erreichbar. Stellen Sie sicher, dass die Firewall ausgehende HTTPS-Verbindungen zur Odoo-Domain erlaubt. Erhöhen Sie das Timeout, falls Ihre Odoo-Instanz langsam antwortet.
Produkte werden nicht synchronisiert
Prüfen Sie das Journal (Seite Logs) auf Fehlereinträge. Aktivieren Sie den Debug-Modus, um auch skipped-Operationen zu erfassen und herauszufinden, ob der Inhalts-Hash bedeutet, dass sich tatsächlich nichts geändert hat.
Bestellungen werden beim Checkout nicht gepusht
Stellen Sie sicher, dass die Option Jede Bestellung beim Auslösen pushen aktiviert ist und die Richtung Bestellungen auf Shopware → Odoo steht. Steht der Statusfilter auf Nur bezahlt und ist die Zahlung asynchron, pusht die geplante Aufgabe die Bestellung wenige Minuten nach dem Zahlungseingang.
Bekannte Einschränkungen
- Odoo-Variantenattribute (
product.attribute) werden noch nicht automatisch zugeordnet. Shopware-Varianten werden als Odoo-Hauptprodukte (product.template) gebündelt. Manuell in Odoo angelegte Varianten bleiben über ihr Parent-Template korrekt verknüpft. Eine native Verwaltung ist für Version 1.1 geplant. - Rabatte auf Bestellpositionen werden als angepasster
price_unitgemeldet, nicht als Odoo-Felddiscount. - Shopware-Zahl- und Versandarten werden nicht auf Odoo-
journal_idabgebildet — es werden die Odoo-Standardwerte verwendet.
Support
Bei Fragen kontaktieren Sie das DataFirefly-Team über das Kontaktformular auf datafirefly.com. Bitte hängen Sie den Journal-Export an (Seite Logs → Export-Button folgt) oder zumindest einen Screenshot der fehlgeschlagenen Zeile sowie die genauen Versionen von Shopware, PHP und Odoo.