Upgrading Odoo 17 to Odoo 18

What changes between Odoo 17 and Odoo 18 only: first what to change in custom modules, then the changes we flagged week by week. Tick them off as you go; ticks stay in this browser.

Framework changes for custom modules · 14

6 breaking, 8 deprecated but still working in 18.0. Started from OCA's migration guides; we checked each one in the Odoo code.

BreakingRemoved in 18.0

Replace div.oe_chatter with <chatter/>

The form compiler now looks for a chatter element only. A form that still has the old div with message_follower_ids and message_ids widgets shows no chatter.

Before
<div class="oe_chatter">
  <field name="message_follower_ids"/>
  <field name="activity_ids"/>
  <field name="message_ids"/>
</div>
After
<chatter/>

Checked in: 17.0/addons/mail/static/src/views/web/form/form_compiler.js:74, 18.0/addons/mail/static/src/chatter/web/form_compiler.js:46 · Odoo: #156463

BreakingOld code works differently from 18.0

Make copy_data overrides work on several records

copy and copy_data now take a multi-record self: copy_data returns one dict per record, in order, and default applies to all of them. Overrides that read fields of self directly fail with a singleton error.

Before
def copy_data(self, default=None):
    default = dict(default or {}, name=_('%s (copy)', self.name))
    return super().copy_data(default)
After
def copy_data(self, default=None):
    vals_list = super().copy_data(default)
    for record, vals in zip(self, vals_list):
        vals['name'] = _('%s (copy)', record.name)
    return vals_list

Checked in: 17.0/odoo/models.py:5483, 18.0/odoo/models.py:5851 · Odoo: #154132

BreakingRemoved in 18.0

Override _search_display_name instead of _name_search

_name_search is gone: name_search now searches display_name with search_fetch, so overrides of _name_search, and of search, are no longer called from it. To search other fields, return a domain from _search_display_name.

Before
@api.model
def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
    domain = ['|', ('code', operator, name), ('name', operator, name)] + (domain or [])
    return self._search(domain, limit=limit, order=order)
After
@api.model
def _search_display_name(self, operator, value):
    return ['|', ('code', operator, value), ('name', operator, value)]

Checked in: 17.0/odoo/models.py:1773, 18.0/odoo/models.py:1823, 18.0/odoo/models.py:1910

BreakingRemoved in 18.0

Split extra_trigger into its own tour step

Tour steps are validated against a schema without extra_trigger, so a tour that uses it fails. Add a step before it with the extra trigger as its trigger.

Before
{
    trigger: ".o_form_button_save",
    extra_trigger: ".o_form_editable",
}
After
{
    trigger: ".o_form_editable",
},
{
    trigger: ".o_form_button_save",
    run: "click",
}

Checked in: 17.0/addons/web_tour/static/src/tour_service/tour_compilers.js:67, 18.0/addons/web_tour/static/src/tour_service/tour_service.js:21

BreakingRemoved in 18.0

Rename the tree view type to list

The view type and the root tag are now list: ir.ui.view and window actions no longer accept tree. Change view_mode, view arches, Python and JS that name the type, and the tree_view_ref context key to list_view_ref. Keep XML IDs that contain tree so dependent modules don't break. Odoo ships a script: odoo-bin upgrade_code --script 17.5-01-tree-to-list.py.

Before
<field name="view_mode">tree,form</field>
<tree>
  <field name="name"/>
</tree>
context="{'tree_view_ref': 'my_module.view_x_tree'}"
After
<field name="view_mode">list,form</field>
<list>
  <field name="name"/>
</list>
context="{'list_view_ref': 'my_module.view_x_tree'}"

Checked in: 17.0/odoo/addons/base/models/ir_ui_view.py:163, 18.0/odoo/addons/base/models/ir_ui_view.py:153, 18.0/odoo/upgrade_code/17.5-01-tree-to-list.py · Odoo: #159909

BreakingRemoved in 18.0

Replace user_has_groups with env.user.has_groups

The model method user_has_groups is gone. res.users.has_groups takes the same comma-separated spec, with ! for negation; has_group checks a single group.

Before
if self.user_has_groups('base.group_system,!base.group_portal'):
After
if self.env.user.has_groups('base.group_system,!base.group_portal'):

Checked in: 17.0/odoo/models.py:1559, 18.0/odoo/addons/base/models/res_users.py:1159 · Odoo: #151597

Heads-upOptional since 18.0, the old way still works

Give window actions a path for readable URLs

Actions have a new path field. With it the URL reads /odoo/my-orders instead of /odoo/action-123.

