[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) <mat@odoo.com>
This commit is contained in:
mreficent
2020-02-20 14:58:33 +00:00
committed by Martin Trigaux
parent 62c9227fda
commit 3dffce34bf
18 changed files with 30 additions and 43 deletions
+2 -4
View File
@@ -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')
+1 -2
View File
@@ -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.")
-1
View File
@@ -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):
+1 -1
View File
@@ -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)
+2 -2
View File
@@ -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):
+1 -1
View File
@@ -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",
@@ -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)
+2 -4
View File
@@ -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')],
+1 -1
View File
@@ -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')
+4 -4
View File
@@ -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(
+1 -2
View File
@@ -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)
+1 -1
View File
@@ -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):
+2 -7
View File
@@ -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,
+2 -5
View File
@@ -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')
+2 -2
View File
@@ -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):
+2 -4
View File
@@ -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)
+1 -1
View File
@@ -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)
+4
View File
@@ -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)