diff --git a/addons/account/models/res_config_settings.py b/addons/account/models/res_config_settings.py index f60834dd7e3..0437ee64bc3 100644 --- a/addons/account/models/res_config_settings.py +++ b/addons/account/models/res_config_settings.py @@ -152,9 +152,11 @@ class ResConfigSettings(models.TransientModel): group_sale_delivery_address = fields.Boolean("Customer Addresses", implied_group='account.group_delivery_invoice_address') def set_values(self): - super(ResConfigSettings, self).set_values() + super().set_values() # install a chart of accounts for the given company (if required) - if self.env.company == self.company_id and self.chart_template_id and self.chart_template_id != self.company_id.chart_template_id: + if self.env.company == self.company_id \ + and self.chart_template_id \ + and self.chart_template_id != self.company_id.chart_template_id: self.chart_template_id._load(15.0, 15.0, self.env.company) @api.depends('company_id') diff --git a/addons/auth_oauth/models/res_config_settings.py b/addons/auth_oauth/models/res_config_settings.py index 0c20ab6613f..2962fccc422 100644 --- a/addons/auth_oauth/models/res_config_settings.py +++ b/addons/auth_oauth/models/res_config_settings.py @@ -1,12 +1,8 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -import logging - from odoo import api, fields, models -_logger = logging.getLogger(__name__) - class ResConfigSettings(models.TransientModel): _inherit = 'res.config.settings' @@ -23,17 +19,18 @@ class ResConfigSettings(models.TransientModel): def get_values(self): res = super(ResConfigSettings, self).get_values() google_provider = self.env.ref('auth_oauth.provider_google', False) - google_provider and res.update( - auth_oauth_google_enabled=google_provider.enabled, - auth_oauth_google_client_id=google_provider.client_id, - server_uri_google=self.get_uri(), - ) + if google_provider: + res.update( + auth_oauth_google_enabled=google_provider.enabled, + auth_oauth_google_client_id=google_provider.client_id, + server_uri_google=self.get_uri()) return res def set_values(self): - super(ResConfigSettings, self).set_values() + super().set_values() google_provider = self.env.ref('auth_oauth.provider_google', False) - google_provider and google_provider.write({ - 'enabled': self.auth_oauth_google_enabled, - 'client_id': self.auth_oauth_google_client_id, - }) + if google_provider: + google_provider.write({ + 'enabled': self.auth_oauth_google_enabled, + 'client_id': self.auth_oauth_google_client_id, + }) diff --git a/addons/auth_signup/models/res_config_settings.py b/addons/auth_signup/models/res_config_settings.py index b4e62cecc68..af347a23aba 100644 --- a/addons/auth_signup/models/res_config_settings.py +++ b/addons/auth_signup/models/res_config_settings.py @@ -1,24 +1,24 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from ast import literal_eval - -from odoo import api, fields, models +from odoo import fields, models class ResConfigSettings(models.TransientModel): _inherit = 'res.config.settings' - auth_signup_reset_password = fields.Boolean(string='Enable password reset from Login page', config_parameter='auth_signup.reset_password') - auth_signup_uninvited = fields.Selection([ - ('b2b', 'On invitation'), - ('b2c', 'Free sign up'), - ], string='Customer Account', default='b2b', config_parameter='auth_signup.invitation_scope') - auth_signup_template_user_id = fields.Many2one('res.users', string='Template user for new users created through signup', - config_parameter='base.template_portal_user_id') - - def open_template_user(self): - action = self.env["ir.actions.actions"]._for_xml_id("base.action_res_users") - action['res_id'] = literal_eval(self.env['ir.config_parameter'].sudo().get_param('base.template_portal_user_id', 'False')) - action['views'] = [[self.env.ref('base.view_users_form').id, 'form']] - return action + auth_signup_reset_password = fields.Boolean( + string='Enable password reset from Login page', + config_parameter='auth_signup.reset_password') + auth_signup_uninvited = fields.Selection( + selection=[ + ('b2b', 'On invitation'), + ('b2c', 'Free sign up'), + ], + string='Customer Account', + default='b2b', + config_parameter='auth_signup.invitation_scope') + auth_signup_template_user_id = fields.Many2one( + 'res.users', + string='Template user for new users created through signup', + config_parameter='base.template_portal_user_id') diff --git a/addons/auth_signup/views/res_config_settings_views.xml b/addons/auth_signup/views/res_config_settings_views.xml index 62d1c74fa46..b405e8b9df2 100644 --- a/addons/auth_signup/views/res_config_settings_views.xml +++ b/addons/auth_signup/views/res_config_settings_views.xml @@ -22,7 +22,7 @@
-
diff --git a/addons/crm/models/res_config_settings.py b/addons/crm/models/res_config_settings.py index ff9e1cc4bec..704a6e96b1c 100644 --- a/addons/crm/models/res_config_settings.py +++ b/addons/crm/models/res_config_settings.py @@ -130,23 +130,32 @@ class ResConfigSettings(models.TransientModel): setting.predictive_lead_scoring_field_labels = _('Stage') def set_values(self): - group_lead_before = self.env.ref('crm.group_use_lead') in self.env.user.groups_id + group_use_lead = self.env.ref('crm.group_use_lead') + has_group_lead_before = group_use_lead in self.env.user.groups_id super(ResConfigSettings, self).set_values() # update use leads / opportunities setting on all teams according to settings update - group_lead_after = self.env.ref('crm.group_use_lead') in self.env.user.groups_id - if group_lead_before != group_lead_after: + has_group_lead_after = group_use_lead in self.env.user.groups_id + if has_group_lead_before != has_group_lead_after: teams = self.env['crm.team'].search([]) - teams.filtered('use_opportunities').use_leads = group_lead_after + teams.filtered('use_opportunities').use_leads = has_group_lead_after for team in teams: team.alias_id.write(team._alias_get_creation_values()) # synchronize cron with settings assign_cron = self.sudo().env.ref('crm.ir_cron_crm_lead_assign', raise_if_not_found=False) if assign_cron: - assign_cron.active = self.crm_use_auto_assignment and self.crm_auto_assignment_action == 'auto' - assign_cron.interval_type = self.crm_auto_assignment_interval_type - assign_cron.interval_number = self.crm_auto_assignment_interval_number - # keep nextcall on cron as it is required whatever the setting - assign_cron.nextcall = self.crm_auto_assignment_run_datetime if self.crm_auto_assignment_run_datetime else assign_cron.nextcall + # Writing on a cron tries to grab a write-lock on the table. This + # could be avoided when saving a res.config without modifying this specific + # configuration + cron_vals = { + 'active': self.crm_use_auto_assignment and self.crm_auto_assignment_action == 'auto', + 'interval_type': self.crm_auto_assignment_interval_type, + 'interval_number': self.crm_auto_assignment_interval_number, + # keep nextcall on cron as it is required whatever the setting + 'nextcall': self.crm_auto_assignment_run_datetime if self.crm_auto_assignment_run_datetime else assign_cron.nextcall, + } + cron_vals = {field_name: value for field_name, value in cron_vals.items() if assign_cron[field_name] != value} + if cron_vals: + assign_cron.write(cron_vals) # TDE FIXME: re create cron if not found ? def _get_crm_auto_assignmment_run_datetime(self, run_datetime, run_interval, run_interval_number): diff --git a/addons/crm_iap_enrich/models/res_config_settings.py b/addons/crm_iap_enrich/models/res_config_settings.py index 64a439f2207..67c46009796 100644 --- a/addons/crm_iap_enrich/models/res_config_settings.py +++ b/addons/crm_iap_enrich/models/res_config_settings.py @@ -15,7 +15,7 @@ class ResConfigSettings(models.TransientModel): return values def set_values(self): - super(ResConfigSettings, self).set_values() + super().set_values() cron = self.sudo().with_context(active_test=False).env.ref('crm_iap_enrich.ir_cron_lead_enrichment', raise_if_not_found=False) - if cron: + if cron and cron.active != self.lead_enrich_auto == 'auto': cron.active = self.lead_enrich_auto == 'auto' diff --git a/addons/hr_attendance/models/res_config_settings.py b/addons/hr_attendance/models/res_config_settings.py index 7516aec2b0f..ebd9cc1e459 100644 --- a/addons/hr_attendance/models/res_config_settings.py +++ b/addons/hr_attendance/models/res_config_settings.py @@ -31,7 +31,7 @@ class ResConfigSettings(models.TransientModel): return res def set_values(self): - super(ResConfigSettings, self).set_values() + super().set_values() company = self.env.company # Done this way to have all the values written at the same time, # to avoid recomputing the overtimes several times with diff --git a/addons/hr_expense/models/res_config_settings.py b/addons/hr_expense/models/res_config_settings.py index 4fa18b0892c..7bcbb559d8e 100644 --- a/addons/hr_expense/models/res_config_settings.py +++ b/addons/hr_expense/models/res_config_settings.py @@ -6,8 +6,11 @@ from odoo import api, fields, models class ResConfigSettings(models.TransientModel): _inherit = 'res.config.settings' - expense_alias_prefix = fields.Char('Default Alias Name for Expenses', compute='_compute_expense_alias_prefix', - store=True, readonly=False) + expense_alias_prefix = fields.Char( + 'Default Alias Name for Expenses', + compute='_compute_expense_alias_prefix', + store=True, + readonly=False) use_mailgateway = fields.Boolean(string='Let your employees record expenses by email', config_parameter='hr_expense.use_mailgateway') @@ -24,8 +27,10 @@ class ResConfigSettings(models.TransientModel): return res def set_values(self): - super(ResConfigSettings, self).set_values() - self.env.ref('hr_expense.mail_alias_expense').write({'alias_name': self.expense_alias_prefix}) + super().set_values() + alias = self.env.ref('hr_expense.mail_alias_expense', raise_if_not_found=False) + if alias and alias.alias_name != self.expense_alias_prefix: + alias.alias_name = self.expense_alias_prefix @api.depends('use_mailgateway') def _compute_expense_alias_prefix(self): diff --git a/addons/point_of_sale/models/res_config_settings.py b/addons/point_of_sale/models/res_config_settings.py index 0927302a09d..038f5fef792 100644 --- a/addons/point_of_sale/models/res_config_settings.py +++ b/addons/point_of_sale/models/res_config_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from odoo import api, fields, models +from odoo import fields, models class ResConfigSettings(models.TransientModel): @@ -18,6 +18,6 @@ class ResConfigSettings(models.TransientModel): def set_values(self): super(ResConfigSettings, self).set_values() if not self.group_product_pricelist: - configs = self.env['pos.config'].search([('use_pricelist', '=', True)]) - for config in configs: - config.use_pricelist = False + self.env['pos.config'].search([ + ('use_pricelist', '=', True) + ]).use_pricelist = False diff --git a/addons/project/models/res_config_settings.py b/addons/project/models/res_config_settings.py index 4c0367852f0..e9375f1c9ed 100644 --- a/addons/project/models/res_config_settings.py +++ b/addons/project/models/res_config_settings.py @@ -68,4 +68,4 @@ class ResConfigSettings(models.TransientModel): if project_stage_change_mail_type.hidden == self['group_project_stages']: project_stage_change_mail_type.hidden = not self['group_project_stages'] - super(ResConfigSettings, self).set_values() + super().set_values() diff --git a/addons/purchase/models/res_config_settings.py b/addons/purchase/models/res_config_settings.py index f19b32cbd17..4d07ddb0b4a 100644 --- a/addons/purchase/models/res_config_settings.py +++ b/addons/purchase/models/res_config_settings.py @@ -39,6 +39,10 @@ class ResConfigSettings(models.TransientModel): self.po_lead = 0.0 def set_values(self): - super(ResConfigSettings, self).set_values() - self.po_lock = 'lock' if self.lock_confirmed_po else 'edit' - self.po_double_validation = 'two_step' if self.po_order_approval else 'one_step' + super().set_values() + po_lock = 'lock' if self.lock_confirmed_po else 'edit' + po_double_validation = 'two_step' if self.po_order_approval else 'one_step' + if self.po_lock != po_lock: + self.po_lock = po_lock + if self.po_double_validation != po_double_validation: + self.po_double_validation = po_double_validation diff --git a/addons/sale/models/res_config_settings.py b/addons/sale/models/res_config_settings.py index dd0e2cb1b2e..b82d2826c18 100644 --- a/addons/sale/models/res_config_settings.py +++ b/addons/sale/models/res_config_settings.py @@ -66,12 +66,12 @@ class ResConfigSettings(models.TransientModel): ) def set_values(self): - super(ResConfigSettings, self).set_values() + super().set_values() if self.default_invoice_policy != 'order': self.env['ir.config_parameter'].set_param('sale.automatic_invoice', False) send_invoice_cron = self.env.ref('sale.send_invoice_cron', raise_if_not_found=False) - if send_invoice_cron: + if send_invoice_cron and send_invoice_cron.active != self.automatic_invoice: send_invoice_cron.active = self.automatic_invoice @api.onchange('use_quotation_validity_days') diff --git a/addons/sale_management/models/res_config_settings.py b/addons/sale_management/models/res_config_settings.py index bdfc0e0d74d..2bc2862037b 100644 --- a/addons/sale_management/models/res_config_settings.py +++ b/addons/sale_management/models/res_config_settings.py @@ -21,8 +21,11 @@ class ResConfigSettings(models.TransientModel): def set_values(self): if not self.group_sale_order_template: - self.company_so_template_id = None - self.env['res.company'].sudo().search([]).write({ - 'sale_order_template_id': False, - }) - return super(ResConfigSettings, self).set_values() + if self.company_so_template_id: + self.company_so_template_id = False + companies = self.env['res.company'].sudo().search([ + 'sale_order_template_id', '!=', False + ]) + if companies: + companies.sale_order_template_id = False + super().set_values() diff --git a/addons/stock/models/res_config_settings.py b/addons/stock/models/res_config_settings.py index 4277ac6d234..0a155ecddb4 100644 --- a/addons/stock/models/res_config_settings.py +++ b/addons/stock/models/res_config_settings.py @@ -69,26 +69,29 @@ class ResConfigSettings(models.TransientModel): warehouse_grp = self.env.ref('stock.group_stock_multi_warehouses') location_grp = self.env.ref('stock.group_stock_multi_locations') base_user = self.env.ref('base.group_user') - if not self.group_stock_multi_locations and location_grp in base_user.implied_ids and warehouse_grp in base_user.implied_ids: + base_user_implied_ids = base_user.implied_ids + if not self.group_stock_multi_locations and location_grp in base_user_implied_ids and warehouse_grp in base_user_implied_ids: raise UserError(_("You can't desactivate the multi-location if you have more than once warehouse by company")) # Deactivate putaway rules with storage category when not in storage category # group. Otherwise, active them. storage_cate_grp = self.env.ref('stock.group_stock_storage_categories') PutawayRule = self.env['stock.putaway.rule'] - if self.group_stock_storage_categories and storage_cate_grp not in base_user.implied_ids: + if self.group_stock_storage_categories and storage_cate_grp not in base_user_implied_ids: putaway_rules = PutawayRule.search([ ('active', '=', False), ('storage_category_id', '!=', False) ]) - putaway_rules.write({'active': True}) - elif not self.group_stock_storage_categories and storage_cate_grp in base_user.implied_ids: + if putaway_rules: + putaway_rules.active = True + elif not self.group_stock_storage_categories and storage_cate_grp in base_user_implied_ids: putaway_rules = PutawayRule.search([('storage_category_id', '!=', False)]) - putaway_rules.write({'active': False}) + if putaway_rules: + putaway_rules.active = False previous_group = self.default_get(['group_stock_multi_locations', 'group_stock_production_lot', 'group_stock_tracking_lot']) was_operations_showed = self.env['stock.picking.type'].with_user(SUPERUSER_ID)._default_show_operations() - res = super(ResConfigSettings, self).set_values() + super().set_values() if not self.user_has_groups('stock.group_stock_manager'): return @@ -99,18 +102,17 @@ class ResConfigSettings(models.TransientModel): warehouse_obj = self.env['stock.warehouse'] if self.group_stock_multi_locations and not previous_group.get('group_stock_multi_locations'): # override active_test that is false in set_values - warehouse_obj.with_context(active_test=True).search([]).mapped('int_type_id').write({'active': True}) + warehouse_obj.with_context(active_test=True).search([]).int_type_id.active = True elif not self.group_stock_multi_locations and previous_group.get('group_stock_multi_locations'): warehouse_obj.search([ ('reception_steps', '=', 'one_step'), - ('delivery_steps', '=', 'ship_only')] - ).mapped('int_type_id').write({'active': False}) + ('delivery_steps', '=', 'ship_only') + ]).int_type_id.active = False if not was_operations_showed and self.env['stock.picking.type'].with_user(SUPERUSER_ID)._default_show_operations(): - picking_types = self.env['stock.picking.type'].with_context(active_test=False).search([ + self.env['stock.picking.type'].with_context(active_test=False).sudo().search([ ('code', '!=', 'incoming'), ('show_operations', '=', False) - ]) - picking_types.sudo().write({'show_operations': True}) + ]).show_operations = True - return res + return diff --git a/addons/website/models/res_config_settings.py b/addons/website/models/res_config_settings.py index b2102ab6304..512ca36b9ba 100644 --- a/addons/website/models/res_config_settings.py +++ b/addons/website/models/res_config_settings.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from ast import literal_eval from odoo import api, fields, models from odoo.exceptions import UserError diff --git a/addons/website_sale_stock/models/res_config_settings.py b/addons/website_sale_stock/models/res_config_settings.py index 1b11ee0c72f..ceabc7b5282 100644 --- a/addons/website_sale_stock/models/res_config_settings.py +++ b/addons/website_sale_stock/models/res_config_settings.py @@ -7,11 +7,20 @@ from odoo import fields, models, api class ResConfigSettings(models.TransientModel): _inherit = 'res.config.settings' - allow_out_of_stock_order = fields.Boolean(string='Continue selling when out-of-stock', default=True) - available_threshold = fields.Float(string='Show Threshold', default=5.0) - show_availability = fields.Boolean(string='Show availability Qty', default=False) - - website_warehouse_id = fields.Many2one('stock.warehouse', related='website_id.warehouse_id', domain="[('company_id', '=', website_company_id)]", readonly=False) + allow_out_of_stock_order = fields.Boolean( + string='Continue selling when out-of-stock', + default=True) + available_threshold = fields.Float( + string='Show Threshold', + default=5.0) + show_availability = fields.Boolean( + string='Show availability Qty', + default=False) + website_warehouse_id = fields.Many2one( + 'stock.warehouse', + related='website_id.warehouse_id', + domain="[('company_id', '=', website_company_id)]", + readonly=False) def set_values(self): super(ResConfigSettings, self).set_values() @@ -30,12 +39,5 @@ class ResConfigSettings(models.TransientModel): res.update( allow_out_of_stock_order=allow_out_of_stock_order if allow_out_of_stock_order is not None else True, available_threshold=IrDefault.get('product.template', 'available_threshold') or 5.0, - show_availability=IrDefault.get('product.template', 'show_availability') or False - ) - + show_availability=IrDefault.get('product.template', 'show_availability') or False) return res - - @api.onchange('website_company_id') - def _onchange_website_company_id(self): - if self.website_warehouse_id.company_id != self.website_company_id: - return {'value': {'website_warehouse_id': False}} diff --git a/odoo/addons/base/models/res_config.py b/odoo/addons/base/models/res_config.py index 8bb5dc5efee..3a885a5bfac 100644 --- a/odoo/addons/base/models/res_config.py +++ b/odoo/addons/base/models/res_config.py @@ -1,12 +1,14 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. + import json import logging import re +from ast import literal_eval from lxml import etree -from odoo import api, models, _, Command +from odoo import api, models, _ from odoo.exceptions import AccessError, RedirectWarning, UserError from odoo.tools import ustr