Before
<record id="action_my_orders" model="ir.actions.act_window">
  <field name="name">My orders</field>
  <field name="res_model">my.order</field>
</record>
After
<record id="action_my_orders" model="ir.actions.act_window">
  <field name="name">My orders</field>
  <field name="res_model">my.order</field>
  <field name="path">my-orders</field>
</record>

Checked in: 18.0/odoo/addons/base/models/ir_actions.py:64

Heads-upDeprecated in 18.0, removed in 20.0

Rename the field attribute group_operator to aggregator

group_operator is mapped to aggregator with a deprecation warning in 18.0 and 19.0. In 20.0 it is an unknown parameter: a warning at startup, and the field falls back to the default aggregate.

Before
price_avg = fields.Float(group_operator='avg')
After
price_avg = fields.Float(aggregator='avg')

Checked in: 17.0/odoo/fields.py:323, 18.0/odoo/fields.py:480, 20.0/odoo/orm/fields.py:562 · Odoo: dd7a10aa

Heads-upDeprecated in 18.0, removed in 20.0

Call check_access instead of check_access_rights and check_access_rule

One method now checks both access rights and record rules; has_access returns a boolean instead of raising. _filter_access_rules and _filter_access_rules_python become _filtered_access. The old names log a deprecation warning in 18.0 and 19.0 and are gone in 20.0.

Before
self.check_access_rights('write')
self.check_access_rule('write')
allowed = records._filter_access_rules('read')
After
self.check_access('write')
if records.has_access('read'): ...
allowed = records._filtered_access('read')

Checked in: 17.0/odoo/models.py:4156, 18.0/odoo/models.py:4442, 19.0/odoo/orm/models.py:4168, 20.0/odoo/orm/models.py:3443 · Odoo: #179148

Heads-upOptional since 18.0, the old way still works

Translate with self.env._

self.env._ takes the language from the environment; the global _ has to find it in the caller's local variables (env, context or cr). Prefer it in model code.

Before
raise UserError(_('No lines to invoice.'))
After
raise UserError(self.env._('No lines to invoice.'))

Checked in: 18.0/odoo/api.py:788 · Odoo: #174844

Heads-upDeprecated in 18.0, removed in 20.0

Use _has_cycle instead of _check_recursion

_check_recursion and _check_m2m_recursion log a deprecation warning in 18.0 and 19.0 and are gone in 20.0. _has_cycle returns the opposite: True when there is a cycle.

Before
if not self._check_recursion():
    raise ValidationError(_('Recursive hierarchy.'))
After
if self._has_cycle():
    raise ValidationError(_('Recursive hierarchy.'))

Checked in: 17.0/odoo/models.py:5657, 18.0/odoo/models.py:6075, 19.0/odoo/orm/models.py:5707, 20.0/odoo/orm/models.py:5122

Heads-upDeprecated in 18.0, removed in 19.0

Rewrite kanban views with a card template

kanban-box still renders in 18.0 with a console warning; 19.0 requires a card template and raises without one. Inside card, fields are plain <field> elements, no wrapping divs; kanban-tooltip is gone, and the color picker is <field name="color" widget="kanban_color_picker"/>.

Before
<templates>
  <t t-name="kanban-box">
    <div class="oe_kanban_global_click">
      <strong><field name="name"/></strong>
      <ul class="oe_kanban_colorpicker" data-field="color"/>
    </div>
  </t>
</templates>
After
<templates>
  <t t-name="card">
    <field name="name" class="fw-bold"/>
    <field name="color" widget="kanban_color_picker"/>
  </t>
</templates>

Checked in: 18.0/addons/web/static/src/views/kanban/kanban_arch_parser.js:153, 19.0/addons/web/static/src/views/kanban/kanban_arch_parser.js:140 · Odoo: #167751

Heads-upOptional since 18.0, the old way still works

Drop the /** @odoo-module **/ comment

Every JS file under static/src and static/tests is now transpiled as a native module, with or without the comment. Remove it when you touch the file; keep @odoo-module ignore where you need it.

Before
/** @odoo-module **/
import { registry } from "@web/core/registry";
After
import { registry } from "@web/core/registry";

Checked in: 17.0/odoo/tools/js_transpiler.py:673, 18.0/odoo/tools/js_transpiler.py:675 · Odoo: #142858

Heads-upDeprecated in 18.0, removed in 19.0

Import Registry from odoo.modules.registry

odoo.registry() logs a deprecation warning in 18.0. In 19.0 the odoo package no longer has it, so the import fails.

Before
from odoo import registry
with registry(db_name).cursor() as cr: ...
After
from odoo.modules.registry import Registry
with Registry(db_name).cursor() as cr: ...

