From 59afbf6686bcbdfa5d31b09303ce295dbed13bea Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Mon, 10 Jul 2023 08:32:42 +0000 Subject: [PATCH] [FIX] web: web_read() on new records with _inherits Part-of: odoo/odoo#127718 --- addons/web/models/models.py | 4 +- .../test_new_api/models/test_unity_read.py | 15 ++++++++ .../test_new_api/security/ir.model.access.csv | 1 + .../test_new_api/tests/test_unity_read.py | 37 +++++++++++++++++++ odoo/models.py | 2 +- 5 files changed, 56 insertions(+), 3 deletions(-) diff --git a/addons/web/models/models.py b/addons/web/models/models.py index b109bb69686..f8087a619be 100644 --- a/addons/web/models/models.py +++ b/addons/web/models/models.py @@ -90,7 +90,7 @@ class Base(models.AbstractModel): if fields_to_read == ['id']: # if we request to read only the ids, we have them already so we can build the return dictionaries immediately # this also avoid a call to read on the co-model that might have different access rules - values_list = [{'id': id_} for id_ in self._ids] + values_list = [{'id': record._origin.id} for record in self] else: values_list: List[Dict] = self.read(fields_to_read, load=None) @@ -117,7 +117,7 @@ class Base(models.AbstractModel): if 'display_name' in field_spec['fields']: for rec in co_records.sudo(): - many2one_data[rec.id]['display_name'] = rec.display_name + many2one_data[rec._origin.id]['display_name'] = rec.display_name for values in values_list: if not values[field_name]: diff --git a/odoo/addons/test_new_api/models/test_unity_read.py b/odoo/addons/test_new_api/models/test_unity_read.py index 0c827138511..a65749ad2dc 100644 --- a/odoo/addons/test_new_api/models/test_unity_read.py +++ b/odoo/addons/test_new_api/models/test_unity_read.py @@ -1,5 +1,8 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + from odoo import models, fields + class Course(models.Model): _name = 'test_new_api.course' _description = 'a course' @@ -15,6 +18,7 @@ class Course(models.Model): def _selection_reference_model(self): return [('test_new_api.lesson', None)] + class Lesson(models.Model): _name = 'test_new_api.lesson' _description = 'a lesson of a course (a day typically)' @@ -35,6 +39,7 @@ class Lesson(models.Model): else: record.display_name = record.name + class Person(models.Model): _name = 'test_new_api.person' _description = 'a person, can be an author, teacher or attendee of a lesson' @@ -52,9 +57,19 @@ class Person(models.Model): for record in self: record.display_name = f"{particular}{record.name}{special}" + class Employer(models.Model): _name = 'test_new_api.employer' _description = 'the employer of a person' name = fields.Char('Name') employee_ids = fields.One2many('test_new_api.person', 'employer_id') + + +class PersonAccount(models.Model): + _name = 'test_new_api.person.account' + _description = 'an account with credentials for a given person' + _inherits = {'test_new_api.person': 'person_id'} + + person_id = fields.Many2one('test_new_api.person', required=True, ondelete='cascade') + login = fields.Char() 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 83e5d23a854..6ef3abacf35 100644 --- a/odoo/addons/test_new_api/security/ir.model.access.csv +++ b/odoo/addons/test_new_api/security/ir.model.access.csv @@ -106,6 +106,7 @@ access_test_new_api_course,access_test_new_api_course,model_test_new_api_course, access_test_new_api_lesson,access_test_new_api_lesson,model_test_new_api_lesson,base.group_user,1,1,1,1 access_test_new_api_person,access_test_new_api_person,model_test_new_api_person,base.group_user,1,1,1,1 access_test_new_api_employer,access_test_new_api_employer,model_test_new_api_employer,base.group_user,1,1,1,1 +access_test_new_api_person_account,access_test_new_api_person_account,model_test_new_api_person_account,base.group_user,1,1,1,1 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 diff --git a/odoo/addons/test_new_api/tests/test_unity_read.py b/odoo/addons/test_new_api/tests/test_unity_read.py index e3382c31782..ed46c88c159 100644 --- a/odoo/addons/test_new_api/tests/test_unity_read.py +++ b/odoo/addons/test_new_api/tests/test_unity_read.py @@ -1,3 +1,5 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + from dateutil.relativedelta import relativedelta from odoo import Command, fields @@ -14,6 +16,10 @@ class TestUnityRead(TransactionCase): cls.only_course_user = new_test_user(cls.env, 'no acc', 'base.group_public') cls.author = cls.env['test_new_api.person'].create({'name': 'ged'}) cls.teacher = cls.env['test_new_api.person'].create({'name': 'aab'}) + cls.account = cls.env['test_new_api.person.account'].create({ + 'person_id': cls.teacher.id, + 'login': 'aab', + }) cls.course = cls.env['test_new_api.course'].create({ 'name': 'introduction to OWL', 'author_id': cls.author.id @@ -146,6 +152,37 @@ class TestUnityRead(TransactionCase): } }]) + def test_new_record_with_inherits(self): + # virtualize a record + new_account = self.account.new(origin=self.account) + self.assertTrue(new_account) + self.assertFalse(new_account.id) + + # read the virtualized record; field 'id' corresponds to record's origin + result = new_account.web_read({ + 'name': {}, + 'login': {}, + }) + self.assertEqual(result, [{ + 'id': new_account._origin.id, + 'name': new_account.name, + 'login': new_account.login, + }]) + + # special case: read the many2one field of _inherits + self.assertTrue(new_account.person_id) + self.assertFalse(new_account.person_id.id) + result = new_account.web_read({ + 'person_id': {'fields': {'name': {}}}, + }) + self.assertEqual(result, [{ + 'id': new_account._origin.id, + 'person_id': { + 'id': new_account.person_id._origin.id, + 'name': new_account.person_id.name, + }, + }]) + def test_multilevel_query_count(self): author = self.env['test_new_api.person'].create({'name': 'AAA'}) teacher1 = self.env['test_new_api.person'].create({'name': 'BBB'}) diff --git a/odoo/models.py b/odoo/models.py index 8b365f9c1e2..9ba686f94d1 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -3354,7 +3354,7 @@ class BaseModel(metaclass=MetaModel): The current method is different from `read` because it retrieves its values from the cache without doing a query when it is avoidable. """ - data = [(record, {'id': record._ids[0]}) for record in self] + data = [(record, {'id': record._origin.id}) for record in self] use_display_name = (load == '_classic_read') for name in fnames: field = self._fields[name]