Wprowadzenie
W Odoo modele określają strukturę danych i sposób ich zapisu w bazie. W praktyce każdy element działalności — zamówienie zakupowe, faktura czy stan magazynowy — jest reprezentowany przez model, który trzyma wszystkie powiązane informacje i reguły.
Dla konsultantów funkcjonalnych i programistów znajomość modeli to podstawa. To one definiują pola, relacje między obiektami i logikę biznesową — inaczej mówiąc: model to rdzeń architektury danych w Odoo.
W tym artykule skupimy się na jednym z kluczowych modeli: purchase.order. Niezależnie od tego, czy tworzysz moduły, integrujesz z zewnętrznymi systemami czy konfigurujesz procesy zakupowe, prędzej czy później trafisz na ten model.
Czym jest model purchase.order
Model purchase.order to zapis zapytań ofertowych (RFQ) i zamówień zakupowych. To centralne miejsce, w którym gromadzone są wszystkie dane o zamówieniach przed tym, jak wygenerowane zostaną dokumenty przyjęcia towaru czy faktury od dostawcy.
Model jest wykorzystywany przez moduł Zakupy. Tworząc RFQ, użytkownik zakłada rekord purchase.order; po potwierdzeniu przez dostawcę lub zatwierdzeniu przez kupującego status przechodzi ze stanu roboczego do potwierdzonego. Ten sam model obsługuje zarówno drafty, jak i finalne zamówienia — pole state odzwierciedla cykl życia dokumentu.
Inne moduły dopisują swoje rozszerzenia do tego modelu przez dziedziczenie. Moduł Magazyn dodaje logikę przyjęć, Księgowość — pola związane z fakturowaniem, a Produkcja może generować zamówienia z BOM-ów. Dzięki temu jądro danych pozostaje jednolite, a funkcje dodawane są modułowo.
Najważniejsze pola w modelu
Poniżej wymienione są kluczowe pola modelu purchase.order — ich znajomość ułatwi pracę z zamówieniami zakupowymi i integracjami.
1. name
Typ: Char. Numer referencyjny zamówienia (np. PO/2026/042). Zazwyczaj generowany automatycznie, widoczny na listach i dokumentach. Służy jako podstawowy identyfikator porządkujący zamówienia.
2. state
Typ: Selection. Reprezentuje etap zamówienia. Najczęstsze wartości: draft (RFQ), sent (wysłane), to approve (do akceptacji), purchase (potwierdzone), done (zakończone), cancel (anulowane). Pole to steruje dostępnymi akcjami i przepływem pracy.
3. partner_id
Typ: Many2one (res.partner). Dostawca. Pole obowiązkowe — określa firmę/kontrahenta, do którego kierowane jest zamówienie. Kluczowe przy raportowaniu i regułach zakupowych.
4. partner_ref
Typ: Char. Numer referencyjny od dostawcy. Przydatny do dopasowywania dokumentów i komunikacji — pokazuje numer PO nadany przez drugą stronę.
5. date_order
Typ: Datetime. Data zamówienia: w stanach roboczych to data utworzenia, w zamówieniach potwierdzonych — data potwierdzenia. Wykorzystywana w raportach i przy ustalaniu terminów linii zamówień.
6. date_approve
Typ: Datetime. Data zatwierdzenia/konfirmacji. Ustawiana przy przejściu do stanu purchase. Pole tylko do odczytu, istotne dla audytu i raportowania.
7. order_line
Typ: One2many (purchase.order.line). Pozycje zamówienia — każdy wiersz zawiera produkt, ilość, cenę i podatki. To szczegółowy opis tego, co zamawiamy.
8. amount_untaxed
Typ: Float. Suma netto przed podatkami. Pole obliczane z pozycji zamówienia — wykorzystywane do prezentacji i analiz.
9. amount_tax
Typ: Float. Kwota podatku. Obliczana na podstawie pozycji i konfiguracji podatkowej. Pokazywana na zamówieniu i przenoszona do faktur.
10. amount_total
Typ: Float. Całkowita kwota brutto z podatkami. Kluczowa dla fakturowania i rozliczeń.
11. currency_id
Typ: Many2one (res.currency). Waluta zamówienia. Zwykle dziedziczona z firmy lub kontrahenta — wszystkie pola finansowe odnoszą się do tej waluty.
12. origin
Typ: Char. Źródłowy dokument, np. numer zlecenia sprzedaży czy produkcji, z którego powstało zamówienie. Przydaje się do śledzenia powiązań między procesami.
13. dest_address_id
Typ: Many2one (res.partner). Adres dostawy. Jeśli nie ustawiony, domyślnie używany jest adres firmy. Przy dropshippingu wskazuje faktyczne miejsce dostawy — często adres klienta.
14. priority
Typ: Selection. Priorytet zamówienia: Normalny lub Pilny. Pomaga sortować i wyróżniać pozycje wymagające szybszej obsługi.
15. invoice_status
Typ: Selection. Status fakturowania: no (brak faktur), to invoice (do fakturowania), invoiced (zafakturowane). Steruje widocznością akcji do tworzenia faktur.
16. invoice_count
Typ: Integer. Ilość powiązanych faktur. Pole obliczane — ułatwia szybki podgląd i nawigację do dokumentów księgowych.
17. invoice_ids
Typ: One2many (account.move). Powiązane faktury zakupowe. Łączy zakupy z księgowością — kluczowe do trójstronnego dopasowania i rozliczeń.
18. picking_ids
Typ: One2many (stock.picking). Powiązane dokumenty magazynowe (przyjęcia/wydań). Używane, gdy moduł Magazyn jest zainstalowany — łączą zamówienie z fizycznym ruchem towaru.
19. picking_count
Typ: Integer. Liczba powiązanych przesunięć magazynowych. Pole obliczane — umożliwia szybkie przejście do listy przyjęć.
20. create_date
Typ: Datetime. Data i czas utworzenia rekordu. Zarządzane automatycznie przez system — przydatne w raportach i audytach.
21. write_date
Typ: Datetime. Data ostatniej modyfikacji rekordu. Też ustawiana automatycznie — pomaga śledzić zmiany danych.
22. notes
Typ: Text. Dodatkowe uwagi lub warunki zamówienia. Mogą być drukowane na dokumentach i służą do przekazywania instrukcji dla dostawcy.
23. company_id
Typ: Many2one (res.company). W środowisku wielofirmowym wskazuje, do której spółki należy zamówienie — determinuje widoczność i reguły dostępu.
24. user_id
Typ: Many2one (res.users). Odpowiedzialny kupujący. Używane przy workflow akceptacji i przy przydziale zadań.
25. fiscal_position_id
Typ: Many2one (account.fiscal.position). Pozycja fiskalna dla mapowania podatków — ważna przy zamówieniach międzynarodowych lub specyficznych reżimach podatkowych.
26. payment_term_id
Typ: Many2one (account.payment.term). Warunki płatności (np. 30 dni, zaliczka 50%). Przenoszone na faktury i wpływają na terminy płatności.
27. display_name
Typ: Char. Pole obliczane do prezentacji — zwykle łączy numer zamówienia z informacją o dostawcy. Używane w listach wyboru i wyszukiwaniach.
28. active
Typ: Boolean. Flaga archiwizacji. Gdy False, rekord ukryty w standardowych widokach — zamówienia są zwykle archiwizowane zamiast usuwane, aby zachować historię.
Jak model używany jest w procesach biznesowych
1. Od RFQ do zamówienia zakupowego
Proces zaczyna się od stworzenia zapytania ofertowego (stan draft), dodania pozycji i wysłania do dostawcy. Po potwierdzeniu przez dostawcę lub ręcznej akceptacji przez kupującego, RFQ przechodzi w zamówienie (state = purchase) i od tego momentu można generować przyjęcia magazynowe i faktury.
2. Przyjęcie od dostawcy
Po przybyciu towaru tworzy się przyjęcie powiązane z zamówieniem. Rejestracja przyjęcia aktualizuje stany magazynowe, a ilości przyjęte wpływają na wycenę produktów, bazując na cenie zakupu z zamówienia.
3. Faktura od dostawcy
Na podstawie potwierdzonego zamówienia tworzy się fakturę zakupową — pozycje i warunki płatności są przejmowane z zamówienia. Pole invoice_status informuje o stopniu zafakturowania zamówienia.
4. Dropshipping
W scenariuszu dropshippingu zamówienie sprzedażowe może wyzwolić zamówienie zakupu; pole origin zawiera referencję do sprzedaży, a dest_address_id ustawiany jest na adres klienta, dzięki czemu dostawca wysyła towar bezpośrednio do odbiorcy.
5. Produkcja i MRP
Gdy zlecenie produkcyjne wymaga materiałów, moduł Produkcja może generować zamówienia zakupowe dla komponentów. Pole origin łączy zamówienie zakupowe z zleceniem produkcyjnym — model purchase.order pełni tu rolę łącznika w procesie procure-to-pay.
Jak programiści rozbudowują ten model
Programiści rozszerzają purchase.order za pomocą kilku wzorców; głównym mechanizmem jest dziedziczenie modeli Odoo.
Dziedziczenie modelu
W praktyce używa się _inherit = 'purchase.order' aby dodać pola, nadpisać metody lub dodać ograniczenia. Dzięki temu zmiany trzyma się w osobnym module, co ułatwia utrzymanie i aktualizacje systemu.
Dodawanie pól
Nowe pola definiuje się w modelu dziedziczącym, dobierając odpowiedni typ: Char, Many2one, Boolean, Integer, Text, Selection. W środowisku wielofirmowym warto rozważyć pola zależne od company_id.
Rozszerzenia w Pythonie
Możesz nadpisać metody takie jak button_confirm, create czy write, pamiętając o wywołaniu super(), by nie przerwać istniejącej logiki. Szczególną uwagę trzeba poświęcić polom obliczanym i zależnościom między nimi.
Odoo Studio
Odoo Studio pozwala szybko dodać pola bez kodowania — przydatne w szybkich customizacjach. Dla bardziej zaawansowanych rozwiązań i długoterminowej konserwacji lepsze są dedykowane moduły. Model purchase.order jest też dostępny przez API XML-RPC i JSON-RPC do integracji z zewnętrznymi systemami.
Dobre praktyki
- Używaj odpowiednich stanów na każdym etapie i nie pomijaj logiki potwierdzania — omijanie kroków może prowadzić do niespójności danych.
- Jeśli dostawca podał własny numer referencyjny, zapisz go w partner_ref — ułatwia to kojarzenie dokumentów i przyspiesza rozliczenia.
- Wypełniaj pole origin aby zachować ślad źródłowego dokumentu — jest to kluczowe przy dropshippingu i integracji z produkcją.
- Przy integracjach API korzystaj z XML-RPC lub JSON-RPC i ostrożnie mapuj identyfikatory zewnętrzne, aby uniknąć duplikatów i błędnych powiązań.
- Dla własnych pól stosuj prefiks x_ lub prefix modułu, by zmniejszyć ryzyko kolizji z przyszłymi wersjami Odoo.
Częste błędy
- Modyfikowanie potwierdzonych zamówień bez sprawdzenia stanu. Po potwierdzeniu niektóre pola są zablokowane — w razie potrzeby utwórz korektę lub użyj przewidzianego workflow.
- Pomylenie partner_id z dest_address_id. partner_id oznacza dostawcę; dest_address_id to miejsce dostawy (np. adres klienta przy dropshippingu).
- Nadpisanie button_confirm bez wywołania super(). Takie działanie może naruszyć logikę innych modułów i utrudnić aktualizacje.
- Dodawanie wymagających pól bez wartości domyślnych. To może spowodować błędy walidacji przy migracji istniejących rekordów.
- Zapominanie o ustawieniu currency_id przy współpracy z dostawcami w różnych walutach. Błędna waluta prowadzi do niepoprawnych cen i problemów księgowych.
Podsumowanie
Model purchase.order to serce modułu Zakupy w Odoo — przechowuje RFQ i potwierdzone zamówienia. Znajomość jego pól i sposobu, w jaki inne moduły go rozszerzają, ułatwi konfigurację, personalizację i integracje.
Niezależnie czy projektujesz procesy zakupowe jako konsultant, czy tworzysz rozszerzenia jako programista, dobre opanowanie modelu purchase.order przyspieszy pracę i zminimalizuje błędy.
Potrzebujesz pomocy z wdrożeniem Odoo?
Dasolo wspiera firmy we wdrożeniach, dopasowywaniu i optymalizacji Odoo. Specjalizujemy się w integracjach API i rozwoju modułów, a nasze doświadczenie obejmuje architekturę danych Odoo i modele takie jak purchase.order.
Jeśli potrzebujesz pomocy przy wdrożeniu Odoo, tworzeniu modułów lub integracji — skontaktuj się z nami. Umów demo i porozmawiajmy o Twoim projekcie.