# DataFirefly Odoo Connector: przewodnik instalacji i konfiguracji

> Ten przewodnik obejmuje instalację, konfigurację i eksploatację pluginu DataFirefly Odoo Connector dla Shopware 6.6 i 6.7. Na koniec Twój sklep będzie synchronizował produkty, stany magazynowe, klientów i zamówienia z Twoją…

- Strona: <https://www.datafirefly.com/pl/documentation/df-odoo-connector/>
- Język: pl
- Zaktualizowano: 2026-10-10
- Inne języki: [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), [de](https://www.datafirefly.com/de/documentation/df-odoo-connector/index.md), [it](https://www.datafirefly.com/it/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)
- Indeks: <https://www.datafirefly.com/pl/documentation/llms.txt>

Ten przewodnik obejmuje instalację, konfigurację i eksploatację pluginu **DataFirefly Odoo Connector** dla Shopware 6.6 i 6.7. Na koniec Twój sklep będzie synchronizował produkty, stany magazynowe, klientów i zamówienia z Twoją instancją Odoo przez natywne XML-RPC, bez żadnej zewnętrznej zależności i bez dopłat za API firm trzecich.

## Wprowadzenie

Plugin buduje dwukierunkowy most między Shopware a Odoo, mówiąc bezpośrednio protokołem XML-RPC Odoo (stabilnym od wersji 8). Żadnego modułu do instalacji po stronie Odoo, żadnego płatnego middleware, żadnego pośredniczącego SaaS.

| Encja | Odoo → Shopware (pull) | Shopware → Odoo (push) |
| --- | --- | --- |
| Produkty (product.template) | ✅ | ✅ |
| Stany magazynowe (qty_available / free_qty) | ✅ | — |
| Kategorie (product.category) | ✅ | ✅ |
| Klienci (res.partner) | — | ✅ z adresami podrzędnymi |
| Zamówienia (sale.order) | — | ✅ z opcjonalnym potwierdzeniem i fakturą |

## Wymagania

- **Shopware** 6.6.x albo 6.7.x (wszystkie wersje pomocnicze).
- **PHP** 8.2, 8.3 albo 8.4.
- **Rozszerzenia PHP**: curl, xml, simplexml (obecne domyślnie u niemal wszystkich hostingów).
- **Odoo** 12, 13, 14, 15, 16, 17 albo 18, w wersji Community albo Enterprise. Odoo.sh, Odoo Online (SaaS) i instancje self-hosted działają identycznie.
- Użytkownik Odoo dedykowany do API (zalecane) z prawami odczytu i zapisu na używanych modelach (product.template, product.product, res.partner, sale.order, stock.warehouse, product.category, res.country, account.tax).

## Instalacja

### Przez przesłanie w administracji

1. Pobierz archiwum `DfOdooConnector-v1.0.0.zip` ze swojego konta klienta.
2. W administracji Shopware: _Rozszerzenia → Moje rozszerzenia → Prześlij rozszerzenie_.
3. Wybierz ZIP, a następnie kliknij _Zainstaluj_.
4. Aktywuj rozszerzenie, klikając przełącznik.

### Przez konsolę SSH

```
cd /path/to/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
```

Rekompilacja administracji, aby załadować moduł Vue 3:

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

**Uwaga**: instalacja tworzy dwie tabele: `df_odoo_mapping` (trwałe powiązania Shopware ↔ Odoo) i `df_odoo_log` (dziennik operacji). Żadna istniejąca tabela nie jest modyfikowana.

## Konfiguracja po stronie Odoo

### Utworzenie dedykowanego użytkownika

Zdecydowanie zalecamy utworzenie użytkownika Odoo dedykowanego integracji, zamiast używania osobistego konta administratora. Pozwala to precyzyjnie audytować działania konektora i odbierać mu dostęp niezależnie.

1. W Odoo: _Ustawienia → Użytkownicy i firmy → Użytkownicy_.
2. Utwórz użytkownika o nazwie na przykład `Shopware Bridge`.
3. Nadaj mu wymagane uprawnienia: Magazyn (użytkownik), Sprzedaż (administrator dokumentów), Fakturowanie (użytkownik, jeśli włączasz tworzenie faktur), Kontakty (użytkownik).

### Wygenerowanie klucza API

1. Zaloguj się do Odoo tym nowym użytkownikiem.
2. Kliknij awatar w prawym górnym rogu → _Preferencje_.
3. Zakładka _Konto_ → _Klucze API_ → _Nowy klucz API_.
4. Nadaj opisową nazwę (na przykład `Shopware Connector`) i skopiuj wygenerowaną wartość.

**Ważne**: klucz API wyświetla się tylko raz. Jeśli go zgubisz, trzeba będzie wygenerować nowy. Zapisz go w menedżerze haseł przed zamknięciem okna.

## Konfiguracja po stronie Shopware

### Uzupełnienie połączenia

W administracji Shopware: _Ustawienia → System → Pluginy → Df Odoo → Ustawienia_ albo bezpośrednio przez menu boczne _Ustawienia → Df Odoo → Ustawienia_.

- **Adres URL Odoo**: pełny adres Twojej instancji bez końcowego ukośnika, na przykład `https://mojekonto.odoo.com`.
- **Nazwa bazy**: widoczna w adresie Odoo po `?db=` albo w _Ustawienia → Techniczne → Baza danych_.
- **Użytkownik**: login dedykowanego użytkownika, zwykle jego adres e-mail.
- **Klucz API Odoo**: wartość skopiowana w poprzednim kroku.
- **Limit czasu**: domyślnie 30 sekund, wystarczające w większości przypadków.

### Test połączenia

Kliknij przycisk _Testuj połączenie_ w prawym górnym rogu. Jeśli wszystko jest poprawne, zielone powiadomienie pokazuje wersję Odoo i identyfikator użytkownika (uid). Jeśli połączenie się nie powiedzie, komunikat błędu zwrócony przez Odoo jest wyświetlany bez zmian.

**Wskazówka**: test połączenia można też wywołać z konsoli, aby oskryptować weryfikację:
`curl -X POST -H "Authorization: Bearer ADMIN_TOKEN" https://twojshopware.com/api/_action/df-odoo/test-connection`

## Kierunki synchronizacji

Każda encja ma niezależny selektor: _wyłączone_, _Odoo → Shopware_ (pull), _Shopware → Odoo_ (push) albo _dwukierunkowo_. Wartości domyślne to:

- **Produkty**: dwukierunkowo
- **Stany magazynowe**: Odoo → Shopware (Odoo jest źródłem prawdy)
- **Klienci**: Shopware → Odoo
- **Zamówienia**: Shopware → Odoo
- **Kategorie**: wyłączone (do włączenia ręcznie, zależnie od Twojej organizacji)

## Synchronizacja produktów

### Strategie dopasowania

Do skonfigurowania są trzy strategie:

- **SKU** (zalecane): Shopware `productNumber` ↔ Odoo `default_code`.
- **ID Odoo**: opiera się wyłącznie na trwałej tabeli mapowania. Przydatne, jeśli Twoje SKU bywają zmienne.
- **Kod kreskowy** (EAN): Shopware `ean` ↔ Odoo `barcode`. Wymaga uzupełnionych EAN po obu stronach.

Po powiązaniu dwa produkty pozostają sparowane przez tabelę `df_odoo_mapping`, nawet jeśli SKU później się zmieni.

### Pull z Odoo

Zadanie cykliczne czyta rekordy `product.template` zmodyfikowane od ostatniego uruchomienia (pole `write_date`) i tworzy albo aktualizuje odpowiadające produkty po stronie Shopware. Synchronizowane pola to: nazwa, SKU, cena sprzedaży, cena zakupu, krótki opis, długi opis, waga, objętość, status aktywności, kategoria, podatki.

### Push do Odoo

Aktywne produkty główne Shopware (z `parentId = null`) są wysyłane do Odoo jako `product.template` typu _product_ (artykuł magazynowy). Warianty Shopware są przekazywane pod ich produktem nadrzędnym.

**Wykrywanie zmian**: przed każdym zapisem hash SHA-1 treści jest porównywany z tym zapamiętanym w mapowaniu. Jeśli nic się nie zmieniło, zapis jest pomijany, a operacja logowana jako `skipped`. To zapobiega zapychaniu Odoo przy kolejnych cronach.

## Synchronizacja stanów magazynowych

Stan magazynowy jest zawsze pobierany z Odoo (nigdy odwrotnie). Co 15 minut zadanie cykliczne czyta warianty `product.product` partiami po 100 według identyfikatora nadrzędnego szablonu, agreguje `qty_available` albo `free_qty` (konfigurowalne globalnie), a następnie aktualizuje pole `stock` każdego produktu Shopware jednym zapytaniem DAL.

**qty_available a free_qty**: `qty_available` odzwierciedla fizyczny stan obecny w magazynie. `free_qty` odejmuje ilości już zarezerwowane na niezrealizowanych zamówieniach. _free_qty_ jest zwykle lepszym wyborem dla sklepu, bo zapobiega nadsprzedaży.

## Synchronizacja kategorii

Domyślnie wyłączona. Włącz ją, jeśli Twoje drzewo kategorii ma pozostawać zsynchronizowane z drzewem Odoo. Hierarchia `parent_id` jest zachowywana po obu stronach. Podobnie jak przy produktach, hash treści zapobiega zbędnym zapisom.

## Synchronizacja klientów

Klienci Shopware są wysyłani jako `res.partner` Odoo wraz z:

- **Deduplikacją po e-mailu**: przed każdym utworzeniem wyszukiwany jest istniejący partner o tym samym e-mailu i `parent_id = false`. Jeśli istnieje, jest aktualizowany zamiast duplikowany.
- **company_type**: _company_, jeśli pole firmy w adresie rozliczeniowym jest uzupełnione, w przeciwnym razie _person_.
- **Adresami podrzędnymi**: domyślny adres rozliczeniowy powstaje jako partner podrzędny z `type='invoice'`, adres dostawy jako partner podrzędny z `type='delivery'`.
- **VAT wewnątrzwspólnotowym**: przenoszonym do pola `vat` partnera głównego.
- **Krajem i regionem**: rozwiązywanymi po kodzie ISO, z cache w pamięci w obrębie żądania.

## Synchronizacja zamówień

### W czasie rzeczywistym przy checkoucie

Jeśli opcja _Wysyłaj każde zamówienie zaraz po zatwierdzeniu_ jest włączona, event subscriber nasłuchuje `CheckoutOrderPlacedEvent` i natychmiast po finalizacji checkoutu wysyła zamówienie do Odoo. Klient jest w razie potrzeby tworzony w Odoo (przez synchronizację klientów), a następnie zamówienie powstaje jako `sale.order` z:

- `partner_id` rozwiązanym przez mapowanie klienta.
- `order_line` w składni krotek Odoo: `[0, 0, {name, product_uom_qty, price_unit, product_id}]`.
- Dodatkową linią na koszty transportu, jeśli `totalPrice` wysyłki jest większe od zera.
- `company_id`, `warehouse_id`, `pricelist_id` zgodnie ze skonfigurowanymi wartościami domyślnymi.

**Checkout nigdy nie jest blokowany**: jeśli Odoo jest niedostępne, błąd trafia do `df_odoo_log`, a zamówienie zostanie podjęte w ciągu 10 minut przez zadanie cykliczne `df_odoo.order_sync`, które skanuje zamówienia z ostatnich 7 dni jeszcze niezmapowane.

### Filtr statusu

Filtr _Status zamówień_ pozwala zawęzić wysyłane zamówienia:

- **Wszystkie**: wysyłane jest każde zatwierdzone zamówienie (zalecane w B2C z płatnością natychmiastową).
- **Tylko opłacone**: wysyłane są wyłącznie zamówienia o statusie płatności _paid_. Zapobiega przekazywaniu porzuconych koszyków z płatnością ręczną.
- **Opłacone albo wysłane**: dokłada do powyższych zamówienia wysłane przed opłaceniem (B2B z terminami).

### Automatyczne potwierdzenie i faktura

Dwie opcje sterują tym, co dzieje się po stronie Odoo po utworzeniu zamówienia:

- **Potwierdź zamówienie**: wywołuje `action_confirm` na `sale.order`, które przechodzi wtedy od razu w stan _zamówienie potwierdzone_ zamiast pozostawać _ofertą_.
- **Utwórz fakturę**: wywołuje `_create_invoices`, aby natychmiast wygenerować zatwierdzoną fakturę. Identyfikator utworzonej faktury jest zapamiętywany jako mapowanie typu `invoice`.

## Wiele sales channels

Wszystkie ustawienia pluginu można nadpisać per kanał sprzedaży. U góry strony _Ustawienia_ natywny selektor Shopware pozwala przełączać się między _Wszystkimi kanałami_ a konkretnym kanałem.

Typowe zastosowania:

- Kanał B2C wysyłający do głównego Odoo i kanał B2B wysyłający do odrębnego Odoo.
- Kanał produkcyjny z kierunkiem _push_ i kanał stagingowy z kierunkiem _wyłączonym_.
- Różne identyfikatory Odoo (warehouse, sales team, pricelist) zależnie od kanału.

## Zadania cykliczne

| Nazwa wewnętrzna | Częstotliwość | Działanie |
| --- | --- | --- |
| `df_odoo.product_sync` | 1 godzina | Pull, a następnie push produktów zgodnie ze skonfigurowanym kierunkiem. Pull analizuje wyłącznie karty zmodyfikowane od -2 h. |
| `df_odoo.stock_sync` | 15 minut | Pull stanów magazynowych z Odoo dla wszystkich już zmapowanych produktów. |
| `df_odoo.customer_sync` | 1 godzina | Push aktywnych klientów jeszcze niezmapowanych (maks. 100 na wykonanie). |
| `df_odoo.order_sync` | 10 minut | Push zamówień z ostatnich 7 dni jeszcze niezmapowanych (maks. 50 na wykonanie). |

Wymuszenie wykonania zadania z konsoli:

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

**Worker Shopware**: aby zadania cykliczne uruchamiały się automatycznie, musi działać worker messengera Shopware (cron `messenger:consume` albo zadanie systemd). Sprawdź w _Ustawienia → System → Kolejka_, czy _scheduled_task_ jest regularnie konsumowane.

## Moduł administracji

W _Ustawienia → Pluginy_ pojawia się sekcja **Df Odoo** z czterema stronami.

### Pulpit

Liczniki na żywo (aktywne mapowania per encja, aktywność z ostatnich 24 h per status), przyciski ręcznej synchronizacji per encja (pull i push), pasek stanu połączenia, lista ostatnich błędów i skróty do pozostałych stron.

### Ustawienia

Kompletny formularz z selektorem kanału sprzedaży. Przyciski _Testuj połączenie_ i _Zapisz_ na pasku akcji.

### Dziennik

Wszystkie operacje są zapisywane w `df_odoo_log` wraz ze statusem (_success_, _error_, _warning_, _skipped_), kierunkiem, daną encją, czasem trwania w milisekundach i pełnym komunikatem. Filtry łączone po statusie, typie encji i kierunku. Stronicowanie po stronie serwera.

**Tryb debug**: operacje _skipped_ trafiają do dziennika tylko wtedy, gdy w ustawieniach włączono tryb debug. Używaj go doraźnie do diagnozowania zachowania i wyłączaj w produkcji, aby nie zapchać tabeli.

### Powiązania

Widok odczytu tabeli `df_odoo_mapping` z wyszukiwaniem, filtrem po typie encji i sortowaniem po dacie ostatniej synchronizacji. Praktyczny do sprawdzenia, czy dany produkt jest zmapowany do oczekiwanego ID Odoo.

## REST API administracji

Wszystkie endpointy wymagają standardowego uwierzytelnienia administracji (Bearer token).

| Metoda | Endpoint | Parametry |
| --- | --- | --- |
| POST | `/api/_action/df-odoo/test-connection` | `salesChannelId` (opcjonalny) |
| 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` |

Przykład wywołania wymuszającego push produktów:

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

## Tabele i przechowywane dane

Plugin tworzy dwie tabele MySQL:

- `df_odoo_mapping`: trwałe powiązania (identyfikator Shopware ↔ identyfikator Odoo) z hashem synchronizacji i opcjonalnym payloadem. Wiersz jest unikalny na parze (typ encji, identyfikator Shopware) oraz (typ encji, identyfikator Odoo).
- `df_odoo_log`: dziennik operacji ze statusem, czasem trwania, komunikatem, payloadem i identyfikatorem kanału sprzedaży.

Żadna standardowa tabela Shopware nie jest modyfikowana.

## Odinstalowanie

Z administracji: _Rozszerzenia → Moje rozszerzenia → Df Odoo → Odinstaluj_.

Okno dialogowe proponuje dwie opcje:

- **Zachowaj dane użytkownika** zaznaczone: tabele `df_odoo_mapping` i `df_odoo_log` są zachowywane, podobnie jak ustawienia systemowe. Praktyczne przy późniejszej ponownej instalacji.
- **Zachowaj dane użytkownika** odznaczone: obie tabele są usuwane (DROP TABLE) przy odinstalowaniu. Instancja Odoo nigdy nie jest ruszana.

## Rozwiązywanie problemów

### "Niekompletna konfiguracja Odoo" przy teście połączenia

Jedno z czterech obowiązkowych pól (adres URL, baza, użytkownik, klucz API) jest puste. Sprawdź, czy przed zapisem wybrano właściwy kanał sprzedaży.

### "401 Unauthorized" albo "access denied"

Klucz API został odwołany po stronie Odoo albo użytkownik nie ma wymaganych uprawnień na docelowym modelu. Wygeneruj nowy klucz API i sprawdź uprawnienia użytkownika w Odoo (zwłaszcza _Magazyn → Użytkownik_ i _Sprzedaż → Administrator dokumentów_).

### "Połączenie odrzucone" albo timeout

Adres URL Odoo nie jest osiągalny z serwera Shopware. Sprawdź, czy firewall zezwala na wychodzące połączenia HTTPS do domeny Odoo. Zwiększ limit czasu, jeśli Twoja instancja Odoo odpowiada wolno.

### Produkty się nie synchronizują

Sprawdź dziennik (strona _Dziennik_) pod kątem wpisów z błędami. Włącz tryb debug, aby logować także operacje _skipped_ i ustalić, czy hash treści nie sprawia, że faktycznie nic się nie zmienia.

### Zamówienia nie wychodzą przy checkoucie

Sprawdź, czy opcja _Wysyłaj każde zamówienie zaraz po zatwierdzeniu_ jest zaznaczona i czy kierunek _Zamówienia_ jest ustawiony na _Shopware → Odoo_. Jeśli filtr statusu jest ustawiony na _Tylko opłacone_, a płatność jest asynchroniczna, zamówienie wysyła zadanie cykliczne kilka minut po zaksięgowaniu.

## Znane ograniczenia

- Atrybuty wariantów Odoo (`product.attribute`) nie są jeszcze mapowane automatycznie. Warianty Shopware są przekazywane jako produkty nadrzędne Odoo (`product.template`). Warianty Odoo utworzone ręcznie pozostają poprawnie powiązane przez swój szablon nadrzędny. Natywna obsługa jest przewidziana w wersji 1.1.
- Rabaty w liniach zamówienia są przenoszone jako skorygowane `price_unit`, a nie jako `discount` Odoo.
- Metody płatności i wysyłki Shopware nie są mapowane na `journal_id` Odoo: używane są wartości domyślne Odoo.

## Wsparcie

W razie pytań skontaktuj się z zespołem DataFirefly przez formularz kontaktowy na [datafirefly.com](https://www.datafirefly.com/pl/kontakt/). Pamiętaj, aby dołączyć eksport dziennika (strona _Dziennik_ → przycisk eksportu w przygotowaniu) albo przynajmniej zrzut wiersza z błędem oraz dokładne wersje Shopware, PHP i Odoo.
