From 53c1295c8e8d7e9a73f61cff0009f4e0e4755f34 Mon Sep 17 00:00:00 2001 From: "Aurelien van Delft (avd)" Date: Tue, 24 Oct 2023 13:23:21 +0000 Subject: [PATCH] [FIX] point_of_sale: skip recomputes on settings change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In v16 the configuration of a pos_config got moved from Point of Sale to Settings, with new settings fields related to pos_config fields. The create method got overriden in point_of_sale to write values on the current pos_config after the creation of the new settings. The side-effect of doing so is that each creation of a res_config_setting, i.e. after changing any given setting (pos-related or not), triggers a write on ~50 fields of the current pos_config. Among those fields there are modifying_relations fields that trigger recomputes on pos.order. Because pos.order can grow quite big in some databases (> 200.000 pos.orders), it makes it almost impossible to change any setting in these database. They reach a TimeoutError on SaaS/SH. To fix this, this commit filter pos_fields_vals to only write new values on pos_config. If no value got changed since the last settings creation, no write is triggered, and no recompute happens. Because we are in the context of res.config.settings create, and all the pos_config settings fields are related fields, everything should be in cache and no (or very few) query should be executed when doing this filtering. opw-3547106 opw-3508239 closes odoo/odoo#148756 X-original-commit: 72f7c0d7d16a1b791bba61fd885261227f73d263 Signed-off-by: Joseph Caburnay (jcb) Signed-off-by: Aurélien van Delft (avd) --- .../point_of_sale/models/res_config_settings.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/addons/point_of_sale/models/res_config_settings.py b/addons/point_of_sale/models/res_config_settings.py index 016fc6e0d65..5e6fe8fb35a 100644 --- a/addons/point_of_sale/models/res_config_settings.py +++ b/addons/point_of_sale/models/res_config_settings.py @@ -106,6 +106,20 @@ class ResConfigSettings(models.TransientModel): pos_trusted_config_ids = fields.Many2many(related='pos_config_id.trusted_config_ids', readonly=False) point_of_sale_ticket_unique_code = fields.Boolean(related='company_id.point_of_sale_ticket_unique_code', readonly=False) + @api.model + def _keep_new_vals(self, pos_config, pos_fields_vals): + """ Keep vals in pos_fields_vals that are different than + pos_config's values. + """ + new_vals = {} + for field, val in pos_fields_vals.items(): + if pos_config._fields.get(field): + cache_value = pos_config._fields.get(field).convert_to_cache(val, pos_config) + record_value = pos_config._fields.get(field).convert_to_record(cache_value, pos_config) + if record_value != pos_config[field]: + new_vals[field] = val + return new_vals + @api.model_create_multi def create(self, vals_list): # STEP: Remove the 'pos' fields from each vals. @@ -150,6 +164,7 @@ class ResConfigSettings(models.TransientModel): # STEP: Finally, we write the value of 'pos' fields to 'pos_config_id'. for pos_config_id, pos_fields_vals in pos_config_id_to_fields_vals_map.items(): pos_config = self.env['pos.config'].browse(pos_config_id) + pos_fields_vals = self._keep_new_vals(pos_config, pos_fields_vals) pos_config.with_context(from_settings_view=True).write(pos_fields_vals) return result