Skip to main content
iVentureTeam

sml_x2_many

The detailed operations list on a stock move. Its Add a line does not create an empty row: it opens the quants that actually hold the product, filtered to what is left after the lines you have already typed.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 27, 2026Updated September 8, 20266 min read
Technical namesml_x2_many
Field typesone2many, many2many
Viewsform, with an embedded list
Modulestock, the Inventory app
Used in core1 occurrence, the detailed operations on a stock move in stock
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0, Odoo 17.0
No-code setupNo. It is tied to the stock move and quant models
Alternativesone2many, pick_from, popover_widget, many2one_barcode

What the move line list does

Recording what was actually picked means saying which stock was taken: from which location, in which lot, in which package. Typed as free text that is slow and error prone, because the person filling it in has to know what is actually there.

This widget changes the add action on the detailed operations list. Instead of creating an empty move line, it opens a selection of the quants that genuinely hold the product, restricted to locations under the operation's source and to quants with stock on hand. You pick from what exists, and the move line is built from your choice.

It also does the arithmetic that makes repeated picking work. Lines you have already entered but not yet saved have not reduced anything in the database, so the widget subtracts them before deciding what to offer: a quant fully used up by your unsaved lines is not offered again, and a partially used one is.

What this means for your team

The gain is accuracy at the point of entry. Warehouse staff pick from a list of what is physically there rather than recalling location codes and lot numbers, which removes an entire class of correction later, and the corrections in inventory are the expensive kind because they move stock valuations.

The unsaved-quantity handling is what makes it usable for a real pick. Splitting a move across three lots means adding three lines in one sitting, and without that adjustment the second and third selections would show stock the first line had already taken. Getting that right is the difference between a feature people use and one they work around.

The fallback matters too. When the move is not configured to show quants, the add action behaves exactly like a normal list, so the same view serves both operations where picking from stock makes sense and those where it does not.

Supported options in Odoo 19

The widget declares no options of its own. It spreads the x2many descriptor, which declares none either, so the options dictionary is forwarded to the embedded list as CRUD settings. What governs the behavior are fields on the move and hardcoded view references, listed below. Read from stock_move_line_x2_many_field.js, Odoo 19.0.

OptionTypeWhat it does
show_quantfield on the moveRead literally. When false, the add action falls back to the standard behavior of creating an empty row, and none of the quant logic runs.
default_location_idcontext keyRead from the field's context. The quant selection is restricted to locations under it.
editablestring (list attribute)Set on the embedded list. Governs inline editing of the move lines themselves, independently of how they are added.

Two view references are hardcoded. The quant selection dialog and the quant creation form are named literally in the source, so the dialog always uses Odoo's simplified quant list and form rather than anything you configure. The widget also exposes an internal switch, documented in the source as an extension point for subcontracting, that decides whether only on-hand quants are offered.

Working examples

The core usage

<field name="move_line_ids" widget="sml_x2_many"/>

No options. The behavior is decided by the move's own data and by the context the view supplies.

The fields and context it reads

# on the move
show_quant        # gates the whole quant behavior
product_id        # restricts the selection
# from context
default_location_id  # restricts to locations under it

Without the gate field the add action behaves like a standard list; without the location in context the selection is not restricted by location.

The plain list instead

<field name="move_line_ids">
  <list editable="bottom"> ... </list>
</field>

Adds an empty row and asks the user to fill in location, lot and package by hand.

Subtracting what you have typed but not saved

The add action starts with a gate. If the move does not say quants should be shown, it delegates straight to the standard behavior and nothing else in the widget runs. That single check is what lets the same widget sit on every move line list.

When the gate is open, the widget first recomputes what it calls its dirty quant data: the quantities entered in the current, unsaved lines, grouped by the quant they came from. Those quantities have not touched the database, so the quant records still show them as available, and without this step the same stock would be offered twice.

It then builds the domain: the move's product, locations under the source location from context, and a positive quantity. When the on-hand switch is on, which it is by default, an additional condition restricts the selection to stock physically present. The unsaved quantities are then folded in, splitting the quants into those fully consumed, which are excluded, and those partially consumed, which remain.

