[IMP] core: raise warnings for related translated stored fields

The _compute_related function can only update one translation but not all. We
decide not to update all translations to avoid increasing the time complexity.
As a result, the value for related translated fields should always be generated
in the runtime, and storing it is illegal.

A related translated stored field may work as expected in a single language
environment. But in mult languages environment, if you have a name field

    name = fields.Char(related="parent_id.name", store=True)

changing parent_id in French, will only change the French translation of the
name field

This PR tries to remove these fields. And a warning is added to prevent
developers creating a related translated stored field in the future.

closes odoo/odoo#102553

Related: odoo/upgrade#4004
Signed-off-by: Wang Chong (cwg) <cwg@odoo.com>
This commit is contained in:
Chong Wang (cwg)
2022-11-10 14:13:41 +01:00
parent 98095e082f
commit b95b549d24
6 changed files with 16 additions and 9 deletions
+1 -2
View File
@@ -32,8 +32,7 @@ class StockMoveLine(models.Model):
sale_price = fields.Float(compute='_compute_sale_price')
destination_country_code = fields.Char(related='picking_id.destination_country_code')
carrier_id = fields.Many2one(related='picking_id.carrier_id')
carrier_name = fields.Char(related='picking_id.carrier_id.name', readonly=True, store=True, string="Carrier Name")
carrier_id = fields.Many2one(related='picking_id.carrier_id', store=True) # need to be stored for the groupby in `stock_move_line_view_search_delivery`
@api.depends('qty_done', 'product_uom_id', 'product_id', 'move_id.sale_line_id', 'move_id.sale_line_id.price_reduce_taxinc', 'move_id.sale_line_id.product_uom')
def _compute_sale_price(self):
@@ -6,10 +6,10 @@
<field name="inherit_id" ref="stock.stock_move_line_view_search"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='owner_id']" position="after">
<field name="carrier_name" invisible="1" string="Carrier name"/>
<field name="carrier_id" invisible="1" string="Carrier name"/>
</xpath>
<xpath expr="//group[@name='groupby']" position="inside">
<filter string="Carrier" name="by_carrier" context="{'group_by': 'carrier_name'}"/>
<filter string="Carrier" name="by_carrier" context="{'group_by': 'carrier_id'}"/>
</xpath>
</field>
</record>
+1 -1
View File
@@ -11,7 +11,7 @@ class LunchOrder(models.Model):
_order = 'id desc'
_display_name = 'product_id'
name = fields.Char(related='product_id.name', string="Product Name", store=True, readonly=True)
name = fields.Char(related='product_id.name', string="Product Name", readonly=True)
topping_ids_1 = fields.Many2many('lunch.topping', 'lunch_order_topping', 'order_id', 'topping_id', string='Extras 1', domain=[('topping_category', '=', 1)])
topping_ids_2 = fields.Many2many('lunch.topping', 'lunch_order_topping', 'order_id', 'topping_id', string='Extras 2', domain=[('topping_category', '=', 2)])
topping_ids_3 = fields.Many2many('lunch.topping', 'lunch_order_topping', 'order_id', 'topping_id', string='Extras 3', domain=[('topping_category', '=', 3)])
+1 -1
View File
@@ -230,7 +230,7 @@ class LunchSupplier(models.Model):
('supplier_id', 'in', available_today.ids),
('state', '=', state),
('date', '=', fields.Date.context_today(self.with_context(tz=self.tz))),
], order="user_id, name")
], order="user_id, product_id")
return orders
def _send_auto_email(self):
+8 -3
View File
@@ -50,7 +50,7 @@ class ir_cron(models.Model):
ir_actions_server_id = fields.Many2one(
'ir.actions.server', 'Server action',
delegate=True, ondelete='restrict', required=True)
cron_name = fields.Char('Name', related='ir_actions_server_id.name', store=True, readonly=False)
cron_name = fields.Char('Name', compute='_compute_cron_name', store=True)
user_id = fields.Many2one('res.users', string='Scheduler User', default=lambda self: self.env.user, required=True)
active = fields.Boolean(default=True)
interval_number = fields.Integer(default=1, help="Repeat every x.")
@@ -65,6 +65,11 @@ class ir_cron(models.Model):
lastcall = fields.Datetime(string='Last Execution Date', help="Previous time the cron ran successfully, provided to the job through the context on the `lastcall` key")
priority = fields.Integer(default=5, help='The priority of the job, as an integer: 0 means higher priority, 10 means lower priority.')
@api.depends('ir_actions_server_id.name')
def _compute_cron_name(self):
for cron in self.with_context(lang='en_US'):
cron.cron_name = cron.ir_actions_server_id.name
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
@@ -179,7 +184,7 @@ class ir_cron(models.Model):
def _get_all_ready_jobs(cls, cr):
""" Return a list of all jobs that are ready to be executed """
cr.execute("""
SELECT *, cron_name->>'en_US' as cron_name
SELECT *
FROM ir_cron
WHERE active = true
AND numbercall != 0
@@ -241,7 +246,7 @@ class ir_cron(models.Model):
# Learn more: https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-ROWS
query = """
SELECT *, cron_name->>'en_US' as cron_name
SELECT *
FROM ir_cron
WHERE active = true
AND numbercall != 0
+3
View File
@@ -627,6 +627,9 @@ class Field(MetaField('DummyField', (object,), {})):
delegate_field = model._fields[self.related.split('.')[0]]
self._modules = tuple({*self._modules, *delegate_field._modules, *field._modules})
if self.store and self.translate:
_logger.warning("Translated stored related field (%s) will not be computed correctly in all languages", self)
def traverse_related(self, record):
""" Traverse the fields of the related field `self` except for the last
one, and return it as a pair `(last_record, last_field)`. """