# DataFirefly Odoo Konnektor — Installations- und Konfigurationsanleitung

> 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…

- Seite: <https://www.datafirefly.com/de/documentation/df-odoo-connector/>
- Sprache: de
- Aktualisiert am: 2026-06-29
- Weitere Sprachen: [fr](https://www.datafirefly.com/documentation/df-odoo-connector/index.md), [en](https://www.datafirefly.com/en/documentation/df-odoo-connector/index.md), [es](https://www.datafirefly.com/es/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/de/documentation/llms.txt>

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

1. Laden Sie `DfOdooConnector-v1.0.0.zip` aus Ihrem Kundenkonto herunter.
2. In der Shopware-Administration: _Erweiterungen → Meine Erweiterungen → Erweiterung hochladen_.
3. Wählen Sie das ZIP aus und klicken Sie auf _Installieren_.
4. 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
```

**Hinweis** — Die Installation erstellt zwei Tabellen: `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.

1. In Odoo: _Einstellungen → Benutzer und Unternehmen → Benutzer_.
2. Legen Sie einen Benutzer beispielsweise namens `Shopware Bridge` an.
3. Vergeben Sie die nötigen Rechte: Lager (Benutzer), Verkauf (Administrator), Buchhaltung (Benutzer, falls Sie die Rechnungserstellung aktivieren), Kontakte (Benutzer).

### API-Schlüssel generieren

1. Melden Sie sich mit diesem neuen Benutzer in Odoo an.
2. Klicken Sie oben rechts auf den Avatar → _Präferenzen_.
3. Reiter _Konto_ → _API-Schlüssel_ → _Neuer API-Schlüssel_.
4. Geben Sie einen aussagekräftigen Namen ein (z. B. `Shopware Connector`) und kopieren Sie den generierten Wert.

**Wichtig** — Der API-Schlüssel wird nur einmal angezeigt. Falls Sie ihn verlieren, müssen Sie einen neuen generieren. Speichern Sie ihn in einem Passwortmanager, bevor Sie den Dialog schließen.

## 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.

**Tipp** — Der Verbindungstest lässt sich auch von der Konsole aufrufen, um eine Health-Check zu skripten:
`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` ↔ Odoo `default_code`.
- **Odoo-ID**: stützt sich ausschließlich auf die persistente Zuordnungstabelle. Nützlich, wenn Ihre SKUs unbeständig sind.
- **Barcode** (EAN): Shopware `ean` ↔ Odoo `barcode`. 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.

**Änderungserkennung** — Vor jeder Schreiboperation wird ein SHA-1-Hash des Inhalts mit dem im Mapping gespeicherten verglichen. Hat sich nichts geändert, wird der Schreibvorgang übersprungen und die Operation als `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 vs. free_qty** — `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 = false` gesucht. 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 mit `type='delivery'`.
- **Innergemeinschaftliche USt-IdNr.**: wird auf das Feld `vat` des 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_line` in Odoo-Tuple-Syntax: `[0, 0, {name, product_uom_qty, price_unit, product_id}]`.
- Eine zusätzliche Position für Versandkosten, wenn die Versand-`totalPrice` größer null ist.
- `company_id`, `warehouse_id`, `pricelist_id` gemäß den konfigurierten Standardwerten.

**Der Checkout wird nie blockiert** — Ist Odoo nicht erreichbar, wird der Fehler in `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_confirm` auf der `sale.order` auf, die direkt in den Zustand _bestätigte Bestellung_ wechselt, statt als _Angebot_ stehen zu bleiben.
- **Rechnung erstellen**: ruft `_create_invoices` auf, um sofort eine validierte Rechnung zu erzeugen. Die ID der erstellten Rechnung wird als Mapping vom Typ `invoice` gespeichert.

## 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
```

**Shopware-Worker** — Damit geplante Aufgaben automatisch auslösen, muss der Shopware Messenger-Worker laufen (Cron `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.

**Debug-Modus** — _Skipped_-Operationen werden nur dann ins Journal geschrieben, wenn der Debug-Modus in den Einstellungen aktiviert ist. Verwenden Sie ihn punktuell zur Diagnose und deaktivieren Sie ihn im Produktivbetrieb, um die Tabelle nicht aufzublähen.

### 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_mapping` und `df_odoo_log` sowie 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_unit` gemeldet, nicht als Odoo-Feld `discount`.
- Shopware-Zahl- und Versandarten werden nicht auf Odoo-`journal_id` abgebildet — es werden die Odoo-Standardwerte verwendet.

## Support

Bei Fragen kontaktieren Sie das DataFirefly-Team über das Kontaktformular auf [datafirefly.com](https://www.datafirefly.com/contact/). 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.
