Skip to main content
iVentureTeam

move_product_label_field

The product cell on a transfer line, with the delivery description tucked underneath it. Its most useful behavior is knowing when that description is worth showing at all.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 27, 2026Updated September 7, 20265 min read
Technical namemove_product_label_field
Field typesmany2one
Viewslist, inside the operations list
Modulestock, the Inventory app
Used in core1 occurrence, the product column of the operations list in stock
VersionsOdoo 20.0, Odoo 19.0
No-code setupNo. It reads a picking-specific description field and the parent transfer's state
Alternativesproduct_label_section_and_note_field, many2one, sol_product_many2one, stock_move_one2many

What the move product cell does

A stock move carries a product and, separately, a description used on the delivery paperwork. Often that description is just the product's name, because nobody changed it. Sometimes it is genuinely different: a customer reference, a packing instruction, a variant note.

This widget renders both in one cell, the product on top and the description beneath it, and applies one rule: if the description matches the product's name, it is treated as empty and nothing is shown. That keeps the list clean in the common case and informative in the rare one.

It also decides when the description can be edited. Being on a read-only field is not enough: the transfer itself has to be done or canceled. On a locked but not finished transfer the description remains editable, which is the behavior warehouse staff expect when they are correcting paperwork.

What this means for your team

Delivery descriptions are one of those fields that is either invisible or important, with nothing in between. Printing the product name twice on every line makes an operations list harder to scan and a delivery note look sloppy, and hiding the description entirely loses the instruction someone deliberately wrote.

The rule this widget applies, show it only when it differs, is the right compromise and worth copying anywhere you have a description that defaults to a name. It costs nothing and removes visual noise from the screen people work in all day.

Supported options in Odoo 19

The widget is registered through the shared many2one description builder, so it declares the full relation option set and adds none of its own. Two field names and a parent field drive its behavior instead, and those are described in the note. Read from the widget's source and the relation field, Odoo 19.0.

OptionTypeWhat it does
description_pickingfield on the moveRead by literal name. Rendered under the product, unless it is identical to the product's display name, in which case it is treated as empty.(since Odoo 19.0)
no_openbooleanInherited from the relation field. Removes the link that opens the product record.(default: false)
no_createbooleanInherited. Removes creation from the product dropdown.(default: false)
no_quick_createbooleanInherited. Removes creation from the typed text while keeping the popup form path.(default: false)
search_thresholdnumberInherited. Minimum typed characters before the product search runs.

Two things are read by literal name. The description comes from the move's picking-specific description field, and the read-only decision reads the parent record's state through the evaluation context. The second means the widget only behaves correctly inside a form that has such a parent; on a standalone list the parent lookup has nothing to read.

Working examples

The core usage

<field name="product_id"
       widget="move_product_label_field"
       context="{'default_is_storable': True}"
       required="1" force_save="1"/>

Inside the operations list on a transfer. The description column itself is not declared; the widget renders it under the product.

Restricting the product dropdown

<field name="product_id"
       widget="move_product_label_field"
       options="{'no_create': True, 'no_open': True}"/>

Inherited from the relation field, since the widget is built from the shared description builder.

The field it reads underneath

# on the move, read by literal name
description_picking
# blanked for display when equal to the product name

Not declared as a dependency, so the move must carry it.

Why an identical description is treated as no description

Three small overrides make up the widget.

The label getter reads the description field, compares it with the product's display name, and returns an empty string when they match, trimming otherwise. That comparison is exact, so a description differing only in trailing whitespace is still shown, and one differing in case is shown too.

The read-only getter is the interesting one. It requires both that the field itself is read-only and that the parent record's state is done or canceled. Reading the parent through the evaluation context is what ties the widget to a form context; in a standalone list there is no parent, and the lookup would fail rather than degrade.

The visibility toggle for the label follows from those two: it is offered when the description is editable, the column is showing both product and label, and there is no label yet. In other words, the affordance to add a description appears exactly when adding one is possible and useful.

