Mirakl nie jest marketplace’em, na którym się sprzedaje. To oprogramowanie, na którym retailer buduje własny: Leroy Merlin, Carrefour, Kingfisher, Macy's czy Best Buy figurują dziś jako klienci na stronie Mirakl. Gdy któryś Cię zaprasza, sprzedajesz u operatora (jego kategorie, jego prowizja, jego umowa), ale Twoje Odoo rozmawia z API Mirakl, takim samym u wszystkich. Dobrze zrobiony konektor Mirakl to nie „konektor Leroy Merlin”: to N marketplace’ów z jednym API i różnymi danymi dostępowymi. A trudne nie jest API: trudne jest rozdzielenie zapasów między kanały, które patrzą na ten sam magazyn.
Sprostowanie na naszej własnej stronie: przez miesiące traktowaliśmy Leroy Merlin i GACD jako osobne integracje. To dwa konta tego samego konektora: ten sam kod z innym hostem, kluczem i katalogiem.
Co mają wspólnego wszyscy operatorzy Mirakl, a co ich różni
API sprzedawcy Mirakl ma kod operacji do każdej czynności, taki sam niezależnie od nazwy operatora: OR11 wyświetla zamówienia, OR23 i OR24 przekazują numer śledzenia i oznaczają wysyłkę, OR28 zwraca pieniądze, OF01 wgrywa oferty plikiem, IV01 zwraca dokumenty rozliczeniowe, M11 to komunikacja z kupującym, a SH21 wyświetla przewoźników. Operator może mieć wyłączone całe grupy funkcji (są tacy bez komunikatora i bez przewoźników, a konektor oznacza endpoint jako niedostępny po odpowiedzi 404 lub 410), ale gdy je udostępnia, jest to to samo wywołanie.
Zmienia się wszystko, co nie jest API: host (adeo-marketplace.mirakl.net w Leroy Merlin), klucz i sklep, drzewo kategorii i wymagane atrybuty (4 844 kategorie i 35 364 atrybuty na naszym koncie Leroy Merlin), obsługiwani przewoźnicy (165 kodów), powody zwrotów, waluta i przede wszystkim tryb podatków: jedni przesyłają ceny z VAT (TAX_INCLUDED), inni bez niego (TAX_EXCLUDED). Ten punkt kosztował nas prawdziwy błąd: konektor przyjmował cenę z VAT jako podstawę, Odoo doliczało go drugi raz i 48,86 € wchodziło jako 59,12 €. Zweryfikowane na 20 prawdziwych zamówieniach z konta.
Jak zamodelować to w Odoo: jedno konto na operatora
W naszym konektorze Mirakl każdy operator to instancja: rekord z podstawowym adresem URL, adresem URL API, kluczem, sklepem, firmą, magazynem i zespołem sprzedaży. Przy teście połączenia odczytuje /platform/configuration, /account i /channels i zapisuje, jaka platforma odpowiada, jaki to sklep i jakie funkcje udostępnia. Na zrzucie wykrytą platformą jest „Marketplace Adeo”, a wykrytym dostawcą leroy_merlin.

