product/models/product_catalog_mixin.py

125 lines
5.2 KiB
Python

from odoo import _, models
class ProductCatalogMixin(models.AbstractModel):
""" This mixin should be inherited when the model should be able to work
with the product catalog.
It assumes the model using this mixin has a O2M field where the products are added/removed and
this field's co-related model should has a method named `_get_product_catalog_lines_data`.
"""
_name = 'product.catalog.mixin'
_description = 'Product Catalog Mixin'
def action_add_from_catalog(self):
kanban_view_id = self.env.ref('product.product_view_kanban_catalog').id
search_view_id = self.env.ref('product.product_view_search_catalog').id
additional_context = self._get_action_add_from_catalog_extra_context()
return {
'type': 'ir.actions.act_window',
'name': _('Products'),
'res_model': 'product.product',
'views': [(kanban_view_id, 'kanban'), (False, 'form')],
'search_view_id': [search_view_id, 'search'],
'domain': self._get_product_catalog_domain(),
'context': {**self.env.context, **additional_context},
}
def _default_order_line_values(self):
return {
'quantity': 0,
'readOnly': self._is_readonly() if self else False,
}
def _get_product_catalog_domain(self):
"""Get the domain to search for products in the catalog.
For a model that uses products that has to be hidden in the catalog, it
must override this method and extend the appropriate domain.
:returns: A list of tuples that represents a domain.
:rtype: list
"""
return [('company_id', 'in', [self.company_id.id, False])]
def _get_product_catalog_record_lines(self, product_ids):
""" Returns the record's lines grouped by product.
Must be overrided by each model using this mixin.
:param list product_ids: The ids of the products currently displayed in the product catalog.
:rtype: dict
"""
return {}
def _get_product_catalog_order_data(self, products, **kwargs):
""" Returns a dict containing the products' data. Those data are for products who aren't in
the record yet. For products already in the record, see `_get_product_catalog_lines_data`.
For each product, its id is the key and the value is another dict with all needed data.
By default, the price is the only needed data but each model is free to add more data.
Must be overrided by each model using this mixin.
:param products: Recordset of `product.product`.
:param dict kwargs: additional values given for inherited models.
:rtype: dict
:return: A dict with the following structure:
{
'productId': int
'quantity': float (optional)
'price': float
'readOnly': bool (optional)
}
"""
return {}
def _get_product_catalog_order_line_info(self, product_ids, **kwargs):
""" Returns products information to be shown in the catalog.
:param list product_ids: The products currently displayed in the product catalog, as a list
of `product.product` ids.
:param dict kwargs: additional values given for inherited models.
:rtype: dict
:return: A dict with the following structure:
{
'productId': int
'quantity': float (optional)
'price': float
'readOnly': bool (optional)
}
"""
order_line_info = {}
default_data = self._default_order_line_values()
for product, record_lines in self._get_product_catalog_record_lines(product_ids).items():
order_line_info[product.id] = record_lines._get_product_catalog_lines_data(**kwargs)
product_ids.remove(product.id)
products = self.env['product.product'].browse(product_ids)
product_data = self._get_product_catalog_order_data(products, **kwargs)
for product_id, data in product_data.items():
order_line_info[product_id] = {**default_data, **data}
return order_line_info
def _get_action_add_from_catalog_extra_context(self):
return {
'product_catalog_order_id': self.id,
'product_catalog_order_model': self._name,
}
def _is_readonly(self):
""" Must be overrided by each model using this mixin.
:return: Whether the record is read-only or not.
:rtype: bool
"""
return False
def _update_order_line_info(self, product_id, quantity, **kwargs):
""" Update the line information for a given product or create a new one if none exists yet.
Must be overrided by each model using this mixin.
:param int product_id: The product, as a `product.product` id.
:param int quantity: The product's quantity.
:param dict kwargs: additional values given for inherited models.
:return: The unit price of the product, based on the pricelist of the
purchase order and the quantity selected.
:rtype: float
"""
return 0