From 3dffce34bf80c2a8d8682ef986d6daafa5bb0b7f Mon Sep 17 00:00:00 2001 From: mreficent Date: Wed, 19 Feb 2020 12:42:23 +0000 Subject: [PATCH] [IMP] fields: log warning for ignored selection When a field is related, defining a selection or selection_add will have no effect and the paramater is ignored. Log a warning and fix all fields badly definied Closes odoo/odoo#45716 closes odoo/odoo#45832 Related: odoo/enterprise#8613 Signed-off-by: Martin Trigaux (mat) --- addons/account/models/res_config_settings.py | 6 ++---- addons/account/wizard/setup_wizards.py | 3 +-- addons/gamification/models/badge.py | 1 - addons/gamification/models/challenge.py | 2 +- addons/gamification/models/goal.py | 4 ++-- addons/hr_holidays/models/hr_leave.py | 2 +- addons/hr_holidays/models/hr_leave_allocation.py | 2 +- addons/mail/models/res_users.py | 6 ++---- addons/mrp/models/mrp_workcenter.py | 2 +- addons/mrp/models/mrp_workorder.py | 8 ++++---- addons/payment/models/payment_acquirer.py | 3 +-- addons/repair/models/repair.py | 2 +- addons/sale/models/sale.py | 9 ++------- addons/sms/wizard/sms_resend.py | 7 ++----- addons/stock/models/stock_inventory.py | 4 ++-- addons/stock/models/stock_picking.py | 6 ++---- addons/stock/models/stock_scrap.py | 2 +- odoo/fields.py | 4 ++++ 18 files changed, 30 insertions(+), 43 deletions(-) diff --git a/addons/account/models/res_config_settings.py b/addons/account/models/res_config_settings.py index 28362a46223..6557f4b907f 100644 --- a/addons/account/models/res_config_settings.py +++ b/addons/account/models/res_config_settings.py @@ -21,10 +21,8 @@ class ResConfigSettings(models.TransientModel): domain="[('visible','=', True)]") sale_tax_id = fields.Many2one('account.tax', string="Default Sale Tax", related='company_id.account_sale_tax_id', readonly=False) purchase_tax_id = fields.Many2one('account.tax', string="Default Purchase Tax", related='company_id.account_purchase_tax_id', readonly=False) - tax_calculation_rounding_method = fields.Selection([ - ('round_per_line', 'Round calculation of taxes per line'), - ('round_globally', 'Round globally calculation of taxes '), - ], related='company_id.tax_calculation_rounding_method', string='Tax calculation rounding method', readonly=False) + tax_calculation_rounding_method = fields.Selection( + related='company_id.tax_calculation_rounding_method', string='Tax calculation rounding method', readonly=False) module_account_accountant = fields.Boolean(string='Accounting') group_analytic_accounting = fields.Boolean(string='Analytic Accounting', implied_group='analytic.group_analytic_accounting') diff --git a/addons/account/wizard/setup_wizards.py b/addons/account/wizard/setup_wizards.py index 56b484ce92b..012c32f6ea7 100644 --- a/addons/account/wizard/setup_wizards.py +++ b/addons/account/wizard/setup_wizards.py @@ -16,8 +16,7 @@ class FinancialYearOpeningWizard(models.TransientModel): opening_date = fields.Date(string='Opening Date', required=True, related='company_id.account_opening_date', help="Date from which the accounting is managed in Odoo. It is the date of the opening entry.", readonly=False) fiscalyear_last_day = fields.Integer(related="company_id.fiscalyear_last_day", required=True, readonly=False, help="The last day of the month will be used if the chosen day doesn't exist.") - fiscalyear_last_month = fields.Selection(selection=[(1, 'January'), (2, 'February'), (3, 'March'), (4, 'April'), (5, 'May'), (6, 'June'), (7, 'July'), (8, 'August'), (9, 'September'), (10, 'October'), (11, 'November'), (12, 'December')], - related="company_id.fiscalyear_last_month", readonly=False, + fiscalyear_last_month = fields.Selection(related="company_id.fiscalyear_last_month", readonly=False, required=True, help="The last day of the month will be used if the chosen day doesn't exist.") diff --git a/addons/gamification/models/badge.py b/addons/gamification/models/badge.py index 7bfdd074644..c202bde3374 100644 --- a/addons/gamification/models/badge.py +++ b/addons/gamification/models/badge.py @@ -24,7 +24,6 @@ class BadgeUser(models.Model): comment = fields.Text('Comment') badge_name = fields.Char(related='badge_id.name', string="Badge Name", readonly=False) level = fields.Selection( - [('bronze', 'Bronze'), ('silver', 'Silver'), ('gold', 'Gold')], string='Badge Level', related="badge_id.level", store=True, readonly=True) def _send_badge(self): diff --git a/addons/gamification/models/challenge.py b/addons/gamification/models/challenge.py index b2fb80e7389..19aa131270e 100644 --- a/addons/gamification/models/challenge.py +++ b/addons/gamification/models/challenge.py @@ -790,7 +790,7 @@ class ChallengeLine(models.Model): target_goal = fields.Float('Target Value to Reach', required=True) name = fields.Char("Name", related='definition_id.name', readonly=False) - condition = fields.Selection("Condition", related='definition_id.condition', readonly=True) + condition = fields.Selection(string="Condition", related='definition_id.condition', readonly=True) definition_suffix = fields.Char("Unit", related='definition_id.suffix', readonly=True) definition_monetary = fields.Boolean("Monetary", related='definition_id.monetary', readonly=True) definition_full_suffix = fields.Char("Suffix", related='definition_id.full_suffix', readonly=True) diff --git a/addons/gamification/models/goal.py b/addons/gamification/models/goal.py index 51fa991d6d1..d6dd9e5a919 100644 --- a/addons/gamification/models/goal.py +++ b/addons/gamification/models/goal.py @@ -179,9 +179,9 @@ class Goal(models.Model): "case of non-manual goal or goal not linked to a challenge.") definition_description = fields.Text("Definition Description", related='definition_id.description', readonly=True) - definition_condition = fields.Selection("Definition Condition", related='definition_id.condition', readonly=True) + definition_condition = fields.Selection(string="Definition Condition", related='definition_id.condition', readonly=True) definition_suffix = fields.Char("Suffix", related='definition_id.full_suffix', readonly=True) - definition_display = fields.Selection("Display Mode", related='definition_id.display_mode', readonly=True) + definition_display = fields.Selection(string="Display Mode", related='definition_id.display_mode', readonly=True) @api.depends('current', 'target_goal', 'definition_id.condition') def _get_completion(self): diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py index fd8e337621d..bcf395f6497 100644 --- a/addons/hr_holidays/models/hr_leave.py +++ b/addons/hr_holidays/models/hr_leave.py @@ -126,7 +126,7 @@ class HolidaysRequest(models.Model): "hr.leave.type", string="Time Off Type", required=True, readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, domain=[('valid', '=', True)]) - validation_type = fields.Selection('Validation Type', related='holiday_status_id.leave_validation_type', readonly=False) + validation_type = fields.Selection(string='Validation Type', related='holiday_status_id.leave_validation_type', readonly=False) # HR data employee_id = fields.Many2one( 'hr.employee', string='Employee', index=True, readonly=True, ondelete="restrict", diff --git a/addons/hr_holidays/models/hr_leave_allocation.py b/addons/hr_holidays/models/hr_leave_allocation.py index 35c34ad1738..3fca9e400c4 100644 --- a/addons/hr_holidays/models/hr_leave_allocation.py +++ b/addons/hr_holidays/models/hr_leave_allocation.py @@ -92,7 +92,7 @@ class HolidaysAllocation(models.Model): second_approver_id = fields.Many2one( 'hr.employee', string='Second Approval', readonly=True, copy=False, help='This area is automaticly filled by the user who validates the allocation with second level (If allocation type need second validation)') - validation_type = fields.Selection('Validation Type', related='holiday_status_id.allocation_validation_type', readonly=True) + validation_type = fields.Selection(string='Validation Type', related='holiday_status_id.allocation_validation_type', readonly=True) can_reset = fields.Boolean('Can reset', compute='_compute_can_reset') can_approve = fields.Boolean('Can Approve', compute='_compute_can_approve') type_request_unit = fields.Selection(related='holiday_status_id.request_unit', readonly=True) diff --git a/addons/mail/models/res_users.py b/addons/mail/models/res_users.py index d7b414eac7c..58037fe43b8 100644 --- a/addons/mail/models/res_users.py +++ b/addons/mail/models/res_users.py @@ -21,10 +21,8 @@ class Users(models.Model): alias_id = fields.Many2one('mail.alias', 'Alias', ondelete="set null", required=False, help="Email address internally associated with this user. Incoming "\ "emails will appear in the user's notifications.", copy=False, auto_join=True) - alias_contact = fields.Selection([ - ('everyone', 'Everyone'), - ('partners', 'Authenticated Partners'), - ('followers', 'Followers only')], string='Alias Contact Security', related='alias_id.alias_contact', readonly=False) + alias_contact = fields.Selection( + string='Alias Contact Security', related='alias_id.alias_contact', readonly=False) notification_type = fields.Selection([ ('email', 'Handle by Emails'), ('inbox', 'Handle in Odoo')], diff --git a/addons/mrp/models/mrp_workcenter.py b/addons/mrp/models/mrp_workcenter.py index fe3ea2a9db5..6f377ceedb4 100644 --- a/addons/mrp/models/mrp_workcenter.py +++ b/addons/mrp/models/mrp_workcenter.py @@ -319,7 +319,7 @@ class MrpWorkcenterProductivity(models.Model): 'mrp.workcenter.productivity.loss', "Loss Reason", ondelete='restrict', required=True) loss_type = fields.Selection( - "Effectiveness", related='loss_id.loss_type', store=True, readonly=False) + string="Effectiveness", related='loss_id.loss_type', store=True, readonly=False) description = fields.Text('Description') date_start = fields.Datetime('Start Date', default=fields.Datetime.now, required=True) date_end = fields.Datetime('End Date') diff --git a/addons/mrp/models/mrp_workorder.py b/addons/mrp/models/mrp_workorder.py index 71255432355..0863d31ffa9 100644 --- a/addons/mrp/models/mrp_workorder.py +++ b/addons/mrp/models/mrp_workorder.py @@ -34,14 +34,14 @@ class MrpWorkorder(models.Model): states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, group_expand='_read_group_workcenter_id', check_company=True) working_state = fields.Selection( - 'Workcenter Status', related='workcenter_id.working_state', readonly=False, + string='Workcenter Status', related='workcenter_id.working_state', readonly=False, help='Technical: used in views only') production_availability = fields.Selection( - 'Stock Availability', readonly=True, + string='Stock Availability', readonly=True, related='production_id.reservation_state', store=True, help='Technical: used in views and domains only.') production_state = fields.Selection( - 'Production State', readonly=True, + string='Production State', readonly=True, related='production_id.state', help='Technical: used in views only.') qty_production = fields.Float('Original Production Quantity', readonly=True, related='production_id.product_qty') @@ -107,7 +107,7 @@ class MrpWorkorder(models.Model): worksheet = fields.Binary( 'Worksheet', related='operation_id.worksheet', readonly=True) worksheet_type = fields.Selection( - 'Worksheet Type', related='operation_id.worksheet_type', readonly=True) + string='Worksheet Type', related='operation_id.worksheet_type', readonly=True) worksheet_google_slide = fields.Char( 'Worksheet URL', related='operation_id.worksheet_google_slide', readonly=True) move_raw_ids = fields.One2many( diff --git a/addons/payment/models/payment_acquirer.py b/addons/payment/models/payment_acquirer.py index ae90f89fa92..6453965ff5f 100644 --- a/addons/payment/models/payment_acquirer.py +++ b/addons/payment/models/payment_acquirer.py @@ -9,7 +9,6 @@ import pprint from odoo import api, exceptions, fields, models, _, SUPERUSER_ID from odoo.tools import consteq, float_round, image_process, ustr -from odoo.addons.base.models import ir_module from odoo.exceptions import ValidationError from odoo.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT from odoo.tools.misc import formatLang @@ -154,7 +153,7 @@ class PaymentAcquirer(models.Model): # TDE FIXME: remove that brol module_id = fields.Many2one('ir.module.module', string='Corresponding Module') - module_state = fields.Selection(selection=ir_module.STATES, string='Installation State', related='module_id.state', store=True) + module_state = fields.Selection(string='Installation State', related='module_id.state', store=True) module_to_buy = fields.Boolean(string='Odoo Enterprise Module', related='module_id.to_buy', readonly=True, store=False) image_128 = fields.Image("Image", max_width=128, max_height=128) diff --git a/addons/repair/models/repair.py b/addons/repair/models/repair.py index 956dfabe2f1..c32cd790f18 100644 --- a/addons/repair/models/repair.py +++ b/addons/repair/models/repair.py @@ -110,7 +110,7 @@ class Repair(models.Model): amount_untaxed = fields.Float('Untaxed Amount', compute='_amount_untaxed', store=True) amount_tax = fields.Float('Taxes', compute='_amount_tax', store=True) amount_total = fields.Float('Total', compute='_amount_total', store=True) - tracking = fields.Selection('Product Tracking', related="product_id.tracking", readonly=False) + tracking = fields.Selection(string='Product Tracking', related="product_id.tracking", readonly=False) @api.depends('partner_id') def _compute_default_address_id(self): diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py index 4b8399d5f44..93742486b71 100644 --- a/addons/sale/models/sale.py +++ b/addons/sale/models/sale.py @@ -1258,13 +1258,8 @@ class SaleOrderLine(models.Model): string="Is a down payment", help="Down payments are made when creating invoices from a sales order." " They are not copied when duplicating a sales order.") - state = fields.Selection([ - ('draft', 'Quotation'), - ('sent', 'Quotation Sent'), - ('sale', 'Sales Order'), - ('done', 'Done'), - ('cancel', 'Cancelled'), - ], related='order_id.state', string='Order Status', readonly=True, copy=False, store=True, default='draft') + state = fields.Selection( + related='order_id.state', string='Order Status', readonly=True, copy=False, store=True, default='draft') customer_lead = fields.Float( 'Lead Time', required=True, default=0.0, diff --git a/addons/sms/wizard/sms_resend.py b/addons/sms/wizard/sms_resend.py index aad00074c67..4d747e38b63 100644 --- a/addons/sms/wizard/sms_resend.py +++ b/addons/sms/wizard/sms_resend.py @@ -12,11 +12,8 @@ class SMSRecipient(models.TransientModel): sms_resend_id = fields.Many2one('sms.resend', required=True) notification_id = fields.Many2one('mail.notification', required=True, ondelete='cascade') resend = fields.Boolean(string="Resend", default=True) - failure_type = fields.Selection([ - ('sms_number_missing', 'Missing Number'), - ('sms_number_format', 'Wrong Number Format'), - ('sms_credit', 'Insufficient Credit'), - ('sms_server', 'Server Error')], related='notification_id.failure_type', related_sudo=True, readonly=True) + failure_type = fields.Selection( + related='notification_id.failure_type', related_sudo=True, readonly=True) partner_id = fields.Many2one('res.partner', 'Partner', related='notification_id.res_partner_id', readonly=True) partner_name = fields.Char('Recipient', readonly='True') sms_number = fields.Char('Number') diff --git a/addons/stock/models/stock_inventory.py b/addons/stock/models/stock_inventory.py index 2f6e3f045fa..056fa55778e 100644 --- a/addons/stock/models/stock_inventory.py +++ b/addons/stock/models/stock_inventory.py @@ -357,7 +357,7 @@ class InventoryLine(models.Model): company_id = fields.Many2one( 'res.company', 'Company', related='inventory_id.company_id', index=True, readonly=True, store=True) - state = fields.Selection('Status', related='inventory_id.state') + state = fields.Selection(string='Status', related='inventory_id.state') theoretical_qty = fields.Float( 'Theoretical Quantity', digits='Product Unit of Measure', readonly=True) @@ -369,7 +369,7 @@ class InventoryLine(models.Model): help="Last date at which the On Hand Quantity has been computed.") outdated = fields.Boolean(string='Quantity outdated', compute='_compute_outdated', search='_search_outdated') - product_tracking = fields.Selection('Tracking', related='product_id.tracking', readonly=True) + product_tracking = fields.Selection(string='Tracking', related='product_id.tracking', readonly=True) @api.depends('product_qty', 'theoretical_qty') def _compute_difference(self): diff --git a/addons/stock/models/stock_picking.py b/addons/stock/models/stock_picking.py index b18920d4435..3fb316194db 100644 --- a/addons/stock/models/stock_picking.py +++ b/addons/stock/models/stock_picking.py @@ -315,10 +315,8 @@ class Picking(models.Model): 'stock.picking.type', 'Operation Type', required=True, readonly=True, states={'draft': [('readonly', False)]}) - picking_type_code = fields.Selection([ - ('incoming', 'Vendors'), - ('outgoing', 'Customers'), - ('internal', 'Internal')], related='picking_type_id.code', + picking_type_code = fields.Selection( + related='picking_type_id.code', readonly=True) picking_type_entire_packs = fields.Boolean(related='picking_type_id.show_entire_packs', readonly=True) diff --git a/addons/stock/models/stock_scrap.py b/addons/stock/models/stock_scrap.py index ea7c5f4c9da..e2c80ac8970 100644 --- a/addons/stock/models/stock_scrap.py +++ b/addons/stock/models/stock_scrap.py @@ -36,7 +36,7 @@ class StockScrap(models.Model): 'uom.uom', 'Unit of Measure', required=True, states={'done': [('readonly', True)]}, domain="[('category_id', '=', product_uom_category_id)]") product_uom_category_id = fields.Many2one(related='product_id.uom_id.category_id') - tracking = fields.Selection('Product Tracking', readonly=True, related="product_id.tracking") + tracking = fields.Selection(string='Product Tracking', readonly=True, related="product_id.tracking") lot_id = fields.Many2one( 'stock.production.lot', 'Lot/Serial', states={'done': [('readonly', True)]}, domain="[('product_id', '=', product_id), ('company_id', '=', company_id)]", check_company=True) diff --git a/odoo/fields.py b/odoo/fields.py index 3de87106fd5..64b8083df7c 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -2143,6 +2143,8 @@ class Selection(Field): # We cannot use field.selection or field.selection_add here # because those attributes are overridden by ``_setup_attrs``. if 'selection' in field.args: + if self.related: + _logger.warning("%s: selection attribute will be ignored as the field is related", self) selection = field.args['selection'] if isinstance(selection, list): if ( @@ -2156,6 +2158,8 @@ class Selection(Field): self.selection = selection if 'selection_add' in field.args: + if self.related: + _logger.warning("%s: selection_add attribute will be ignored as the field is related", self) selection_add = field.args['selection_add'] assert isinstance(selection_add, list), \ "%s: selection_add=%r must be a list" % (self, selection_add)