From 3f4f77fd9d5c79c21665fa08d703bba7571decd8 Mon Sep 17 00:00:00 2001
From: Adrian Torres <adt@odoo.com>
Date: Mon, 24 Sep 2018 12:22:45 +0200
Subject: [PATCH] [REF] *: adapt code to new related default behaviour

This commit adapts the business code to changes introduced by
the parent commit in order to keep the same behaviour as before.

All readonly=False fields will have to be checked afterwards to confirm
that the business case requires write access to the source field.
---
 addons/account/models/account.py              |  6 +--
 .../account/models/account_bank_statement.py  |  2 +-
 addons/account/models/account_invoice.py      |  4 +-
 addons/account/models/account_move.py         | 12 ++---
 addons/account/models/company.py              |  8 ++--
 addons/account/models/res_config_settings.py  | 24 +++++-----
 addons/account/wizard/setup_wizards.py        |  4 +-
 addons/account_asset/models/account_asset.py  |  4 +-
 .../models/res_config_settings.py             | 10 ++--
 .../account_voucher/models/account_voucher.py |  2 +-
 addons/analytic/models/analytic_account.py    |  2 +-
 .../auth_ldap/models/res_config_settings.py   |  2 +-
 .../base_gengo/models/res_config_settings.py  |  8 ++--
 .../base_setup/models/res_config_settings.py  |  6 +--
 addons/base_vat/models/res_config_settings.py |  2 +-
 .../models/res_config_settings.py             |  2 +-
 addons/delivery/models/delivery_carrier.py    |  2 +-
 addons/digest/models/digest.py                |  2 +-
 addons/event/models/event.py                  |  2 +-
 addons/fleet/models/fleet_vehicle.py          | 10 ++--
 addons/fleet/models/fleet_vehicle_cost.py     |  8 ++--
 addons/fleet/models/fleet_vehicle_model.py    |  6 +--
 addons/gamification/models/badge.py           |  2 +-
 addons/gamification/models/challenge.py       |  2 +-
 addons/gamification/models/goal.py            |  2 +-
 .../models/res_config_settings.py             |  2 +-
 addons/hr/models/hr.py                        |  6 +--
 addons/hr/models/res_config_settings.py       |  2 +-
 addons/hr_contract/models/hr_contract.py      |  6 +--
 addons/hr_expense/models/hr_expense.py        |  2 +-
 addons/hr_expense_check/models/payment.py     |  2 +-
 addons/hr_holidays/models/hr_leave.py         |  2 +-
 .../hr_recruitment/models/hr_recruitment.py   |  8 ++--
 .../models/hr_applicant.py                    |  2 +-
 .../hr_timesheet/models/analytic_account.py   |  2 +-
 addons/hr_timesheet/models/project.py         |  2 +-
 .../models/res_config_settings.py             |  4 +-
 .../models/hr_contract.py                     | 10 ++--
 .../models/res_config_settings.py             |  2 +-
 addons/l10n_ch/models/account_invoice.py      |  2 +-
 addons/l10n_ch/models/account_journal.py      |  2 +-
 addons/l10n_ch/models/res_config_settings.py  | 10 ++--
 addons/l10n_fr/models/l10n_fr.py              |  2 +-
 .../models/res_config_settings.py             | 10 ++--
 .../models/l10n_in_hr_payroll.py              |  4 +-
 addons/l10n_sg/models/res_company.py          |  2 +-
 addons/lunch/models/lunch.py                  |  4 +-
 addons/mail/models/mail_activity.py           | 16 +++----
 addons/mail/models/mail_channel.py            |  2 +-
 addons/mail/models/mail_message.py            |  2 +-
 addons/mail/models/res_users.py               |  2 +-
 addons/mail/wizard/mail_resend_message.py     |  4 +-
 addons/mass_mailing/models/mass_mailing.py    |  6 +--
 addons/mrp/models/mrp_bom.py                  |  4 +-
 addons/mrp/models/mrp_production.py           |  4 +-
 addons/mrp/models/mrp_workcenter.py           | 10 ++--
 addons/mrp/models/mrp_workorder.py            |  6 +--
 addons/mrp/models/res_config_settings.py      |  2 +-
 addons/mrp/models/stock_move.py               |  2 +-
 addons/mrp/wizard/mrp_product_produce.py      |  4 +-
 addons/pad/models/res_config_settings.py      |  4 +-
 addons/payment/models/payment_acquirer.py     |  4 +-
 addons/payment_authorize/models/payment.py    |  4 +-
 addons/point_of_sale/models/pos_config.py     |  2 +-
 addons/point_of_sale/models/pos_order.py      | 10 ++--
 addons/point_of_sale/models/pos_session.py    |  2 +-
 addons/point_of_sale/models/product.py        |  2 +-
 .../models/res_config_settings.py             |  2 +-
 addons/product/models/product.py              |  4 +-
 addons/product/models/product_template.py     |  4 +-
 addons/product_expiry/models/stock_quant.py   |  2 +-
 .../models/res_config_settings.py             |  4 +-
 addons/purchase/models/purchase.py            |  6 +--
 addons/purchase/models/res_config_settings.py |  8 ++--
 .../models/purchase_requisition.py            |  4 +-
 addons/rating/models/rating.py                |  6 +--
 addons/repair/models/repair.py                |  2 +-
 addons/resource/models/res_users.py           |  2 +-
 addons/resource/models/resource_mixin.py      |  6 +--
 addons/sale/models/res_config_settings.py     |  8 ++--
 addons/sale/models/sale.py                    |  4 +-
 .../models/sale_order_template.py             |  2 +-
 .../sale_stock/models/res_config_settings.py  |  2 +-
 addons/sale_stock/models/stock.py             |  2 +-
 .../wizard/project_create_sale_order.py       |  4 +-
 .../snailmail/models/res_config_settings.py   |  4 +-
 .../models/res_config_settings.py             |  2 +-
 addons/stock/models/product.py                |  2 +-
 addons/stock/models/res_config_settings.py    |  2 +-
 addons/stock/models/stock_inventory.py        |  2 +-
 addons/stock/models/stock_move.py             | 10 ++--
 addons/stock/models/stock_move_line.py        |  6 +--
 addons/stock/models/stock_package_level.py    |  2 +-
 addons/stock/models/stock_picking.py          |  2 +-
 addons/stock/models/stock_production_lot.py   |  2 +-
 addons/stock/models/stock_quant.py            |  2 +-
 addons/stock/models/stock_rule.py             |  2 +-
 .../stock/wizard/stock_change_product_qty.py  |  2 +-
 addons/stock/wizard/stock_picking_return.py   |  2 +-
 .../models/stock_landed_cost.py               |  2 +-
 addons/survey/models/survey.py                | 12 ++---
 addons/website/models/ir_attachment.py        |  2 +-
 addons/website/models/res_config_settings.py  | 48 +++++++++----------
 addons/website/models/website.py              | 10 ++--
 addons/website_blog/models/website_blog.py    |  2 +-
 .../website_crm/models/res_config_settings.py |  4 +-
 .../website_event_track/models/event_track.py |  6 +--
 addons/website_form/models/models.py          |  2 +-
 addons/website_forum/models/forum.py          |  4 +-
 addons/website_forum/models/gamification.py   |  2 +-
 .../models/res_config_settings.py             |  2 +-
 addons/website_rating/models/rating.py        |  2 +-
 addons/website_sale/models/product.py         |  2 +-
 .../models/res_config_settings.py             |  6 +--
 addons/website_sale/models/website.py         |  2 +-
 .../website_sale_delivery/models/delivery.py  |  2 +-
 .../models/res_config_settings.py             |  2 +-
 .../models/res_config_settings.py             |  6 +--
 odoo/addons/base/models/ir_cron.py            |  2 +-
 odoo/addons/base/models/res_bank.py           |  4 +-
 odoo/addons/base/models/res_company.py        | 12 ++---
 odoo/addons/base/models/res_users.py          |  6 +--
 odoo/addons/test_new_api/models.py            | 16 +++----
 123 files changed, 293 insertions(+), 293 deletions(-)

diff --git a/addons/account/models/account.py b/addons/account/models/account.py
index 6f1e1f101b75..3818a98d1a18 100644
--- a/addons/account/models/account.py
+++ b/addons/account/models/account.py
@@ -465,14 +465,14 @@ class AccountJournal(models.Model):
     company_partner_id = fields.Many2one('res.partner', related='company_id.partner_id', string='Account Holder', readonly=True, store=False)
     bank_account_id = fields.Many2one('res.partner.bank', string="Bank Account", ondelete='restrict', copy=False, domain="[('partner_id','=', company_partner_id)]")
     bank_statements_source = fields.Selection(selection=_get_bank_statements_available_sources, string='Bank Feeds', default='undefined', help="Defines how the bank statements will be registered")
-    bank_acc_number = fields.Char(related='bank_account_id.acc_number')
-    bank_id = fields.Many2one('res.bank', related='bank_account_id.bank_id')
+    bank_acc_number = fields.Char(related='bank_account_id.acc_number', readonly=False)
+    bank_id = fields.Many2one('res.bank', related='bank_account_id.bank_id', readonly=False)
     post_at_bank_rec = fields.Boolean(string="Post At Bank Reconciliation", help="Whether or not the payments made in this journal should be generated in draft state, so that the related journal entries are only posted when performing bank reconciliation.")
 
     # alias configuration for 'purchase' type journals
     alias_id = fields.Many2one('mail.alias', string='Alias')
     alias_domain = fields.Char('Alias domain', compute='_compute_alias_domain', default=lambda self: self.env["ir.config_parameter"].sudo().get_param("mail.catchall.domain"))
-    alias_name = fields.Char('Alias Name for Vendor Bills', related='alias_id.alias_name', help="It creates draft vendor bill by sending an email.")
+    alias_name = fields.Char('Alias Name for Vendor Bills', related='alias_id.alias_name', help="It creates draft vendor bill by sending an email.", readonly=False)
 
     _sql_constraints = [
         ('code_company_uniq', 'unique (code, name, company_id)', 'The code and name of the journal must be unique per company !'),
diff --git a/addons/account/models/account_bank_statement.py b/addons/account/models/account_bank_statement.py
index e899374d0c8f..f1758d9a92bf 100644
--- a/addons/account/models/account_bank_statement.py
+++ b/addons/account/models/account_bank_statement.py
@@ -143,7 +143,7 @@ class AccountBankStatement(models.Model):
     state = fields.Selection([('open', 'New'), ('confirm', 'Validated')], string='Status', required=True, readonly=True, copy=False, default='open')
     currency_id = fields.Many2one('res.currency', compute='_compute_currency', oldname='currency', string="Currency")
     journal_id = fields.Many2one('account.journal', string='Journal', required=True, states={'confirm': [('readonly', True)]}, default=_default_journal)
-    journal_type = fields.Selection(related='journal_id.type', help="Technical field used for usability purposes")
+    journal_type = fields.Selection(related='journal_id.type', help="Technical field used for usability purposes", readonly=False)
     company_id = fields.Many2one('res.company', related='journal_id.company_id', string='Company', store=True, readonly=True,
         default=lambda self: self.env['res.company']._company_default_get('account.bank.statement'))
 
diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py
index 0d92a946f79f..fa1dc45f4598 100644
--- a/addons/account/models/account_invoice.py
+++ b/addons/account/models/account_invoice.py
@@ -1575,7 +1575,7 @@ class AccountInvoiceLine(models.Model):
         ondelete='set null', index=True, oldname='uos_id')
     product_id = fields.Many2one('product.product', string='Product',
         ondelete='restrict', index=True)
-    product_image = fields.Binary('Product Image', related="product_id.image", store=False)
+    product_image = fields.Binary('Product Image', related="product_id.image", store=False, readonly=False)
     account_id = fields.Many2one('account.account', string='Account', domain=[('deprecated', '=', False)],
         default=_default_account,
         help="The income or expense account related to the selected product.")
@@ -1602,7 +1602,7 @@ class AccountInvoiceLine(models.Model):
         related='invoice_id.company_id', store=True, readonly=True, related_sudo=False)
     partner_id = fields.Many2one('res.partner', string='Partner',
         related='invoice_id.partner_id', store=True, readonly=True, related_sudo=False)
-    currency_id = fields.Many2one('res.currency', related='invoice_id.currency_id', store=True, related_sudo=False)
+    currency_id = fields.Many2one('res.currency', related='invoice_id.currency_id', store=True, related_sudo=False, readonly=False)
     company_currency_id = fields.Many2one('res.currency', related='invoice_id.company_currency_id', readonly=True, related_sudo=False)
     is_rounding_line = fields.Boolean(string='Rounding Line', help='Is a rounding line in case of cash rounding.')
 
diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py
index e0066eb155b2..6e8b5e43769c 100644
--- a/addons/account/models/account_move.py
+++ b/addons/account/models/account_move.py
@@ -611,8 +611,8 @@ class AccountMoveLine(models.Model):
         ondelete="cascade", domain=[('deprecated', '=', False)], default=lambda self: self._context.get('account_id', False))
     move_id = fields.Many2one('account.move', string='Journal Entry', ondelete="cascade",
         help="The move of this entry line.", index=True, required=True, auto_join=True)
-    narration = fields.Text(related='move_id.narration', string='Narration')
-    ref = fields.Char(related='move_id.ref', string='Reference', store=True, copy=False, index=True)
+    narration = fields.Text(related='move_id.narration', string='Narration', readonly=False)
+    ref = fields.Char(related='move_id.ref', string='Reference', store=True, copy=False, index=True, readonly=False)
     payment_id = fields.Many2one('account.payment', string="Originator Payment", help="Payment that created this entry", copy=False)
     statement_line_id = fields.Many2one('account.bank.statement.line', index=True, string='Bank statement line reconciled with this entry', copy=False, readonly=True)
     statement_id = fields.Many2one('account.bank.statement', related='statement_line_id.statement_id', string='Statement', store=True,
@@ -623,13 +623,13 @@ class AccountMoveLine(models.Model):
         help='Debit journal items that are matched with this journal item.')
     matched_credit_ids = fields.One2many('account.partial.reconcile', 'debit_move_id', String='Matched Credits',
         help='Credit journal items that are matched with this journal item.')
-    journal_id = fields.Many2one('account.journal', related='move_id.journal_id', string='Journal',
+    journal_id = fields.Many2one('account.journal', related='move_id.journal_id', string='Journal', readonly=False,
         index=True, store=True, copy=False)  # related is required
     blocked = fields.Boolean(string='No Follow-up', default=False,
         help="You can check this box to mark this journal item as a litigation with the associated partner")
     date_maturity = fields.Date(string='Due date', index=True, required=True,
         help="This field is used for payable and receivable journal entries. You can put the limit date for the payment of this line.")
-    date = fields.Date(related='move_id.date', string='Date', index=True, store=True, copy=False)  # related is required
+    date = fields.Date(related='move_id.date', string='Date', index=True, store=True, copy=False, readonly=False)  # related is required
     analytic_line_ids = fields.One2many('account.analytic.line', 'move_id', string='Analytic lines', oldname="analytic_lines")
     tax_ids = fields.Many2many('account.tax', string='Taxes', domain=['|', ('active', '=', False), ('active', '=', True)])
     tax_line_id = fields.Many2one('account.tax', string='Originator tax', ondelete='restrict')
@@ -641,7 +641,7 @@ class AccountMoveLine(models.Model):
     # TODO: put the invoice link and partner_id on the account_move
     invoice_id = fields.Many2one('account.invoice', oldname="invoice")
     partner_id = fields.Many2one('res.partner', string='Partner', ondelete='restrict')
-    user_type_id = fields.Many2one('account.account.type', related='account_id.user_type_id', index=True, store=True, oldname="user_type")
+    user_type_id = fields.Many2one('account.account.type', related='account_id.user_type_id', index=True, store=True, oldname="user_type", readonly=False)
     tax_exigible = fields.Boolean(string='Appears in VAT report', default=True,
         help="Technical field used to mark a tax line as exigible in the vat report or not (only exigible journal items are displayed). By default all new journal items are directly exigible, but with the feature cash_basis on taxes, some will become exigible only when the payment is recorded.")
     parent_state = fields.Char(compute="_compute_parent_state", help="State of the parent account.move")
@@ -1376,7 +1376,7 @@ class AccountPartialReconcile(models.Model):
     currency_id = fields.Many2one('res.currency', string='Currency')
     company_currency_id = fields.Many2one('res.currency', string="Company Currency", related='company_id.currency_id', readonly=True,
         help='Utility field to express amount currency')
-    company_id = fields.Many2one('res.company', related='debit_move_id.company_id', store=True, string='Company')
+    company_id = fields.Many2one('res.company', related='debit_move_id.company_id', store=True, string='Company', readonly=False)
     full_reconcile_id = fields.Many2one('account.full.reconcile', string="Full Reconcile", copy=False)
     max_date = fields.Date(string='Max Date of Matched Lines', compute='_compute_max_date',
         readonly=True, copy=False, store=True,
diff --git a/addons/account/models/company.py b/addons/account/models/company.py
index 2f49a85962e8..223c37eea7f1 100644
--- a/addons/account/models/company.py
+++ b/addons/account/models/company.py
@@ -38,9 +38,9 @@ class ResCompany(models.Model):
         ('round_globally', 'Round Globally'),
         ], default='round_per_line', string='Tax Calculation Rounding Method')
     currency_exchange_journal_id = fields.Many2one('account.journal', string="Exchange Gain or Loss Journal", domain=[('type', '=', 'general')])
