Web Widget One2Many Product Picker
Añade el widget móvil amigable 'one2many_product_picker' para crear líneas one2many vinculadas con registros product.product.
Traducción automática al español (DeepSeek) de la descripción original de OCA, que está en inglés.
auto_awesome Qué hace este módulo
Generado por IA a partir del código · Odoo 13.0Añade un widget selector de productos adaptado a dispositivos móviles para líneas one2many, permitiendo a los usuarios añadir, editar, eliminar y asignar precio a productos directamente desde una vista de tarjetas, a la vez que evita que el mismo producto se añada dos veces.
Este módulo añade un nuevo widget, el "one2many product picker", que se puede usar en campos one2many vinculados a productos. En lugar de una lista clásica, los usuarios obtienen un selector basado en tarjetas diseñado para pantallas móviles, donde pueden buscar y seleccionar productos y gestionar las líneas.
Desde el selector, los usuarios pueden: - Añadir una línea de producto mediante un formulario de creación rápida. - Cambiar una línea existente o descartar los cambios no guardados. - Eliminar una línea. - Abrir un pequeño formulario de precio para ajustar el precio unitario y el descuento, con el precio con descuento mostrado automáticamente.
El módulo también añade una regla del lado del servidor: cuando se crean o actualizan líneas a través del selector, Odoo comprueba que el mismo producto no se añada dos veces para el mismo registro padre. Si se encuentra un duplicado, se genera un error de validación y la línea no se guarda.
El widget es un componente técnico: aparece donde un desarrollador lo configure en un campo one2many, y funciona con registros product.product. No añade su propio menú ni informe.
Depende de
Lo necesitan otros módulos
Modelos y campos (1)
- base · amplía un modelo existente
Texto generado por IA (DeepSeek) al leer el código de la versión 13.0 en GitHub; puede contener errores, así que verifícalo en el código antes de decidir. El módulo es muy grande y solo se ha leído una parte del código. Ver el código en GitHub
Disponibilidad por versión
Revisado: 2026-11-03Estado de confirmación: 2 confirmadas, 7 sin información de 9 versiones.
Fuentes · Odoo 12.0
Confirmado el 2026-11-03 en la rama 12.0 de OCA/web.
terminal Instalación y uso
Documentación de OCA · Odoo 13.0Instalación
Fuente · Odoo 13.0Es recomendable instalar 'web_widget_numeric_step' para tener una mejor usabilidad en pantallas táctiles.
Configuración
Fuente · Odoo 13.0Cree o edite una nueva vista y utilice el nuevo widget llamado 'one2many_product_picker'. Debe definir los campos de la vista. La vista debe ser de tipo form.
Opciones del widget:
* groups > Array of dictionaries -> Declare the groups
* name -> The group name
* string -> The text displayed
* domain -> Forced domain to use
* order -> The order
* name -> The field name to order
* asc -> Flag to use 'asc' order
* records_per_page > Integer -> Used to control the load more behaviour (16 by default)
* active -> Boolean -> Select the default group to use ('false' by default = 'All' group)
* currency_field > Model field used to format monetary values ('currency_id' by default)
* field_map > Dictionary:
* product -> The field that represent the product (`product_id` by default)
* name -> The field that represent a name ('name' by default)
* product_uom -> The field that represent a product_uom ('product_uom' by default)
* product_uom_qty -> The field that represent a product_uom_qty ('product_uom_qty' by default)
* price_unit -> The field that represent a price_unit ('price_unit' by default)
* discount -> The field that represent a discount ('discount' by default)
* search > Array of dictionaries (defines to use name_search by default)
* name -> The name to display
* domain -> The domain to use
* $search -> Replaces it with the current value of the searchbox
* $number_search -> Replaces all the leaf with the current value of the searchbox as a number
* name_search_value -> Enables the use of 'name_search' instead of 'search_read' and defines the value to search ('$search' by default)
* operator -> Operator used in 'name_search' ('ilike' by default)
* edit_discount > Enable/Disable discount edits (False by default)
* edit_price > Enable/Disable price edits (True by default)
* show_discount > Enable/Disable display discount (False by default)
* show_subtotal > Enable/Disable show subtotal (True by default)
* auto_save > Enable/Disable auto save (False by default)
* auto_save_delay > The time (in milliseconds) to wait after the last interaction before launching the autosave (1500 by default)
* all_domain > The domain used in 'All' section ([] by default)
If using auto save feature, you should keep in mind that the "Save" and "Discard" buttons
will lose part of its functionality as the document will be saved every time you
modify/create a record with the widget.
* ignore_warning > Enable/Disable display onchange warnings (False by default)
* instant_search > Enable/Disable instant search mode (False by default)
* trigger_refresh_fields > Fields in the main record that dispatch a widget refresh (["partner_id", "currency_id"] by default)
* auto_focus > Keep the focus on the search box after performing a search (True by default)
All widget options are optional.
Notice that you can call '_' method to use translations. This only can be used with this widget.
Example:
.. code::
options="{'search': [{'name': _('Starts With'), 'domain': [('name', '=like', '$search%')]}], 'groups': [{'name': 'cheap', 'string': _('Cheap'), 'domain': [('list_price', '<', 10.0)], 'field_map': { 'product': 'my_product_id' }}]}"
Default context:El widget envía un contexto de valores predeterminados con la solicitud 'search_read':
- active_search_group_name > Contiene el nombre del grupo de búsqueda activo
- 'all' > Es el nombre codificado para el grupo 'All'
- 'main_lines' > Es el nombre codificado para el grupo 'Lines'
- active_search_involved_fields > Contiene un array de diccionarios con los campos utilizados con el contenido del cuadro de búsqueda
- 'type' > Puede ser 'text' o 'number'
- 'field' > El nombre del campo
- 'oper' > El operador utilizado
Ejemplos:
This is an example that uses the 'sale.order.line' fields:
.. code:: xml
<field
name="order_line"
attrs="{'readonly': [('state', 'in', ('done','cancel'))]}"
nolabel="1"
mode="form"
widget="one2many_product_picker"
options="{'search': [{'name': 'Test', 'domain': [['name', 'ilike', '$search']]}] ,'edit_discount': True, 'show_discount': True, 'groups': [{'name': 'desk', 'string': _('Desks'), 'domain': [('name', 'ilike', '%desk%')], 'order': [{'name': 'id', 'asc': true}]}, {'name': 'chair', 'string': _('Chairs'), 'domain': [('name', 'ilike', '%chair%')]}]}"
>
<form>
<field name="state" invisible="1" />
<field name="display_type" invisible="1" />
<field name="currency_id" invisible="1" />
<field name="discount" widget="numeric_step" options="{'max': 100}" invisible="1"/>
<field name="price_unit" widget="numeric_step" invisible="1"/>
<field name="name" invisible="1" />
<field name="product_id" invisible="1" />
<field name="order_id" invisible="1"/>
<field name="product_uom_qty" class="mb-1" widget="numeric_step" context="{
'partner_id': parent.partner_id,
'quantity': product_uom_qty,
'pricelist': parent.pricelist_id,
'uom': product_uom,
'company_id': parent.company_id
}" />
<field name="product_uom" force_save="1" attrs="{
'readonly': [('state', 'in', ('sale','done', 'cancel'))],
'required': [('display_type', '=', False)],
}" context="{'company_id': parent.company_id}" class="mb-2" options="{'no_open': True, 'no_create': True, 'no_edit': True}" />
</form>
</field>
** In this example we don't use 'field_map' option because the default match with the sale.order.line field names.
Other example for 'purchase.order.line' fields:
.. code:: xml
<field
name="order_line"
attrs="{'readonly': [('state', 'in', ('done','cancel'))]}"
nolabel="1"
widget="one2many_product_picker"
mode="form"
options="{'search': [{'name': _('Name'), 'domain': [['name', 'ilike', '$search']]}, {'name': _('Price'), 'domain': [['list_price', '=', $number_search]]}], 'field_map': {'product_uom_qty': 'product_qty'}, 'groups': [{'name': _('Desk'), 'domain': [['name', 'ilike', 'desk']], 'order': {'name': 'id', 'asc': true}}, {'name': _('Chairs'), 'domain': [['name', 'ilike', 'chair']]}]}"
>
<form>
<field name="name" invisible="1" />
<field name="product_id" invisible="1" />
<field name="price_unit" invisible="1" />
<field name="currency_id" invisible="1" />
<field name="order_id" invisible="1" />
<field name="date_planned" class="mb-1" />
<field name="product_qty" class="mb-1" widget="numeric_step" required="1" />
<field name="product_uom" class="mb-2" options="{'no_open': True, 'no_create': True, 'no_edit': True}" />
</form>
</field>
Boostrap Modifications:El contenedor de la vista del selector de productos tiene un espacio de media queries personalizado que añade un nuevo tamaño de pantalla llamado 'xxl' (>= 1440px) y modifica las columnas para tener 24 en lugar de 12. Esto significa que puede usar "col-xxl-" dentro del contenedor de la vista del selector de productos.
Cuando cambias el valor de un campo y pasas a editar otro registro, los cambios se aplican al registro anterior sin necesidad de hacer clic en aceptar cambios.
Partes del widget:
.. image:: ../static/img/product_picker_anat.png
Preview:Traducción automática al español (DeepSeek) de la documentación original de OCA; los comandos y el código no se traducen.
Las instrucciones de instalación, el paquete de distribución, las dependencias y los pasos de configuración no se muestran porque todavía no se han verificado en la documentación del módulo para ninguna versión.
Datos importados de GitHub: esta ficha refleja la última revisión del catálogo, no una consulta en directo. Verifica siempre en la documentación del módulo y en staging antes de instalar en producción.