Checked in: 17.0/odoo/__init__.py:97, 18.0/odoo/__init__.py:37, 19.0/odoo/init.py · Odoo: #178784

Modules removed or renamed · 71

26 removed, 3 replaced, 8 renamed, 33 merged, 1 moved. If a custom module depends on one of these, change its depends before you upgrade.

ModuleIn Odoo 18Edition
account_consolidationConsolidationRemovedThe Consolidation app is replaced by shared accounts in Accounting.Enterprise
account_taxcloudAccount TaxCloudRemovedTaxCloud integration dropped.Enterprise
documents_spreadsheet_accountSpreadsheet Accounting TemplatesRemovedEnterprise
documents_spreadsheet_crmSpreadsheet CRM TemplatesRemovedEnterprise
l10n_account_customer_statementsAccounting Customer StatementsRemovedEnterprise
l10n_be_codabox_bridgeCodaBox BridgeRemovedAdded to 17.0 after its release; not in 18.0.Enterprise
l10n_be_us_consolidation_demoAccount Consolidation Demo DataRemovedRemoved with the Consolidation app.Enterprise
l10n_dk_ediDenmark - UNSPSC product codeRemovedEnterprise
l10n_in_reports_debit_noteIndian - GSTR eFiling for Debit NoteRemovedAdded to 17.0 after its release; not in 18.0.Enterprise
l10n_uk_customer_statementsUK - Customer StatementsRemovedEnterprise
mrp_subcontracting_studioMRP Subcontracting StudioRemovedIt was empty.Enterprise
payment_alipayPayment Provider: AlipayRemovedDeprecated payment provider.a4786d51Community
payment_payulatamPayment Provider: PayU LatamRemovedDeprecated payment provider.a4786d51Community
payment_payumoneyPayment Provider: PayUmoneyRemovedDeprecated payment provider.a4786d51Community
pos_mercuryVantiv Payment ServicesRemovedVantiv's API is deprecated.c9d3b596Community
sale_account_taxcloudAccount TaxCloud - SaleRemovedTaxCloud integration dropped.Enterprise
sale_amazon_taxcloudAmazon/TaxCloud BridgeRemovedTaxCloud integration dropped.Enterprise
sale_ebayeBay ConnectorRemovedThe eBay connector is gone.Enterprise
sale_loyalty_taxcloudAccount Taxcloud - Sale (loyalty)RemovedTaxCloud integration dropped.Enterprise
sale_loyalty_taxcloud_deliveryAccount Taxcloud - Sale (loyalty) - DeliveryRemovedTaxCloud integration dropped.Enterprise
sale_subscription_taxcloudTaxCloud and SubscriptionsRemovedTaxCloud integration dropped.Enterprise
stock_account_enterpriseStock account enterpriseRemovedIts dashboard had already been removed.Enterprise
website_event_twitter_wallConfigure a Twitter Wall on your EventRemovedThe Twitter apps are gone.Enterprise
website_sale_account_taxcloudAccount TaxCloud - EcommerceRemovedTaxCloud integration dropped.Enterprise
website_twitterTwitter SnippetRemovedThe Twitter snippet is gone.b2355d0cCommunity
website_twitter_wallTwitter WallRemovedThe Twitter apps are gone.Enterprise
payment_ogonePayment Provider: OgoneReplaced by payment_worldline34911deeCommunity
payment_sipsPayment Provider: Worldline SIPSReplaced by payment_worldline8be750a4Community
spreadsheet_dashboard_purchaseSpreadsheet dashboard for purchasesReplacedThe Purchase and Vendors dashboards became one dashboard, in Enterprise.bd3b26abCommunity
account_bacsUK BACS Payment FilesRenamed to l10n_uk_bacsEnterprise
account_sepaSEPA Credit TransferRenamed to account_iso20022Enterprise
hr_payroll_account_sepaSEPA Payments for PayrollRenamed to hr_payroll_account_iso20022Enterprise
l10n_au_keypayEmployment Hero Australian PayrollRenamed to l10n_employment_heroEnterprise
l10n_es_pos_tbaiSpain - POS + TicketBAIRenamed to l10n_es_edi_tbai_pos46096344Community
mrp_subonctracting_landed_costsLanded Costs With Subcontracting orderRenamed to mrp_subcontracting_landed_costsTypo in the name fixed.88bacc13Community
website_form_projectOnline Task SubmissionRenamed to website_projectd978e4d4Community
website_sale_pickingOn site Payment & PickingRenamed to website_sale_collectNow Click & Collect.087c48c4Community
account_audit_trailAccount Audit TrailMerged into accountThe audit trail is now a setting in Accounting.dd5d5d51Community
account_debit_note_sequenceDebit Note SequenceMerged into account_debit_noteAdded to 17.0 after its release; the separate debit note sequence is built in.Community
account_lockIrreversible Lock DateMerged into accountLock dates were reworked: a hard lock date that can't be lowered replaces this module.c73d4300Community
account_payment_termPayment Term - Days end of month on theMerged into accountAdded to 17.0 after its release.aa0cc769Community
account_reports_tax_reminderAccounting Reports Tax ReminderMerged into account_reportsEnterprise
data_mergeData Cleaning (merge)Merged into data_cleaningEnterprise
im_livechat_mail_botOdooBot for livechatMerged into mail_bot4643c028Community
l10n_be_codabox_bridge_wizardCodaBox Bridge WizardMerged into l10n_be_codaboxAdded to 17.0 after its release.Enterprise
l10n_br_avatax_servicesAvatax Brazil for ServicesMerged into l10n_br_avataxEnterprise
l10n_br_edi_sale_servicesAvatax Brazil Sale for ServicesMerged into l10n_br_edi_saleEnterprise
l10n_br_edi_servicesBrazilian Accounting EDI for servicesMerged into l10n_br_ediEnterprise
l10n_br_pixBrazil Pix QR codesMerged into l10n_br3c7887f4Community
l10n_ch_hr_payroll_elmSwitzerland - Payroll (ELM Standard)Merged into l10n_ch_hr_payrollEnterprise
l10n_cl_edi_boletasChile - Electronic ReceiptMerged into l10n_cl_ediEnterprise
l10n_de_audit_trailGermany - audit trailMerged into account and l10n_deThe audit trail moved to Accounting; the German localization turns it on by default.dd5d5d51Community
l10n_dk_audit_trailDenmark - audit trailMerged into l10n_dk2a1fd42bCommunity
l10n_dk_bookkeepingDenmark - Bookkeeping ActMerged into accountInvoices now always store and show the currency rate.bedffa80Community
l10n_es_edi_facturae_adm_centersSpain - Facturae EDI - Administrative Centers PatchMerged into l10n_es_edi_facturae0f5c89b4Community
l10n_es_edi_facturae_invoice_periodSpain - Facturae EDI - Invoice PeriodMerged into l10n_es_edi_facturaeb52701c1Community
l10n_es_edi_tbai_multi_refundTicketBAI multi refundMerged into l10n_es_edi_tbaiAdded to 17.0 after its release.Community
l10n_fr_fecFrance - FEC ExportMerged into l10n_fr_accountThe FEC export now runs on the report engine.0e71e2a3Community
l10n_fr_invoice_addrFrance - Adding Mandatory Invoice Mentions (Decree no. 2022-1299)Merged into l10n_fr_accountAdded to 17.0 after its release.Community
l10n_fr_reports_extendedFrance - Accounting Reports ExtensionMerged into l10n_fr_reportsAdded to 17.0 after its release.Enterprise
l10n_mx_edi_stock_30Mexico - Electronic Delivery Guide - Version 3.0Merged into l10n_mx_edi_stockCarta Porte 2.0 dropped.Enterprise
l10n_mx_edi_stock_extendedMexico - Electronic Delivery Guide ComexMerged into l10n_mx_edi_stockEnterprise
l10n_mx_edi_stock_extended_30Mexico - Electronic Delivery Guide Comex - Version 3.0Merged into l10n_mx_edi_stockCarta Porte 2.0 dropped.Enterprise
l10n_mx_edi_stock_extended_31Mexico - Electronic Delivery Guide Comex - Version 3.1Merged into l10n_mx_edi_stockEnterprise
l10n_ro_efacturaRomania - Send E-FacturaMerged into l10n_ro_ediAdded to 17.0 after its release.Community
pos_sale_product_configuratorPOS - Sale Product ConfiguratorMerged into pos_salefdcd3d58Community
sale_product_configuratorSale Product ConfiguratorMerged into salefdcd3d58Community
stock_landed_costs_companyLanded Costs for company's branchesMerged into stock_landed_costsAdded to 17.0 after its release.Community
website_sale_product_configuratorWebsite Sale Product ConfiguratorMerged into website_salefdcd3d58Community
website_sale_renting_product_configuratoreCommerce Rental with Product ConfiguratorMerged into website_sale_rentingEnterprise
spreadsheet_dashboard_purchase_stockSpreadsheet dashboard for purchasesMoved now in EnterpriseCommunity
New modules in Odoo 18 · 194