Do instancji przypisane jest wszystko, co dotyczy operatora: słownik kategorii, atrybutów i wartości (unikalny dla instancji i kodu, więc dwaj operatorzy nigdy sobie nie przeszkadzają), mapowanie kategorii i przewoźników oraz reguły cen i zapasów. Produkt Odoo ma jeden binding na instancję: ten sam produkt, inna oferta u każdego operatora, z własnym SKU, ceną i ilością. Dodanie drugiego operatora (GACD, którego API sprzedawcy odpowiada pod tdmp.mirakl.net, lub dowolnego innego) to kolejna instancja. Profile z katalogu tylko wypełniają wartości domyślne; kod komunikujący się z Mirakl jest jeden.
Prawdziwy problem: podział zapasów
Dwaj operatorzy Mirakl, ManoMano, Amazon, Temu albo Twój sklep mogą patrzeć na ten sam magazyn. Tylko dwaj pierwsi to Mirakl: pozostali mają własne API sprzedawcy (Amazon, SP-API) i wymagają osobnych konektorów. Ale wszyscy sprzedają z tych samych zapasów i żaden nie wie o pozostałych: każdy dostaje ilość, którą mu eksportujesz, i sprzedaje z niej do następnego eksportu. Nie rozwiązuje się tego „w czasie rzeczywistym”, bo ani API, ani operator tak nie działają; rozwiązuje się to regułami na kanał. Każda instancja decyduje o czterech sprawach, zanim opublikuje ilość:
- Na jaką ilość patrzy: na stanie, prognozowaną, wolną (po odjęciu zarezerwowanej) albo na stanie tylko w magazynach tej instancji.
- Ile zatrzymuje: bufor na instancję, który pokrywa sprzedaż w innych kanałach między dwoma eksportami.
- Minimum do publikacji: jeśli po odjęciu bufora zostaje mniej niż N sztuk, publikowane jest zero: sprzedaż ostatniej sztuki w trzech miejscach to klasyczna nadsprzedaż.
- Maksimum publikowane: limit na instancję, by nie pokazywać jednemu operatorowi zapasu obiecanego już innemu.
Kolejność jest zapisana w kodzie: ilość według strategii, minus bufor, zero jeśli nie osiąga minimum, przycięcie do maksimum. Przy 12 wolnych sztukach, buforze 2, minimum 3 i maksimum 5 każdy operator widzi 5. Jeśli wszyscy dostają po prostu ilość na stanie, pierwszy, kto sprzeda ostatnią sztukę, zostawia pozostałych ze sprzedażą powietrza. Bufor i częstotliwość omawiamy w zapasach w czasie rzeczywistym dla marketplace’ów, a to, jak zarządzać całością z jednego Odoo, w sprzedaży na wielu marketplace’ach i w rozwiązaniach.
Zamówienia i statusy: z Mirakl do Odoo i z powrotem
Mirakl ma więcej statusów zamówień, niż potrzebuje Odoo, i sprowadza je do sześciu: WAITING_ACCEPTANCE, WAITING_DEBIT, STAGING i INCIDENT_OPEN to „oczekujące”; SHIPPING to „w wysyłce” (kupujący zapłacił i biegnie termin nadania); SHIPPED to „wysłane”; RECEIVED i CLOSED to „zamknięte”; CANCELED i REFUSED to „anulowane”; REFUNDED to „zwrócone”. Zamówienie ze zrzutu weszło jako SHIPPED, zmapowano je na „Wysłane” i powiązano z zamówieniem sprzedaży S00509, z walutą, kwotą i podatkiem z payloadu operatora.