-    income_currency_exchange_account_id = fields.Many2one('account.account', related='currency_exchange_journal_id.default_credit_account_id',
+    income_currency_exchange_account_id = fields.Many2one('account.account', related='currency_exchange_journal_id.default_credit_account_id', readonly=False,
         string="Gain Exchange Rate Account", domain="[('internal_type', '=', 'other'), ('deprecated', '=', False), ('company_id', '=', id)]")
-    expense_currency_exchange_account_id = fields.Many2one('account.account', related='currency_exchange_journal_id.default_debit_account_id',
+    expense_currency_exchange_account_id = fields.Many2one('account.account', related='currency_exchange_journal_id.default_debit_account_id', readonly=False,
         string="Loss Exchange Rate Account", domain="[('internal_type', '=', 'other'), ('deprecated', '=', False), ('company_id', '=', id)]")
     anglo_saxon_accounting = fields.Boolean(string="Use anglo-saxon accounting")
     property_stock_account_input_categ_id = fields.Many2one('account.account', string="Input Account for Stock Valuation", oldname="property_stock_account_input_categ")
@@ -73,8 +73,8 @@ Best Regards,'''))
 
     #Fields of the setup step for opening move
     account_opening_move_id = fields.Many2one(string='Opening Journal Entry', comodel_name='account.move', help="The journal entry containing the initial balance of all this company's accounts.")
-    account_opening_journal_id = fields.Many2one(string='Opening Journal', comodel_name='account.journal', related='account_opening_move_id.journal_id', help="Journal where the opening entry of this company's accounting has been posted.")
-    account_opening_date = fields.Date(string='Opening Date', related='account_opening_move_id.date', help="Date at which the opening entry of this company's accounting has been posted.")
+    account_opening_journal_id = fields.Many2one(string='Opening Journal', comodel_name='account.journal', related='account_opening_move_id.journal_id', help="Journal where the opening entry of this company's accounting has been posted.", readonly=False)
+    account_opening_date = fields.Date(string='Opening Date', related='account_opening_move_id.date', help="Date at which the opening entry of this company's accounting has been posted.", readonly=False)
 
     # Fields marking the completion of a setup step
     # YTI FIXME : The selection should be factorize as a static list in base, like ONBOARDING_STEP_STATES
diff --git a/addons/account/models/res_config_settings.py b/addons/account/models/res_config_settings.py
index b7ebec882863..978b85017bed 100644
--- a/addons/account/models/res_config_settings.py
+++ b/addons/account/models/res_config_settings.py
@@ -8,23 +8,23 @@ class ResConfigSettings(models.TransientModel):
     _inherit = 'res.config.settings'
 
     has_accounting_entries = fields.Boolean(compute='_compute_has_chart_of_accounts')
-    currency_id = fields.Many2one('res.currency', related="company_id.currency_id", required=True,
+    currency_id = fields.Many2one('res.currency', related="company_id.currency_id", required=True, readonly=False,
         string='Currency', help="Main currency of the company.")
     currency_exchange_journal_id = fields.Many2one(
         'account.journal',
-        related='company_id.currency_exchange_journal_id',
+        related='company_id.currency_exchange_journal_id', readonly=False,
         string="Exchange Gain or Loss Journal",
         domain="[('company_id', '=', company_id), ('type', '=', 'general')]",
         help='The accounting journal where automatic exchange differences will be registered')
     has_chart_of_accounts = fields.Boolean(compute='_compute_has_chart_of_accounts', string='Company has a chart of accounts')
     chart_template_id = fields.Many2one('account.chart.template', string='Template',
         domain="[('visible','=', True)]")
-    sale_tax_id = fields.Many2one('account.tax', string="Default Sale Tax", related='company_id.account_sale_tax_id')
-    purchase_tax_id = fields.Many2one('account.tax', string="Default Purchase Tax", related='company_id.account_purchase_tax_id')
+    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')
+        ], 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')
@@ -76,19 +76,19 @@ class ResConfigSettings(models.TransientModel):
     module_l10n_eu_service = fields.Boolean(string="EU Digital Goods VAT")
     module_account_taxcloud = fields.Boolean(string="Account TaxCloud")
     module_account_invoice_extract = fields.Boolean(string="Automate Bill Processing")
-    tax_exigibility = fields.Boolean(string='Cash Basis', related='company_id.tax_exigibility')
-    tax_cash_basis_journal_id = fields.Many2one('account.journal', related='company_id.tax_cash_basis_journal_id', string="Tax Cash Basis Journal")
+    tax_exigibility = fields.Boolean(string='Cash Basis', related='company_id.tax_exigibility', readonly=False)
+    tax_cash_basis_journal_id = fields.Many2one('account.journal', related='company_id.tax_cash_basis_journal_id', string="Tax Cash Basis Journal", readonly=False)
     invoice_reference_type = fields.Selection(string='Communication',
-        related='company_id.invoice_reference_type', help='Default Reference Type on Invoices.')
+        related='company_id.invoice_reference_type', help='Default Reference Type on Invoices.', readonly=False)
     account_bank_reconciliation_start = fields.Date(string="Bank Reconciliation Threshold",
-        related='company_id.account_bank_reconciliation_start',
+        related='company_id.account_bank_reconciliation_start', readonly=False,
         help="""The bank reconciliation widget won't ask to reconcile payments older than this date.
                This is useful if you install accounting after having used invoicing for some time and
                don't want to reconcile all the past payments with bank statements.""")
 
-    qr_code = fields.Boolean(string='Display SEPA QR code', related='company_id.qr_code')
-    invoice_is_print = fields.Boolean(string='Print', related='company_id.invoice_is_print')
-    invoice_is_email = fields.Boolean(string='Send Email', related='company_id.invoice_is_email')
+    qr_code = fields.Boolean(string='Display SEPA QR code', related='company_id.qr_code', readonly=False)
+    invoice_is_print = fields.Boolean(string='Print', related='company_id.invoice_is_print', readonly=False)
+    invoice_is_email = fields.Boolean(string='Send Email', related='company_id.invoice_is_email', readonly=False)
 
     @api.multi
     def set_values(self):
diff --git a/addons/account/wizard/setup_wizards.py b/addons/account/wizard/setup_wizards.py
index 64f6aef13754..75ee6d7c4fc6 100644
--- a/addons/account/wizard/setup_wizards.py
+++ b/addons/account/wizard/setup_wizards.py
@@ -10,11 +10,11 @@ class FinancialYearOpeningWizard(models.TransientModel):
 
     company_id = fields.Many2one(comodel_name='res.company', required=True)
     opening_move_posted = fields.Boolean(string='Opening Move Posted', compute='_compute_opening_move_posted')
-    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.")
+    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,
                                          help="The last day of the month will be taken 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",
+                                             related="company_id.fiscalyear_last_month", readonly=False,
                                              required=True,
                                              help="The last day of the month will be taken if the chosen day doesn't exist.")
 
diff --git a/addons/account_asset/models/account_asset.py b/addons/account_asset/models/account_asset.py
index 276f72268df8..e6ce20919684 100644
--- a/addons/account_asset/models/account_asset.py
+++ b/addons/account_asset/models/account_asset.py
@@ -109,7 +109,7 @@ class AccountAssetAsset(models.Model):
     salvage_value = fields.Float(string='Salvage Value', digits=0, readonly=True, states={'draft': [('readonly', False)]},
         help="It is the amount you plan to have that you cannot depreciate.")
     invoice_id = fields.Many2one('account.invoice', string='Invoice', states={'draft': [('readonly', False)]}, copy=False)
-    type = fields.Selection(related="category_id.type", string='Type', required=True)
+    type = fields.Selection(related="category_id.type", string='Type', required=True, readonly=False)
     account_analytic_id = fields.Many2one('account.analytic.account', string='Analytic Account')
     analytic_tag_ids = fields.Many2many('account.analytic.tag', string='Analytic Tag')
     date_first_depreciation = fields.Selection([
@@ -477,7 +477,7 @@ class AccountAssetDepreciationLine(models.Model):
     name = fields.Char(string='Depreciation Name', required=True, index=True)
     sequence = fields.Integer(required=True)
     asset_id = fields.Many2one('account.asset.asset', string='Asset', required=True, ondelete='cascade')
-    parent_state = fields.Selection(related='asset_id.state', string='State of Asset')
+    parent_state = fields.Selection(related='asset_id.state', string='State of Asset', readonly=False)
     amount = fields.Float(string='Current Depreciation', digits=0, required=True)
     remaining_value = fields.Float(string='Next Period Depreciation', digits=0, required=True)
     depreciated_value = fields.Float(string='Cumulative Depreciation', required=True)
diff --git a/addons/account_check_printing/models/res_config_settings.py b/addons/account_check_printing/models/res_config_settings.py
index 2ba9bc94323b..b31823234909 100644
--- a/addons/account_check_printing/models/res_config_settings.py
+++ b/addons/account_check_printing/models/res_config_settings.py
@@ -11,13 +11,13 @@ class ResConfigSettings(models.TransientModel):
     account_check_printing_layout = fields.Selection(related='company_id.account_check_printing_layout', string="Check Layout",
         help="Select the format corresponding to the check paper you will be printing your checks on.\n"
              "In order to disable the printing feature, select 'None'.")
-    account_check_printing_date_label = fields.Boolean(related='company_id.account_check_printing_date_label', string="Print Date Label",
+    account_check_printing_date_label = fields.Boolean(related='company_id.account_check_printing_date_label', string="Print Date Label", readonly=False,
         help="This option allows you to print the date label on the check as per CPA. Disable this if your pre-printed check includes the date label.")
-    account_check_printing_multi_stub = fields.Boolean(related='company_id.account_check_printing_multi_stub', string='Multi-Pages Check Stub',
+    account_check_printing_multi_stub = fields.Boolean(related='company_id.account_check_printing_multi_stub', string='Multi-Pages Check Stub', readonly=False,
         help="This option allows you to print check details (stub) on multiple pages if they don't fit on a single page.")
-    account_check_printing_margin_top = fields.Float(related='company_id.account_check_printing_margin_top', string='Check Top Margin',
+    account_check_printing_margin_top = fields.Float(related='company_id.account_check_printing_margin_top', string='Check Top Margin', readonly=False,
         help="Adjust the margins of generated checks to make it fit your printer's settings.")
-    account_check_printing_margin_left = fields.Float(related='company_id.account_check_printing_margin_left', string='Check Left Margin',
+    account_check_printing_margin_left = fields.Float(related='company_id.account_check_printing_margin_left', string='Check Left Margin', readonly=False,
         help="Adjust the margins of generated checks to make it fit your printer's settings.")
-    account_check_printing_margin_right = fields.Float(related='company_id.account_check_printing_margin_right', string='Check Right Margin',
+    account_check_printing_margin_right = fields.Float(related='company_id.account_check_printing_margin_right', string='Check Right Margin', readonly=False,
         help="Adjust the margins of generated checks to make it fit your printer's settings.")
diff --git a/addons/account_voucher/models/account_voucher.py b/addons/account_voucher/models/account_voucher.py
index b348e13a62e4..c979480bf35f 100644
--- a/addons/account_voucher/models/account_voucher.py
+++ b/addons/account_voucher/models/account_voucher.py
@@ -416,7 +416,7 @@ class AccountVoucherLine(models.Model):
     analytic_tag_ids = fields.Many2many('account.analytic.tag', string='Analytic Tags')
     company_id = fields.Many2one('res.company', related='voucher_id.company_id', string='Company', store=True, readonly=True)
     tax_ids = fields.Many2many('account.tax', string='Tax', help="Only for tax excluded from price")
-    currency_id = fields.Many2one('res.currency', related='voucher_id.currency_id')
+    currency_id = fields.Many2one('res.currency', related='voucher_id.currency_id', readonly=False)
 
     @api.one
     @api.depends('price_unit', 'tax_ids', 'quantity', 'product_id', 'voucher_id.currency_id')
diff --git a/addons/analytic/models/analytic_account.py b/addons/analytic/models/analytic_account.py
index 199f6097ae12..46fdbb172594 100644
--- a/addons/analytic/models/analytic_account.py
+++ b/addons/analytic/models/analytic_account.py
@@ -14,7 +14,7 @@ class AccountAnalyticDistribution(models.Model):
 
     account_id = fields.Many2one('account.analytic.account', string='Analytic Account', required=True)
     percentage = fields.Float(string='Percentage', required=True, default=100.0)
-    name = fields.Char(string='Name', related='account_id.name')
+    name = fields.Char(string='Name', related='account_id.name', readonly=False)
     tag_id = fields.Many2one('account.analytic.tag', string="Parent tag", required=True)
 
     _sql_constraints = [
diff --git a/addons/auth_ldap/models/res_config_settings.py b/addons/auth_ldap/models/res_config_settings.py
index 92158e3fa3b7..4cc12be31e1e 100644
--- a/addons/auth_ldap/models/res_config_settings.py
+++ b/addons/auth_ldap/models/res_config_settings.py
@@ -7,4 +7,4 @@ from odoo import fields, models
 class ResConfigSettings(models.TransientModel):
     _inherit = 'res.config.settings'
 
-    ldaps = fields.One2many(related='company_id.ldaps', string="LDAP Parameters")
+    ldaps = fields.One2many(related='company_id.ldaps', string="LDAP Parameters", readonly=False)
diff --git a/addons/base_gengo/models/res_config_settings.py b/addons/base_gengo/models/res_config_settings.py
index 17bbc2b24af3..78161d214290 100644
--- a/addons/base_gengo/models/res_config_settings.py
+++ b/addons/base_gengo/models/res_config_settings.py
@@ -7,11 +7,11 @@ from odoo import api, models, fields
 class ResConfigSettings(models.TransientModel):
     _inherit = 'res.config.settings'
 
-    gengo_private_key = fields.Text(string="Gengo Private Key", related="company_id.gengo_private_key")
-    gengo_public_key = fields.Text(string="Gengo Public Key", related="company_id.gengo_public_key")
+    gengo_private_key = fields.Text(string="Gengo Private Key", related="company_id.gengo_private_key", readonly=False)
+    gengo_public_key = fields.Text(string="Gengo Public Key", related="company_id.gengo_public_key", readonly=False)
     gengo_comment = fields.Text(string="Comments", related="company_id.gengo_comment",
       help="This comment will be automatically be enclosed in each an every request sent to Gengo")
-    gengo_auto_approve = fields.Boolean(string="Auto Approve Translation ?", related="company_id.gengo_auto_approve",
+    gengo_auto_approve = fields.Boolean(string="Auto Approve Translation ?", related="company_id.gengo_auto_approve", readonly=False,
       help="Jobs are Automatically Approved by Gengo.")
-    gengo_sandbox = fields.Boolean(string="Sandbox Mode", related="company_id.gengo_sandbox",
+    gengo_sandbox = fields.Boolean(string="Sandbox Mode", related="company_id.gengo_sandbox", readonly=False,
       help="Check this box if you're using the sandbox mode of Gengo, mainly used for testing purpose.")
diff --git a/addons/base_setup/models/res_config_settings.py b/addons/base_setup/models/res_config_settings.py
index d23737db9013..bb6c718b29d9 100644
--- a/addons/base_setup/models/res_config_settings.py
+++ b/addons/base_setup/models/res_config_settings.py
@@ -36,12 +36,12 @@ class ResConfigSettings(models.TransientModel):
         help="Share your partners to all companies defined in your instance.\n"
              " * Checked : Partners are visible for every companies, even if a company is defined on the partner.\n"
              " * Unchecked : Each company can see only its partner (partners where company is defined). Partners not related to a company are visible for all companies.")
-    report_footer = fields.Text(related="company_id.report_footer", string='Custom Report Footer', help="Footer text displayed at the bottom of all reports.")
+    report_footer = fields.Text(related="company_id.report_footer", string='Custom Report Footer', help="Footer text displayed at the bottom of all reports.", readonly=False)
     group_multi_currency = fields.Boolean(string='Multi-Currencies',
             implied_group='base.group_multi_currency',
             help="Allows to work in a multi currency environment")
-    paperformat_id = fields.Many2one(related="company_id.paperformat_id", string='Paper format')
-    external_report_layout_id = fields.Many2one(related="company_id.external_report_layout_id")
+    paperformat_id = fields.Many2one(related="company_id.paperformat_id", string='Paper format', readonly=False)
+    external_report_layout_id = fields.Many2one(related="company_id.external_report_layout_id", readonly=False)
     show_effect = fields.Boolean(string="Show Effect", config_parameter='base_setup.show_effect')
 
     @api.model
diff --git a/addons/base_vat/models/res_config_settings.py b/addons/base_vat/models/res_config_settings.py
index 0bcb8445cee8..c5a06f872d42 100644
--- a/addons/base_vat/models/res_config_settings.py
+++ b/addons/base_vat/models/res_config_settings.py
@@ -6,5 +6,5 @@ from odoo import fields, models
 class ResConfigSettings(models.TransientModel):
     _inherit = 'res.config.settings'
 
-    vat_check_vies = fields.Boolean(related='company_id.vat_check_vies',
+    vat_check_vies = fields.Boolean(related='company_id.vat_check_vies', readonly=False,
         string='Verify VAT Numbers')
diff --git a/addons/crm_phone_validation/models/res_config_settings.py b/addons/crm_phone_validation/models/res_config_settings.py
index 1ec56636935d..b22f4552b5f6 100644
--- a/addons/crm_phone_validation/models/res_config_settings.py
+++ b/addons/crm_phone_validation/models/res_config_settings.py
@@ -7,4 +7,4 @@ from odoo import fields, models
 class ResConfigSettings(models.TransientModel):
     _inherit = 'res.config.settings'
 
-    crm_phone_valid_method = fields.Selection(related="company_id.phone_international_format", required=True)
+    crm_phone_valid_method = fields.Selection(related="company_id.phone_international_format", required=True, readonly=False)
diff --git a/addons/delivery/models/delivery_carrier.py b/addons/delivery/models/delivery_carrier.py
index d7797cb01fa9..77f34f856d03 100644
--- a/addons/delivery/models/delivery_carrier.py
+++ b/addons/delivery/models/delivery_carrier.py
@@ -42,7 +42,7 @@ class DeliveryCarrier(models.Model):
     integration_level = fields.Selection([('rate', 'Get Rate'), ('rate_and_ship', 'Get Rate and Create Shipment')], string="Integration Level", default='rate_and_ship', help="Action while validating Delivery Orders")
     prod_environment = fields.Boolean("Environment", help="Set to True if your credentials are certified for production.")
     debug_logging = fields.Boolean('Debug logging', help="Log requests in order to ease debugging")
-    company_id = fields.Many2one('res.company', string='Company', related='product_id.company_id', store=True)
+    company_id = fields.Many2one('res.company', string='Company', related='product_id.company_id', store=True, readonly=False)
     product_id = fields.Many2one('product.product', string='Delivery Product', required=True, ondelete='restrict')
 
     country_ids = fields.Many2many('res.country', 'delivery_carrier_country_rel', 'carrier_id', 'country_id', 'Countries')
diff --git a/addons/digest/models/digest.py b/addons/digest/models/digest.py
index d89016bd78b7..7dc03b405a6d 100644
--- a/addons/digest/models/digest.py
+++ b/addons/digest/models/digest.py
@@ -32,7 +32,7 @@ class Digest(models.Model):
                                   domain="[('model','=','digest.digest')]",
                                   default=lambda self: self.env.ref('digest.digest_mail_template'),
                                   required=True)
-    currency_id = fields.Many2one(related="company_id.currency_id", string='Currency')
+    currency_id = fields.Many2one(related="company_id.currency_id", string='Currency', readonly=False)
     company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.user.company_id.id)
     available_fields = fields.Char(compute='_compute_available_fields')
     is_subscribed = fields.Boolean('Is user subscribed', compute='_compute_is_subscribed')
diff --git a/addons/event/models/event.py b/addons/event/models/event.py
index 06156e3a99ee..dc15eead79f4 100644
--- a/addons/event/models/event.py
+++ b/addons/event/models/event.py
@@ -159,7 +159,7 @@ class EventEvent(models.Model):
         default=lambda self: self.env.user.company_id.partner_id,
         readonly=False, states={'done': [('readonly', True)]},
         track_visibility="onchange")
-    country_id = fields.Many2one('res.country', 'Country',  related='address_id.country_id', store=True)
+    country_id = fields.Many2one('res.country', 'Country',  related='address_id.country_id', store=True, readonly=False)
     twitter_hashtag = fields.Char('Twitter Hashtag')
     description = fields.Html(
         string='Description', oldname='note', translate=html_translate, sanitize_attributes=False,
diff --git a/addons/fleet/models/fleet_vehicle.py b/addons/fleet/models/fleet_vehicle.py
index 3eadaca7a2c0..7a00aea283fb 100644
--- a/addons/fleet/models/fleet_vehicle.py
+++ b/addons/fleet/models/fleet_vehicle.py
@@ -26,7 +26,7 @@ class FleetVehicle(models.Model):
     driver_id = fields.Many2one('res.partner', 'Driver', track_visibility="onchange", help='Driver of the vehicle', copy=False)
     model_id = fields.Many2one('fleet.vehicle.model', 'Model',
         track_visibility="onchange", required=True, help='Model of the vehicle')
-    brand_id = fields.Many2one('fleet.vehicle.model.brand', 'Brand', related="model_id.brand_id", store=True)
+    brand_id = fields.Many2one('fleet.vehicle.model.brand', 'Brand', related="model_id.brand_id", store=True, readonly=False)
     log_drivers = fields.One2many('fleet.vehicle.assignation.log', 'vehicle_id', string='Assignation Logs')
     log_fuel = fields.One2many('fleet.vehicle.log.fuel', 'vehicle_id', 'Fuel Logs')
     log_services = fields.One2many('fleet.vehicle.log.services', 'vehicle_id', 'Services Logs')
@@ -66,9 +66,9 @@ class FleetVehicle(models.Model):
     horsepower_tax = fields.Float('Horsepower Taxation')
     power = fields.Integer('Power', help='Power in kW of the vehicle')
     co2 = fields.Float('CO2 Emissions', help='CO2 emissions of the vehicle')
-    image = fields.Binary(related='model_id.image', string="Logo")
-    image_medium = fields.Binary(related='model_id.image_medium', string="Logo (medium)")
-    image_small = fields.Binary(related='model_id.image_small', string="Logo (small)")
+    image = fields.Binary(related='model_id.image', string="Logo", readonly=False)
+    image_medium = fields.Binary(related='model_id.image_medium', string="Logo (medium)", readonly=False)
+    image_small = fields.Binary(related='model_id.image_small', string="Logo (small)", readonly=False)
     contract_renewal_due_soon = fields.Boolean(compute='_compute_contract_reminder', search='_search_contract_renewal_due_soon',
         string='Has Contracts to renew', multi='contract_info')
     contract_renewal_overdue = fields.Boolean(compute='_compute_contract_reminder', search='_search_get_overdue_contract_reminder',
@@ -292,7 +292,7 @@ class FleetVehicleOdometer(models.Model):
     value = fields.Float('Odometer Value', group_operator="max")
     vehicle_id = fields.Many2one('fleet.vehicle', 'Vehicle', required=True)
     unit = fields.Selection(related='vehicle_id.odometer_unit', string="Unit", readonly=True)
-    driver_id = fields.Many2one(related="vehicle_id.driver_id", string="Driver")
+    driver_id = fields.Many2one(related="vehicle_id.driver_id", string="Driver", readonly=False)
 
     @api.depends('vehicle_id', 'date')
     def _compute_vehicle_log_name(self):
diff --git a/addons/fleet/models/fleet_vehicle_cost.py b/addons/fleet/models/fleet_vehicle_cost.py
index f51cf01597ac..422645912de0 100644
--- a/addons/fleet/models/fleet_vehicle_cost.py
+++ b/addons/fleet/models/fleet_vehicle_cost.py
@@ -12,7 +12,7 @@ class FleetVehicleCost(models.Model):
     _description = 'Cost related to a vehicle'
     _order = 'date desc, vehicle_id asc'
 
-    name = fields.Char(related='vehicle_id.name', string='Name', store=True)
+    name = fields.Char(related='vehicle_id.name', string='Name', store=True, readonly=False)
     vehicle_id = fields.Many2one('fleet.vehicle', 'Vehicle', required=True, help='Vehicle concerned by this log')
     cost_subtype_id = fields.Many2one('fleet.service.type', 'Type', help='Cost type purchased with this cost')
     amount = fields.Float('Total Price')
@@ -134,7 +134,7 @@ class FleetVehicleLogContract(models.Model):
     # we need to keep this field as a related with store=True because the graph view doesn't support
     # (1) to address fields from inherited table
     # (2) fields that aren't stored in database
-    cost_amount = fields.Float(related='cost_id.amount', string='Amount', store=True)
+    cost_amount = fields.Float(related='cost_id.amount', string='Amount', store=True, readonly=False)
     odometer = fields.Float(string='Odometer at creation', 
         help='Odometer measure of the vehicle at the moment of the contract creation')
 
@@ -317,7 +317,7 @@ class FleetVehicleLogFuel(models.Model):
     # we need to keep this field as a related with store=True because the graph view doesn't support
     # (1) to address fields from inherited table
     # (2) fields that aren't stored in database
-    cost_amount = fields.Float(related='cost_id.amount', string='Amount', store=True)
+    cost_amount = fields.Float(related='cost_id.amount', string='Amount', store=True, readonly=False)
 
     @api.onchange('vehicle_id')
     def _onchange_vehicle(self):
@@ -366,7 +366,7 @@ class FleetVehicleLogServices(models.Model):
     vendor_id = fields.Many2one('res.partner', 'Vendor', domain="[('supplier','=',True)]")
     # we need to keep this field as a related with store=True because the graph view doesn't support
     # (1) to address fields from inherited table and (2) fields that aren't stored in database
-    cost_amount = fields.Float(related='cost_id.amount', string='Amount', store=True)
+    cost_amount = fields.Float(related='cost_id.amount', string='Amount', store=True, readonly=False)
     notes = fields.Text()
     cost_id = fields.Many2one('fleet.vehicle.cost', 'Cost', required=True, ondelete='cascade')
 
diff --git a/addons/fleet/models/fleet_vehicle_model.py b/addons/fleet/models/fleet_vehicle_model.py
index 55a76f2e7695..ded926fc2a0f 100644
--- a/addons/fleet/models/fleet_vehicle_model.py
+++ b/addons/fleet/models/fleet_vehicle_model.py
@@ -12,9 +12,9 @@ class FleetVehicleModel(models.Model):
     name = fields.Char('Model name', required=True)
     brand_id = fields.Many2one('fleet.vehicle.model.brand', 'Make', required=True, help='Make of the vehicle')
     vendors = fields.Many2many('res.partner', 'fleet_vehicle_model_vendors', 'model_id', 'partner_id', string='Vendors')
-    image = fields.Binary(related='brand_id.image', string="Logo")
-    image_medium = fields.Binary(related='brand_id.image_medium', string="Logo (medium)")
-    image_small = fields.Binary(related='brand_id.image_small', string="Logo (small)")
+    image = fields.Binary(related='brand_id.image', string="Logo", readonly=False)
+    image_medium = fields.Binary(related='brand_id.image_medium', string="Logo (medium)", readonly=False)
+    image_small = fields.Binary(related='brand_id.image_small', string="Logo (small)", readonly=False)
 
     @api.multi
     @api.depends('name', 'brand_id')
diff --git a/addons/gamification/models/badge.py b/addons/gamification/models/badge.py
index 4e0d9d1c27cc..6686b29fee5a 100644
--- a/addons/gamification/models/badge.py
+++ b/addons/gamification/models/badge.py
@@ -21,7 +21,7 @@ class BadgeUser(models.Model):
     badge_id = fields.Many2one('gamification.badge', string='Badge', required=True, ondelete="cascade", index=True)
     challenge_id = fields.Many2one('gamification.challenge', string='Challenge originating', help="If this badge was rewarded through a challenge")
     comment = fields.Text('Comment')
-    badge_name = fields.Char(related='badge_id.name', string="Badge Name")
+    badge_name = fields.Char(related='badge_id.name', string="Badge Name", readonly=False)
 
     def _send_badge(self):
         """Send a notification to a user for receiving a badge
diff --git a/addons/gamification/models/challenge.py b/addons/gamification/models/challenge.py
index 1c088cd2bac5..bf8e17fa4a2b 100644
--- a/addons/gamification/models/challenge.py
+++ b/addons/gamification/models/challenge.py
@@ -781,7 +781,7 @@ class ChallengeLine(models.Model):
     sequence = fields.Integer('Sequence', help='Sequence number for ordering', default=1)
     target_goal = fields.Float('Target Value to Reach', required=True)
 
-    name = fields.Char("Name", related='definition_id.name')
+    name = fields.Char("Name", related='definition_id.name', readonly=False)
     condition = fields.Selection("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)
diff --git a/addons/gamification/models/goal.py b/addons/gamification/models/goal.py
index 3f98b352bc9e..a812764e5c6a 100644
--- a/addons/gamification/models/goal.py
+++ b/addons/gamification/models/goal.py
@@ -172,7 +172,7 @@ class Goal(models.Model):
     to_update = fields.Boolean('To update')
     closed = fields.Boolean('Closed goal', help="These goals will not be recomputed.")
 
-    computation_mode = fields.Selection(related='definition_id.computation_mode')
+    computation_mode = fields.Selection(related='definition_id.computation_mode', readonly=False)
     remind_update_delay = fields.Integer(
         "Remind delay", help="The number of days after which the user "
                              "assigned to a manual goal will be reminded. "
diff --git a/addons/google_spreadsheet/models/res_config_settings.py b/addons/google_spreadsheet/models/res_config_settings.py
index ee47df724dec..71c91daae991 100644
--- a/addons/google_spreadsheet/models/res_config_settings.py
+++ b/addons/google_spreadsheet/models/res_config_settings.py
@@ -7,4 +7,4 @@ from odoo import fields, models
 class ResConfigSettings(models.TransientModel):
     _inherit = "res.config.settings"
 
-    google_drive_uri_copy = fields.Char(related='google_drive_uri', string='URI Copy', help="The URL to generate the authorization code from Google")
+    google_drive_uri_copy = fields.Char(related='google_drive_uri', string='URI Copy', help="The URL to generate the authorization code from Google", readonly=False)
diff --git a/addons/hr/models/hr.py b/addons/hr/models/hr.py
index cb53273cf6d7..e6e7d2e47d53 100644
--- a/addons/hr/models/hr.py
+++ b/addons/hr/models/hr.py
@@ -107,9 +107,9 @@ class Employee(models.Model):
 
     # resource and user
     # required on the resource, make sure required="True" set in the view
-    name = fields.Char(related='resource_id.name', store=True, oldname='name_related')
-    user_id = fields.Many2one('res.users', 'User', related='resource_id.user_id', store=True)
-    active = fields.Boolean('Active', related='resource_id.active', default=True, store=True)
+    name = fields.Char(related='resource_id.name', store=True, oldname='name_related', readonly=False)
+    user_id = fields.Many2one('res.users', 'User', related='resource_id.user_id', store=True, readonly=False)
+    active = fields.Boolean('Active', related='resource_id.active', default=True, store=True, readonly=False)
     # private partner
     address_home_id = fields.Many2one(
         'res.partner', 'Private Address', help='Enter here the private address of the employee, not the one linked to your company.',
diff --git a/addons/hr/models/res_config_settings.py b/addons/hr/models/res_config_settings.py
index d66006cc101f..4512d6e04f37 100644
--- a/addons/hr/models/res_config_settings.py
+++ b/addons/hr/models/res_config_settings.py
@@ -8,5 +8,5 @@ class ResConfigSettings(models.TransientModel):
 
     resource_calendar_id = fields.Many2one(
         'resource.calendar', 'Company Working Hours',
-        related='company_id.resource_calendar_id')
+        related='company_id.resource_calendar_id', readonly=False)
     module_hr_org_chart = fields.Boolean(string="Show Organizational Chart")
diff --git a/addons/hr_contract/models/hr_contract.py b/addons/hr_contract/models/hr_contract.py
index b0670634ee11..bb30f94856e6 100644
--- a/addons/hr_contract/models/hr_contract.py
+++ b/addons/hr_contract/models/hr_contract.py
@@ -77,9 +77,9 @@ class Contract(models.Model):
        track_visibility='onchange', help='Status of the contract', default='draft')
     company_id = fields.Many2one('res.company', default=lambda self: self.env.user.company_id)
     currency_id = fields.Many2one(string="Currency", related='company_id.currency_id', readonly=True)
-    permit_no = fields.Char('Work Permit No', related="employee_id.permit_no")
-    visa_no = fields.Char('Visa No', related="employee_id.visa_no")
-    visa_expire = fields.Date('Visa Expire Date', related="employee_id.visa_expire")
+    permit_no = fields.Char('Work Permit No', related="employee_id.permit_no", readonly=False)
+    visa_no = fields.Char('Visa No', related="employee_id.visa_no", readonly=False)
+    visa_expire = fields.Date('Visa Expire Date', related="employee_id.visa_expire", readonly=False)
     reported_to_secretariat = fields.Boolean('Social Secretariat',
         help='Green this button when the contract information has been transfered to the social secretariat.')
 
diff --git a/addons/hr_expense/models/hr_expense.py b/addons/hr_expense/models/hr_expense.py
index b4e261748078..287bb0ac8b50 100644
--- a/addons/hr_expense/models/hr_expense.py
+++ b/addons/hr_expense/models/hr_expense.py
@@ -57,7 +57,7 @@ class HrExpense(models.Model):
     total_amount_company = fields.Monetary("Total (Company Currency)", compute='_compute_total_amount_company', store=True, currency_field='company_currency_id', digits=dp.get_precision('Account'))
     company_id = fields.Many2one('res.company', string='Company', readonly=True, states={'draft': [('readonly', False)], 'refused': [('readonly', False)]}, default=lambda self: self.env.user.company_id)
     currency_id = fields.Many2one('res.currency', string='Currency', readonly=True, states={'draft': [('readonly', False)], 'refused': [('readonly', False)]}, default=lambda self: self.env.user.company_id.currency_id)
-    company_currency_id = fields.Many2one('res.currency', string="Report Company Currency", related='sheet_id.currency_id', store=True)
+    company_currency_id = fields.Many2one('res.currency', string="Report Company Currency", related='sheet_id.currency_id', store=True, readonly=False)
     analytic_account_id = fields.Many2one('account.analytic.account', string='Analytic Account', states={'post': [('readonly', True)], 'done': [('readonly', True)]}, oldname='analytic_account')
     analytic_tag_ids = fields.Many2many('account.analytic.tag', string='Analytic Tags', states={'post': [('readonly', True)], 'done': [('readonly', True)]})
     account_id = fields.Many2one('account.account', string='Account', states={'post': [('readonly', True)], 'done': [('readonly', True)]}, default=_default_account_id, help="An expense account is expected")
diff --git a/addons/hr_expense_check/models/payment.py b/addons/hr_expense_check/models/payment.py
index 857ac4a030d6..e4bd4418791b 100644
--- a/addons/hr_expense_check/models/payment.py
+++ b/addons/hr_expense_check/models/payment.py
@@ -7,7 +7,7 @@ class HrExpenseRegisterPaymentWizard(models.TransientModel):
     _inherit = "hr.expense.sheet.register.payment.wizard"
 
     check_amount_in_words = fields.Char(string="Amount in Words")
-    check_manual_sequencing = fields.Boolean(related='journal_id.check_manual_sequencing')
+    check_manual_sequencing = fields.Boolean(related='journal_id.check_manual_sequencing', readonly=False)
     # Note: a check_number == 0 means that it will be attributed when the check is printed
     check_number = fields.Integer(string="Check Number", readonly=True, copy=False, default=0,
         help="Number of the check corresponding to this payment. If your pre-printed check are not already numbered, "
diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py
index 902ba6afd28b..742986ab227c 100644
--- a/addons/hr_holidays/models/hr_leave.py
+++ b/addons/hr_holidays/models/hr_leave.py
@@ -115,7 +115,7 @@ class HolidaysRequest(models.Model):
         states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]},
         domain=[('valid', '=', True)])
     leave_type_request_unit = fields.Selection(related='holiday_status_id.request_unit', readonly=True)
-    validation_type = fields.Selection('Validation Type', related='holiday_status_id.validation_type')
+    validation_type = fields.Selection('Validation Type', related='holiday_status_id.validation_type', readonly=False)
     # HR data
     employee_id = fields.Many2one(
         'hr.employee', string='Employee', index=True, readonly=True,
diff --git a/addons/hr_recruitment/models/hr_recruitment.py b/addons/hr_recruitment/models/hr_recruitment.py
index 8c7093b5c5cc..7f146ca5d565 100644
--- a/addons/hr_recruitment/models/hr_recruitment.py
+++ b/addons/hr_recruitment/models/hr_recruitment.py
@@ -157,16 +157,16 @@ class Applicant(models.Model):
     emp_id = fields.Many2one('hr.employee', string="Employee", track_visibility="onchange", help="Employee linked to the applicant.")
     user_email = fields.Char(related='user_id.email', type="char", string="User Email", readonly=True)
     attachment_number = fields.Integer(compute='_get_attachment_number', string="Number of Attachments")
-    employee_name = fields.Char(related='emp_id.name', string="Employee Name")
+    employee_name = fields.Char(related='emp_id.name', string="Employee Name", readonly=False)
     attachment_ids = fields.One2many('ir.attachment', 'res_id', domain=[('res_model', '=', 'hr.applicant')], string='Attachments')
     kanban_state = fields.Selection([
         ('normal', 'Grey'),
         ('done', 'Green'),
         ('blocked', 'Red')], string='Kanban State',
         copy=False, default='normal', required=True)
-    legend_blocked = fields.Char(related='stage_id.legend_blocked', string='Kanban Blocked')
-    legend_done = fields.Char(related='stage_id.legend_done', string='Kanban Valid')
-    legend_normal = fields.Char(related='stage_id.legend_normal', string='Kanban Ongoing')
+    legend_blocked = fields.Char(related='stage_id.legend_blocked', string='Kanban Blocked', readonly=False)
+    legend_done = fields.Char(related='stage_id.legend_done', string='Kanban Valid', readonly=False)
+    legend_normal = fields.Char(related='stage_id.legend_normal', string='Kanban Ongoing', readonly=False)
     
 
     @api.depends('date_open', 'date_closed')
diff --git a/addons/hr_recruitment_survey/models/hr_applicant.py b/addons/hr_recruitment_survey/models/hr_applicant.py
index c83649269bba..46fb9445da0c 100644
--- a/addons/hr_recruitment_survey/models/hr_applicant.py
+++ b/addons/hr_recruitment_survey/models/hr_applicant.py
@@ -6,7 +6,7 @@ from odoo import api, fields, models
 class Applicant(models.Model):
     _inherit = "hr.applicant"
 
-    survey_id = fields.Many2one('survey.survey', related='job_id.survey_id', string="Survey")
+    survey_id = fields.Many2one('survey.survey', related='job_id.survey_id', string="Survey", readonly=False)
     response_id = fields.Many2one('survey.user_input', "Response", ondelete="set null", oldname="response")
 
     @api.multi
diff --git a/addons/hr_timesheet/models/analytic_account.py b/addons/hr_timesheet/models/analytic_account.py
index eba72e424560..8e794bf42558 100644
--- a/addons/hr_timesheet/models/analytic_account.py
+++ b/addons/hr_timesheet/models/analytic_account.py
@@ -9,7 +9,7 @@ class AccountAnalyticAccount(models.Model):
     _inherit = 'account.analytic.account'
     _description = 'Analytic Account'
 
-    company_uom_id = fields.Many2one('uom.uom', related='company_id.project_time_mode_id', string="Company UOM")
+    company_uom_id = fields.Many2one('uom.uom', related='company_id.project_time_mode_id', string="Company UOM", readonly=False)
     project_ids = fields.One2many('project.project', 'analytic_account_id', string='Projects')
     project_count = fields.Integer("Project Count", compute='_compute_project_count')
 
diff --git a/addons/hr_timesheet/models/project.py b/addons/hr_timesheet/models/project.py
index e34f395b87b1..e93a3c5deac4 100644
--- a/addons/hr_timesheet/models/project.py
+++ b/addons/hr_timesheet/models/project.py
@@ -96,7 +96,7 @@ class Task(models.Model):
     _inherit = "project.task"
 
     analytic_account_active = fields.Boolean("Analytic Account", related='project_id.analytic_account_id.active', readonly=True)
-    allow_timesheets = fields.Boolean("Allow timesheets", related='project_id.allow_timesheets', help="Timesheets can be logged on this task.")
+    allow_timesheets = fields.Boolean("Allow timesheets", related='project_id.allow_timesheets', help="Timesheets can be logged on this task.", readonly=False)
     remaining_hours = fields.Float("Remaining Hours", compute='_compute_remaining_hours', store=True, readonly=True, help="Total remaining time, can be re-estimated periodically by the assignee of the task.")
     effective_hours = fields.Float("Hours Spent", compute='_compute_effective_hours', compute_sudo=True, store=True, help="Computed using the sum of the task work done.")
     total_hours_spent = fields.Float("Total Hours", compute='_compute_total_hours_spent', store=True, help="Computed as: Time Spent + Sub-tasks Hours.")
diff --git a/addons/hr_timesheet/models/res_config_settings.py b/addons/hr_timesheet/models/res_config_settings.py
index 73d57d048fa4..3253224b00c0 100644
--- a/addons/hr_timesheet/models/res_config_settings.py
+++ b/addons/hr_timesheet/models/res_config_settings.py
@@ -10,11 +10,11 @@ class ResConfigSettings(models.TransientModel):
     module_project_timesheet_synchro = fields.Boolean("Awesome Timesheet")
     module_project_timesheet_holidays = fields.Boolean("Leaves")
     project_time_mode_id = fields.Many2one(
-        'uom.uom', related='company_id.project_time_mode_id', string='Project Time Unit',
+        'uom.uom', related='company_id.project_time_mode_id', string='Project Time Unit', readonly=False,
         help="This will set the unit of measure used in projects and tasks.\n"
              "If you use the timesheet linked to projects, don't "
              "forget to setup the right unit of measure in your employees.")
     timesheet_encode_uom_id = fields.Many2one('uom.uom', string="Encoding Unit",
-        related='company_id.timesheet_encode_uom_id',
+        related='company_id.timesheet_encode_uom_id', readonly=False,
         help="""This will set the unit of measure used to encode timesheet. This will simply provide tools
         and widgets to help the encoding. All reporting will still be expressed in hours (default value).""")
diff --git a/addons/l10n_be_hr_payroll_fleet/models/hr_contract.py b/addons/l10n_be_hr_payroll_fleet/models/hr_contract.py
index 2864a2a7f0d6..05dd20a00fec 100644
--- a/addons/l10n_be_hr_payroll_fleet/models/hr_contract.py
+++ b/addons/l10n_be_hr_payroll_fleet/models/hr_contract.py
@@ -18,11 +18,11 @@ class HrContract(models.Model):
     # YTI: Check if could be removed
     new_car_model_id = fields.Many2one('fleet.vehicle.model', string="Model", domain=lambda self: self._get_possible_model_domain())
     max_unused_cars = fields.Integer(compute='_compute_max_unused_cars')
-    acquisition_date = fields.Date(related='car_id.acquisition_date')
-    car_value = fields.Float(related="car_id.car_value")
-    fuel_type = fields.Selection(related="car_id.fuel_type")
-    co2 = fields.Float(related="car_id.co2")
-    driver_id = fields.Many2one('res.partner', related="car_id.driver_id")
+    acquisition_date = fields.Date(related='car_id.acquisition_date', readonly=False)
+    car_value = fields.Float(related="car_id.car_value", readonly=False)
+    fuel_type = fields.Selection(related="car_id.fuel_type", readonly=False)
+    co2 = fields.Float(related="car_id.co2", readonly=False)
+    driver_id = fields.Many2one('res.partner', related="car_id.driver_id", readonly=False)
     car_open_contracts_count = fields.Integer(compute='_compute_car_open_contracts_count')
     recurring_cost_amount_depreciated = fields.Float(
         compute='_compute_recurring_cost_amount_depreciated',
diff --git a/addons/l10n_be_invoice_bba/models/res_config_settings.py b/addons/l10n_be_invoice_bba/models/res_config_settings.py
index b95cac58f89e..26f62dc966dd 100644
--- a/addons/l10n_be_invoice_bba/models/res_config_settings.py
+++ b/addons/l10n_be_invoice_bba/models/res_config_settings.py
@@ -6,6 +6,6 @@ from odoo import api, fields, models
 class ResConfigSettings(models.TransientModel):
     _inherit = 'res.config.settings'
 
-    l10n_be_structured_comm = fields.Selection(related='company_id.l10n_be_structured_comm',
+    l10n_be_structured_comm = fields.Selection(related='company_id.l10n_be_structured_comm', readonly=False,
         string='Communication Algorithm', default='random',
         help='Choose an algorithm to generate the structured communication.')
diff --git a/addons/l10n_ch/models/account_invoice.py b/addons/l10n_ch/models/account_invoice.py
index 6afa172d6171..6373d00f8a73 100644
--- a/addons/l10n_ch/models/account_invoice.py
+++ b/addons/l10n_ch/models/account_invoice.py
@@ -26,7 +26,7 @@ class AccountInvoice(models.Model):
     l10n_ch_isr_valid = fields.Boolean(compute='_compute_l10n_ch_isr_valid', help='Boolean value. True iff all the data required to generate the ISR are present')
 
     l10n_ch_isr_sent = fields.Boolean(defaut=False, help="Boolean value telling whether or not the ISR corresponding to this invoice has already been printed or sent by mail.")
-    l10n_ch_currency_name = fields.Char(related='currency_id.name', string="Currency Name", help="The name of this invoice's currency") #This field is used in the "invisible" condition field of the 'Print ISR' button.
+    l10n_ch_currency_name = fields.Char(related='currency_id.name', readonly=False, string="Currency Name", help="The name of this invoice's currency") #This field is used in the "invisible" condition field of the 'Print ISR' button.
 
     @api.depends('partner_bank_id.bank_id.l10n_ch_postal_eur', 'partner_bank_id.bank_id.l10n_ch_postal_chf')
     def _compute_l10n_ch_isr_postal(self):
diff --git a/addons/l10n_ch/models/account_journal.py b/addons/l10n_ch/models/account_journal.py
index 4ad11b5d84c0..a42e163a299b 100644
--- a/addons/l10n_ch/models/account_journal.py
+++ b/addons/l10n_ch/models/account_journal.py
@@ -13,7 +13,7 @@ class AccountJournal(models.Model):
     _inherit = 'account.journal'
 
     # creation of bank journals by giving the account number, allow craetion of the
-    l10n_ch_postal = fields.Char(related='bank_account_id.l10n_ch_postal')
+    l10n_ch_postal = fields.Char(related='bank_account_id.l10n_ch_postal', readonly=False)
 
     @api.model
     def create(self, vals):
diff --git a/addons/l10n_ch/models/res_config_settings.py b/addons/l10n_ch/models/res_config_settings.py
index 31bc5fc7bede..0b972855e669 100644
--- a/addons/l10n_ch/models/res_config_settings.py
+++ b/addons/l10n_ch/models/res_config_settings.py
@@ -8,13 +8,13 @@ class ResConfigSettings(models.TransientModel):
     _inherit = 'res.config.settings'
 
     l10n_ch_isr_preprinted_account = fields.Boolean(string='Preprinted account',
-        related="company_id.l10n_ch_isr_preprinted_account")
+        related="company_id.l10n_ch_isr_preprinted_account", readonly=False)
     l10n_ch_isr_preprinted_bank = fields.Boolean(string='Preprinted bank',
-        related="company_id.l10n_ch_isr_preprinted_bank")
+        related="company_id.l10n_ch_isr_preprinted_bank", readonly=False)
     l10n_ch_isr_print_bank_location = fields.Boolean(string="Print bank on ISR",
-        related="company_id.l10n_ch_isr_print_bank_location",
+        related="company_id.l10n_ch_isr_print_bank_location", readonly=False,
         required=True)
     l10n_ch_isr_scan_line_left = fields.Float(string='Horizontal offset',
-        related="company_id.l10n_ch_isr_scan_line_left")
+        related="company_id.l10n_ch_isr_scan_line_left", readonly=False)
     l10n_ch_isr_scan_line_top = fields.Float(string='Vertical offset',
-        related="company_id.l10n_ch_isr_scan_line_top")
+        related="company_id.l10n_ch_isr_scan_line_top", readonly=False)
diff --git a/addons/l10n_fr/models/l10n_fr.py b/addons/l10n_fr/models/l10n_fr.py
index dfa228db3f53..16d7709ab118 100644
--- a/addons/l10n_fr/models/l10n_fr.py
+++ b/addons/l10n_fr/models/l10n_fr.py
@@ -7,7 +7,7 @@ from odoo import fields, models
 class ResCompany(models.Model):
     _inherit = 'res.company'
 
-    siret = fields.Char(related='partner_id.siret', string='SIRET', size=14)
+    siret = fields.Char(related='partner_id.siret', string='SIRET', size=14, readonly=False)
     ape = fields.Char(string='APE')
 
 class ResPartner(models.Model):
diff --git a/addons/l10n_fr_hr_payroll/models/res_config_settings.py b/addons/l10n_fr_hr_payroll/models/res_config_settings.py
index 1ae73b14698e..8f70e8636d9e 100644
--- a/addons/l10n_fr_hr_payroll/models/res_config_settings.py
+++ b/addons/l10n_fr_hr_payroll/models/res_config_settings.py
@@ -7,8 +7,8 @@ from odoo import fields, models
 class ResConfigSettings(models.TransientModel):
     _inherit = 'res.config.settings'
 
-    plafond_secu = fields.Float(related='company_id.plafond_secu', string="Plafond de la Securite Sociale")
-    nombre_employes = fields.Integer(related='company_id.nombre_employes', string="Nombre d'employes")
-    cotisation_prevoyance = fields.Float(related='company_id.cotisation_prevoyance', string='Cotisation Patronale Prevoyance')
-    org_ss = fields.Char(related='company_id.org_ss', string="Organisme de securite sociale")
-    conv_coll = fields.Char(related='company_id.conv_coll', string="Convention collective")
+    plafond_secu = fields.Float(related='company_id.plafond_secu', string="Plafond de la Securite Sociale", readonly=False)
+    nombre_employes = fields.Integer(related='company_id.nombre_employes', string="Nombre d'employes", readonly=False)
+    cotisation_prevoyance = fields.Float(related='company_id.cotisation_prevoyance', string='Cotisation Patronale Prevoyance', readonly=False)
+    org_ss = fields.Char(related='company_id.org_ss', string="Organisme de securite sociale", readonly=False)
+    conv_coll = fields.Char(related='company_id.conv_coll', string="Convention collective", readonly=False)
diff --git a/addons/l10n_in_hr_payroll/models/l10n_in_hr_payroll.py b/addons/l10n_in_hr_payroll/models/l10n_in_hr_payroll.py
index 8421058a60d1..25fbe7da64ac 100644
--- a/addons/l10n_in_hr_payroll/models/l10n_in_hr_payroll.py
+++ b/addons/l10n_in_hr_payroll/models/l10n_in_hr_payroll.py
@@ -168,8 +168,8 @@ class HrPayrollAdviceLine(models.Model):
     employee_id = fields.Many2one('hr.employee', string='Employee', required=True)
     bysal = fields.Float(string='By Salary', digits=dp.get_precision('Payroll'))
     debit_credit = fields.Char(string='C/D', default='C')
-    company_id = fields.Many2one('res.company', related='advice_id.company_id', string='Company', store=True)
-    ifsc = fields.Boolean(related='advice_id.neft', string='IFSC')
+    company_id = fields.Many2one('res.company', related='advice_id.company_id', string='Company', store=True, readonly=False)
+    ifsc = fields.Boolean(related='advice_id.neft', string='IFSC', readonly=False)
 
     @api.onchange('employee_id')
     def onchange_employee_id(self):
diff --git a/addons/l10n_sg/models/res_company.py b/addons/l10n_sg/models/res_company.py
index 8c560b59a121..e63b66210692 100644
--- a/addons/l10n_sg/models/res_company.py
+++ b/addons/l10n_sg/models/res_company.py
@@ -7,4 +7,4 @@ class ResCompany(models.Model):
     _description = 'Companies'
     _inherit = 'res.company'
 
-    l10n_sg_unique_entity_number = fields.Char(string='UEN', related="partner_id.l10n_sg_unique_entity_number")
+    l10n_sg_unique_entity_number = fields.Char(string='UEN', related="partner_id.l10n_sg_unique_entity_number", readonly=False)
diff --git a/addons/lunch/models/lunch.py b/addons/lunch/models/lunch.py
index 36cd7d1408c4..facc3d44809d 100644
--- a/addons/lunch/models/lunch.py
+++ b/addons/lunch/models/lunch.py
@@ -46,7 +46,7 @@ class LunchOrder(models.Model):
                              'Status', readonly=True, index=True, copy=False,
                              compute='_compute_order_state', store=True)
     alerts = fields.Text(compute='_compute_alerts_get', string="Alerts")
-    company_id = fields.Many2one('res.company', related='user_id.company_id', store=True)
+    company_id = fields.Many2one('res.company', related='user_id.company_id', store=True, readonly=False)
     currency_id = fields.Many2one('res.currency', related='company_id.currency_id', readonly=True, store=True)
     cash_move_balance = fields.Monetary(compute='_compute_cash_move_balance', multi='cash_move_balance')
     balance_visible = fields.Boolean(compute='_compute_cash_move_balance', multi='cash_move_balance')
@@ -183,7 +183,7 @@ class LunchOrderLine(models.Model):
                               ('cancelled', 'Cancelled')],
                              'Status', readonly=True, index=True, default='new')
     cashmove = fields.One2many('lunch.cashmove', 'order_id', 'Cash Move')
-    currency_id = fields.Many2one('res.currency', related='order_id.currency_id')
+    currency_id = fields.Many2one('res.currency', related='order_id.currency_id', readonly=False)
 
     def _check_supplier_availibility(self):
         products = self.mapped('product_id')
diff --git a/addons/mail/models/mail_activity.py b/addons/mail/models/mail_activity.py
index 2f72a277396e..4e41d9b69670 100644
--- a/addons/mail/models/mail_activity.py
+++ b/addons/mail/models/mail_activity.py
@@ -122,9 +122,9 @@ class MailActivity(models.Model):
     activity_type_id = fields.Many2one(
         'mail.activity.type', 'Activity',
         domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]", ondelete='restrict')
-    activity_category = fields.Selection(related='activity_type_id.category')
-    activity_decoration = fields.Selection(related='activity_type_id.decoration_type')
-    icon = fields.Char('Icon', related='activity_type_id.icon')
+    activity_category = fields.Selection(related='activity_type_id.category', readonly=False)
+    activity_decoration = fields.Selection(related='activity_type_id.decoration_type', readonly=False)
+    icon = fields.Char('Icon', related='activity_type_id.icon', readonly=False)
     summary = fields.Char('Summary')
     note = fields.Html('Note')
     feedback = fields.Html('Feedback')
@@ -152,8 +152,8 @@ class MailActivity(models.Model):
         'Next activities available',
         compute='_compute_has_recommended_activities',
         help='Technical field for UX purpose')
-    mail_template_ids = fields.Many2many(related='activity_type_id.mail_template_ids')
-    force_next = fields.Boolean(related='activity_type_id.force_next')
+    mail_template_ids = fields.Many2many(related='activity_type_id.mail_template_ids', readonly=False)
+    force_next = fields.Boolean(related='activity_type_id.force_next', readonly=False)
 
     @api.multi
     @api.onchange('previous_activity_type_id')
@@ -502,12 +502,12 @@ class MailActivityMixin(models.AbstractModel):
              'Today: Activity date is today\nPlanned: Future activities.')
     activity_user_id = fields.Many2one(
         'res.users', 'Responsible User',
-        related='activity_ids.user_id',
+        related='activity_ids.user_id', readonly=False,
         search='_search_activity_user_id',
         groups="base.group_user")
     activity_type_id = fields.Many2one(
         'mail.activity.type', 'Next Activity Type',
-        related='activity_ids.activity_type_id',
+        related='activity_ids.activity_type_id', readonly=False,
         search='_search_activity_type_id',
         groups="base.group_user")
     activity_date_deadline = fields.Date(
@@ -517,7 +517,7 @@ class MailActivityMixin(models.AbstractModel):
         groups="base.group_user")
     activity_summary = fields.Char(
         'Next Activity Summary',
-        related='activity_ids.summary',
+        related='activity_ids.summary', readonly=False,
         search='_search_activity_summary',
         groups="base.group_user",)
 
diff --git a/addons/mail/models/mail_channel.py b/addons/mail/models/mail_channel.py
index d1c3c3f6fa6d..d2a375f4fc9c 100644
--- a/addons/mail/models/mail_channel.py
+++ b/addons/mail/models/mail_channel.py
@@ -27,7 +27,7 @@ class ChannelPartner(models.Model):
     _primary_email = ['partner_email']
 
     partner_id = fields.Many2one('res.partner', string='Recipient', ondelete='cascade')
-    partner_email = fields.Char('Email', related='partner_id.email')
+    partner_email = fields.Char('Email', related='partner_id.email', readonly=False)
     channel_id = fields.Many2one('mail.channel', string='Channel', ondelete='cascade')
     seen_message_id = fields.Many2one('mail.message', string='Last Seen')
     fold_state = fields.Selection([('open', 'Open'), ('folded', 'Folded'), ('closed', 'Closed')], string='Conversation Fold State', default='open')
diff --git a/addons/mail/models/mail_message.py b/addons/mail/models/mail_message.py
index fa298bf3c5a4..39ed66416876 100644
--- a/addons/mail/models/mail_message.py
+++ b/addons/mail/models/mail_message.py
@@ -76,7 +76,7 @@ class Message(models.Model):
         'res.partner', 'Author', index=True,
         ondelete='set null', default=_get_default_author,
         help="Author of the message. If not set, email_from may hold an email address that did not match any partner.")
-    author_avatar = fields.Binary("Author's avatar", related='author_id.image_small')
+    author_avatar = fields.Binary("Author's avatar", related='author_id.image_small', readonly=False)
     # recipients: include inactive partners (they may have been archived after
     # the message was sent, but they should remain visible in the relation)
     partner_ids = fields.Many2many('res.partner', string='Recipients',
diff --git a/addons/mail/models/res_users.py b/addons/mail/models/res_users.py
index 18da52a96fcc..495b9ae87221 100644
--- a/addons/mail/models/res_users.py
+++ b/addons/mail/models/res_users.py
@@ -24,7 +24,7 @@ class Users(models.Model):
     alias_contact = fields.Selection([
         ('everyone', 'Everyone'),
         ('partners', 'Authenticated Partners'),
-        ('followers', 'Followers only')], string='Alias Contact Security', related='alias_id.alias_contact')
+        ('followers', 'Followers only')], 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/mail/wizard/mail_resend_message.py b/addons/mail/wizard/mail_resend_message.py
index 4a76e40be97a..c8ea6bb73c3d 100644
--- a/addons/mail/wizard/mail_resend_message.py
+++ b/addons/mail/wizard/mail_resend_message.py
@@ -101,8 +101,8 @@ class PartnerResend(models.TransientModel):
     _description = 'Partner with additionnal information for mail resend'
 
     partner_id = fields.Many2one('res.partner', string='Partner', required=True, ondelete='cascade')
-    name = fields.Char(related="partner_id.name", related_sudo=False)
-    email = fields.Char(related="partner_id.email", related_sudo=False)
+    name = fields.Char(related="partner_id.name", related_sudo=False, readonly=False)
+    email = fields.Char(related="partner_id.email", related_sudo=False, readonly=False)
     resend = fields.Boolean(string="Send Again", default=True)
     resend_wizard_id = fields.Many2one('mail.resend.message', string="Resend wizard")
     message = fields.Char(string="Help message")
diff --git a/addons/mass_mailing/models/mass_mailing.py b/addons/mass_mailing/models/mass_mailing.py
index 2005575b2167..c26a9bab5a70 100644
--- a/addons/mass_mailing/models/mass_mailing.py
+++ b/addons/mass_mailing/models/mass_mailing.py
@@ -54,9 +54,9 @@ class MassMailingContactListRel(models.Model):
     opt_out = fields.Boolean(string='Opt Out',
                              help='The contact has chosen not to receive mails anymore from this list', default=False)
     unsubscription_date = fields.Datetime(string='Unsubscription Date')
-    contact_count = fields.Integer(related='list_id.contact_nbr', store=False)
-    message_bounce = fields.Integer(related='contact_id.message_bounce', store=False)
-    is_blacklisted = fields.Boolean(related='contact_id.is_blacklisted', store=False)
+    contact_count = fields.Integer(related='list_id.contact_nbr', store=False, readonly=False)
+    message_bounce = fields.Integer(related='contact_id.message_bounce', store=False, readonly=False)
+    is_blacklisted = fields.Boolean(related='contact_id.is_blacklisted', store=False, readonly=False)
 
     _sql_constraints = [
         ('unique_contact_list', 'unique (contact_id, list_id)',
diff --git a/addons/mrp/models/mrp_bom.py b/addons/mrp/models/mrp_bom.py
index a3cb538229d4..fcab8f82015f 100644
--- a/addons/mrp/models/mrp_bom.py
+++ b/addons/mrp/models/mrp_bom.py
@@ -213,7 +213,7 @@ class MrpBomLine(models.Model):
 
     product_id = fields.Many2one(
         'product.product', 'Component', required=True)
-    product_tmpl_id = fields.Many2one('product.template', 'Product Template', related='product_id.product_tmpl_id')
+    product_tmpl_id = fields.Many2one('product.template', 'Product Template', related='product_id.product_tmpl_id', readonly=False)
     product_qty = fields.Float(
         'Quantity', default=1.0,
         digits=dp.get_precision('Product Unit of Measure'), required=True)
@@ -227,7 +227,7 @@ class MrpBomLine(models.Model):
         help="Gives the sequence order when displaying.")
     routing_id = fields.Many2one(
         'mrp.routing', 'Routing',
-        related='bom_id.routing_id', store=True,
+        related='bom_id.routing_id', store=True, readonly=False,
         help="The list of operations to produce the finished product. The routing is mainly used to "
              "compute work center costs during operations and to plan future loads on work centers "
              "based on production planning.")
diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py
index c3c8465e01f7..2896c4cef491 100644
--- a/addons/mrp/models/mrp_production.py
+++ b/addons/mrp/models/mrp_production.py
@@ -52,7 +52,7 @@ class MrpProduction(models.Model):
         domain=[('type', 'in', ['product', 'consu'])],
         readonly=True, required=True,
         states={'confirmed': [('readonly', False)]})
-    product_tmpl_id = fields.Many2one('product.template', 'Product Template', related='product_id.product_tmpl_id')
+    product_tmpl_id = fields.Many2one('product.template', 'Product Template', related='product_id.product_tmpl_id', readonly=False)
     product_qty = fields.Float(
         'Quantity To Produce',
         default=1.0, digits=dp.get_precision('Product Unit of Measure'),
@@ -163,7 +163,7 @@ class MrpProduction(models.Model):
                                 readonly=True, states={'confirmed': [('readonly', False)]}, default='1')
     is_locked = fields.Boolean('Is Locked', default=True, copy=False)
     show_final_lots = fields.Boolean('Show Final Lots', compute='_compute_show_lots')
-    production_location_id = fields.Many2one('stock.location', "Production Location", related='product_id.property_stock_production')
+    production_location_id = fields.Many2one('stock.location', "Production Location", related='product_id.property_stock_production', readonly=False)
     picking_ids = fields.Many2many('stock.picking', compute='_compute_picking_ids', string='Picking associated to this manufacturing order')
     delivery_count = fields.Integer(string='Delivery Orders', compute='_compute_picking_ids')
 
diff --git a/addons/mrp/models/mrp_workcenter.py b/addons/mrp/models/mrp_workcenter.py
index 2d9aa26b7fd4..be92616c5090 100644
--- a/addons/mrp/models/mrp_workcenter.py
+++ b/addons/mrp/models/mrp_workcenter.py
@@ -14,9 +14,9 @@ class MrpWorkcenter(models.Model):
     _inherit = ['resource.mixin']
 
     # resource
-    name = fields.Char('Work Center', related='resource_id.name', store=True)
-    time_efficiency = fields.Float('Time Efficiency', related='resource_id.time_efficiency', default=100, store=True)
-    active = fields.Boolean('Active', related='resource_id.active', default=True, store=True)
+    name = fields.Char('Work Center', related='resource_id.name', store=True, readonly=False)
+    time_efficiency = fields.Float('Time Efficiency', related='resource_id.time_efficiency', default=100, store=True, readonly=False)
+    active = fields.Boolean('Active', related='resource_id.active', default=True, store=True, readonly=False)
 
     code = fields.Char('Code', copy=False)
     note = fields.Text(
@@ -205,7 +205,7 @@ class MrpWorkcenterProductivityLoss(models.Model):
     sequence = fields.Integer('Sequence', default=1)
     manual = fields.Boolean('Is a Blocking Reason', default=True)
     loss_id = fields.Many2one('mrp.workcenter.productivity.loss.type', domain=([('loss_type', 'in', ['quality', 'availability'])]), string='Category')
-    loss_type = fields.Selection(string='Effectiveness Category', related='loss_id.loss_type', store=True)
+    loss_type = fields.Selection(string='Effectiveness Category', related='loss_id.loss_type', store=True, readonly=False)
 
 
 class MrpWorkcenterProductivity(models.Model):
@@ -224,7 +224,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)
+        "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 ed55bf176c96..b12d0eb6e0aa 100644
--- a/addons/mrp/models/mrp_workorder.py
+++ b/addons/mrp/models/mrp_workorder.py
@@ -23,7 +23,7 @@ class MrpWorkorder(models.Model):
         'mrp.workcenter', 'Work Center', required=True,
         states={'done': [('readonly', True)], 'cancel': [('readonly', True)]})
     working_state = fields.Selection(
-        'Workcenter Status', related='workcenter_id.working_state',
+        'Workcenter Status', related='workcenter_id.working_state', readonly=False,
         help='Technical: used in views only')
 
     production_id = fields.Many2one(
@@ -47,7 +47,7 @@ class MrpWorkorder(models.Model):
         related='production_id.state',
         help='Technical: used in views only.')
     product_tracking = fields.Selection(
-        'Product Tracking', related='production_id.product_id.tracking',
+        'Product Tracking', related='production_id.product_id.tracking', readonly=False,
         help='Technical: used in views only.')
     qty_production = fields.Float('Original Production Quantity', readonly=True, related='production_id.product_qty')
     qty_remaining = fields.Float('Quantity To Be Produced', compute='_compute_qty_remaining', digits=dp.get_precision('Product Unit of Measure'))
@@ -124,7 +124,7 @@ class MrpWorkorder(models.Model):
     next_work_order_id = fields.Many2one('mrp.workorder', "Next Work Order")
     scrap_ids = fields.One2many('stock.scrap', 'workorder_id')
     scrap_count = fields.Integer(compute='_compute_scrap_move_count', string='Scrap Move')
-    production_date = fields.Datetime('Production Date', related='production_id.date_planned_start', store=True)
+    production_date = fields.Datetime('Production Date', related='production_id.date_planned_start', store=True, readonly=False)
     color = fields.Integer('Color', compute='_compute_color')
     capacity = fields.Float(
         'Capacity', default=1.0,
diff --git a/addons/mrp/models/res_config_settings.py b/addons/mrp/models/res_config_settings.py
index 5445a0b3fa3f..5e47515b1f3a 100644
--- a/addons/mrp/models/res_config_settings.py
+++ b/addons/mrp/models/res_config_settings.py
@@ -7,7 +7,7 @@ from odoo import api, fields, models
 class ResConfigSettings(models.TransientModel):
     _inherit = 'res.config.settings'
 
-    manufacturing_lead = fields.Float(related='company_id.manufacturing_lead', string="Manufacturing Lead Time")
+    manufacturing_lead = fields.Float(related='company_id.manufacturing_lead', string="Manufacturing Lead Time", readonly=False)
     use_manufacturing_lead = fields.Boolean(string="Default Manufacturing Lead Time", config_parameter='mrp.use_manufacturing_lead', oldname='default_use_manufacturing_lead')
     module_mrp_byproduct = fields.Boolean("By-Products")
     module_mrp_mps = fields.Boolean("Master Production Schedule")
diff --git a/addons/mrp/models/stock_move.py b/addons/mrp/models/stock_move.py
index b76a77ccc440..83444b708a7e 100644
--- a/addons/mrp/models/stock_move.py
+++ b/addons/mrp/models/stock_move.py
@@ -17,7 +17,7 @@ class StockMoveLine(models.Model):
         'Quantity Finished Product', digits=dp.get_precision('Product Unit of Measure'),
         help="Informative, not used in matching")
     done_wo = fields.Boolean('Done for Work Order', default=True, help="Technical Field which is False when temporarily filled in in work order")  # TDE FIXME: naming
-    done_move = fields.Boolean('Move Done', related='move_id.is_done', store=True)  # TDE FIXME: naming
+    done_move = fields.Boolean('Move Done', related='move_id.is_done', readonly=False, store=True)  # TDE FIXME: naming
 
     def _get_similar_move_lines(self):
         lines = super(StockMoveLine, self)._get_similar_move_lines()
diff --git a/addons/mrp/wizard/mrp_product_produce.py b/addons/mrp/wizard/mrp_product_produce.py
index 6cd21a094f50..aaea368454ed 100644
--- a/addons/mrp/wizard/mrp_product_produce.py
+++ b/addons/mrp/wizard/mrp_product_produce.py
@@ -46,7 +46,7 @@ class MrpProductProduce(models.TransientModel):
     product_uom_id = fields.Many2one('uom.uom', 'Unit of Measure')
     lot_id = fields.Many2one('stock.production.lot', string='Lot/Serial Number')
     produce_line_ids = fields.One2many('mrp.product.produce.line', 'product_produce_id', string='Product to Track')
-    product_tracking = fields.Selection(related="product_id.tracking")
+    product_tracking = fields.Selection(related="product_id.tracking", readonly=False)
 
     @api.multi
     def do_produce(self):
@@ -172,7 +172,7 @@ class MrpProductProduceLine(models.TransientModel):
 
     product_produce_id = fields.Many2one('mrp.product.produce')
     product_id = fields.Many2one('product.product', 'Product')
-    product_tracking = fields.Selection(related="product_id.tracking")
+    product_tracking = fields.Selection(related="product_id.tracking", readonly=False)
     lot_id = fields.Many2one('stock.production.lot', 'Lot/Serial Number')
     qty_to_consume = fields.Float('To Consume', digits=dp.get_precision('Product Unit of Measure'))
     product_uom_id = fields.Many2one('uom.uom', 'Unit of Measure')
diff --git a/addons/pad/models/res_config_settings.py b/addons/pad/models/res_config_settings.py
index 939bb10e9345..a89abe3601da 100644
--- a/addons/pad/models/res_config_settings.py
+++ b/addons/pad/models/res_config_settings.py
@@ -7,5 +7,5 @@ from odoo import fields, models
 class ResConfigSettings(models.TransientModel):
     _inherit = 'res.config.settings'
 
-    pad_server = fields.Char(related='company_id.pad_server', string="Pad Server *")
-    pad_key = fields.Char(related='company_id.pad_key', string="Pad Api Key *")
+    pad_server = fields.Char(related='company_id.pad_server', string="Pad Server *", readonly=False)
+    pad_key = fields.Char(related='company_id.pad_key', string="Pad Api Key *", readonly=False)
diff --git a/addons/payment/models/payment_acquirer.py b/addons/payment/models/payment_acquirer.py
index 0016e41ed626..93efd9212aaa 100644
--- a/addons/payment/models/payment_acquirer.py
+++ b/addons/payment/models/payment_acquirer.py
@@ -147,7 +147,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')
+    module_state = fields.Selection(selection=ir_module.STATES, string='Installation State', related='module_id.state', readonly=False)
 
     image = fields.Binary(
         "Image", attachment=True,
@@ -168,7 +168,7 @@ class PaymentAcquirer(models.Model):
         ('s2s','Payment from Odoo')],
         default='form', required=True, string='Payment Flow',
         help="""Note: Subscriptions does not take this field in account, it uses server to server by default.""")
-    inbound_payment_method_ids = fields.Many2many('account.payment.method', related='journal_id.inbound_payment_method_ids')
+    inbound_payment_method_ids = fields.Many2many('account.payment.method', related='journal_id.inbound_payment_method_ids', readonly=False)
 
     @api.onchange('payment_flow')
     def _onchange_payment_flow(self):
diff --git a/addons/payment_authorize/models/payment.py b/addons/payment_authorize/models/payment.py
index 2cb98f74b24d..c1380db1fd6d 100644
--- a/addons/payment_authorize/models/payment.py
+++ b/addons/payment_authorize/models/payment.py
@@ -343,8 +343,8 @@ class PaymentToken(models.Model):
 
     authorize_profile = fields.Char(string='Authorize.net Profile ID', help='This contains the unique reference '
                                     'for this partner/payment token combination in the Authorize.net backend')
-    provider = fields.Selection(string='Provider', related='acquirer_id.provider')
-    save_token = fields.Selection(string='Save Cards', related='acquirer_id.save_token')
+    provider = fields.Selection(string='Provider', related='acquirer_id.provider', readonly=False)
+    save_token = fields.Selection(string='Save Cards', related='acquirer_id.save_token', readonly=False)
 
     @api.model
     def authorize_create(self, values):
diff --git a/addons/point_of_sale/models/pos_config.py b/addons/point_of_sale/models/pos_config.py
index 8e3156c1bf63..8411e864faa0 100644
--- a/addons/point_of_sale/models/pos_config.py
+++ b/addons/point_of_sale/models/pos_config.py
@@ -71,7 +71,7 @@ class PosConfig(models.Model):
         'pos_config_id', 'journal_id', string='Available Payment Methods',
         domain="[('journal_user', '=', True ), ('type', 'in', ['bank', 'cash'])]",)
     picking_type_id = fields.Many2one('stock.picking.type', string='Operation Type')
-    use_existing_lots = fields.Boolean(related='picking_type_id.use_existing_lots')
+    use_existing_lots = fields.Boolean(related='picking_type_id.use_existing_lots', readonly=False)
     stock_location_id = fields.Many2one(
         'stock.location', string='Stock Location',
         domain=[('usage', '=', 'internal')], required=True, default=_get_default_location)
diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py
index e7c7cb70b1ad..fc52d816c494 100644
--- a/addons/point_of_sale/models/pos_order.py
+++ b/addons/point_of_sale/models/pos_order.py
@@ -504,8 +504,8 @@ class PosOrder(models.Model):
         'pos.session', string='Session', required=True, index=True,
         domain="[('state', '=', 'opened')]", states={'draft': [('readonly', False)]},
         readonly=True, default=_default_session)
-    config_id = fields.Many2one('pos.config', related='session_id.config_id', string="Point of Sale")
-    invoice_group = fields.Boolean(related="config_id.module_account")
+    config_id = fields.Many2one('pos.config', related='session_id.config_id', string="Point of Sale", readonly=False)
+    invoice_group = fields.Boolean(related="config_id.module_account", readonly=False)
     state = fields.Selection(
         [('draft', 'New'), ('cancel', 'Cancelled'), ('paid', 'Paid'), ('done', 'Posted'), ('invoiced', 'Invoiced')],
         'Status', readonly=True, copy=False, default='draft')
@@ -513,7 +513,7 @@ class PosOrder(models.Model):
     invoice_id = fields.Many2one('account.invoice', string='Invoice', copy=False)
     account_move = fields.Many2one('account.move', string='Journal Entry', readonly=True, copy=False)
     picking_id = fields.Many2one('stock.picking', string='Picking', readonly=True, copy=False)
-    picking_type_id = fields.Many2one('stock.picking.type', related='session_id.config_id.picking_type_id', string="Operation Type")
+    picking_type_id = fields.Many2one('stock.picking.type', related='session_id.config_id.picking_type_id', string="Operation Type", readonly=False)
     location_id = fields.Many2one(
         comodel_name='stock.location',
         related='session_id.config_id.stock_location_id',
@@ -1056,9 +1056,9 @@ class PosOrderLineLot(models.Model):
     _description = "Specify product lot/serial number in pos order line"
 
     pos_order_line_id = fields.Many2one('pos.order.line')
-    order_id = fields.Many2one('pos.order', related="pos_order_line_id.order_id")
+    order_id = fields.Many2one('pos.order', related="pos_order_line_id.order_id", readonly=False)
     lot_name = fields.Char('Lot Name')
-    product_id = fields.Many2one('product.product', related='pos_order_line_id.product_id')
+    product_id = fields.Many2one('product.product', related='pos_order_line_id.product_id', readonly=False)
 
 
 class ReportSaleDetails(models.AbstractModel):
diff --git a/addons/point_of_sale/models/pos_session.py b/addons/point_of_sale/models/pos_session.py
index 8b6ee9aef2e9..aabcb4307d48 100644
--- a/addons/point_of_sale/models/pos_session.py
+++ b/addons/point_of_sale/models/pos_session.py
@@ -55,7 +55,7 @@ class PosSession(models.Model):
         readonly=True,
         states={'opening_control': [('readonly', False)]},
         default=lambda self: self.env.uid)
-    currency_id = fields.Many2one('res.currency', related='config_id.currency_id', string="Currency")
+    currency_id = fields.Many2one('res.currency', related='config_id.currency_id', string="Currency", readonly=False)
     start_at = fields.Datetime(string='Opening Date', readonly=True)
     stop_at = fields.Datetime(string='Closing Date', readonly=True, copy=False)
 
diff --git a/addons/point_of_sale/models/product.py b/addons/point_of_sale/models/product.py
index 57e5bf664902..b5cd2b2bbf51 100644
--- a/addons/point_of_sale/models/product.py
+++ b/addons/point_of_sale/models/product.py
@@ -49,4 +49,4 @@ class UomCateg(models.Model):
 class Uom(models.Model):
     _inherit = 'uom.uom'
 
-    is_pos_groupable = fields.Boolean(related='category_id.is_pos_groupable')
+    is_pos_groupable = fields.Boolean(related='category_id.is_pos_groupable', readonly=False)
diff --git a/addons/point_of_sale/models/res_config_settings.py b/addons/point_of_sale/models/res_config_settings.py
index 14acf115ba88..cda8fe38f764 100644
--- a/addons/point_of_sale/models/res_config_settings.py
+++ b/addons/point_of_sale/models/res_config_settings.py
@@ -6,7 +6,7 @@ from odoo import api, fields, models
 class ResConfigSettings(models.TransientModel):
     _inherit = 'res.config.settings'
 
-    sale_tax_id = fields.Many2one('account.tax', string="Default Sale Tax", related='company_id.account_sale_tax_id')
+    sale_tax_id = fields.Many2one('account.tax', string="Default Sale Tax", related='company_id.account_sale_tax_id', readonly=False)
     module_pos_mercury = fields.Boolean(string="Integrated Card Payments", help="The transactions are processed by Vantiv. Set your Vantiv credentials on the related payment journal.")
     pos_sales_price = fields.Boolean("Multiple Product Prices", config_parameter='point_of_sale.pos_sales_price')
     pos_pricelist_setting = fields.Selection([
diff --git a/addons/product/models/product.py b/addons/product/models/product.py
index 0bad75eec379..0649bc10ced8 100644
--- a/addons/product/models/product.py
+++ b/addons/product/models/product.py
@@ -626,7 +626,7 @@ class SupplierInfo(models.Model):
         'Sequence', default=1, help="Assigns the priority to the list of product vendor.")
     product_uom = fields.Many2one(
         'uom.uom', 'Unit of Measure',
-        readonly="1", related='product_tmpl_id.uom_po_id',
+        related='product_tmpl_id.uom_po_id',
         help="This comes from the product form.")
     min_qty = fields.Float(
         'Minimal Quantity', default=0.0, required=True,
@@ -649,7 +649,7 @@ class SupplierInfo(models.Model):
     product_tmpl_id = fields.Many2one(
         'product.template', 'Product Template',
         index=True, ondelete='cascade', oldname='product_id')
-    product_variant_count = fields.Integer('Variant Count', related='product_tmpl_id.product_variant_count')
+    product_variant_count = fields.Integer('Variant Count', related='product_tmpl_id.product_variant_count', readonly=False)
     delay = fields.Integer(
         'Delivery Lead Time', default=1, required=True,
         help="Lead time in days between the confirmation of the purchase order and the receipt of the products in your warehouse. Used by the scheduler for automatic computation of the purchase order planning.")
diff --git a/addons/product/models/product_template.py b/addons/product/models/product_template.py
index 636331219a6d..5dfcec1b0636 100644
--- a/addons/product/models/product_template.py
+++ b/addons/product/models/product_template.py
@@ -69,7 +69,7 @@ class ProductTemplate(models.Model):
         digits=dp.get_precision('Product Price'),
         help="Price at which the product is sold to customers.")
     lst_price = fields.Float(
-        'Public Price', related='list_price',
+        'Public Price', related='list_price', readonly=False,
         digits=dp.get_precision('Product Price'))
     standard_price = fields.Float(
         'Cost', compute='_compute_standard_price',
@@ -123,7 +123,7 @@ class ProductTemplate(models.Model):
         '# Product Variants', compute='_compute_product_variant_count')
 
     # related to display product product information if is_product_variant
-    barcode = fields.Char('Barcode', oldname='ean13', related='product_variant_ids.barcode')
+    barcode = fields.Char('Barcode', oldname='ean13', related='product_variant_ids.barcode', readonly=False)
     default_code = fields.Char(
         'Internal Reference', compute='_compute_default_code',
         inverse='_set_default_code', store=True)
diff --git a/addons/product_expiry/models/stock_quant.py b/addons/product_expiry/models/stock_quant.py
index 4dd0945aeefd..af036fcdc3cc 100644
--- a/addons/product_expiry/models/stock_quant.py
+++ b/addons/product_expiry/models/stock_quant.py
@@ -7,7 +7,7 @@ from odoo import api, fields, models
 class StockQuant(models.Model):
     _inherit = 'stock.quant'
 
-    removal_date = fields.Datetime(related='lot_id.removal_date', store=True)
+    removal_date = fields.Datetime(related='lot_id.removal_date', store=True, readonly=False)
 
     @api.model
     def _get_removal_strategy_order(self, removal_strategy):
diff --git a/addons/project_timesheet_holidays/models/res_config_settings.py b/addons/project_timesheet_holidays/models/res_config_settings.py
index 6e264971e769..60b56b39bae9 100644
--- a/addons/project_timesheet_holidays/models/res_config_settings.py
+++ b/addons/project_timesheet_holidays/models/res_config_settings.py
@@ -7,5 +7,5 @@ from odoo import fields, models
 class ResConfigSettings(models.TransientModel):
     _inherit = 'res.config.settings'
 
-    leave_timesheet_project_id = fields.Many2one(related='company_id.leave_timesheet_project_id', string="Internal Project")
-    leave_timesheet_task_id = fields.Many2one(related='company_id.leave_timesheet_task_id', string="Leave Task")
+    leave_timesheet_project_id = fields.Many2one(related='company_id.leave_timesheet_project_id', string="Internal Project", readonly=False)
+    leave_timesheet_task_id = fields.Many2one(related='company_id.leave_timesheet_task_id', string="Leave Task", readonly=False)
diff --git a/addons/purchase/models/purchase.py b/addons/purchase/models/purchase.py
index 90ac6e930f12..9b13a39b6e37 100644
--- a/addons/purchase/models/purchase.py
+++ b/addons/purchase/models/purchase.py
@@ -121,7 +121,7 @@ class PurchaseOrder(models.Model):
     payment_term_id = fields.Many2one('account.payment.term', 'Payment Terms')
     incoterm_id = fields.Many2one('account.incoterms', 'Incoterm', states={'done': [('readonly', True)]}, help="International Commercial Terms are a series of predefined commercial terms used in international transactions.")
 
-    product_id = fields.Many2one('product.product', related='order_line.product_id', string='Product')
+    product_id = fields.Many2one('product.product', related='order_line.product_id', string='Product', readonly=False)
     user_id = fields.Many2one('res.users', string='Purchase Representative', index=True, track_visibility='onchange', default=lambda self: self.env.user)
     company_id = fields.Many2one('res.company', 'Company', required=True, index=True, states=READONLY_STATES, default=lambda self: self.env.user.company_id.id)
 
@@ -408,7 +408,7 @@ class PurchaseOrderLine(models.Model):
     product_uom = fields.Many2one('uom.uom', string='Product Unit of Measure', required=True)
     product_id = fields.Many2one('product.product', string='Product', domain=[('purchase_ok', '=', True)], change_default=True, required=True)
     product_image = fields.Binary(
-        'Product Image', related="product_id.image",
+        'Product Image', related="product_id.image", readonly=False,
         help="Non-stored related field to allow portal user to see the image of the product he has ordered")
     product_type = fields.Selection(related='product_id.type', readonly=True)
     price_unit = fields.Float(string='Unit Price', required=True, digits=dp.get_precision('Product Price'))
@@ -421,7 +421,7 @@ class PurchaseOrderLine(models.Model):
     account_analytic_id = fields.Many2one('account.analytic.account', string='Analytic Account')
     analytic_tag_ids = fields.Many2many('account.analytic.tag', string='Analytic Tags')
     company_id = fields.Many2one('res.company', related='order_id.company_id', string='Company', store=True, readonly=True)
-    state = fields.Selection(related='order_id.state', store=True)
+    state = fields.Selection(related='order_id.state', store=True, readonly=False)
 
     invoice_lines = fields.One2many('account.invoice.line', 'purchase_line_id', string="Bill Lines", readonly=True, copy=False)
 
diff --git a/addons/purchase/models/res_config_settings.py b/addons/purchase/models/res_config_settings.py
index 47b183d144ff..c7ef268c9594 100644
--- a/addons/purchase/models/res_config_settings.py
+++ b/addons/purchase/models/res_config_settings.py
@@ -8,10 +8,10 @@ class ResConfigSettings(models.TransientModel):
     _inherit = 'res.config.settings'
 
     lock_confirmed_po = fields.Boolean("Lock Confirmed Orders", default=lambda self: self.env.user.company_id.po_lock == 'lock')
-    po_lock = fields.Selection(related='company_id.po_lock', string="Purchase Order Modification *")
+    po_lock = fields.Selection(related='company_id.po_lock', string="Purchase Order Modification *", readonly=False)
     po_order_approval = fields.Boolean("Purchase Order Approval", default=lambda self: self.env.user.company_id.po_double_validation == 'two_step')
-    po_double_validation = fields.Selection(related='company_id.po_double_validation', string="Levels of Approvals *")
-    po_double_validation_amount = fields.Monetary(related='company_id.po_double_validation_amount', string="Minimum Amount", currency_field='company_currency_id')
+    po_double_validation = fields.Selection(related='company_id.po_double_validation', string="Levels of Approvals *", readonly=False)
+    po_double_validation_amount = fields.Monetary(related='company_id.po_double_validation_amount', string="Minimum Amount", currency_field='company_currency_id', readonly=False)
     company_currency_id = fields.Many2one('res.currency', related='company_id.currency_id', string="Company Currency", readonly=True,
         help='Utility field to express amount currency')
     default_purchase_method = fields.Selection([
@@ -25,7 +25,7 @@ class ResConfigSettings(models.TransientModel):
         implied_group="purchase.group_manage_vendor_price")
     module_account_3way_match = fields.Boolean("3-way matching: purchases, receptions and bills")
     module_purchase_requisition = fields.Boolean("Purchase Agreements")
-    po_lead = fields.Float(related='company_id.po_lead')
+    po_lead = fields.Float(related='company_id.po_lead', readonly=False)
     use_po_lead = fields.Boolean(
         string="Security Lead Time for Purchase",
         oldname='default_new_po_lead',
diff --git a/addons/purchase_requisition/models/purchase_requisition.py b/addons/purchase_requisition/models/purchase_requisition.py
index 0c4ac448e487..80d122b66826 100644
--- a/addons/purchase_requisition/models/purchase_requisition.py
+++ b/addons/purchase_requisition/models/purchase_requisition.py
@@ -184,7 +184,7 @@ class SupplierInfo(models.Model):
     _inherit = "product.supplierinfo"
     _order = 'sequence, purchase_requisition_id desc, min_qty desc, price'
 
-    purchase_requisition_id = fields.Many2one('purchase.requisition', related='purchase_requisition_line_id.requisition_id', string='Blanket order')
+    purchase_requisition_id = fields.Many2one('purchase.requisition', related='purchase_requisition_line_id.requisition_id', string='Blanket order', readonly=False)
     purchase_requisition_line_id = fields.Many2one('purchase.requisition.line')
 
 
@@ -296,7 +296,7 @@ class PurchaseOrder(models.Model):
     _inherit = "purchase.order"
 
     requisition_id = fields.Many2one('purchase.requisition', string='Purchase Agreement', copy=False)
-    is_quantity_copy = fields.Selection(related='requisition_id.is_quantity_copy')
+    is_quantity_copy = fields.Selection(related='requisition_id.is_quantity_copy', readonly=False)
 
     @api.onchange('requisition_id')
     def _onchange_requisition_id(self):
diff --git a/addons/rating/models/rating.py b/addons/rating/models/rating.py
index 3aea681b0fbb..d0cda7f1bda3 100644
--- a/addons/rating/models/rating.py
+++ b/addons/rating/models/rating.py
@@ -38,7 +38,7 @@ class Rating(models.Model):
     res_id = fields.Integer(string='Document', required=True, help="Identifier of the rated object", index=True)
     parent_res_name = fields.Char('Parent Document Name', compute='_compute_parent_res_name', store=True)
     parent_res_model_id = fields.Many2one('ir.model', 'Parent Related Document Model', index=True, ondelete='cascade')
-    parent_res_model = fields.Char('Parent Document Model', store=True, related='parent_res_model_id.model', index=True)
+    parent_res_model = fields.Char('Parent Document Model', store=True, related='parent_res_model_id.model', index=True, readonly=False)
     parent_res_id = fields.Integer('Parent Document', index=True)
     rated_partner_id = fields.Many2one('res.partner', string="Rated person", help="Owner of the rated resource")
     partner_id = fields.Many2one('res.partner', string='Customer', help="Author of the rating")
@@ -139,8 +139,8 @@ class RatingMixin(models.AbstractModel):
 
     rating_ids = fields.One2many('rating.rating', 'res_id', string='Rating', domain=lambda self: [('res_model', '=', self._name)], auto_join=True)
     rating_last_value = fields.Float('Rating Last Value', compute='_compute_rating_last_value', compute_sudo=True, store=True)
-    rating_last_feedback = fields.Text('Rating Last Feedback', related='rating_ids.feedback')
-    rating_last_image = fields.Binary('Rating Last Image', related='rating_ids.rating_image')
+    rating_last_feedback = fields.Text('Rating Last Feedback', related='rating_ids.feedback', readonly=False)
+    rating_last_image = fields.Binary('Rating Last Image', related='rating_ids.rating_image', readonly=False)
     rating_count = fields.Integer('Rating count', compute="_compute_rating_count")
 
     @api.multi
diff --git a/addons/repair/models/repair.py b/addons/repair/models/repair.py
index 1302cb93a01c..de88001fb577 100644
--- a/addons/repair/models/repair.py
+++ b/addons/repair/models/repair.py
@@ -114,7 +114,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")
+    tracking = fields.Selection('Product Tracking', related="product_id.tracking", readonly=False)
 
     @api.one
     @api.depends('partner_id')
diff --git a/addons/resource/models/res_users.py b/addons/resource/models/res_users.py
index 9793a560da08..12290b916ec4 100644
--- a/addons/resource/models/res_users.py
+++ b/addons/resource/models/res_users.py
@@ -11,4 +11,4 @@ class ResUsers(models.Model):
         'resource.resource', 'user_id', 'Resources')
     resource_calendar_id = fields.Many2one(
         'resource.calendar', 'Default Working Hours',
-        related='resource_ids.calendar_id')
+        related='resource_ids.calendar_id', readonly=False)
diff --git a/addons/resource/models/resource_mixin.py b/addons/resource/models/resource_mixin.py
index c74db0753954..7770efb46335 100644
--- a/addons/resource/models/resource_mixin.py
+++ b/addons/resource/models/resource_mixin.py
@@ -22,13 +22,13 @@ class ResourceMixin(models.AbstractModel):
     company_id = fields.Many2one(
         'res.company', 'Company',
         default=lambda self: self.env['res.company']._company_default_get(),
-        index=True, related='resource_id.company_id', store=True)
+        index=True, related='resource_id.company_id', store=True, readonly=False)
     resource_calendar_id = fields.Many2one(
         'resource.calendar', 'Working Hours',
         default=lambda self: self.env['res.company']._company_default_get().resource_calendar_id,
-        index=True, related='resource_id.calendar_id', store=True)
+        index=True, related='resource_id.calendar_id', store=True, readonly=False)
     tz = fields.Selection(
-        string='Timezone', related='resource_id.tz',
+        string='Timezone', related='resource_id.tz', readonly=False,
         help="This field is used in order to define in which timezone the resources will work.")
 
     @api.model
diff --git a/addons/sale/models/res_config_settings.py b/addons/sale/models/res_config_settings.py
index 71f2e83d6567..0a5060483a47 100644
--- a/addons/sale/models/res_config_settings.py
+++ b/addons/sale/models/res_config_settings.py
@@ -7,18 +7,18 @@ from odoo import api, fields, models
 class ResConfigSettings(models.TransientModel):
     _inherit = 'res.config.settings'
 
-    sale_note = fields.Text(related='company_id.sale_note', string="Terms & Conditions")
+    sale_note = fields.Text(related='company_id.sale_note', string="Terms & Conditions", readonly=False)
     use_sale_note = fields.Boolean(
         string='Default Terms & Conditions',
         oldname='default_use_sale_note',
         config_parameter='sale.use_sale_note')
     group_discount_per_so_line = fields.Boolean("Discounts", implied_group='sale.group_discount_per_so_line')
     module_sale_margin = fields.Boolean("Margins")
-    quotation_validity_days = fields.Integer(related='company_id.quotation_validity_days', string="Default Quotation Validity (Days)")
+    quotation_validity_days = fields.Integer(related='company_id.quotation_validity_days', string="Default Quotation Validity (Days)", readonly=False)
     use_quotation_validity_days = fields.Boolean("Default Quotation Validity", config_parameter='sale.use_quotation_validity_days')
     group_warning_sale = fields.Boolean("Sale Order Warnings", implied_group='sale.group_warning_sale')
-    portal_confirmation_sign = fields.Boolean(related='company_id.portal_confirmation_sign', string='Online Signature')
-    portal_confirmation_pay = fields.Boolean(related='company_id.portal_confirmation_pay', string='Online Payment')
+    portal_confirmation_sign = fields.Boolean(related='company_id.portal_confirmation_sign', string='Online Signature', readonly=False)
+    portal_confirmation_pay = fields.Boolean(related='company_id.portal_confirmation_pay', string='Online Payment', readonly=False)
     group_sale_delivery_address = fields.Boolean("Customer Addresses", implied_group='sale.group_delivery_invoice_address')
     multi_sales_price = fields.Boolean("Multiple Sales Prices per Product")
     multi_sales_price_method = fields.Selection([
diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py
index 13c8943094c1..4d184741d4fe 100644
--- a/addons/sale/models/sale.py
+++ b/addons/sale/models/sale.py
@@ -1136,7 +1136,7 @@ class SaleOrderLine(models.Model):
     # It allows keeping track of the extra_price associated to those attribute values and add them to the SO line description
     product_no_variant_attribute_values = fields.Many2many('product.template.attribute.value', string='Product attribute values that do not create variants')
     # Non-stored related field to allow portal user to see the image of the product he has ordered
-    product_image = fields.Binary('Product Image', related="product_id.image", store=False)
+    product_image = fields.Binary('Product Image', related="product_id.image", store=False, readonly=False)
 
     qty_delivered_method = fields.Selection([
         ('manual', 'Manual'),
@@ -1162,7 +1162,7 @@ class SaleOrderLine(models.Model):
     salesman_id = fields.Many2one(related='order_id.user_id', store=True, string='Salesperson', readonly=True)
     currency_id = fields.Many2one(related='order_id.currency_id', depends=['order_id'], store=True, string='Currency', readonly=True)
     company_id = fields.Many2one(related='order_id.company_id', string='Company', store=True, readonly=True)
-    order_partner_id = fields.Many2one(related='order_id.partner_id', store=True, string='Customer')
+    order_partner_id = fields.Many2one(related='order_id.partner_id', store=True, string='Customer', readonly=False)
     analytic_tag_ids = fields.Many2many('account.analytic.tag', string='Analytic Tags')
     analytic_line_ids = fields.One2many('account.analytic.line', 'so_line', string="Analytic lines")
     is_expense = fields.Boolean('Is expense', help="Is true if the sales order line comes from an expense or a vendor bills")
diff --git a/addons/sale_quotation_builder/models/sale_order_template.py b/addons/sale_quotation_builder/models/sale_order_template.py
index ba7aa199128c..2147a0c08814 100644
--- a/addons/sale_quotation_builder/models/sale_order_template.py
+++ b/addons/sale_quotation_builder/models/sale_order_template.py
@@ -23,7 +23,7 @@ class SaleOrderTemplate(models.Model):
 class SaleOrderTemplateLine(models.Model):
     _inherit = "sale.order.template.line"
 
-    website_description = fields.Html('Website Description', related='product_id.product_tmpl_id.quotation_only_description', translate=html_translate)
+    website_description = fields.Html('Website Description', related='product_id.product_tmpl_id.quotation_only_description', translate=html_translate, readonly=False)
 
     @api.onchange('product_id')
     def _onchange_product_id(self):
diff --git a/addons/sale_stock/models/res_config_settings.py b/addons/sale_stock/models/res_config_settings.py
index 5908814e9cf4..2a80982ba6bf 100644
--- a/addons/sale_stock/models/res_config_settings.py
+++ b/addons/sale_stock/models/res_config_settings.py
@@ -7,7 +7,7 @@ from odoo import api, fields, models
 class ResConfigSettings(models.TransientModel):
     _inherit = 'res.config.settings'
 
-    security_lead = fields.Float(related='company_id.security_lead', string="Security Lead Time")
+    security_lead = fields.Float(related='company_id.security_lead', string="Security Lead Time", readonly=False)
     group_route_so_lines = fields.Boolean("Order-Specific Routes",
         implied_group='sale_stock.group_route_so_lines')
     group_display_incoterm = fields.Boolean("Incoterms", implied_group='sale_stock.group_display_incoterm')
diff --git a/addons/sale_stock/models/stock.py b/addons/sale_stock/models/stock.py
index c9fa2afb52b1..f622c61820e1 100644
--- a/addons/sale_stock/models/stock.py
+++ b/addons/sale_stock/models/stock.py
@@ -63,7 +63,7 @@ class StockRule(models.Model):
 class StockPicking(models.Model):
     _inherit = 'stock.picking'
 
-    sale_id = fields.Many2one(related="group_id.sale_id", string="Sales Order", store=True)
+    sale_id = fields.Many2one(related="group_id.sale_id", string="Sales Order", store=True, readonly=False)
 
 
     def _log_less_quantities_than_expected(self, moves):
diff --git a/addons/sale_timesheet/wizard/project_create_sale_order.py b/addons/sale_timesheet/wizard/project_create_sale_order.py
index 781403dddbba..1062722fc12e 100644
--- a/addons/sale_timesheet/wizard/project_create_sale_order.py
+++ b/addons/sale_timesheet/wizard/project_create_sale_order.py
@@ -31,7 +31,7 @@ class ProjectCreateSalesOrder(models.TransientModel):
     partner_id = fields.Many2one('res.partner', string="Customer", domain=[('customer', '=', True)], required=True, help="Customer of the sales order")
     product_id = fields.Many2one('product.product', domain=[('type', '=', 'service'), ('invoice_policy', '=', 'delivery'), ('service_type', '=', 'timesheet')], string="Service", help="Product of the sales order item. Must be a service invoiced based on timesheets on tasks.")
     price_unit = fields.Float("Unit Price", help="Unit price of the sales order item.")
-    currency_id = fields.Many2one('res.currency', string="Currency", related='product_id.currency_id')
+    currency_id = fields.Many2one('res.currency', string="Currency", related='product_id.currency_id', readonly=False)
 
     billable_type = fields.Selection([
         ('project_rate', 'At Project Rate'),
@@ -201,7 +201,7 @@ class ProjectCreateSalesOrderLine(models.TransientModel):
     product_id = fields.Many2one('product.product', domain=[('type', '=', 'service'), ('invoice_policy', '=', 'delivery'), ('service_type', '=', 'timesheet')], string="Service", required=True,
         help="Product of the sales order item. Must be a service invoiced based on timesheets on tasks.")
     price_unit = fields.Float("Unit Price", default=1.0, help="Unit price of the sales order item.")
-    currency_id = fields.Many2one('res.currency', string="Currency", related='product_id.currency_id')
+    currency_id = fields.Many2one('res.currency', string="Currency", related='product_id.currency_id', readonly=False)
     employee_id = fields.Many2one('hr.employee', string="Employee", required=True, help="Employee that has timesheets on the project.")
 
     _sql_constraints = [
diff --git a/addons/snailmail/models/res_config_settings.py b/addons/snailmail/models/res_config_settings.py
index 7b916ce0e1f6..bf79ec83c3d7 100644
--- a/addons/snailmail/models/res_config_settings.py
+++ b/addons/snailmail/models/res_config_settings.py
@@ -7,5 +7,5 @@ from odoo import fields, models
 class ResConfigSettings(models.TransientModel):	
     _inherit = 'res.config.settings'	
 
-    snailmail_color = fields.Boolean(string='Print In Color', related='company_id.snailmail_color')	
-    snailmail_duplex = fields.Boolean(string='Print Both sides', related='company_id.snailmail_duplex')
+    snailmail_color = fields.Boolean(string='Print In Color', related='company_id.snailmail_color', readonly=False)
+    snailmail_duplex = fields.Boolean(string='Print Both sides', related='company_id.snailmail_duplex', readonly=False)
diff --git a/addons/snailmail_account/models/res_config_settings.py b/addons/snailmail_account/models/res_config_settings.py
index 06a1eb983735..bab192ef4e19 100644
--- a/addons/snailmail_account/models/res_config_settings.py
+++ b/addons/snailmail_account/models/res_config_settings.py
@@ -7,4 +7,4 @@ from odoo import fields, models
 class ResConfigSettings(models.TransientModel):	
     _inherit = 'res.config.settings'	
 
-    invoice_is_snailmail = fields.Boolean(string='Send by Post', related='company_id.invoice_is_snailmail')
+    invoice_is_snailmail = fields.Boolean(string='Send by Post', related='company_id.invoice_is_snailmail', readonly=False)
diff --git a/addons/stock/models/product.py b/addons/stock/models/product.py
index 2e8b73d3ee85..c6a65af4e76c 100644
--- a/addons/stock/models/product.py
+++ b/addons/stock/models/product.py
@@ -451,7 +451,7 @@ class ProductTemplate(models.Model):
     # TDE FIXME: seems only visible in a view - remove me ?
     route_from_categ_ids = fields.Many2many(
         relation="stock.location.route", string="Category Routes",
-        related='categ_id.total_route_ids')
+        related='categ_id.total_route_ids', readonly=False)
 
     def _is_cost_method_standard(self):
         return True
diff --git a/addons/stock/models/res_config_settings.py b/addons/stock/models/res_config_settings.py
index 544209a5cef6..ebf7d339d395 100644
--- a/addons/stock/models/res_config_settings.py
+++ b/addons/stock/models/res_config_settings.py
@@ -26,7 +26,7 @@ class ResConfigSettings(models.TransientModel):
         implied_group='stock.group_adv_location',
         help="Add and customize route operations to process product moves in your warehouse(s): e.g. unload > quality control > stock for incoming products, pick > pack > ship for outgoing products. \n You can also set putaway strategies on warehouse locations in order to send incoming products into specific child locations straight away (e.g. specific bins, racks).")
     group_warning_stock = fields.Boolean("Warnings for Stock", implied_group='stock.group_warning_stock')
-    propagation_minimum_delta = fields.Integer(related='company_id.propagation_minimum_delta', string="Minimum Delta for Propagation")
+    propagation_minimum_delta = fields.Integer(related='company_id.propagation_minimum_delta', string="Minimum Delta for Propagation", readonly=False)
     use_propagation_minimum_delta = fields.Boolean(
         string="No Rescheduling Propagation",
         oldname='default_new_propagation_minimum_delta',
diff --git a/addons/stock/models/stock_inventory.py b/addons/stock/models/stock_inventory.py
index 486431d1818f..1e66ccffe20d 100644
--- a/addons/stock/models/stock_inventory.py
+++ b/addons/stock/models/stock_inventory.py
@@ -352,7 +352,7 @@ class InventoryLine(models.Model):
         'Theoretical Quantity', compute='_compute_theoretical_qty',
         digits=dp.get_precision('Product Unit of Measure'), readonly=True, store=True)
     inventory_location_id = fields.Many2one(
-        'stock.location', 'Inventory Location', related='inventory_id.location_id', related_sudo=False)
+        'stock.location', 'Inventory Location', related='inventory_id.location_id', related_sudo=False, readonly=False)
     product_tracking = fields.Selection('Tracking', related='product_id.tracking', readonly=True)
 
     @api.one
diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py
index 0b10b239fac6..6b8c9fe85c23 100644
--- a/addons/stock/models/stock_move.py
+++ b/addons/stock/models/stock_move.py
@@ -65,7 +65,7 @@ class StockMove(models.Model):
     # TDE FIXME: make it stored, otherwise group will not work
     product_tmpl_id = fields.Many2one(
         'product.template', 'Product Template',
-        related='product_id.product_tmpl_id',
+        related='product_id.product_tmpl_id', readonly=False,
         help="Technical: used in views")
     product_packaging = fields.Many2one(
         'product.packaging', 'Preferred Packaging',
@@ -91,7 +91,7 @@ class StockMove(models.Model):
         copy=False,
         help="Optional: previous stock move when chaining them")
     picking_id = fields.Many2one('stock.picking', 'Transfer Reference', index=True, states={'done': [('readonly', True)]})
-    picking_partner_id = fields.Many2one('res.partner', 'Transfer Destination Address', related='picking_id.partner_id')
+    picking_partner_id = fields.Many2one('res.partner', 'Transfer Destination Address', related='picking_id.partner_id', readonly=False)
     note = fields.Text('Notes')
     state = fields.Selection([
         ('draft', 'New'), ('cancel', 'Cancelled'),
@@ -109,7 +109,7 @@ class StockMove(models.Model):
     price_unit = fields.Float(
         'Unit Price', help="Technical field used to record the product cost set by the user during a picking confirmation (when costing "
                            "method used is 'average price' or 'real'). Value given in company currency and in product uom.", copy=False)  # as it's a technical field, we intentionally don't provide the digits attribute
-    backorder_id = fields.Many2one('stock.picking', 'Back Order of', related='picking_id.backorder_id', index=True)
+    backorder_id = fields.Many2one('stock.picking', 'Back Order of', related='picking_id.backorder_id', index=True, readonly=False)
     origin = fields.Char("Source Document")
     procure_method = fields.Selection([
         ('make_to_stock', 'Default: Take From Stock'),
@@ -145,9 +145,9 @@ class StockMove(models.Model):
     restrict_partner_id = fields.Many2one('res.partner', 'Owner ', help="Technical field used to depict a restriction on the ownership of quants to consider when marking this move as 'done'")
     route_ids = fields.Many2many('stock.location.route', 'stock_location_route_move', 'move_id', 'route_id', 'Destination route', help="Preferred route")
     warehouse_id = fields.Many2one('stock.warehouse', 'Warehouse', help="Technical field depicting the warehouse to consider for the route selection on the next procurement (if any).")
-    has_tracking = fields.Selection(related='product_id.tracking', string='Product with Tracking')
+    has_tracking = fields.Selection(related='product_id.tracking', string='Product with Tracking', readonly=False)
     quantity_done = fields.Float('Quantity Done', compute='_quantity_done_compute', digits=dp.get_precision('Product Unit of Measure'), inverse='_quantity_done_set')
-    show_operations = fields.Boolean(related='picking_id.picking_type_id.show_operations')
+    show_operations = fields.Boolean(related='picking_id.picking_type_id.show_operations', readonly=False)
     show_details_visible = fields.Boolean('Details Visible', compute='_compute_show_details_visible')
     show_reserved_availability = fields.Boolean('From Supplier', compute='_compute_show_reserved_availability')
     picking_code = fields.Selection(related='picking_id.picking_type_id.code', readonly=True)
diff --git a/addons/stock/models/stock_move_line.py b/addons/stock/models/stock_move_line.py
index 9584fa842ef0..ccd2aea5a85b 100644
--- a/addons/stock/models/stock_move_line.py
+++ b/addons/stock/models/stock_move_line.py
@@ -44,12 +44,12 @@ class StockMoveLine(models.Model):
     lots_visible = fields.Boolean(compute='_compute_lots_visible')
     picking_type_use_create_lots = fields.Boolean(related='picking_id.picking_type_id.use_create_lots', readonly=True)
     picking_type_use_existing_lots = fields.Boolean(related='picking_id.picking_type_id.use_existing_lots', readonly=True)
-    state = fields.Selection(related='move_id.state', store=True, related_sudo=False)
-    is_initial_demand_editable = fields.Boolean(related='move_id.is_initial_demand_editable')
+    state = fields.Selection(related='move_id.state', store=True, related_sudo=False, readonly=False)
+    is_initial_demand_editable = fields.Boolean(related='move_id.is_initial_demand_editable', readonly=False)
     is_locked = fields.Boolean(related='move_id.is_locked', default=True, readonly=True)
     consume_line_ids = fields.Many2many('stock.move.line', 'stock_move_line_consume_rel', 'consume_line_id', 'produce_line_id', help="Technical link to see who consumed what. ")
     produce_line_ids = fields.Many2many('stock.move.line', 'stock_move_line_consume_rel', 'produce_line_id', 'consume_line_id', help="Technical link to see which line was produced with this. ")
-    reference = fields.Char(related='move_id.reference', store=True, related_sudo=False)
+    reference = fields.Char(related='move_id.reference', store=True, related_sudo=False, readonly=False)
     tracking = fields.Selection(related='product_id.tracking', readonly=True)
     picking_type_entire_packs = fields.Boolean(related='picking_id.picking_type_id.show_entire_packs', readonly=True)
 
diff --git a/addons/stock/models/stock_package_level.py b/addons/stock/models/stock_package_level.py
index 1d01face6b58..a4d0c5be010b 100644
--- a/addons/stock/models/stock_package_level.py
+++ b/addons/stock/models/stock_package_level.py
@@ -27,7 +27,7 @@ class StockPackageLevel(models.Model):
     ],string='State', compute='_compute_state')
     is_fresh_package = fields.Boolean(compute='_compute_fresh_pack')
 
-    picking_source_location = fields.Many2one('stock.location', related='picking_id.location_id')
+    picking_source_location = fields.Many2one('stock.location', related='picking_id.location_id', readonly=False)
     show_lots_m2o = fields.Boolean(compute='_compute_show_lot')
     show_lots_text = fields.Boolean(compute='_compute_show_lot')
 
diff --git a/addons/stock/models/stock_picking.py b/addons/stock/models/stock_picking.py
index e1aa4ecfd6c3..310f7b6bef53 100644
--- a/addons/stock/models/stock_picking.py
+++ b/addons/stock/models/stock_picking.py
@@ -294,7 +294,7 @@ class Picking(models.Model):
                                'initial demand. When the picking is done this allows '
                                'changing the done quantities.')
     # Used to search on pickings
-    product_id = fields.Many2one('product.product', 'Product', related='move_lines.product_id')
+    product_id = fields.Many2one('product.product', 'Product', related='move_lines.product_id', readonly=False)
     show_operations = fields.Boolean(compute='_compute_show_operations')
     show_lots_text = fields.Boolean(compute='_compute_show_lots_text')
     has_tracking = fields.Boolean(compute='_compute_has_tracking')
diff --git a/addons/stock/models/stock_production_lot.py b/addons/stock/models/stock_production_lot.py
index 7011c79d1429..584215620e63 100644
--- a/addons/stock/models/stock_production_lot.py
+++ b/addons/stock/models/stock_production_lot.py
@@ -19,7 +19,7 @@ class ProductionLot(models.Model):
         domain=[('type', 'in', ['product', 'consu'])], required=True)
     product_uom_id = fields.Many2one(
         'uom.uom', 'Unit of Measure',
-        related='product_id.uom_id', store=True)
+        related='product_id.uom_id', store=True, readonly=False)
     quant_ids = fields.One2many('stock.quant', 'lot_id', 'Quants', readonly=True)
     product_qty = fields.Float('Quantity', compute='_product_qty')
 
diff --git a/addons/stock/models/stock_quant.py b/addons/stock/models/stock_quant.py
index 123e48569714..7ad562792fb4 100644
--- a/addons/stock/models/stock_quant.py
+++ b/addons/stock/models/stock_quant.py
@@ -24,7 +24,7 @@ class StockQuant(models.Model):
     # so user can filter on template in webclient
     product_tmpl_id = fields.Many2one(
         'product.template', string='Product Template',
-        related='product_id.product_tmpl_id')
+        related='product_id.product_tmpl_id', readonly=False)
     product_uom_id = fields.Many2one(
         'uom.uom', 'Unit of Measure',
         readonly=True, related='product_id.uom_id')
diff --git a/addons/stock/models/stock_rule.py b/addons/stock/models/stock_rule.py
index 724edff2df24..2ffaf454b57b 100644
--- a/addons/stock/models/stock_rule.py
+++ b/addons/stock/models/stock_rule.py
@@ -49,7 +49,7 @@ class StockRule(models.Model):
         default='make_to_stock', required=True,
         help="""Create Procurement: A procurement will be created in the source location and the system will try to find a rule to resolve it. The available stock will be ignored.
              Take from Stock: The products will be taken from the available stock.""")
-    route_sequence = fields.Integer('Route Sequence', related='route_id.sequence', store=True)
+    route_sequence = fields.Integer('Route Sequence', related='route_id.sequence', store=True, readonly=False)
     picking_type_id = fields.Many2one(
         'stock.picking.type', 'Operation Type',
         required=True)
diff --git a/addons/stock/wizard/stock_change_product_qty.py b/addons/stock/wizard/stock_change_product_qty.py
index 7301555d993b..f33a6c10e36b 100644
--- a/addons/stock/wizard/stock_change_product_qty.py
+++ b/addons/stock/wizard/stock_change_product_qty.py
@@ -13,7 +13,7 @@ class ProductChangeQuantity(models.TransientModel):
     # TDE FIXME: strange dfeault method, was present before migration ? to check
     product_id = fields.Many2one('product.product', 'Product', required=True)
     product_tmpl_id = fields.Many2one('product.template', 'Template', required=True)
-    product_variant_count = fields.Integer('Variant Count', related='product_tmpl_id.product_variant_count')
+    product_variant_count = fields.Integer('Variant Count', related='product_tmpl_id.product_variant_count', readonly=False)
     new_quantity = fields.Float(
         'New Quantity on Hand', default=1,
         digits=dp.get_precision('Product Unit of Measure'), required=True,
diff --git a/addons/stock/wizard/stock_picking_return.py b/addons/stock/wizard/stock_picking_return.py
index 103c2a8cb26c..0a836c934990 100644
--- a/addons/stock/wizard/stock_picking_return.py
+++ b/addons/stock/wizard/stock_picking_return.py
@@ -14,7 +14,7 @@ class ReturnPickingLine(models.TransientModel):
 
     product_id = fields.Many2one('product.product', string="Product", required=True, domain="[('id', '=', product_id)]")
     quantity = fields.Float("Quantity", digits=dp.get_precision('Product Unit of Measure'), required=True)
-    uom_id = fields.Many2one('uom.uom', string='Unit of Measure', related='move_id.product_uom')
+    uom_id = fields.Many2one('uom.uom', string='Unit of Measure', related='move_id.product_uom', readonly=False)
     wizard_id = fields.Many2one('stock.return.picking', string="Wizard")
     move_id = fields.Many2one('stock.move', "Move")
 
diff --git a/addons/stock_landed_costs/models/stock_landed_cost.py b/addons/stock_landed_costs/models/stock_landed_cost.py
index d41a53cd6766..0722183757cd 100644
--- a/addons/stock_landed_costs/models/stock_landed_cost.py
+++ b/addons/stock_landed_costs/models/stock_landed_cost.py
@@ -52,7 +52,7 @@ class LandedCost(models.Model):
         'account.journal', 'Account Journal',
         required=True, states={'done': [('readonly', True)]})
     company_id = fields.Many2one('res.company', string="Company",
-        related='account_journal_id.company_id')
+        related='account_journal_id.company_id', readonly=False)
 
     @api.one
     @api.depends('cost_lines.price_unit')
diff --git a/addons/survey/models/survey.py b/addons/survey/models/survey.py
index 210c8153ecac..95a1cc1fdd1b 100644
--- a/addons/survey/models/survey.py
+++ b/addons/survey/models/survey.py
@@ -77,7 +77,7 @@ class Survey(models.Model):
     thank_you_message = fields.Html("Thanks Message", translate=True, help="This message will be displayed when survey is completed")
     quizz_mode = fields.Boolean("Quizz Mode")
     active = fields.Boolean("Active", default=True)
-    is_closed = fields.Boolean("Is closed", related='stage_id.closed')
+    is_closed = fields.Boolean("Is closed", related='stage_id.closed', readonly=False)
 
     def _is_designed(self):
         for survey in self:
@@ -424,7 +424,7 @@ class SurveyQuestion(models.Model):
     # Question metadata
     page_id = fields.Many2one('survey.page', string='Survey page',
             ondelete='cascade', required=True, default=lambda self: self.env.context.get('page_id'))
-    survey_id = fields.Many2one('survey.survey', related='page_id.survey_id', string='Survey')
+    survey_id = fields.Many2one('survey.survey', related='page_id.survey_id', string='Survey', readonly=False)
     sequence = fields.Integer('Sequence', default=10)
 
     # Question
@@ -716,8 +716,8 @@ class SurveyUserInput(models.Model):
     user_input_line_ids = fields.One2many('survey.user_input_line', 'user_input_id', string='Answers', copy=True)
 
     # URLs used to display the answers
-    result_url = fields.Char("Public link to the survey results", related='survey_id.result_url')
-    print_url = fields.Char("Public link to the empty survey", related='survey_id.print_url')
+    result_url = fields.Char("Public link to the survey results", related='survey_id.result_url', readonly=False)
+    print_url = fields.Char("Public link to the empty survey", related='survey_id.print_url', readonly=False)
 
     quizz_score = fields.Float("Score for the quiz", compute="_compute_quizz_score", default=0.0)
 
@@ -781,8 +781,8 @@ class SurveyUserInputLine(models.Model):
 
     user_input_id = fields.Many2one('survey.user_input', string='User Input', ondelete='cascade', required=True)
     question_id = fields.Many2one('survey.question', string='Question', ondelete='restrict', required=True)
-    page_id = fields.Many2one(related='question_id.page_id', string="Page")
-    survey_id = fields.Many2one(related='user_input_id.survey_id', string='Survey', store=True)
+    page_id = fields.Many2one(related='question_id.page_id', string="Page", readonly=False)
+    survey_id = fields.Many2one(related='user_input_id.survey_id', string='Survey', store=True, readonly=False)
     date_create = fields.Datetime('Create Date', default=fields.Datetime.now, required=True)
     skipped = fields.Boolean('Skipped')
     answer_type = fields.Selection([
diff --git a/addons/website/models/ir_attachment.py b/addons/website/models/ir_attachment.py
index f49611e6e057..8fe190a5a472 100644
--- a/addons/website/models/ir_attachment.py
+++ b/addons/website/models/ir_attachment.py
@@ -13,7 +13,7 @@ class Attachment(models.Model):
     _inherit = "ir.attachment"
 
     # related for backward compatibility with saas-6
-    website_url = fields.Char(string="Website URL", related='local_url', deprecated=True)
+    website_url = fields.Char(string="Website URL", related='local_url', deprecated=True, readonly=False)
     key = fields.Char(help='Technical field used to resolve multiple attachments in a multi-website environment.')
     website_id = fields.Many2one('website')
 
diff --git a/addons/website/models/res_config_settings.py b/addons/website/models/res_config_settings.py
index 8dc651707ba4..2c796fd5aeb1 100644
--- a/addons/website/models/res_config_settings.py
+++ b/addons/website/models/res_config_settings.py
@@ -15,40 +15,40 @@ class ResConfigSettings(models.TransientModel):
 
     website_id = fields.Many2one('website', string="website",
                                  default=_default_website, ondelete='cascade')
-    website_name = fields.Char('Website Name', related='website_id.name')
-    website_domain = fields.Char('Website Domain', related='website_id.domain')
-    website_country_group_ids = fields.Many2many(related='website_id.country_group_ids')
-    website_company_id = fields.Many2one(related='website_id.company_id', string='Website Company')
-    language_ids = fields.Many2many(related='website_id.language_ids', relation='res.lang')
+    website_name = fields.Char('Website Name', related='website_id.name', readonly=False)
+    website_domain = fields.Char('Website Domain', related='website_id.domain', readonly=False)
+    website_country_group_ids = fields.Many2many(related='website_id.country_group_ids', readonly=False)
+    website_company_id = fields.Many2one(related='website_id.company_id', string='Website Company', readonly=False)
+    language_ids = fields.Many2many(related='website_id.language_ids', relation='res.lang', readonly=False)
     language_count = fields.Integer(string='Number of languages', compute='_compute_language_count', readonly=True)
     website_default_lang_id = fields.Many2one(
-        string='Default language', related='website_id.default_lang_id',
+        string='Default language', related='website_id.default_lang_id', readonly=False,
         relation='res.lang', required=True,
         oldname='default_lang_id')
     website_default_lang_code = fields.Char(
-        'Default language code', related='website_id.default_lang_code',
+        'Default language code', related='website_id.default_lang_code', readonly=False,
         oldname='default_lang_code')
-    specific_user_account = fields.Boolean(related='website_id.specific_user_account',
+    specific_user_account = fields.Boolean(related='website_id.specific_user_account', readonly=False,
                                            help='Are newly created user accounts website specific')
 
-    google_analytics_key = fields.Char('Google Analytics Key', related='website_id.google_analytics_key')
-    google_management_client_id = fields.Char('Google Client ID', related='website_id.google_management_client_id')
-    google_management_client_secret = fields.Char('Google Client Secret', related='website_id.google_management_client_secret')
+    google_analytics_key = fields.Char('Google Analytics Key', related='website_id.google_analytics_key', readonly=False)
+    google_management_client_id = fields.Char('Google Client ID', related='website_id.google_management_client_id', readonly=False)
+    google_management_client_secret = fields.Char('Google Client Secret', related='website_id.google_management_client_secret', readonly=False)
 
-    cdn_activated = fields.Boolean(related='website_id.cdn_activated')
-    cdn_url = fields.Char(related='website_id.cdn_url')
-    cdn_filters = fields.Text(related='website_id.cdn_filters')
+    cdn_activated = fields.Boolean(related='website_id.cdn_activated', readonly=False)
+    cdn_url = fields.Char(related='website_id.cdn_url', readonly=False)
+    cdn_filters = fields.Text(related='website_id.cdn_filters', readonly=False)
     module_website_version = fields.Boolean("A/B Testing")
     module_website_links = fields.Boolean("Link Trackers")
-    auth_signup_uninvited = fields.Selection("Customer Account", related='website_id.auth_signup_uninvited')
+    auth_signup_uninvited = fields.Selection("Customer Account", related='website_id.auth_signup_uninvited', readonly=False)
 
-    social_twitter = fields.Char(related='website_id.social_twitter')
-    social_facebook = fields.Char(related='website_id.social_facebook')
-    social_github = fields.Char(related='website_id.social_github')
-    social_linkedin = fields.Char(related='website_id.social_linkedin')
-    social_youtube = fields.Char(related='website_id.social_youtube')
-    social_googleplus = fields.Char(related='website_id.social_googleplus')
-    social_instagram = fields.Char(related='website_id.social_instagram')
+    social_twitter = fields.Char(related='website_id.social_twitter', readonly=False)
+    social_facebook = fields.Char(related='website_id.social_facebook', readonly=False)
+    social_github = fields.Char(related='website_id.social_github', readonly=False)
+    social_linkedin = fields.Char(related='website_id.social_linkedin', readonly=False)
+    social_youtube = fields.Char(related='website_id.social_youtube', readonly=False)
+    social_googleplus = fields.Char(related='website_id.social_googleplus', readonly=False)
+    social_instagram = fields.Char(related='website_id.social_instagram', readonly=False)
 
     @api.depends('website_id', 'social_twitter', 'social_facebook', 'social_github', 'social_linkedin', 'social_youtube', 'social_googleplus', 'social_instagram')
     def has_social_network(self):
@@ -67,9 +67,9 @@ class ResConfigSettings(models.TransientModel):
 
     has_social_network = fields.Boolean("Configure Social Network", compute=has_social_network, inverse=inverse_has_social_network)
 
-    favicon = fields.Binary('Favicon', related='website_id.favicon')
+    favicon = fields.Binary('Favicon', related='website_id.favicon', readonly=False)
 
-    google_maps_api_key = fields.Char(related='website_id.google_maps_api_key')
+    google_maps_api_key = fields.Char(related='website_id.google_maps_api_key', readonly=False)
     group_multi_website = fields.Boolean("Multi-website", implied_group="website.group_multi_website")
 
     @api.depends('website_id')
diff --git a/addons/website/models/website.py b/addons/website/models/website.py
index a577f147cb16..7ed335f8d2ed 100644
--- a/addons/website/models/website.py
+++ b/addons/website/models/website.py
@@ -56,7 +56,7 @@ class Website(models.Model):
     company_id = fields.Many2one('res.company', string="Company", default=lambda self: self.env.ref('base.main_company').id, required=True)
     language_ids = fields.Many2many('res.lang', 'website_lang_rel', 'website_id', 'lang_id', 'Languages', default=_active_languages)
     default_lang_id = fields.Many2one('res.lang', string="Default Language", default=_default_language, required=True)
-    default_lang_code = fields.Char("Default language code", related='default_lang_id.code', store=True)
+    default_lang_code = fields.Char("Default language code", related='default_lang_id.code', store=True, readonly=False)
     auto_redirect_lang = fields.Boolean('Autoredirect Language', default=True, help="Should users be redirected to their browser's language")
 
     def _default_social_facebook(self):
@@ -98,7 +98,7 @@ class Website(models.Model):
     cdn_activated = fields.Boolean('Content Delivery Network (CDN)')
     cdn_url = fields.Char('CDN Base URL', default='')
     cdn_filters = fields.Text('CDN Filters', default=lambda s: '\n'.join(DEFAULT_CDN_FILTERS), help="URL matching those filters will be rewritten using the CDN Base URL")
-    partner_id = fields.Many2one(related='user_id.partner_id', relation='res.partner', string='Public Partner')
+    partner_id = fields.Many2one(related='user_id.partner_id', relation='res.partner', string='Public Partner', readonly=False)
     menu_id = fields.Many2one('website.menu', compute='_compute_menu', string='Main Menu')
     homepage_id = fields.Many2one('website.page', string='Homepage')
     favicon = fields.Binary(string="Website Favicon", help="This field holds the image used to display a favicon on the website.")
@@ -776,7 +776,7 @@ class WebsitePublishedMixin(models.AbstractModel):
     _name = "website.published.mixin"
     _description = 'Website Published Mixin'
 
-    website_published = fields.Boolean('Visible on current website', related='is_published')
+    website_published = fields.Boolean('Visible on current website', related='is_published', readonly=False)
     is_published = fields.Boolean('Is published')
     website_url = fields.Char('Website URL', compute='_compute_website_url', help='The full URL to access the document through the website.')
 
@@ -815,7 +815,7 @@ class WebsitePublishedMultiMixin(WebsitePublishedMixin):
     website_published = fields.Boolean(compute='_compute_website_published',
                                        inverse='_inverse_website_published',
                                        search='_search_website_published',
-                                       related=False)
+                                       related=False, readonly=False)
 
     @api.multi
     @api.depends('is_published', 'website_id')
@@ -870,7 +870,7 @@ class Page(models.Model):
     header_color = fields.Char()
 
     # don't use mixin website_id but use website_id on ir.ui.view instead
-    website_id = fields.Many2one(related='view_id.website_id', store=True)
+    website_id = fields.Many2one(related='view_id.website_id', store=True, readonly=False)
 
     @api.one
     def _compute_homepage(self):
diff --git a/addons/website_blog/models/website_blog.py b/addons/website_blog/models/website_blog.py
index dc6f2d167365..6616b62ce43e 100644
--- a/addons/website_blog/models/website_blog.py
+++ b/addons/website_blog/models/website_blog.py
@@ -165,7 +165,7 @@ class BlogPost(models.Model):
     create_uid = fields.Many2one('res.users', 'Created by', index=True, readonly=True)
     write_date = fields.Datetime('Last Updated on', index=True, readonly=True)
     write_uid = fields.Many2one('res.users', 'Last Contributor', index=True, readonly=True)
-    author_avatar = fields.Binary(related='author_id.image_small', string="Avatar")
+    author_avatar = fields.Binary(related='author_id.image_small', string="Avatar", readonly=False)
     visits = fields.Integer('No of Views', copy=False)
     ranking = fields.Float(compute='_compute_ranking', string='Ranking')
 
diff --git a/addons/website_crm/models/res_config_settings.py b/addons/website_crm/models/res_config_settings.py
index 98ba0e20939f..f9b3f1c2c33e 100644
--- a/addons/website_crm/models/res_config_settings.py
+++ b/addons/website_crm/models/res_config_settings.py
@@ -13,9 +13,9 @@ class ResConfigSettings(models.TransientModel):
             return [('use_opportunities', '=', True)]
 
     crm_default_team_id = fields.Many2one(
-        'crm.team', string='Default Sales Team', related='website_id.crm_default_team_id',
+        'crm.team', string='Default Sales Team', related='website_id.crm_default_team_id', readonly=False,
         domain=lambda self: self._get_crm_default_team_domain(),
         help='Default Sales Team for new leads created through the Contact Us form.')
     crm_default_user_id = fields.Many2one(
-        'res.users', string='Default Salesperson', related='website_id.crm_default_user_id', domain=[('share', '=', False)],
+        'res.users', string='Default Salesperson', related='website_id.crm_default_user_id', domain=[('share', '=', False)], readonly=False,
         help='Default salesperson for new leads created through the Contact Us form.')
diff --git a/addons/website_event_track/models/event_track.py b/addons/website_event_track/models/event_track.py
index 1661167e0cd4..2f35e86bb0e0 100644
--- a/addons/website_event_track/models/event_track.py
+++ b/addons/website_event_track/models/event_track.py
@@ -88,7 +88,7 @@ class Track(models.Model):
         ('0', 'Low'), ('1', 'Medium'),
         ('2', 'High'), ('3', 'Highest')],
         'Priority', required=True, default='1')
-    image = fields.Binary('Image', related='partner_id.image_medium', store=True, attachment=True)
+    image = fields.Binary('Image', related='partner_id.image_medium', store=True, attachment=True, readonly=False)
 
     @api.multi
     @api.depends('name')
@@ -209,5 +209,5 @@ class Sponsor(models.Model):
     sponsor_type_id = fields.Many2one('event.sponsor.type', 'Sponsoring Type', required=True)
     partner_id = fields.Many2one('res.partner', 'Sponsor/Customer', required=True)
     url = fields.Char('Sponsor Website')
-    sequence = fields.Integer('Sequence', store=True, related='sponsor_type_id.sequence')
-    image_medium = fields.Binary(string='Logo', related='partner_id.image_medium', store=True, attachment=True)
+    sequence = fields.Integer('Sequence', store=True, related='sponsor_type_id.sequence', readonly=False)
+    image_medium = fields.Binary(string='Logo', related='partner_id.image_medium', store=True, attachment=True, readonly=False)
diff --git a/addons/website_form/models/models.py b/addons/website_form/models/models.py
index 6ad987f89e66..1256ac4935ca 100644
--- a/addons/website_form/models/models.py
+++ b/addons/website_form/models/models.py
@@ -18,7 +18,7 @@ class website_form_config(models.Model):
 
 class ResConfigSettings(models.TransientModel):
     _inherit = 'res.config.settings'
-    website_form_enable_metadata = fields.Boolean(related="website_id.website_form_enable_metadata")
+    website_form_enable_metadata = fields.Boolean(related="website_id.website_form_enable_metadata", readonly=False)
 
 
 class website_form_model(models.Model):
diff --git a/addons/website_forum/models/forum.py b/addons/website_forum/models/forum.py
index d1dce1b378e8..7fb50947993d 100644
--- a/addons/website_forum/models/forum.py
+++ b/addons/website_forum/models/forum.py
@@ -869,8 +869,8 @@ class Vote(models.Model):
     user_id = fields.Many2one('res.users', string='User', required=True, default=lambda self: self._uid)
     vote = fields.Selection([('1', '1'), ('-1', '-1'), ('0', '0')], string='Vote', required=True, default='1')
     create_date = fields.Datetime('Create Date', index=True, readonly=True)
-    forum_id = fields.Many2one('forum.forum', string='Forum', related="post_id.forum_id", store=True)
-    recipient_id = fields.Many2one('res.users', string='To', related="post_id.create_uid", store=True)
+    forum_id = fields.Many2one('forum.forum', string='Forum', related="post_id.forum_id", store=True, readonly=False)
+    recipient_id = fields.Many2one('res.users', string='To', related="post_id.create_uid", store=True, readonly=False)
 
     def _get_karma_value(self, old_vote, new_vote, up_karma, down_karma):
         _karma_upd = {
diff --git a/addons/website_forum/models/gamification.py b/addons/website_forum/models/gamification.py
index 73819aa97f5e..5c83dcc1ad62 100644
--- a/addons/website_forum/models/gamification.py
+++ b/addons/website_forum/models/gamification.py
@@ -24,4 +24,4 @@ class UserBadge(models.Model):
          ('silver', 'silver'),
          ('gold', 'gold')],
         string='Forum Badge Level',
-        related="badge_id.level", store=True)
+        related="badge_id.level", store=True, readonly=False)
diff --git a/addons/website_livechat/models/res_config_settings.py b/addons/website_livechat/models/res_config_settings.py
index 6b0c96cd2e03..9c47f28b83ec 100644
--- a/addons/website_livechat/models/res_config_settings.py
+++ b/addons/website_livechat/models/res_config_settings.py
@@ -7,4 +7,4 @@ from odoo import fields, models
 class ResConfigSettings(models.TransientModel):
     _inherit = 'res.config.settings'
 
-    channel_id = fields.Many2one('im_livechat.channel', string='Website Live Channel', related='website_id.channel_id')
+    channel_id = fields.Many2one('im_livechat.channel', string='Website Live Channel', related='website_id.channel_id', readonly=False)
diff --git a/addons/website_rating/models/rating.py b/addons/website_rating/models/rating.py
index 673299e6df42..33184ca90514 100644
--- a/addons/website_rating/models/rating.py
+++ b/addons/website_rating/models/rating.py
@@ -9,4 +9,4 @@ class Rating(models.Model):
     # Add this related field to mail.message for performance reason
     # This field may one day be deplaced to another module (like 'website_rating') if it is required for
     # another usage not related to website_sale.
-    website_published = fields.Boolean(related='message_id.website_published', store=True)
+    website_published = fields.Boolean(related='message_id.website_published', store=True, readonly=False)
diff --git a/addons/website_sale/models/product.py b/addons/website_sale/models/product.py
index ff3fb29f6c60..727775b90272 100644
--- a/addons/website_sale/models/product.py
+++ b/addons/website_sale/models/product.py
@@ -185,7 +185,7 @@ class ProductTemplate(models.Model):
 class Product(models.Model):
     _inherit = "product.product"
 
-    website_id = fields.Many2one(related='product_tmpl_id.website_id')
+    website_id = fields.Many2one(related='product_tmpl_id.website_id', readonly=False)
 
     website_price = fields.Float('Website price', compute='_website_price', digits=dp.get_precision('Product Price'))
     website_public_price = fields.Float('Website public price', compute='_website_price', digits=dp.get_precision('Product Price'))
diff --git a/addons/website_sale/models/res_config_settings.py b/addons/website_sale/models/res_config_settings.py
index 44a41472cbcc..bceea238fa62 100644
--- a/addons/website_sale/models/res_config_settings.py
+++ b/addons/website_sale/models/res_config_settings.py
@@ -15,7 +15,7 @@ class ResConfigSettings(models.TransientModel):
         except ValueError:
             return False
 
-    salesperson_id = fields.Many2one('res.users', related='website_id.salesperson_id', string='Salesperson')
+    salesperson_id = fields.Many2one('res.users', related='website_id.salesperson_id', string='Salesperson', readonly=False)
     salesteam_id = fields.Many2one('crm.team', related='website_id.salesteam_id', string='Sales Team', domain=[('team_type', '!=', 'pos')])
     module_website_sale_delivery = fields.Boolean("eCommerce Shipping Costs")
     # field used to have a nice radio in form view, resuming the 2 fields above
@@ -35,9 +35,9 @@ class ResConfigSettings(models.TransientModel):
     module_account = fields.Boolean("Invoicing")
 
     cart_recovery_mail_template = fields.Many2one('mail.template', string='Cart Recovery Email', domain="[('model', '=', 'sale.order')]",
-                                                  default=_default_recovery_mail_template, related='website_id.cart_recovery_mail_template_id')
+                                                  default=_default_recovery_mail_template, related='website_id.cart_recovery_mail_template_id', readonly=False)
     cart_abandoned_delay = fields.Float("Abandoned Delay", help="Number of hours after which the cart is considered abandoned.",
-                                        default=1.0, related='website_id.cart_abandoned_delay')
+                                        default=1.0, related='website_id.cart_abandoned_delay', readonly=False)
 
     @api.model
     def get_values(self):
diff --git a/addons/website_sale/models/website.py b/addons/website_sale/models/website.py
index b5d03aa6d2f5..570ef96c45f3 100644
--- a/addons/website_sale/models/website.py
+++ b/addons/website_sale/models/website.py
@@ -14,7 +14,7 @@ class Website(models.Model):
     _inherit = 'website'
 
     pricelist_id = fields.Many2one('product.pricelist', compute='_compute_pricelist_id', string='Default Pricelist')
-    currency_id = fields.Many2one('res.currency', related='pricelist_id.currency_id', related_sudo=False, string='Default Currency')
+    currency_id = fields.Many2one('res.currency', related='pricelist_id.currency_id', related_sudo=False, string='Default Currency', readonly=False)
     salesperson_id = fields.Many2one('res.users', string='Salesperson')
     salesteam_id = fields.Many2one('crm.team', string='Sales Team')
     pricelist_ids = fields.One2many('product.pricelist', compute="_compute_pricelist_ids",
diff --git a/addons/website_sale_delivery/models/delivery.py b/addons/website_sale_delivery/models/delivery.py
index 2e0b878b8da8..5a7270c7f1cc 100644
--- a/addons/website_sale_delivery/models/delivery.py
+++ b/addons/website_sale_delivery/models/delivery.py
@@ -8,5 +8,5 @@ class DeliveryCarrier(models.Model):
     _name = 'delivery.carrier'
     _inherit = ['delivery.carrier', 'website.published.multi.mixin']
 
-    website_description = fields.Text(related='product_id.description_sale', string='Description for Online Quotations')
+    website_description = fields.Text(related='product_id.description_sale', string='Description for Online Quotations', readonly=False)
     website_published = fields.Boolean(default=False)
diff --git a/addons/website_slides/models/res_config_settings.py b/addons/website_slides/models/res_config_settings.py
index 7ea6470a1273..77bec337ff0f 100644
--- a/addons/website_slides/models/res_config_settings.py
+++ b/addons/website_slides/models/res_config_settings.py
@@ -7,4 +7,4 @@ from odoo import api, fields, models
 class ResConfigSettings(models.TransientModel):
     _inherit = "res.config.settings"
 
-    website_slide_google_app_key = fields.Char(related='website_id.website_slide_google_app_key')
+    website_slide_google_app_key = fields.Char(related='website_id.website_slide_google_app_key', readonly=False)
diff --git a/addons/website_twitter/models/res_config_settings.py b/addons/website_twitter/models/res_config_settings.py
index b34299f5b624..4cb58e52d72f 100644
--- a/addons/website_twitter/models/res_config_settings.py
+++ b/addons/website_twitter/models/res_config_settings.py
@@ -27,15 +27,15 @@ class ResConfigSettings(models.TransientModel):
     _inherit = 'res.config.settings'
 
     twitter_api_key = fields.Char(
-        related='website_id.twitter_api_key',
+        related='website_id.twitter_api_key', readonly=False,
         string='API Key',
         help='Twitter API key you can get it from https://apps.twitter.com/')
     twitter_api_secret = fields.Char(
-        related='website_id.twitter_api_secret',
+        related='website_id.twitter_api_secret', readonly=False,
         string='API secret',
         help='Twitter API secret you can get it from https://apps.twitter.com/')
     twitter_screen_name = fields.Char(
-        related='website_id.twitter_screen_name',
+        related='website_id.twitter_screen_name', readonly=False,
         string='Favorites From',
         help='Screen Name of the Twitter Account from which you want to load favorites.'
              'It does not have to match the API Key/Secret.')
diff --git a/odoo/addons/base/models/ir_cron.py b/odoo/addons/base/models/ir_cron.py
index 0af758223294..4d8c0d3ea36e 100644
--- a/odoo/addons/base/models/ir_cron.py
+++ b/odoo/addons/base/models/ir_cron.py
@@ -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)
+    cron_name = fields.Char('Name', related='ir_actions_server_id.name', store=True, readonly=False)
     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.")
diff --git a/odoo/addons/base/models/res_bank.py b/odoo/addons/base/models/res_bank.py
index 4b5147ed0fee..88ff7b7984c3 100644
--- a/odoo/addons/base/models/res_bank.py
+++ b/odoo/addons/base/models/res_bank.py
@@ -74,8 +74,8 @@ class ResPartnerBank(models.Model):
     acc_holder_name = fields.Char(string='Account Holder Name', help="Account holder name, in case it is different than the name of the Account Holder")
     partner_id = fields.Many2one('res.partner', 'Account Holder', ondelete='cascade', index=True, domain=['|', ('is_company', '=', True), ('parent_id', '=', False)], required=True)
     bank_id = fields.Many2one('res.bank', string='Bank')
-    bank_name = fields.Char(related='bank_id.name')
-    bank_bic = fields.Char(related='bank_id.bic')
+    bank_name = fields.Char(related='bank_id.name', readonly=False)
+    bank_bic = fields.Char(related='bank_id.bic', readonly=False)
     sequence = fields.Integer()
     currency_id = fields.Many2one('res.currency', string='Currency')
     company_id = fields.Many2one('res.company', 'Company', default=lambda self: self.env.user.company_id, ondelete='cascade')
diff --git a/odoo/addons/base/models/res_company.py b/odoo/addons/base/models/res_company.py
index cc5a1fb6175a..64fb3ee6fb26 100644
--- a/odoo/addons/base/models/res_company.py
+++ b/odoo/addons/base/models/res_company.py
@@ -29,14 +29,14 @@ class Company(models.Model):
         currency_id = self.env['res.users'].browse(self._uid).company_id.currency_id
         return currency_id or self._get_euro()
 
-    name = fields.Char(related='partner_id.name', string='Company Name', required=True, store=True)
+    name = fields.Char(related='partner_id.name', string='Company Name', required=True, store=True, readonly=False)
     sequence = fields.Integer(help='Used to order Companies in the company switcher', default=10)
     parent_id = fields.Many2one('res.company', string='Parent Company', index=True)
     child_ids = fields.One2many('res.company', 'parent_id', string='Child Companies')
     partner_id = fields.Many2one('res.partner', string='Partner', required=True)
     report_header = fields.Text(string='Company Tagline', help="Appears by default on the top right corner of your printed documents (report header).")
     report_footer = fields.Text(string='Report Footer', translate=True, help="Footer text displayed at the bottom of all reports.")
-    logo = fields.Binary(related='partner_id.image', default=_get_logo, string="Company Logo")
+    logo = fields.Binary(related='partner_id.image', default=_get_logo, string="Company Logo", readonly=False)
     # logo_web: do not store in attachments, since the image is retrieved in SQL for
     # performance reasons (see addons/web/controllers/main.py, Binary.company_logo)
     logo_web = fields.Binary(compute='_compute_logo_web', store=True)
@@ -50,10 +50,10 @@ class Company(models.Model):
     state_id = fields.Many2one('res.country.state', compute='_compute_address', inverse='_inverse_state', string="Fed. State")
     bank_ids = fields.One2many('res.partner.bank', 'company_id', string='Bank Accounts', help='Bank accounts related to this company')
     country_id = fields.Many2one('res.country', compute='_compute_address', inverse='_inverse_country', string="Country")
-    email = fields.Char(related='partner_id.email', store=True)
-    phone = fields.Char(related='partner_id.phone', store=True)
-    website = fields.Char(related='partner_id.website')
-    vat = fields.Char(related='partner_id.vat', string="Tax ID")
+    email = fields.Char(related='partner_id.email', store=True, readonly=False)
+    phone = fields.Char(related='partner_id.phone', store=True, readonly=False)
+    website = fields.Char(related='partner_id.website', readonly=False)
+    vat = fields.Char(related='partner_id.vat', string="Tax ID", readonly=False)
     company_registry = fields.Char()
     paperformat_id = fields.Many2one('report.paperformat', 'Paper format', default=lambda self: self.env.ref('base.paperformat_euro', raise_if_not_found=False))
     external_report_layout_id = fields.Many2one('ir.ui.view', 'Document Template')
diff --git a/odoo/addons/base/models/res_users.py b/odoo/addons/base/models/res_users.py
index 90b4003156b7..b1aee2245f03 100644
--- a/odoo/addons/base/models/res_users.py
+++ b/odoo/addons/base/models/res_users.py
@@ -228,7 +228,7 @@ class Users(models.Model):
         help="If specified, this action will be opened at log on for this user, in addition to the standard menu.")
     groups_id = fields.Many2many('res.groups', 'res_groups_users_rel', 'uid', 'gid', string='Groups', default=_default_groups)
     log_ids = fields.One2many('res.users.log', 'create_uid', string='User log entries')
-    login_date = fields.Datetime(related='log_ids.create_date', string='Latest connection')
+    login_date = fields.Datetime(related='log_ids.create_date', string='Latest connection', readonly=False)
     share = fields.Boolean(compute='_compute_share', compute_sudo=True, string='Share User', store=True,
          help="External user with limited access, created only for the purpose of sharing data.")
     companies_count = fields.Integer(compute='_compute_companies_count', string="Number of Companies", default=_companies_count)
@@ -248,8 +248,8 @@ class Users(models.Model):
 
     # overridden inherited fields to bypass access rights, in case you have
     # access to the user but not its corresponding partner
-    name = fields.Char(related='partner_id.name', inherited=True)
-    email = fields.Char(related='partner_id.email', inherited=True)
+    name = fields.Char(related='partner_id.name', inherited=True, readonly=False)
+    email = fields.Char(related='partner_id.email', inherited=True, readonly=False)
 
     _sql_constraints = [
         ('login_key', 'UNIQUE (login)',  'You can not have two users with the same login !')
diff --git a/odoo/addons/test_new_api/models.py b/odoo/addons/test_new_api/models.py
index bb55424b9c9c..a932197afc94 100644
--- a/odoo/addons/test_new_api/models.py
+++ b/odoo/addons/test_new_api/models.py
@@ -123,7 +123,7 @@ class Message(models.Model):
     display_name = fields.Char(string='Abstract', compute='_compute_display_name')
     size = fields.Integer(compute='_compute_size', search='_search_size')
     double_size = fields.Integer(compute='_compute_double_size')
-    discussion_name = fields.Char(related='discussion.name', string="Discussion Name")
+    discussion_name = fields.Char(related='discussion.name', string="Discussion Name", readonly=False)
     author_partner = fields.Many2one(
         'res.partner', compute='_compute_author_partner',
         search='_search_author_partner')
@@ -239,7 +239,7 @@ class Edition(models.Model):
     name = fields.Char()
     res_id = fields.Integer(required=True)
     res_model_id = fields.Many2one('ir.model', required=True)
-    res_model = fields.Char(related='res_model_id.model', store=True)
+    res_model = fields.Char(related='res_model_id.model', store=True, readonly=False)
 
 
 class Book(models.Model):
@@ -321,8 +321,8 @@ class Bar(models.Model):
 
     name = fields.Char()
     foo = fields.Many2one('test_new_api.foo', compute='_compute_foo')
-    value1 = fields.Integer(related='foo.value1')
-    value2 = fields.Integer(related='foo.value2')
+    value1 = fields.Integer(related='foo.value1', readonly=False)
+    value2 = fields.Integer(related='foo.value2', readonly=False)
 
     @api.depends('name')
     def _compute_foo(self):
@@ -336,12 +336,12 @@ class Related(models.Model):
 
     name = fields.Char()
     # related fields with a single field
-    related_name = fields.Char(related='name', string='A related on Name')
-    related_related_name = fields.Char(related='related_name', string='A related on a related on Name')
+    related_name = fields.Char(related='name', string='A related on Name', readonly=False)
+    related_related_name = fields.Char(related='related_name', string='A related on a related on Name', readonly=False)
 
     message = fields.Many2one('test_new_api.message')
-    message_name = fields.Text(related="message.body", related_sudo=False, string='Message Body')
-    message_currency = fields.Many2one(related="message.author", string='Message Author')
+    message_name = fields.Text(related="message.body", related_sudo=False, string='Message Body', readonly=False)
+    message_currency = fields.Many2one(related="message.author", string='Message Author', readonly=False)
 
 class ComputeProtected(models.Model):
     _name = 'test_new_api.compute.protected'
-- 
GitLab