# Odoo 19 to 20 Manufacturing migration: a guide for custom modules

> A broad but mostly surface-level release for manufacturing: the biggest recurring theme is a unit-of-measure field rename across BoMs and related models, plus the retirement of several maintenance and MRP helper methods and legacy fields.

Start by grepping your module for the unit-of-measure fields on BoMs, BoM lines, byproducts and the consumption-warning models — that single rename touches more places than anything else here and is the most likely source of silent breakage. Once that's clean, work through the removed helper methods, since anything you call or override from them will fail outright rather than degrade quietly.

The areas most likely to bite are the maintenance request/stage lifecycle (a couple of state fields and their scheduling logic are gone), the BoM structure and days-to-prepare reporting, and the consumption-warning flow around manufacturing orders. This guide tracks the Odoo 20 development branch while it is still pre-release, so treat it as a working map and expect a refresh at general availability.

## What needs the closest look

### Maintenance activity rescheduling is gone

*Removed method — `maintenance.request.activity_update`*

This method used to keep each maintenance request's scheduled activity in sync with its planned date — creating, rescheduling or removing the reminder as the date changed. It has been removed, so if your module called it after changing a request's schedule date, or overrode it to tweak that behaviour, you'll need to hook the activity handling in yourself or rely on the standard flow instead.

Removed in Odoo 20 — it was defined as:

```python
def activity_update(self):
```

### The manual archive flag on maintenance requests is dropped

*Removed field — `maintenance.request.archive`*

Requests previously carried their own boolean to hide them without deleting. That has been removed in favour of standard archiving. If your code reads or writes this field to hide requests, switch to the normal active/archive mechanism.

Present in Odoo 19, **removed in 20**:

```python
archive = fields.Boolean(default=False, help="Set archive to true to hide the maintenance request without deleting it.")
```

### The 'done' marker on maintenance stages is removed

*Removed field — `maintenance.stage.done`*

Stages no longer carry a dedicated flag to indicate a completed request. Anywhere you tested a stage for being a 'done' stage will break; rework that logic around the stage's position or fold-state as the standard now expects.

Present in Odoo 19, **removed in 20**:

```python
done = fields.Boolean('Request Done')
```

### Blocked request counter renamed to 'changes requested'

*Renamed field — `maintenance.team.todo_request_count_changes_requested`*

The team-level counter that tallied blocked requests has been renamed to reflect a 'changes requested' state, and its compute method changed accordingly. Update any view, filter or code referencing the old blocked-count field, and note the underlying meaning shifted, not just the name.

**Before — Odoo 19**

```python
todo_request_count_block = fields.Integer(string="Number of Requests Blocked", compute='_compute_todo_requests')
```

**After — Odoo 20**

```python
todo_request_count_changes_requested = fields.Integer(string="Number of Requests with Changes Requested", compute='_compute_todo_requests')
```

### BoM 'days to prepare' is no longer computed on demand

*Removed method — `mrp.bom.action_compute_bom_days`*

This action used to calculate a BoM's preparation lead time by pulling from the BoM structure report and component delays. It has been removed. If a button or automation in your module triggered this recompute, remove that call and lean on the standard computation of the days-to-prepare value.

Removed in Odoo 20 — it was defined as:

```python
def action_compute_bom_days(self):
```

### Consumption tolerance moved off the BoM

*Removed field — `mrp.bom.consumption`*

The selection that decided whether operators could over- or under-consume components (allowed, warning, or blocked) is no longer stored on the BoM itself. Any custom logic reading this setting to drive consumption checks needs to source that policy from wherever it now lives rather than from the BoM record.

Present in Odoo 19, **removed in 20**:

```python
consumption = fields.Selection([
        ('flexible', 'Allowed'),
        ('warning', 'Allowed with warning'),
        ('strict', 'Blocked')],
        help="Defines if you can consume more or less components than the quantity defined on the BoM:\n"
             "  * Allowed: allowed for all manufacturing users.\n"
             "  * Allowed with warning: allowed for all manufacturing users with summary of consumption differences when closing the manufacturing order.\n"
             "  Note that in the case of component Highlight Consumption, where consumption is registered manually exclusively, consumption warnings will still be issued when appropriate also.\n"
             "  * Blocked: only a manager can close a manufacturing order when the BoM consumption is not respected.",
        default='warning',
        string='Flexible Consumption',
        required=True
    )
```

### Byproduct unit field renamed to the shorter uom_id

*Renamed field — `mrp.bom.byproduct.uom_id`*

The byproduct's unit-of-measure field and its compute were renamed from the product-prefixed name to the plain uom_id. This is part of a consistent rename across manufacturing models, so update every reference on byproducts and expect the same change on sibling models below.

**Before — Odoo 19**

```python
product_uom_id = fields.Many2one('uom.uom', 'Unit', required=True,
                                     compute="_compute_product_uom_id", store=True, readonly=False, precompute=True)
```

**After — Odoo 20**

```python
uom_id = fields.Many2one('uom.uom', 'Unit', required=True,
                                     compute="_compute_uom_id", store=True, readonly=False, precompute=True)
```

## Also worth checking

**Unit-of-measure rename (do this everywhere).** The same unit field rename applied to the byproduct also lands on the BoM itself, on BoM lines, on the consumption-warning line, and on the production-split wizard. These all moved from the product-prefixed unit field to the plain uom_id. Treat this as one sweep across your manufacturing code and views — any reference to the old name on any of these models will break.

**Maintenance lifecycle.** Beyond the removed archive and scheduling logic covered above, the request model also loses its equipment-request helper, its own done flag, and the field that linked to a Google Slides instruction. If your module surfaced instructions or drove the equipment-request path, rework those against the current model.

**BoM attachments.** BoM lines no longer expose their attachment count or the action that opened attached documents. If your views showed that badge or wired up that button, remove them or point to the standard attachments widget.

**Manufacturing order actions.** Several production-order buttons are gone: planning based on component availability, opening the reception report, and the scrap shortcut. If any of your buttons, server actions or overrides call these, replace them with the current equivalents or drop them.

**Consumption warnings.** Both the consumption-warning record and its lines lose the consumption-policy field that mirrored the old BoM setting, consistent with removing that selection from the BoM.

Beyond these, 413 smaller internal changes exist — only relevant if you override Odoo's private helpers or compute methods.

## Your migration checklist

1. Search your codebase and views for the old product-prefixed unit fields on BoMs, BoM lines, byproducts, the consumption-warning line and the production-split wizard, and rename them to uom_id.
2. Find every call to the removed methods (maintenance activity update and equipment request, BoM days computation and attachment action, and the production planning/reception/scrap buttons) and either remove them or repoint to current behaviour.
3. Rework any logic depending on the dropped state fields — the maintenance archive and done flags, the maintenance stage done flag, and the consumption policy on BoMs and warnings.
4. Update the team dashboard counter reference from the old blocked-request field to the renamed changes-requested field, checking the meaning shift too.
5. Clean up views and buttons that showed the BoM line attachment count or the removed production-order actions.
6. Install the module against the pre-release branch, exercise the maintenance and manufacturing-order flows end to end, and plan a re-check at general availability.