Cykl powrotny: oczekujące zamówienie jest akceptowane przez PUT na /orders/{id}/accept, partiami z limitem na przebieg; po zatwierdzeniu dostawy wysyłany jest numer śledzenia (OR23) i oznaczana jest wysyłka (OR24), a dostawa zostaje opatrzona zapisem żądania i odpowiedzi; zatwierdzona faktura jest wgrywana do zamówienia (OR74), po uprzednim usunięciu poprzedniej tego samego typu (OR72, OR76). A okno przyrostowe pobierane jest według daty aktualizacji, nie utworzenia: zamówienie, które zmienia status po tygodniach, nigdy by już nie wróciło.
Gdzie następuje duplikacja, jeśli konektor nie jest idempotentny
W trzech miejscach. Zamówienie: baza odrzuca dwa rekordy z tym samym identyfikatorem w tej samej instancji (unique(instance_id, mirakl_order_id)); import aktualizuje istniejący. Wysyłka: konektor najpierw ponownie odczytuje status; jeśli jest już SHIPPED, nie powtarza jej, a jeśli ponowny odczyt się nie powiedzie, niczego nie zakłada i wywołuje, bo przyjęcie za pewnik, że „już wysłano”, przy timeoucie zostawiało zamówienia bez numeru śledzenia. I zwrot, czyli pieniądze: w audycie wersji 16.15.1 zobaczyliśmy, że klient HTTP ponawiał każde żądanie po 5xx lub timeoucie, także to z OR28. Timeout nie mówi, że żądanie nie dotarło: mówi, że nie wiesz. Dziś ponawiane są tylko odczyty, z wyjątkiem 429, który gwarantuje, że nic nie zostało przetworzone; a przycisk odmawia wysłania drugiego pełnego zwrotu, jeśli zamówienie jest już oznaczone jako zwrócone.
Rozliczenia: co zwraca API i dlaczego zasługują na osobne uzgodnienie
Mirakl nie płaci Ci za zamówienie po zamówieniu: okresowo przelewa kwotę netto, a IV01 zwraca dokument, który ją wyjaśnia, z przelaną kwotą i czterema koszykami: zamówienia, prowizje, zwroty i zwrócone prowizje. Konektor zapisuje każdy dokument per instancja (okres, waluta, status płatności) i oblicza własną kwotę netto z tych koszyków. Do przelanej kwoty brakuje „innych opłat”, prawie zawsze abonamentu operatora: jedno prawdziwe rozliczenie ciągnęło różnicę 39,00 €, dopóki nie uwzględniliśmy tej reszty, i teraz widać ją jako kolejną pozycję, zamiast chować się w różnicy bez nazwy.
Kiedy operator Mirakl się nie opłaca
To, że API jest to samo, nie znaczy, że każde zaproszenie zasługuje na „tak”. Koszt wejścia leży w katalogu, nie w integracji: mapowanie Twoich kategorii na drzewo z tysiącami węzłów i uzupełnianie wymaganych atrybutów każdej rodziny to praca ludzi, powtarzana u każdego operatora. Mało pasujących kategorii, prowizja, która po opłacie zjada marżę, albo termin akceptacji, którego Twój magazyn nie dotrzyma: żaden z tych przypadków się nie opłaca, choćby podłączenie było łatwe. Sygnał daje instancja, zanim cokolwiek opublikujesz: zsynchronizuj słownik, zmapuj dziesięć rodzin i policz, ilu wymaganych atrybutów Ci brakuje. Jeśli to setki, kosztować Cię to będzie więcej, niż sprzeda.
Konektor, na którym to wszystko zrobiliśmy, działa produkcyjnie z prawdziwymi zamówieniami i na zielono (163 z 163 testów) w Odoo 19, 18 i 17, po audycie wersji 16.15.1 (121 kandydatów na błędy, 18 potwierdzonych). Jeśli dziedziczysz konektor Mirakl po kimś innym, na co patrzeć, opisujemy w audycie odziedziczonego konektora Odoo; jeśli to Twoja platforma ma rozmawiać z Odoo, to konektor Odoo dla Twojego oprogramowania.
Najczęstsze pytania
Czyli sprzedaję „w Mirakl”?
Nie. Sprzedajesz u operatora, który Cię zaprosił: to on ustala kategorie, prowizję, terminy i umowę. Mirakl to oprogramowanie, na którym ten operator prowadzi swój marketplace, a jego API jest tym, z czym integruje się Twoje Odoo.
Czy potrzebuję konektora na każdego operatora Mirakl?
Nie. Potrzebujesz jednej instancji na operatora w ramach tego samego konektora: z własnym hostem, kluczem, sklepem, słownikiem, przewoźnikami i regułami zapasów. Kod komunikujący się z API jest ten sam.
Dlaczego zapasy nie mogą działać „w czasie rzeczywistym”?
Bo każdy operator dostaje ilość, którą mu eksportujesz, i sprzedaje z niej do następnego eksportu, nie wiedząc o pozostałych. Nadsprzedaży zapobiega reguła na kanał: na jaką ilość się patrzy, bufor, minimum i maksimum, plus rozsądna częstotliwość.
Przydatne linki w FlexigoTech
Co robimy w tym temacie
Zaprosił Cię operator Mirakl i sprzedajesz z Odoo?
Napisz nam, który to operator, ile kanałów patrzy już na Twój magazyn i w jakiej wersji Odoo pracujesz. Powiemy Ci, co trzeba, by podłączyć go jako kolejną instancję, i jakie reguły zapasów musiałbyś ustawić przed publikacją. Napisz na comercial@flexigobe.com lub zadzwoń pod numer +34 616 809 504.

