[IMP] product: add product tag model

This commit adds the product tag model.

Purpose
=======

The product tags allows to easily tag given types of product
independently from their category, following their product range, their
seasonal collection, their theme, etc

Specification
=============

A product template takes tags that are valid for all their variants.
In order to add granularity, product variants can also take additionnal
tags.
A field is defined on product variants to allow searching on both
product template and product variant tags.

task-2675384

Part-of: odoo/odoo#79296
This commit is contained in:
Thibault Libioulle
2022-01-17 14:07:45 +00:00
committed by Yannick Tivisse
parent 244e4cae03
commit 5b64d252d2
9 changed files with 118 additions and 0 deletions
+1
View File
@@ -36,6 +36,7 @@ Print product labels with barcode.
'views/product_views.xml',
'views/product_template_views.xml',
'views/product_pricelist_views.xml',
'views/product_tag_views.xml',
'views/res_partner_views.xml',
'report/product_reports.xml',
'report/product_product_templates.xml',
+1
View File
@@ -14,6 +14,7 @@ from . import product
from . import product_attribute
from . import product_pricelist
from . import product_tag
from . import res_company
from . import res_currency
from . import res_partner
+13
View File
@@ -122,6 +122,9 @@ class ProductProduct(models.Model):
'product.packaging', 'product_id', 'Product Packages',
help="Gives the different ways to package the same product.")
additional_product_tag_ids = fields.Many2many('product.tag', 'product_tag_product_product_rel')
all_product_tag_ids = fields.Many2many('product.tag', compute='_compute_all_product_tag_ids', search='_search_all_product_tag_ids')
# all image fields are base64 encoded and PIL-supported
# all image_variant fields are technical and should not be displayed to the user
@@ -295,6 +298,16 @@ class ProductProduct(models.Model):
'&', ('product_id', '=', product.id), ('applied_on', '=', '0_product_variant')]
product.pricelist_item_count = self.env['product.pricelist.item'].search_count(domain)
@api.depends('product_tag_ids', 'additional_product_tag_ids')
def _compute_all_product_tag_ids(self):
for product in self:
product.all_product_tag_ids = product.product_tag_ids | product.additional_product_tag_ids
def _search_all_product_tag_ids(self, operator, operand):
if operator in expression.NEGATIVE_TERM_OPERATORS:
return [('product_tag_ids', operator, operand), ('additional_product_tag_ids', operator, operand)]
return ['|', ('product_tag_ids', operator, operand), ('additional_product_tag_ids', operator, operand)]
@api.onchange('uom_id')
def _onchange_uom_id(self):
if self.uom_id:
+37
View File
@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from random import randint
from odoo import api, fields, models
from odoo.osv import expression
class ProductTag(models.Model):
_name = 'product.tag'
_description = 'Product Tag'
def _get_default_color(self):
return randint(1, 11)
name = fields.Char('Tag Name', required=True, translate=True)
color = fields.Integer('Color', default=_get_default_color)
product_template_ids = fields.Many2many('product.template', 'product_tag_product_template_rel')
product_product_ids = fields.Many2many('product.product', 'product_tag_product_product_rel')
product_ids = fields.Many2many(
'product.product', string='All Product Variants using this Tag',
compute='_compute_product_ids', search='_search_product_ids'
)
_sql_constraints = [
('name_uniq', 'unique (name)', "Tag name already exists !"),
]
@api.depends('product_template_ids', 'product_product_ids')
def _compute_product_ids(self):
for tag in self:
tag.product_ids = tag.product_template_ids.product_variant_ids | tag.product_product_ids
def _search_product_ids(self, operator, operand):
if operator in expression.NEGATIVE_TERM_OPERATORS:
return [('product_template_ids.product_variant_ids', operator, operand), ('product_product_ids', operator, operand)]
return ['|', ('product_template_ids.product_variant_ids', operator, operand), ('product_product_ids', operator, operand)]
@@ -140,6 +140,8 @@ class ProductTemplate(models.Model):
('1', 'Favorite'),
], default='0', string="Favorite")
product_tag_ids = fields.Many2many('product.tag', 'product_tag_product_template_rel', string='Product Tags')
def _compute_item_count(self):
for template in self:
# Pricelist item count counts the rules applicable on current template or on its variants.
@@ -13,6 +13,7 @@ access_product_attribute_custom_value_user,product.attribute.custom value manage
access_product_product_attribute,product.template.attribute value,model_product_template_attribute_value,base.group_user,1,0,0,0
access_product_template_attribute_exclusion,product..template.attribute exclusion,model_product_template_attribute_exclusion,base.group_user,1,0,0,0
access_product_template_attribute_line,product.template.attribute line,model_product_template_attribute_line,base.group_user,1,0,0,0
access_product_tag_user,product.tag.user,model_product_tag,base.group_user,1,0,0,0
access_product_category_manager,product.category.manager,model_product_category,base.group_system,1,1,1,1
access_product_template_manager,product.template.manager,model_product_template,base.group_system,1,1,1,1
access_product_packaging_manager,product.packaging.manager,model_product_packaging,base.group_system,1,1,1,1
@@ -27,3 +28,4 @@ access_product_product_attribute_manager,product.template.attribute value manage
access_product_template_attribute_exclusion_manager,product.template.attribute exclusion manager,model_product_template_attribute_exclusion,base.group_system,1,1,1,1
access_product_template_attribute_line_manager,product.template.attribute line manager,model_product_template_attribute_line,base.group_system,1,1,1,1
access_product_label_layout_user,product.label.layout.user,model_product_label_layout,base.group_system,1,1,1,1
access_product_tag_manager,product.tag.manager,model_product_tag,base.group_system,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
13 access_product_product_attribute product.template.attribute value model_product_template_attribute_value base.group_user 1 0 0 0
14 access_product_template_attribute_exclusion product..template.attribute exclusion model_product_template_attribute_exclusion base.group_user 1 0 0 0
15 access_product_template_attribute_line product.template.attribute line model_product_template_attribute_line base.group_user 1 0 0 0
16 access_product_tag_user product.tag.user model_product_tag base.group_user 1 0 0 0
17 access_product_category_manager product.category.manager model_product_category base.group_system 1 1 1 1
18 access_product_template_manager product.template.manager model_product_template base.group_system 1 1 1 1
19 access_product_packaging_manager product.packaging.manager model_product_packaging base.group_system 1 1 1 1
28 access_product_template_attribute_exclusion_manager product.template.attribute exclusion manager model_product_template_attribute_exclusion base.group_system 1 1 1 1
29 access_product_template_attribute_line_manager product.template.attribute line manager model_product_template_attribute_line base.group_system 1 1 1 1
30 access_product_label_layout_user product.label.layout.user model_product_label_layout base.group_system 1 1 1 1
31 access_product_tag_manager product.tag.manager model_product_tag base.group_system 1 1 1 1
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Product Tags -->
<record id="product_tag_form_view" model="ir.ui.view">
<field name="name">product.tag.form</field>
<field name="model">product.tag</field>
<field name="arch" type="xml">
<form string="Product Tag">
<sheet>
<group>
<group>
<field name="name"/>
<field name="color" widget="color_picker"/>
</group>
</group>
<group>
<field name="product_ids" widget="many2many_tags"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="product_tag_tree_view" model="ir.ui.view">
<field name="name">product.tag.tree</field>
<field name="model">product.tag</field>
<field name="arch" type="xml">
<tree string="Product Tags">
<field name="name"/>
<field name="color" widget="color_picker"/>
</tree>
</field>
</record>
<record id="product_tag_action" model="ir.actions.act_window">
<field name="name">Product Tags</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">product.tag</field>
<field name="view_mode">tree,form</field>
<field name="view_id" eval="False"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Define a new tag
</p><p>
Tags are used to search product for a given theme.
</p>
</field>
</record>
</odoo>
@@ -15,6 +15,7 @@
<field name="priority" widget="priority" optional="show" nolabel="1"/>
<field name="name" string="Product Name"/>
<field name="default_code" optional="show"/>
<field name="product_tag_ids" widget="many2many_tags" options="{'color_field': 'color'}" optional="show"/>
<field name="barcode" optional="hide" attrs="{'readonly': [('product_variant_count', '>', 1)]}"/>
<field name="company_id" options="{'no_create_edit': True}"
groups="base.group_multi_company" optional="hide"/>
+14
View File
@@ -87,6 +87,7 @@
</span>
</div>
<field name="categ_id" string="Product Category"/>
<field name="product_tag_ids" widget="many2many_tags" options="{'color_field': 'color', 'no_edit_color': 1}"/>
<field name="company_id" groups="base.group_multi_company"
options="{'no_create': True}"/>
<field name="currency_id" invisible="1"/>
@@ -289,6 +290,12 @@
context="{'tree_view_ref':'product.product_packaging_tree_view2'}"/>
</group>
</group>
<group>
<group name="tags" string="Tags">
<field name="product_tag_ids" string="Product Template Tags" widget="many2many_tags" readonly="1" options="{'no_open': True, 'color_field': 'color'}"/>
<field name="additional_product_tag_ids" widget="many2many_tags" options="{'color_field': 'color', 'no_edit_color': 1}"/>
</group>
</group>
</sheet>
</form>
</field>
@@ -335,6 +342,7 @@
<field name="lst_price" optional="show" string="Sales Price"/>
<field name="standard_price" optional="show"/>
<field name="categ_id" optional="hide"/>
<field name="product_tag_ids" widget="many2many_tags" options="{'color_field': 'color', 'no_edit_color': 1}" optional="hide"/>
<field name="type" optional="hide" readonly="1"/>
<field name="uom_id" options="{'no_open': True, 'no_create': True}" groups="uom.group_uom" optional="show" readonly="1"/>
<field name="product_tmpl_id" invisible="1" readonly="1"/>
@@ -373,6 +381,12 @@
<xpath expr="//div[hasclass('oe_title')]" position="inside">
<field name="product_template_variant_value_ids" widget="many2many_tags" readonly="1" groups="product.group_product_variant"/>
</xpath>
<field name="product_tag_ids" position="attributes">
<attribute name="options">{'no_open': true}</attribute>
</field>
<field name="product_tag_ids" position="after">
<field name="additional_product_tag_ids" options="{'color_field': 'color', 'no_edit_color': 1}"/>
</field>
</field>
</record>