From d10a40b14d0a649857ee3cdc4bb47f3f2e5208dd Mon Sep 17 00:00:00 2001 From: "Abdelouahab (abla)" Date: Wed, 17 May 2023 14:09:27 +0000 Subject: [PATCH] [FIX] fields: read unstored one2many field without search function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit > The bug is not present in 16.2+, but we keep the test To Reproduce: ============= - on a contact add a one2many field using studio - in related field choose a field that is not stored and doesn't have a search function implemented - close studio and notice all the lines of the selected field are listed on the contact even if are not linked to it Problem: ======== - when searching a field that is not stored and doesn't have a search function, all the lines are returned Solution: ========= in this usecase filter the returned lines and only keep the ones linked to the record opw-3265982 closes odoo/odoo#123563 X-original-commit: 7b29e9dff1d5ef97c5fb2a2ae0709bb21fd3fa3a Signed-off-by: Rémy Voet Signed-off-by: abla001 --- .../test_new_api/models/test_new_api.py | 15 ++++++ .../test_new_api/security/ir.model.access.csv | 1 + .../test_new_api/tests/test_one2many.py | 46 +++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/odoo/addons/test_new_api/models/test_new_api.py b/odoo/addons/test_new_api/models/test_new_api.py index d35be917e44..096c5c0669b 100644 --- a/odoo/addons/test_new_api/models/test_new_api.py +++ b/odoo/addons/test_new_api/models/test_new_api.py @@ -1803,3 +1803,18 @@ class TeamMember(models.Model): name = fields.Char('Name') team_id = fields.Many2one('test_new_api.team') parent_id = fields.Many2one('test_new_api.team', related='team_id.parent_id') + + +class UnsearchableO2M(models.Model): + _name = 'test_new_api.unsearchable.o2m' + _description = 'Test non-stored unsearchable o2m' + + name = fields.Char('Name') + stored_parent_id = fields.Many2one('test_new_api.unsearchable.o2m', store=True) + parent_id = fields.Many2one('test_new_api.unsearchable.o2m', store=False, compute="_compute_parent_id") + child_ids = fields.One2many('test_new_api.unsearchable.o2m', 'parent_id') + + @api.depends('stored_parent_id') + def _compute_parent_id(self): + for r in self: + r.parent_id = r.stored_parent_id diff --git a/odoo/addons/test_new_api/security/ir.model.access.csv b/odoo/addons/test_new_api/security/ir.model.access.csv index c49d35e6969..16b61d840b5 100644 --- a/odoo/addons/test_new_api/security/ir.model.access.csv +++ b/odoo/addons/test_new_api/security/ir.model.access.csv @@ -110,3 +110,4 @@ access_test_new_api_employer,access_test_new_api_employer,model_test_new_api_emp public_access_test_new_api_course,access_test_new_api_course,model_test_new_api_course,base.group_public,1,0,0,0 access_test_new_api_team,access_test_new_api_team,model_test_new_api_team,base.group_user,1,0,0,0 access_test_new_api_team_member,access_test_new_api_team_member,model_test_new_api_team_member,base.group_user,1,0,0,0 +access_test_new_api_unsearchable_o2m,access_test_new_api_unsearchable_o2m,model_test_new_api_unsearchable_o2m,,1,1,1,1 diff --git a/odoo/addons/test_new_api/tests/test_one2many.py b/odoo/addons/test_new_api/tests/test_one2many.py index 814690f9864..e9116da4891 100644 --- a/odoo/addons/test_new_api/tests/test_one2many.py +++ b/odoo/addons/test_new_api/tests/test_one2many.py @@ -2,6 +2,7 @@ from odoo.tests.common import TransactionCase from odoo.exceptions import MissingError from odoo import Command +from odoo.tools import mute_logger class One2manyCase(TransactionCase): @@ -434,3 +435,48 @@ class One2manyCase(TransactionCase): # Check that the search is not stuck in the loop Team.search([('id', 'parent_of', team1.id)]) Team.search([('id', 'child_of', team1.id)]) + + @mute_logger('odoo.osv.expression') + def test_create_one2many_with_unsearchable_field(self): + # odoo.osv.expression is muted as reading a non-stored and unsearchable field will log an error and makes the runbot red + + unsearchableO2M = self.env['test_new_api.unsearchable.o2m'] + + # Create a parent record + parent_record1 = unsearchableO2M.create({ + 'name': 'Parent 1', + }) + + # Create another parent record + parent_record2 = unsearchableO2M.create({ + 'name': 'Parent 2', + }) + + children = {parent_record1.id : [], parent_record2.id : []} + # Create child records linked to parent_record1 + for i in range(5): + child = unsearchableO2M.create({ + 'name': f'Child {i}', + 'stored_parent_id': parent_record1.id, + 'parent_id': parent_record1.id, + }) + self.assertEqual(child.parent_id, parent_record1) + children[parent_record1.id].append(child.id) + + # Create child records linked to parent_record2 + for i in range(5, 10): + child = unsearchableO2M.create({ + 'name': f'Child {i}', + 'stored_parent_id': parent_record2.id, + 'parent_id': parent_record2.id, + }) + self.assertEqual(child.parent_id, parent_record2) + children[parent_record2.id].append(child.id) + + # invalidating the cache to force reading one2many again + self.env.invalidate_all() + # Make sure the parent_record1 only has its own child records + self.assertEqual(parent_record1.child_ids.ids, children[parent_record1.id]) + + # Make sure the parent_record2 only has its own child records + self.assertEqual(parent_record2.child_ids.ids, children[parent_record2.id])