Wstęp
W Odoo „model” to przepis na to, jak przechowywać dane — struktura tabeli, typy pól i zależności między nimi. Każdy dokument biznesowy: zamówienie sprzedaży, faktura czy ruch magazynowy — ma swoją reprezentację w postaci modelu, który kontroluje, co i jak trafia do bazy danych.
Znajomość modeli jest niezbędna zarówno dla konsultantów funkcjonalnych, jak i programistów. To one definiują pola, relacje i logikę biznesową — czyli fundament całej architektury danych w Odoo. Bez tej wiedzy trudno bezpiecznie konfigurować procesy czy pisać rozszerzenia.
W artykule skupiamy się na jednym z kluczowych modeli związanych z magazynem — stock.move. Jeśli projektujesz magazyn, integrujesz zewnętrzne systemy logistyczne lub dostosowujesz przepływy magazynowe, to na pewno spotkasz ten model.
Czym jest model stock.move
Model stock.move opisuje pojedynczy ruch magazynowy — transfer konkretnego produktu z jednego miejsca do drugiego. Gdy towar opuszcza półkę, zmienia magazyn lub trafia do klienta, w systemie powstaje rekord stock.move, który śledzi tę operację.
Model ten jest wykorzystywany przez moduł Magazyn (Inventory). Różne moduły — Sprzedaż, Zakupy, Produkcja czy e‑commerce — generują wpisy stock.move przy uruchamianiu operacji magazynowych. Potwierdzenie dostawy, przyjęcie towaru od dostawcy czy zamknięcie zlecenia produkcyjnego to momenty, kiedy powstają lub są aktualizowane ruchy magazynowe.
Definicja modelu znajduje się w module stock, a inne moduły go rozszerzają dzięki dziedziczeniu modeli w Odoo. Moduł sprzedaży dodaje powiązanie do linii zamówienia sprzedaży, zakupy — do linii zamówienia zakupu, produkcja — do zlecenia produkcyjnego. Każdy moduł dokłada tylko to, co jest potrzebne, bez duplikowania rdzenia.
Kluczowe pola w modelu
Poniżej omówione są najważniejsze pola modelu stock.move — ich zrozumienie ułatwi pracę z ruchami magazynowymi i debugowanie procesów.
1. name
Typ: Char. Pole przechowujące nazwę lub opis ruchu. Najczęściej składa się z nazwy produktu i ilości. Widoczne w wielu widokach Odoo; pomaga szybko rozpoznać ruch na liście.
2. product_id
Typ: Many2one (product.product). Produkt, którego dotyczy ruch. Pole obowiązkowe — bez niego ruch nie ma sensu. Na jego podstawie system liczy stany i stosuje reguły magazynowe.
3. product_uom
Typ: Many2one (uom.uom). Jednostka miary dla ilości. Obowiązkowa. Zazwyczaj odpowiada domyślnej jednostce produktu. Odoo weryfikuje, czy ilości podawane są w tej jednostce.
4. product_uom_qty
Typ: Float. Ilość do przemieszczenia w zadeklarowanej jednostce — tzw. zapotrzebowanie. Po zrealizowaniu ruchu rzeczywista przetworzona ilość trafia do pola quantity_done.
5. quantity
Typ: Float. Pole obliczane lub prezentacyjne pokazujące ilość. Często używane w widokach, by ułatwić odczyt użytkownikowi. Może odpowiadać product_uom_qty albo być przeliczoną wartością.
6. location_id
Typ: Many2one (stock.location). Lokalizacja źródłowa — skąd pochodzi towar. Pole obowiązkowe. Dla wysyłek jest to magazyn, dla przyjęć może to być lokalizacja dostawcy lub produkcji.
7. location_dest_id
Typ: Many2one (stock.location). Lokalizacja docelowa — dokąd trafia towar. Pole obowiązkowe. Dla przyjęć jest to magazyn; dla wysyłek — lokalizacja klienta lub miejsce skupu/utylizacji.
8. picking_id
Typ: Many2one (stock.picking). Dokument grupujący ruchy — np. zamówienie dostawy, przyjęcie czy przesunięcie wewnętrzne. Ruchy zwykle są obsługiwane grupowo w obrębie pickingów.
9. picking_type_id
Typ: Many2one (stock.picking.type). Typ operacji — definiuje, czy ruch to wysyłka, przyjęcie czy przesunięcie wewnętrzne. To pole determinuje domyślne lokalizacje i przebieg workflow.
10. state
Typ: Selection. Aktualny status ruchu: draft, waiting, confirmed, assigned, done, cancelled. Draft — niepotwierdzony; Assigned — rezerwacja wykonana; Done — ruch zakończony.
11. date
Typ: Datetime. Termin/zaplanowana data ruchu. Wykorzystywana przy planowaniu operacji i priorytetyzacji zadań magazynowych.
12. date_deadline
Typ: Datetime. Ostateczny termin wykonania ruchu. Dla dostaw do klienta to często obiecana data dostawy; używane do obliczania pilności.
13. origin
Typ: Char. Odniesienie do dokumentu źródłowego — np. numer SO, PO lub zlecenia produkcyjnego. Ułatwia śledzenie skąd pochodzi ruch.
14. move_dest_id
Typ: Many2one (stock.move). Powiązanie z następnym ruchem w łańcuchu. Gdy wynik jednego ruchu zasila inny (np. wyjście produkcyjne trafia do wysyłki), to pole łączy te rekordy.
15. move_orig_ids
Typ: One2many (stock.move). Lista ruchów źródłowych — odwrotność move_dest_id. Pomaga w rozliczaniu powiązanych operacji i ich śledzeniu.
16. move_line_ids
Typ: One2many (stock.move.line). Szczegółowe linie ruchu — zawierają numery partii, numery seryjne, konkretne lokalizacje. Rejestruje się je podczas rezerwacji i realizacji ruchu.
17. partner_id
Typ: Many2one (res.partner). Kontrahent powiązany z ruchem — klient przy wysyłce, dostawca przy przyjęciu. Przydatne przy adresowaniu i raportowaniu.
18. company_id
Typ: Many2one (res.company). W konfiguracjach wielofirmowych wskazuje, której spółki dotyczy ruch. Ma wpływ na widoczność i zasady międzyfirmowe.
19. quantity_done
Typ: Float. Ilość faktycznie przetworzona. Aktualizowana podczas kompletacji lub przyjęcia. Ruch uznaje się za zakończony, gdy quantity_done = product_uom_qty.
20. reserved_availability
Typ: Float. Ilość zarezerwowana pod ruch. Pokazuje, ile towaru zostało przydzielone w momencie przypisania (assigned).
21. create_date
Typ: Datetime. Data i godzina utworzenia rekordu. Zarządzane automatycznie; pomocne przy audycie i raportach.
22. write_date
Typ: Datetime. Data ostatniej modyfikacji rekordu. Również automatycznie uaktualniana; pomaga śledzić zmiany.
23. sequence
Typ: Integer. Kolejność wyświetlania ruchów w ramach jednego pickingu. Mniejsze liczby wyświetlane są wcześniej — przydatne przy sortowaniu zadań.
24. priority
Typ: Selection. Poziom pilności — np. normalny lub pilny. Wpływa na harmonogramowanie i sposób obsługi zadań magazynowych.
25. description_picking
Typ: Char. Dodatkowy opis widoczny na dokumencie picking — instrukcje obsługi, uwagi dla magazynierów itp.
26. reference
Typ: Char. Pole na własne kody czy odniesienia wewnętrzne — użyteczne przy mapowaniu z systemami zewnętrznymi.
27. group_id
Typ: Many2one (procurement.group). Grupa zaopatrzeniowa — łączy ruchy pochodzące z tego samego zapotrzebowania (np. całe zamówienie sprzedaży). Ułatwia planowanie i łączenie procesów.
28. procure_method
Typ: Selection. Tryb realizacji — make-to-stock lub make-to-order. Określa, czy korzystać z dostępnego stanu magazynowego, czy wygenerować zamówienie/producję.
29. sale_line_id
Typ: Many2one (sale.order.line). Pole dopisane przez moduł Sprzedaż. Łączy ruch z konkretną linią zamówienia sprzedaży — ważne dla raportów i śledzenia pochodzenia towaru.
30. purchase_line_id
Typ: Many2one (purchase.order.line). Dodane przez moduł Zakupy. Wiąże ruch z linią zamówienia zakupu — używane przy przyjęciach od dostawców.
31. production_id
Typ: Many2one (mrp.production). Dodane przez Produkcję. Łączy ruch z zleceniem produkcyjnym — przydatne do rozliczania surowców i produktów gotowych.
32. active
Typ: Boolean. Flaga archiwizacji. Gdy False, rekord jest ukrywany w standardowych widokach (soft delete). Rekordy nie są fizycznie usuwane.
Jak model wykorzystuje się w procesach biznesowych
1. Dostawa do klienta
Po potwierdzeniu zamówienia sprzedaży Odoo tworzy dla każdej pozycji ruchy magazynowe. Dla tych ruchów location_id to magazyn, a location_dest_id to lokalizacja klienta. Wszystkie ruchy grupowane są w picking (dokument dostawy). W trakcie kompletacji magazynier uzupełnia quantity_done, a status ruchu przechodzi na done.
2. Przyjęcie od dostawcy
Potwierdzenie zamówienia zakupowego generuje ruchy przychodowe: source to lokalizacja dostawcy, destination to magazyn. Powstaje dokument przyjęcia; po odbiorze i weryfikacji użytkownik zatwierdza ruch, ustawiając quantity_done.
3. Przesunięcie wewnętrzne
Transfery między magazynami lub lokalizacjami tworzą ruchy z odpowiednimi lokalizacjami źródłowymi i docelowymi. Stosuje się je do uzupełnień, wyrównania stanów oraz operacji w strukturach wielomagazynowych.
4. Produkcja
Zlecenia produkcyjne generują ruchy dwóch rodzajów: pobrania surowców do produkcji i dodania wyrobów gotowych do magazynu. Pole production_id wiąże ruchy z danym zleceniem; dodatkowo ruchy mogą być połączone przez move_dest_id, żeby wynik produkcji trafił dalej (np. do wysyłki).
5. Zwroty i złomowanie
Zwroty klientów są realizowane przez ruchy odwrotne, a operacje złomowania przesuwają towar do wyznaczonej lokalizacji złomu. Ten sam model stock.move obsługuje wszystkie scenariusze; to picking_type_id określa sposób ich przetwarzania.
Jak deweloperzy rozszerzają ten model
Deweloperzy rozszerzają stock.move kilkoma sprawdzonymi wzorcami; głównym mechanizmem jest dziedziczenie modeli w Odoo.
Dziedziczenie modelu
Użyj _inherit = 'stock.move' w swoim module, by dodać pola, nadpisać metody lub wprowadzić ograniczenia. Dzięki temu zmiany pozostają w oddzielnym module — łatwiej je utrzymać i aktualizować razem z systemem.
Dodawanie pól
W klasie dziedziczącej definiuj nowe pola: Char, Many2one, Boolean, Integer, Text, Selection itd. Pomyśl o polach zależnych od firmy w systemach multi‑company. W praktyce dla ruchów magazynowych często dodaje się np. numer śledzenia, odniesienie do przewoźnika czy dodatkowe atrybuty partii.
Rozszerzenia w Pythonie
Nadpisuj metody takie jak _action_done, _action_assign czy _action_cancel, wstawiając własną logikę i wywołując super(), żeby zachować oryginalne zachowanie. Trzeba jednak uważać przy aktualizacji stanów magazynowych i przy łączeniu ruchów — łatwo wprowadzić niespójności.
Odoo Studio
Odoo Studio pozwala szybko dodać pola bez programowania — dobre rozwiązanie do prostych zmian. Przy bardziej złożonych wymaganiach, jak nowe workflowy czy integracje, lepsze i trwalsze są dedykowane moduły Pythonowe.
Dobre praktyki
- Zawsze prawidłowo ustawiaj location_id i location_dest_id. Błędne lokalizacje prowadzą do nieprawidłowych stanów magazynowych i trudnych do wykrycia błędów.
- Używaj picking_id do grupowania ruchów powiązanych. Nie twórz izolowanych ruchów należących do transferu — to może zaburzyć proces rezerwacji i obsługi.
- Przy integracjach API korzystaj z XML‑RPC lub JSON‑RPC. Model stock.move jest w pełni dostępny — mapuj identyfikatory zewnętrzne uważnie, by uniknąć duplikatów.
- Dla pól niestandardowych stosuj prefiks x_ lub prefiks modułu, by zminimalizować ryzyko konfliktów przy aktualizacjach Odoo.
- Wykorzystuj move_dest_id i move_orig_ids dla pełnej śledzalności. Tworząc łańcuchy ruchów programowo, pamiętaj, żeby poprawnie ustawić te relacje.
- Zwracaj uwagę na różnicę między quantity_done a product_uom_qty — system dopuszcza częściowe realizacje, więc walidacja ilości jest kluczowa.
Częste błędy
- Tworzenie ruchów z nieodpowiednimi typami lokalizacji. Źródło i cel muszą być kompatybilne — np. nie powinno się łączyć dwóch lokalizacji typu "klient".
- Modyfikowanie product_uom_qty po utworzeniu move lines. Zmiana ilości przy istniejących liniach ruchu może doprowadzić do rozbieżności. Bezpieczniej anulować ruch i utworzyć go ponownie.
- Zapominanie o polu origin. Brak odniesienia do dokumentu źródłowego utrudnia późniejsze śledzenie i raporty.
- Nadpisanie _action_done bez wywołania super(). To częsta przyczyna, dla której inne moduły lub aktualizacje przestają poprawnie aktualizować stany magazynowe.
- Tworzenie ruchów bez przechodzenia przez odpowiedni workflow (np. pomijanie stock.picking). Omijanie pickingu zakłóca proces rezerwacji i przypisywania zasobów.
- Ignorowanie move_dest_id przy dzieleniu lub łączeniu ruchów. Brak tych powiązań może pozostawić ruchy osierocone, trudne do powiązania z innymi operacjami.
Podsumowanie
Model stock.move to oś działań magazynowych w Odoo — rejestruje każdy przemieszczenie towaru między lokalizacjami. Zrozumienie pól i sposobu rozszerzania modelu ułatwia konfigurację, rozwój i integracje systemu.
Niezależnie od tego, czy projektujesz procesy magazynowe, czy tworzysz niestandardowe moduły, dobra znajomość stock.move oszczędzi czas i zapobiegnie typowym błędom.
Potrzebujesz pomocy przy wdrożeniu Odoo?
Dasolo wspiera firmy przy wdrożeniach, dostosowaniach i optymalizacji Odoo. Specjalizujemy się w integracjach API i rozwijaniu modułów — mamy doświadczenie w pracy z modelem stock.move i architekturą danych Odoo.
Jeżeli potrzebujesz wsparcia przy wdrożeniu Odoo, tworzeniu modułów lub integracjach — skontaktuj się z nami, chętnie pomożemy. Zarezerwuj demo by omówić swój projekt.