The last override neutralizes the parent's label parsing, keeping whatever the user typed verbatim. On sales and purchase lines the parent widget interprets the typed value; here the delivery description is taken literally.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Behavior identical on the development branch; internals follow the shared component.
Odoo 19.0VerifiedFirst version, with the rewritten operations list. Verified against the shipped source.
Odoo 18.0Not availableWidget does not exist. The product column was a plain relation field.
Odoo 17.0Not availableWidget does not exist.
Odoo 16.0Not availableWidget does not exist.

Upgrade note. The widget is new in Odoo 19, together with the rewritten operations list. On Odoo 18 and earlier the product column used a plain relation field and the description was a separate column, so an upgrade changes the appearance of the operations list without needing any view change.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. The development branch is unstable and this may still change; we re-verify the page after release.

No behavior change. The label rule, the read-only condition and the literal parsing are identical on the development branch. The differences are internal, following the wider migration of the shared product label component it extends.

Common problems and fixes

SymptomCause and fix
The description never showsIt is identical to the product's name, which the widget treats as empty. Expected. Edit the description to something different and it appears.
The description cannot be edited on a locked transferThe field is read-only and the transfer is done or canceled, which is the only combination that locks the description. Expected. Reset the transfer to draft if the paperwork genuinely has to change.
An error about reading the parent stateThe widget is used outside a form that provides a parent record. Use it only inside the operations list on a transfer form, or use a plain relation field.
The description column is missing entirelyThe move does not carry the picking description field. Make sure the field exists on the model; the widget reads it by literal name.
The add label affordance does not appearIt is offered only when the description is editable, the column shows both product and label, and there is no description yet. Check all three conditions.
Typed descriptions are altered on saveSomething other than this widget is parsing the value; this one keeps it verbatim. Check for a customization on the description field.

Move product cell vs the alternatives

WidgetBest forKey difference
move_product_label_fieldThe product column on transfer operations, with its delivery descriptionHides the description when it repeats the product name, and unlocks it unless the transfer is finished
product_label_section_and_note_fieldThe product cell on sales and purchase documentsSame idea without the picking description or the parent state check
many2oneA plain product relationNo description underneath and no parent dependency
sol_product_many2oneThe product cell on sale order linesAdds combo and configurator handling instead
stock_move_one2manyThe list this cell lives inThe list widget rather than a cell

On sales and purchase documents, the shared product label field is the right widget and has the same idea without the picking-specific description and parent state check. On a standalone list with no parent form, a plain relation field is safer, because the read-only rule here needs a parent to read.

Frequently asked questions

Why is the delivery description not shown?+
Because it is identical to the product's name. The widget compares the two and treats a matching description as empty, so the same text is never printed twice.
When can the description be edited?+
Unless the field is read-only and the transfer is done or canceled. A locked but unfinished transfer still allows the description to be corrected.
Can I use it outside a transfer?+
Not safely. The read-only rule reads the parent record's state through the evaluation context, so it needs a parent form. Use a plain relation field elsewhere.
Which options does it accept?+
The full relation option set, because it is registered through the shared many2one description builder. It declares nothing extra of its own.
Which versions have it?+
Odoo 19 onwards, introduced with the rewritten operations list. Earlier versions used a plain relation field with a separate description column.

Delivery paperwork that says what your customer needs

Line descriptions, packing instructions and document layouts are small settings with a direct effect on delivery disputes. We tune Odoo Inventory documents and the data behind them, on versions 16 through 19.

Book a free consultation

How this page was produced

The label rule, the read-only condition, the label toggle and the literal parsing were read from stock_move_product_label.js on the Odoo 19.0 branch, with the inherited behavior read from the shared product name and description component in the product module and the relation description builder in web. The usage comes from stock/views/stock_picking_views.xml. Version coverage comes from the absence of the file on 16.0, 17.0 and 18.0, and a comparison against the public development branch. Spotted an error? Tell us and we will correct the page.