Community · 77

Enterprise · 117

  • account_bank_statement_extract
  • account_extract
  • account_iso20022
  • account_loans
  • account_no_followup
  • account_online_payment
  • accountant
  • appointment_google_reserve
  • appointment_microsoft_calendar
  • crm_sale_subscription
  • delivery_envia
  • documents_account_peppol
  • hr_payroll_account_iso20022
  • hr_recruitment_integration_base
  • hr_recruitment_integration_monster
  • hr_recruitment_integration_skills_monster
  • hr_recruitment_integration_website
  • hr_recruitment_integration_website_monster
  • industry_fsm_repair
  • l10n_ae_reports
  • l10n_bd_hr_payroll
  • l10n_bd_hr_payroll_account
  • l10n_be_hr_contract_salary_mobility_budget
  • l10n_be_hr_payroll_acerta
  • l10n_be_hr_payroll_dmfa_sftp
  • l10n_be_hr_payroll_group_s
  • l10n_be_hr_payroll_partena
  • l10n_be_hr_payroll_prisma
  • l10n_be_hr_payroll_ucm
  • l10n_bg_reports_ledger
  • l10n_br_avatax_sale
  • l10n_br_edi_pos
  • l10n_br_edi_stock
  • l10n_br_edi_website_sale
  • l10n_ca_payment_cpa005
  • l10n_cl_edi_factoring
  • l10n_cn_reports
  • l10n_co_dian
  • l10n_co_edi_mandate
  • l10n_co_edi_pos
  • l10n_do_check_printing
  • l10n_ec_edi_stock
  • l10n_eg_hr_payroll
  • l10n_eg_hr_payroll_account
  • l10n_employment_hero
  • l10n_eu_iot_scale_cert
  • l10n_fr_intrastat
  • l10n_fr_intrastat_services
  • l10n_gt_edi
  • l10n_hk_reports
  • l10n_id_hr_payroll
  • l10n_id_hr_payroll_account
  • l10n_in_enet_batch_payment
  • l10n_in_reports_tds_tcs
  • l10n_it_pos
  • l10n_jo_hr_payroll
  • l10n_jo_hr_payroll_account
  • l10n_kh_reports
  • l10n_kr_reports
  • l10n_lv_reports
  • l10n_lv_tax_report
  • l10n_mx_hr_payroll_localisation
  • l10n_my_hr_payroll
  • l10n_my_hr_payroll_account
  • l10n_nl_reports_vat_pay_wizard
  • l10n_nz_reports
  • l10n_pe_reports_lib
  • l10n_pk_hr_payroll
  • l10n_pk_hr_payroll_account
  • l10n_pl_reports_account_saft
  • l10n_pl_reports_jpk_fa
  • l10n_pl_reports_vat_eu
  • l10n_ro_saft_stock
  • l10n_se_bban
  • l10n_tr_hr_payroll
  • l10n_tr_hr_payroll_account
  • l10n_uk_bacs
  • l10n_uk_hmrc
  • l10n_uk_reports_cis
  • l10n_us_hr_payroll_adp
  • l10n_uy_edi_stock
  • l10n_vn_reports
  • marketing_automation_website_sale
  • marketing_automation_whatsapp
  • pos_avatax
  • pos_barcodelookup
  • pos_hr_preparation_display
  • pos_mobile
  • pos_no_followup
  • pos_restaurant_urban_piper
  • pos_sale_purchase_stock_inter_company_rules
  • pos_tyro
  • pos_urban_piper
  • pos_urban_piper_enhancements
  • pos_urban_piper_swiggy
  • pos_urban_piper_ubereats
  • pos_urban_piper_zomato
  • product_barcodelookup
  • project_enterprise_hr_skills
  • project_mrp_workorder_account
  • quality_repair
  • sale_commission
  • sale_commission_margin
  • sale_commission_subscription
  • sale_purchase_stock_inter_company_rules
  • sale_renting_planning
  • sale_renting_project
  • sale_shopee
  • sale_subscription_timesheet
  • spreadsheet_dashboard_marketing_automation
  • spreadsheet_sale_management
  • stock_barcode_barcodelookup
  • stock_fleet_enterprise
  • website_appointment_sale_project
  • website_generator_sale
  • website_product_barcodelookup
  • whatsapp_hr_referral

From the module lists of both branches. Community commits link to the change that removed the module; Enterprise code is private, so we only name its modules.

Breaking: action required · 1

Custom modules or integrations need a change before or during the upgrade.

Heads-up · 1

Behaviour changes to check in testing. Usually nothing to change.

Flagged in the weekly digest · 2

My stack

Pick the versions and apps you run. Weekly digests, this week's table and All changes then show only what concerns you. Saved in this browser.

Versions
Apps
Modules