Produkty

W Odoo określenie „product” odnosi się zarówno do produktów własnych jak i kupowanych towarów. Podstawowe modele opisujące produkty to product.template i product.product. Można o nich myśleć jak o klasach (template) i obiektach klasy (product). Template to „szablon do stworzenia produktu”. Produkt jest więc wariantem klasy produktów (https://www.odoo.com/documentation/user/9.0/inventory/settings/products/variants.html) .

Jednemu wierszowi product.template odpowiada jeden wiersz tabeli product.product. Nie ma zatem możliwości usunięcia produktów z pozostawieniem ich wzorca. Z punktu widzenia bazy danych ten podział na dwie tabele jest nieco sztuczny. Jeśli usuniemy wiersze tylko z tabeli product.product – pojawi się pewna niespójność: lista produktów jest tworzona na podstawie product.template ale wybór produktu przy sprzedaży/zakupie następuje z tabeli product.product. Można to poprawić dokonując w Odoo archwiwizacji i przywrócenia produktu (po prywróceniu rekord w tabeli product pojawia się na nowo).

Jeśli ustawimy (Sprzedaż – Ustawienia) możliwość tworzenia produktów wariantami (na przykład różne kolory) – dodatkowo wykorzystywane będą modele product.attribute (atrybuty) oraz product.attribute.values (wartości atrybutów).

Z każdym atrybutem jest związana cena. W module sprzedaży internetowej możemy ustawić warianty atrybutu (dodatkowe pole do product.attribute) określające sposób wyboru opcji: Radio (jeden z wielu), Wybierz i Ukryty. Wartością domyślną jest Radio. Do zdefiniowania powiązań jeden do wielu (atrybut z wariantami produktu) służy model product_attribute_line.

Obrót magazynowy

Aby powiązać zakupy z magazynami, konieczne jest zainstalowanie modułu purchase (Zakupy). Wówczas można wystawiać fakturę zakupu do zamówienia. Powoduje to powstanie obrotów magazynowych stock.move. Podobnie ze sprzedażą (moduł sale_stock). Tyle, że tu najpierw wystawiamy sprzedaż a z tego dokumentu powstaje faktura i dokument obrotu magazynowego stock.move. Kolekcji pozycji stock.move odpowiada element ze stock.picking.

Obroty na magazynach:

SELECT m.product_id produkt, m.warehouse_id magazyn, 
       m.product_qty ilosc,
       pt.code
FROM stock_move AS m
LEFT OUTER JOIN stock_picking_type AS pt ON
     pt.id=m.picking_type_id;

Zakupy i wydania (bez przesunięć wewnętrznych i operacji MRP):

SELECT m.product_id produkt, m.warehouse_id magazyn, 
  (select sum(m1.product_qty) FROM stock_move AS m1
   LEFT OUTER JOIN stock_picking_type AS pt1 ON
     pt1.id=m1.picking_type_id 
   WHERE pt1.code='incoming'
    AND m.product_id=m1.product_id 
    AND m.warehouse_id=m1.warehouse_id) przychod,
  (select sum(m2.product_qty) 
   FROM stock_move AS m2
   LEFT OUTER JOIN stock_picking_type AS pt2 ON
     pt2.id=m2.picking_type_id 
   WHERE pt2.code='outgoing'
     AND m.product_id=m2.product_id 
     AND m.warehouse_id=m2.warehouse_id) rozchod
FROM stock_move as m
GROUP BY m.product_id, m.warehouse_id;

Wyliczenie stanu z uwzględnieniem wszystkich aspektów nie jest proste - najlepiej sięgnąć po funkcję w Pythonie:

product = self.env['product.product']
for p in product.search([]):
  print '%s: %s' % (p.name,p.qty_available)

Jednostki miary dla produktów (Unit of Measure) znajdują się w modelu product.uom.