Files
odoo_source/addons/product/tests/test_name.py
T
Adrien Widart 5fdd2d178a [FIX] product: search on template's default code
When filtering on product templates with a negative operator, the
result

is incorrect

To reproduce the issue:
(Need mrp)
1. Create two products P_compo, P_finished:
    - Internal Reference:
        - P_compo: 123
        - P_finished: 456
2. Create a BoM:
    - Product: P_finished
    - Components:
        - 1 x P_compo
3. Manufacturing > Master Data > Bills Of Materials
4. Remove search filters and apply this custom one:
    - "Product doesn't contain 456"

Error: P_finished's BoM is still in the list, but '456' is the internal
reference of P_finished, so this BoM should not be displayed

The filter is applied on the field `product_tmpl_id` of the BoM, which
leads to the override of `_name_search` in `product.template`. In this
method, a call to the `_name_search` of `product.product` is executed:
https://github.com/odoo/odoo/blob/5ff4eb022757d7a522ccb975f8eb64053ef9780b/addons/product/models/product_template.py#L456
which is a good thing because the version of `product.product` handles
the case of the Internal Reference (`default_code`)
https://github.com/odoo/odoo/blob/1e8982e4cf6b604e4da2773f10bdf6cf94c7e683/addons/product/models/product.py#L532-L538
So, the call to this `_name_search` will not return P_finished. However,
later on in the `_name_search` of `product.template`, we call the
`_name_search` of `super` with the same domain (i.e., 'not 456 in name')
https://github.com/odoo/odoo/blob/5ff4eb022757d7a522ccb975f8eb64053ef9780b/addons/product/models/product_template.py#L474-L485
This is the issue: it leads to the `_name_search` of `BaseModel`, which
is the classic version: it does only consider the record's name. So,
this call will return P_finished.

In the `_name_search` of `product.template`, there are actually two
calls to `super`. Considering the commits [1] and [2], it seems that the
goal is the same in both cases: find the `product.template` that do have
any variant yet. However, in the first commit, the domain given to
`super` excludes the templates that have at least one variant, which is
not the case with the second commit (the "problematic" one).

Since both codes have the same goal, we should merge them by keeping the
best idea of each one. From [1], we keep the idea of restricting the
domain: we only look for templates that do not have any variant.
However, this domain needs to be improved: we need to include the
templates whose all variants are archived. From [2], we keep the idea of
looking for the templates outside the `while True` loop. This allows us
to do the search only if required.

[1] 21ae503
[2] 99bae2c

OPW-2791255

closes odoo/odoo#90248

X-original-commit: 942814844e982cbaec2329709c6ba9dd810d0c3f
Signed-off-by: Nicolas Lempereur (nle) <nle@odoo.com>
Signed-off-by: Adrien Widart <awt@odoo.com>
2022-05-02 10:37:04 +02:00

30 lines
1.2 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.tests.common import TransactionCase
class TestName(TransactionCase):
def setUp(self):
super().setUp()
self.product_name = 'Product Test Name'
self.product_code = 'PTN'
self.product = self.env['product.product'].create({
'name': self.product_name,
'default_code': self.product_code,
})
def test_10_product_name(self):
display_name = self.product.display_name
self.assertEqual(display_name, "[%s] %s" % (self.product_code, self.product_name),
"Code should be preprended the the name as the context is not preventing it.")
display_name = self.product.with_context(display_default_code=False).display_name
self.assertEqual(display_name, self.product_name,
"Code should not be preprended to the name as context should prevent it.")
def test_default_code_and_negative_operator(self):
res = self.env['product.template'].name_search(name='PTN', operator='not ilike')
res_ids = [r[0] for r in res]
self.assertNotIn(self.product.id, res_ids)