A broad but mostly mechanical Inventory release for custom modules, dominated by the removal of copy behaviour overrides, a handful of pricelist and product fields disappearing, and a batch of unit-of-measure fields being renamed to a consistent name.
Odoo 20 was released on 24 September 2026. This guide covers Odoo 19 → 20 Inventory, Community Edition, built from the released version; Enterprise modules are not included in these counts. It counts 1,645 verified changes across 10 core modules.
One module disappears outright: stock_picking_batch is removed in Odoo 20 and batch and wave picking now live in stock. A manifest that depends on stock_picking_batch fails at install, so fix depends before anything else.
Start by treating this as two separate jobs. The first is field-level plumbing: several unit-of-measure fields have been renamed to a shorter, consistent uom_id, and a few fields on pricelists, products and settings are simply gone. Grep your module for those old names first, because any read, write, domain or view reference to a renamed or removed field will break loudly and is quick to fix. The second job is behavioural: Odoo has stripped out a number of copy_data overrides and a couple of routing/pricing helpers, so if your logic depended on the '(copy)' naming or on those helpers you'll need to adjust.
The areas most likely to bite are duplication/copy flows, pricelist item configuration, and anything touching product routes or supplier/lot units of measure.
What needs the closest look
Product document creation hook is gone
Removed method — ProductDocumentController.get_additional_create_params
This controller method existed purely as an extension point so other modules could inject extra values when a product document was created via the frontend. It has been removed, so if your module overrode it to add create parameters, that hook no longer fires — you'll need to move that logic into whatever create path now remains, or reintroduce the extension yourself.
Removed in Odoo 20 — it was defined as:
def get_additional_create_params(self, **kwargs):
Delivery carriers no longer auto-rename on duplicate
Removed method — delivery.carrier.copy_data
The carrier's copy override used to append '(copy)' to the name when you duplicated a record. It's been removed, so duplicated carriers keep the original name. If your module relied on that suffix to distinguish copies, add your own naming logic.
Removed in Odoo 20 — it was defined as:
def copy_data(self, default=None):
Product categories no longer auto-rename on duplicate
Removed method — product.category.copy_data
Same story as carriers: the category duplication no longer forces a '(copy)' suffix on the name. Anywhere you counted on duplicated categories being uniquely named, handle that explicitly.
Removed in Odoo 20 — it was defined as:
def copy_data(self, default=None):
Pricelists no longer auto-rename on duplicate
Removed method — product.pricelist.copy_data
The pricelist copy override that added '(copy)' to the name has been dropped. Duplicating a pricelist now preserves the name as-is, so revisit any code or test that assumed the renamed copy.
Removed in Odoo 20 — it was defined as:
def copy_data(self, default=None):
Pricelist rule 'applied on' selector removed
Removed field — product.pricelist.item.display_applied_on
This was the field driving whether a pricelist item applied to a product or a category. It's been removed, which means the underlying way rules are scoped has changed. If your module read or set display_applied_on on pricelist items, you must rework it against the current pricelist item structure.
Present in Odoo 19, removed in 20:
display_applied_on = fields.Selection(
selection=[
('1_product', "Product"),
('2_product_category', "Category"),
],
default='1_product',
required=True,
help="Pricelist Item applicable on selected option")
Percentage-based pricelist price removed
Removed field — product.pricelist.item.percent_price
The dedicated percentage price field on pricelist items is gone. Any custom rule creation or reporting that wrote to or read percent_price needs to be redirected to the remaining price computation fields on the item.
Present in Odoo 19, removed in 20:
percent_price = fields.Float(
string="Percentage Price",
help="You can apply a mark-up by setting a negative discount.")
The product 'total routes' extension point is gone
Removed method — product.product.get_total_routes
This method returned the full set of routes for a product and was designed for other modules to extend. With it removed, if your module overrode get_total_routes to add routes, that contribution point no longer exists — find where routes are now aggregated and hook in there instead.
Removed in Odoo 20 — it was defined as:
def get_total_routes(self):
Also worth checking
Duplication behaviour across the board. Beyond the carriers, categories and pricelists called out above, the copy_data overrides have also been removed from product tags, product templates and stock locations. The common thread is that Odoo has stopped forcing '(copy)' suffixes on duplicated records in Inventory. If any of your flows or tests depend on a duplicated record's name being changed automatically, add that behaviour yourself.
Unit-of-measure field renames. Several models have had their product_uom_id field renamed to the shorter uom_id: this affects product replenishment, supplier info, and stock lots. These are purely name changes, but they touch commonly-referenced records, so scan your domains, views and Python for the old product_uom_id on those models and update them.
Stock move destination rename. The move field that pointed at the final/forecasted location has been renamed from location_final_id to forecasted_location_id. If your module reasons about where a move ultimately lands, point at the new name.
Fields that simply disappeared. A few product and partner fields are gone entirely: the 'in selected section of order' flag and the 'exclude for' attribute-value field on products, the pickup-location flag on partners, and the reception-report setting group plus the bpost and DHL delivery module toggles in settings. If you referenced any of these in logic or views, remove or replace those references. Also note the write override on pricelist items has been removed, so any customisation that relied on chaining through it should be re-checked.
Beyond these, 728 smaller internal changes exist — only relevant if you override Odoo's private helpers or compute methods.
Your migration checklist
- Search your module for the renamed fields (
product_uom_idon replenish, supplierinfo and stock.lot, andlocation_final_idon stock.move) and update every reference to the new names. - Search for the removed fields (
display_applied_on,percent_price,is_in_selected_section_of_order,exclude_for,is_pickup_location, and the settings toggles) and remove or rework any code and views touching them. - Review every place you override or call the removed
copy_datamethods and the pricelist itemwrite, and reimplement the naming or write logic your module actually needs. - Find any use of the removed extension points —
get_additional_create_paramsandget_total_routes— and relocate that logic to the surviving code paths. - Rework pricelist item creation and pricing logic to fit the current item structure now that the applied-on selector and percentage price are gone.
- Run your full test suite on Odoo 20 and exercise every affected workflow end to end before go-live.