The dialog itself is a select-or-create using a named simplified quant list, with a title naming the product, and a context marking it as a single product selection. Choosing rows creates the corresponding move lines; choosing to create instead opens the quant form, and the newly created quant is then selected, so even the create path ends with a real quant behind the line.

A small courtesy in the create path: the widget remembers which element had focus and restores it when the dialog closes, so keyboard entry continues where it left off.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Byte-identical to Odoo 19 on the development branch.
Odoo 19.0VerifiedVerified against the shipped source.
Odoo 18.0VerifiedSame quant selection and unsaved quantity handling.
Odoo 17.0VerifiedFirst version.
Odoo 16.0Not availableWidget does not exist. Detailed operations were entered as plain rows.

Upgrade note. No view change is needed between Odoo 17 and Odoo 19. The widget does not exist in Odoo 16, where detailed operations were entered as plain rows. Custom move views that replaced the move line field should adopt the widget to get quant-based picking.

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.

Byte-identical. The file on the development branch matches Odoo 19 exactly, including the unsaved-quantity handling and the hardcoded view references. Nothing about this widget changes in Odoo 20.

Common problems and fixes

SymptomCause and fix
Add a line creates an empty row instead of opening the dialogThe move's quant flag is false, which gates the whole behavior. Expected on operations where picking from stock does not apply. Check the flag if you believe it should.
The dialog offers no quantsThere is no stock for the product under the source location, or the on-hand restriction excludes it. Check the product's on-hand quantities in that location branch.
The same stock is offered twiceThe unsaved line quantities were not recomputed, usually because a customization bypassed the add handler. Add lines through the widget's own action rather than a custom button.
A quant I expected is missingIt is fully consumed by lines you have already entered but not saved. Expected. Save the lines to see the real remaining stock.
The dialog uses the wrong list viewThe quant list and form views are named literally in the source. They cannot be changed from XML; extend the widget if a different view is required.
The selection ignores the locationThe field's context does not carry the source location default. Supply it in the field's context, as the core move view does.

Move line list vs the alternatives

WidgetBest forKey difference
sml_x2_manyRecording what was actually picked, by choosing from real on-hand stockReplaces the add action with a quant selection that accounts for lines you have typed but not saved
one2manyMove lines entered by handAdds an empty row with no knowledge of what stock exists
pick_fromShowing where a line was picked fromA display cell summarizing location, lot and package rather than a picker
popover_widgetExplaining a row's exceptionContextual notes rather than record creation
many2one_barcodeScanning to select a recordA relation picker with scanning, not a quant selection

Use a plain child list wherever the lines are not about physical stock, and this widget wherever they are. If your process needs picking from stock on a model that is not a stock move, the extension point the source documents is the intended route: subclass and override the on-hand switch rather than copying the whole file.

Frequently asked questions

Why does Add a line open a dialog?+
Because the widget replaces the add action with a selection of quants that actually hold the product, restricted to locations under the operation's source and to stock on hand. You pick from what exists rather than typing it.
Why is a quant missing from the list?+
Most likely it is fully consumed by lines you have already entered but not yet saved. The widget subtracts unsaved quantities before deciding what to offer.
When does it behave like a normal list?+
When the move's quant flag is false. That gate is checked first, and everything else in the widget is skipped.
Can I change the views used in the dialog?+
Not from XML. The simplified quant list and the quant form are named literally in the source, so a different view requires extending the widget.
Which versions have it?+
Odoo 17 onwards. It does not exist in Odoo 16, and the file is byte-identical between Odoo 19 and the Odoo 20 development branch.

Stock figures your finance team can rely on

Accurate picking, lot tracking and the valuation that follows are one chain, and it breaks at data entry. We implement Odoo Inventory so what gets recorded matches what moved, on versions 16 through 19.

Book a free consultation

How this page was produced

The gate on the move's quant flag, the unsaved quantity adjustment, the selection domain, the hardcoded quant list and form references, the create path and the focus restoration were read from stock_move_line_x2_many_field.js on the Odoo 19.0 branch, with the usage taken from stock/views/stock_move_views.xml. Version coverage comes from the absence of the file on 16.0, comparisons with 17.0 and 18.0, and a byte comparison against the public development branch. Spotted an error? Tell us and we will correct the page.