mirror of https://github.com/OCA/web.git
[IMP] web_widget_one2many_product_picker: Modify rpc request context
parent
148b60b6fb
commit
f36b75005d
|
@ -37,6 +37,141 @@ Installation
|
|||
|
||||
It's advisable to install 'web_widget_numeric_step' to have a better usability on touch screens.
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
Create or edit a new view and use the new widget called 'one2many_product_picker'.
|
||||
You need to define the view fields. The view must be of ``form`` type.
|
||||
|
||||
|
||||
Widget options:
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
* product_per_page > Integer -> Used to control the load more behaviour (16 by default)
|
||||
* 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
|
||||
|
||||
* 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 or Array of 'triplets' ([[field_map.name, 'ilike', '$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
|
||||
|
||||
* 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)
|
||||
|
||||
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:
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
The widget sends a defaults context with the 'search_read' request:
|
||||
|
||||
* active_search_group_name > Contains the name of the active search group
|
||||
|
||||
* 'all' > Is the hard-coded name for the 'All' group
|
||||
* 'main_lines' > Is the hard-coded name for the 'Lines' group
|
||||
|
||||
* active_search_involved_fields > Contains an array of dictionaries with the fields used with the searchbox content
|
||||
|
||||
* 'type' > Can be 'text' or 'number'
|
||||
* 'field' > The field name
|
||||
* 'oper' > The operator used
|
||||
|
||||
|
||||
Examples:
|
||||
~~~~~~~~~
|
||||
|
||||
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>
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
|
@ -87,7 +222,7 @@ Other example for 'purchase.order.line' fields:
|
|||
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': {'name': 'name', 'product': 'product_id', 'product_uom': 'product_uom', 'price': 'price_unit', 'parent_id': 'order_id', 'product_uom_qty': 'product_qty'}, 'groups': [{'name': _('Desk'), 'domain': [['name', 'ilike', 'desk']], 'order': {'name': 'id', 'asc': true}}, {'name': _('Chairs'), 'domain': [['name', 'ilike', 'chair']]}]}"
|
||||
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" />
|
||||
|
@ -114,6 +249,12 @@ The widget sends a defaults context with the 'search_read' request:
|
|||
* 'all' > Is the hard-coded name for the 'All' group
|
||||
* 'main_lines' > Is the hard-coded name for the 'Lines' group
|
||||
|
||||
* active_search_involved_fields > Contains an array of dictionaries with the fields used with the searchbox content
|
||||
|
||||
* 'type' > Can be 'text' or 'number'
|
||||
* 'field' > The field name
|
||||
* 'oper' > The operator used
|
||||
|
||||
|
||||
Preview:
|
||||
~~~~~~~~
|
||||
|
@ -124,7 +265,7 @@ Known issues / Roadmap
|
|||
======================
|
||||
|
||||
* Translations in the xml 'options' attribute of the field that use the widget can't be exported automatically to be translated
|
||||
* The product card animations can be improved. Currently the card is recreated, so we lost some states to apply correct effects.
|
||||
* The product card animations can be improved. Currently the card is recreated, so we lost some elements to apply correct effects.
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
Create or edit a new view and use the new widget called 'one2many_product_picker'.
|
||||
|
||||
Widget options:
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
* product_per_page > Integer -> Used to control the load more behaviour (16 by default)
|
||||
* 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
|
||||
|
||||
* 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 or Array of 'triplets' ([[field_map.name, 'ilike', '$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
|
||||
|
||||
* 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)
|
||||
|
||||
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' }}]}"
|
|
@ -1 +0,0 @@
|
|||
It's recommendable install 'web_widget_numeric_step' to have a better usability on touch screens.
|
|
@ -0,0 +1,131 @@
|
|||
Create or edit a new view and use the new widget called 'one2many_product_picker'.
|
||||
You need to define the view fields. The view must be of ``form`` type.
|
||||
|
||||
|
||||
Widget options:
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
* product_per_page > Integer -> Used to control the load more behaviour (16 by default)
|
||||
* 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
|
||||
|
||||
* 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 or Array of 'triplets' ([[field_map.name, 'ilike', '$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
|
||||
|
||||
* 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)
|
||||
|
||||
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:
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
The widget sends a defaults context with the 'search_read' request:
|
||||
|
||||
* active_search_group_name > Contains the name of the active search group
|
||||
|
||||
* 'all' > Is the hard-coded name for the 'All' group
|
||||
* 'main_lines' > Is the hard-coded name for the 'Lines' group
|
||||
|
||||
* active_search_involved_fields > Contains an array of dictionaries with the fields used with the searchbox content
|
||||
|
||||
* 'type' > Can be 'text' or 'number'
|
||||
* 'field' > The field name
|
||||
* 'oper' > The operator used
|
||||
|
||||
|
||||
Examples:
|
||||
~~~~~~~~~
|
||||
|
||||
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>
|
|
@ -1,2 +1,2 @@
|
|||
* Translations in the xml 'options' attribute of the field that use the widget can't be exported automatically to be translated
|
||||
* The product card animations can be improved. Currently the card is recreated, so we lost some states to apply correct effects.
|
||||
* The product card animations can be improved. Currently the card is recreated, so we lost some elements to apply correct effects.
|
||||
|
|
|
@ -45,7 +45,7 @@ Other example for 'purchase.order.line' fields:
|
|||
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': {'name': 'name', 'product': 'product_id', 'product_uom': 'product_uom', 'price': 'price_unit', 'parent_id': 'order_id', 'product_uom_qty': 'product_qty'}, 'groups': [{'name': _('Desk'), 'domain': [['name', 'ilike', 'desk']], 'order': {'name': 'id', 'asc': true}}, {'name': _('Chairs'), 'domain': [['name', 'ilike', 'chair']]}]}"
|
||||
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" />
|
||||
|
@ -72,6 +72,12 @@ The widget sends a defaults context with the 'search_read' request:
|
|||
* 'all' > Is the hard-coded name for the 'All' group
|
||||
* 'main_lines' > Is the hard-coded name for the 'Lines' group
|
||||
|
||||
* active_search_involved_fields > Contains an array of dictionaries with the fields used with the searchbox content
|
||||
|
||||
* 'type' > Can be 'text' or 'number'
|
||||
* 'field' > The field name
|
||||
* 'oper' > The operator used
|
||||
|
||||
|
||||
Preview:
|
||||
~~~~~~~~
|
||||
|
|
|
@ -372,28 +372,194 @@ ul.auto-toc {
|
|||
<p><strong>Table of contents</strong></p>
|
||||
<div class="contents local topic" id="contents">
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#installation" id="id1">Installation</a></li>
|
||||
<li><a class="reference internal" href="#usage" id="id2">Usage</a><ul>
|
||||
<li><a class="reference internal" href="#default-context" id="id3">Default context:</a></li>
|
||||
<li><a class="reference internal" href="#preview" id="id4">Preview:</a></li>
|
||||
<li><a class="reference internal" href="#installation" id="id2">Installation</a></li>
|
||||
<li><a class="reference internal" href="#configuration" id="id3">Configuration</a><ul>
|
||||
<li><a class="reference internal" href="#widget-options" id="id4">Widget options:</a></li>
|
||||
<li><a class="reference internal" href="#default-context" id="id5">Default context:</a></li>
|
||||
<li><a class="reference internal" href="#examples" id="id6">Examples:</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#known-issues-roadmap" id="id5">Known issues / Roadmap</a></li>
|
||||
<li><a class="reference internal" href="#bug-tracker" id="id6">Bug Tracker</a></li>
|
||||
<li><a class="reference internal" href="#credits" id="id7">Credits</a><ul>
|
||||
<li><a class="reference internal" href="#authors" id="id8">Authors</a></li>
|
||||
<li><a class="reference internal" href="#contributors" id="id9">Contributors</a></li>
|
||||
<li><a class="reference internal" href="#maintainers" id="id10">Maintainers</a></li>
|
||||
<li><a class="reference internal" href="#usage" id="id7">Usage</a><ul>
|
||||
<li><a class="reference internal" href="#id1" id="id8">Default context:</a></li>
|
||||
<li><a class="reference internal" href="#preview" id="id9">Preview:</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#known-issues-roadmap" id="id10">Known issues / Roadmap</a></li>
|
||||
<li><a class="reference internal" href="#bug-tracker" id="id11">Bug Tracker</a></li>
|
||||
<li><a class="reference internal" href="#credits" id="id12">Credits</a><ul>
|
||||
<li><a class="reference internal" href="#authors" id="id13">Authors</a></li>
|
||||
<li><a class="reference internal" href="#contributors" id="id14">Contributors</a></li>
|
||||
<li><a class="reference internal" href="#maintainers" id="id15">Maintainers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="installation">
|
||||
<h1><a class="toc-backref" href="#id1">Installation</a></h1>
|
||||
<h1><a class="toc-backref" href="#id2">Installation</a></h1>
|
||||
<p>It’s advisable to install ‘web_widget_numeric_step’ to have a better usability on touch screens.</p>
|
||||
</div>
|
||||
<div class="section" id="configuration">
|
||||
<h1><a class="toc-backref" href="#id3">Configuration</a></h1>
|
||||
<p>Create or edit a new view and use the new widget called ‘one2many_product_picker’.
|
||||
You need to define the view fields. The view must be of <tt class="docutils literal">form</tt> type.</p>
|
||||
<div class="section" id="widget-options">
|
||||
<h2><a class="toc-backref" href="#id4">Widget options:</a></h2>
|
||||
<ul>
|
||||
<li><p class="first">product_per_page > Integer -> Used to control the load more behaviour (16 by default)</p>
|
||||
</li>
|
||||
<li><p class="first">groups > Array of dictionaries -> Declare the groups</p>
|
||||
<blockquote>
|
||||
<ul>
|
||||
<li><p class="first">name -> The group name</p>
|
||||
</li>
|
||||
<li><p class="first">string -> The text displayed</p>
|
||||
</li>
|
||||
<li><p class="first">domain -> Forced domain to use</p>
|
||||
</li>
|
||||
<li><p class="first">order -> The order</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>name -> The field name to order</li>
|
||||
<li>asc -> Flag to use ‘asc’ order</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</li>
|
||||
<li><p class="first">currency_field > Model field used to format monetary values (‘currency_id’ by default)</p>
|
||||
</li>
|
||||
<li><p class="first">field_map > Dictionary:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>product -> The field that represent the product (<cite>product_id</cite> by default)</li>
|
||||
<li>name -> The field that represent a name (‘name’ by default)</li>
|
||||
<li>product_uom -> The field that represent a product_uom (‘product_uom’ by default)</li>
|
||||
<li>product_uom_qty -> The field that represent a product_uom_qty (‘product_uom_qty’ by default)</li>
|
||||
<li>price_unit -> The field that represent a price_unit (‘price_unit’ by default)</li>
|
||||
<li>discount -> The field that represent a discount (‘discount’ by default)</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</li>
|
||||
<li><p class="first">search > Array of dictionaries or Array of ‘triplets’ ([[field_map.name, ‘ilike’, ‘$search’]] by default)</p>
|
||||
<blockquote>
|
||||
<ul>
|
||||
<li><p class="first">name -> The name to display</p>
|
||||
</li>
|
||||
<li><p class="first">domain -> The domain to use</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>$search -> Replaces it with the current value of the searchbox</li>
|
||||
<li>$number_search -> Replaces all the leaf with the current value of the searchbox as a number</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</li>
|
||||
<li><p class="first">edit_discount > Enable/Disable discount edits (False by default)</p>
|
||||
</li>
|
||||
<li><p class="first">edit_price > Enable/Disable price edits (True by default)</p>
|
||||
</li>
|
||||
<li><p class="first">show_discount > Enable/Disable display discount (False by default)</p>
|
||||
</li>
|
||||
<li><p class="first">show_subtotal > Enable/Disable show subtotal (True by default)</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>All widget options are optional.
|
||||
Notice that you can call ‘_’ method to use translations. This only can be used with this widget.</p>
|
||||
<p>Example:</p>
|
||||
<pre class="code literal-block">
|
||||
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' }}]}"
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section" id="default-context">
|
||||
<h2><a class="toc-backref" href="#id5">Default context:</a></h2>
|
||||
<p>The widget sends a defaults context with the ‘search_read’ request:</p>
|
||||
<blockquote>
|
||||
<ul>
|
||||
<li><p class="first">active_search_group_name > Contains the name of the active search group</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>‘all’ > Is the hard-coded name for the ‘All’ group</li>
|
||||
<li>‘main_lines’ > Is the hard-coded name for the ‘Lines’ group</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</li>
|
||||
<li><p class="first">active_search_involved_fields > Contains an array of dictionaries with the fields used with the searchbox content</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>‘type’ > Can be ‘text’ or ‘number’</li>
|
||||
<li>‘field’ > The field name</li>
|
||||
<li>‘oper’ > The operator used</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</div>
|
||||
<div class="section" id="examples">
|
||||
<h2><a class="toc-backref" href="#id6">Examples:</a></h2>
|
||||
<p>This is an example that uses the ‘sale.order.line’ fields:</p>
|
||||
<pre class="code xml literal-block">
|
||||
<span class="nt"><field</span>
|
||||
<span class="na">name=</span><span class="s">"order_line"</span>
|
||||
<span class="na">attrs=</span><span class="s">"{'readonly': [('state', 'in', ('done','cancel'))]}"</span>
|
||||
<span class="na">nolabel=</span><span class="s">"1"</span>
|
||||
<span class="na">mode=</span><span class="s">"form"</span>
|
||||
<span class="na">widget=</span><span class="s">"one2many_product_picker"</span>
|
||||
<span class="na">options=</span><span class="s">"{'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%')]}]}"</span>
|
||||
<span class="nt">></span>
|
||||
<span class="nt"><form></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"state"</span> <span class="na">invisible=</span><span class="s">"1"</span> <span class="nt">/></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"display_type"</span> <span class="na">invisible=</span><span class="s">"1"</span> <span class="nt">/></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"currency_id"</span> <span class="na">invisible=</span><span class="s">"1"</span> <span class="nt">/></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"discount"</span> <span class="na">widget=</span><span class="s">"numeric_step"</span> <span class="na">options=</span><span class="s">"{'max': 100}"</span> <span class="na">invisible=</span><span class="s">"1"</span><span class="nt">/></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"price_unit"</span> <span class="na">widget=</span><span class="s">"numeric_step"</span> <span class="na">invisible=</span><span class="s">"1"</span><span class="nt">/></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"name"</span> <span class="na">invisible=</span><span class="s">"1"</span> <span class="nt">/></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"product_id"</span> <span class="na">invisible=</span><span class="s">"1"</span> <span class="nt">/></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"order_id"</span> <span class="na">invisible=</span><span class="s">"1"</span><span class="nt">/></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"product_uom_qty"</span> <span class="na">class=</span><span class="s">"mb-1"</span> <span class="na">widget=</span><span class="s">"numeric_step"</span> <span class="na">context=</span><span class="s">"{
|
||||
'partner_id': parent.partner_id,
|
||||
'quantity': product_uom_qty,
|
||||
'pricelist': parent.pricelist_id,
|
||||
'uom': product_uom,
|
||||
'company_id': parent.company_id
|
||||
}"</span> <span class="nt">/></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"product_uom"</span> <span class="na">force_save=</span><span class="s">"1"</span> <span class="na">attrs=</span><span class="s">"{
|
||||
'readonly': [('state', 'in', ('sale','done', 'cancel'))],
|
||||
'required': [('display_type', '=', False)],
|
||||
}"</span> <span class="na">context=</span><span class="s">"{'company_id': parent.company_id}"</span> <span class="na">class=</span><span class="s">"mb-2"</span> <span class="na">options=</span><span class="s">"{'no_open': True, 'no_create': True, 'no_edit': True}"</span> <span class="nt">/></span>
|
||||
<span class="nt"></form></span>
|
||||
<span class="nt"></field></span>
|
||||
</pre>
|
||||
<p>** In this example we don’t use ‘field_map’ option because the default match with the sale.order.line field names.</p>
|
||||
<p>Other example for ‘purchase.order.line’ fields:</p>
|
||||
<pre class="code xml literal-block">
|
||||
<span class="nt"><field</span>
|
||||
<span class="na">name=</span><span class="s">"order_line"</span>
|
||||
<span class="na">attrs=</span><span class="s">"{'readonly': [('state', 'in', ('done','cancel'))]}"</span>
|
||||
<span class="na">nolabel=</span><span class="s">"1"</span>
|
||||
<span class="na">widget=</span><span class="s">"one2many_product_picker"</span>
|
||||
<span class="na">mode=</span><span class="s">"form"</span>
|
||||
<span class="na">options=</span><span class="s">"{'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']]}]}"</span>
|
||||
<span class="nt">></span>
|
||||
<span class="nt"><form></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"name"</span> <span class="na">invisible=</span><span class="s">"1"</span> <span class="nt">/></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"product_id"</span> <span class="na">invisible=</span><span class="s">"1"</span> <span class="nt">/></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"price_unit"</span> <span class="na">invisible=</span><span class="s">"1"</span> <span class="nt">/></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"currency_id"</span> <span class="na">invisible=</span><span class="s">"1"</span> <span class="nt">/></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"order_id"</span> <span class="na">invisible=</span><span class="s">"1"</span> <span class="nt">/></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"date_planned"</span> <span class="na">class=</span><span class="s">"mb-1"</span> <span class="nt">/></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"product_qty"</span> <span class="na">class=</span><span class="s">"mb-1"</span> <span class="na">widget=</span><span class="s">"numeric_step"</span> <span class="na">required=</span><span class="s">"1"</span> <span class="nt">/></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"product_uom"</span> <span class="na">class=</span><span class="s">"mb-2"</span> <span class="na">options=</span><span class="s">"{'no_open': True, 'no_create': True, 'no_edit': True}"</span> <span class="nt">/></span>
|
||||
<span class="nt"></form></span>
|
||||
<span class="nt"></field></span>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="usage">
|
||||
<h1><a class="toc-backref" href="#id2">Usage</a></h1>
|
||||
<h1><a class="toc-backref" href="#id7">Usage</a></h1>
|
||||
<p>You need to define the view fields. The view must be of <tt class="docutils literal">form</tt> type.
|
||||
This is an example that uses the ‘sale.order.line’ fields:</p>
|
||||
<pre class="code xml literal-block">
|
||||
|
@ -436,7 +602,7 @@ This is an example that uses the ‘sale.order.line’ fields:</p>
|
|||
<span class="na">nolabel=</span><span class="s">"1"</span>
|
||||
<span class="na">widget=</span><span class="s">"one2many_product_picker"</span>
|
||||
<span class="na">mode=</span><span class="s">"form"</span>
|
||||
<span class="na">options=</span><span class="s">"{'search': [{'name': _('Name'), 'domain': [['name', 'ilike', '$search']]}, {'name': _('Price'), 'domain': [['list_price', '=', $number_search]]}], 'field_map': {'name': 'name', 'product': 'product_id', 'product_uom': 'product_uom', 'price': 'price_unit', 'parent_id': 'order_id', 'product_uom_qty': 'product_qty'}, 'groups': [{'name': _('Desk'), 'domain': [['name', 'ilike', 'desk']], 'order': {'name': 'id', 'asc': true}}, {'name': _('Chairs'), 'domain': [['name', 'ilike', 'chair']]}]}"</span>
|
||||
<span class="na">options=</span><span class="s">"{'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']]}]}"</span>
|
||||
<span class="nt">></span>
|
||||
<span class="nt"><form></span>
|
||||
<span class="nt"><field</span> <span class="na">name=</span><span class="s">"name"</span> <span class="na">invisible=</span><span class="s">"1"</span> <span class="nt">/></span>
|
||||
|
@ -451,8 +617,8 @@ This is an example that uses the ‘sale.order.line’ fields:</p>
|
|||
<span class="nt"></field></span>
|
||||
</pre>
|
||||
<p>** In this example we don’t use ‘field_map’ option because the default match with the sale.order.line field names.</p>
|
||||
<div class="section" id="default-context">
|
||||
<h2><a class="toc-backref" href="#id3">Default context:</a></h2>
|
||||
<div class="section" id="id1">
|
||||
<h2><a class="toc-backref" href="#id8">Default context:</a></h2>
|
||||
<p>The widget sends a defaults context with the ‘search_read’ request:</p>
|
||||
<blockquote>
|
||||
<ul>
|
||||
|
@ -464,25 +630,34 @@ This is an example that uses the ‘sale.order.line’ fields:</p>
|
|||
</ul>
|
||||
</blockquote>
|
||||
</li>
|
||||
<li><p class="first">active_search_involved_fields > Contains an array of dictionaries with the fields used with the searchbox content</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>‘type’ > Can be ‘text’ or ‘number’</li>
|
||||
<li>‘field’ > The field name</li>
|
||||
<li>‘oper’ > The operator used</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</div>
|
||||
<div class="section" id="preview">
|
||||
<h2><a class="toc-backref" href="#id4">Preview:</a></h2>
|
||||
<h2><a class="toc-backref" href="#id9">Preview:</a></h2>
|
||||
<blockquote>
|
||||
<img alt="https://raw.githubusercontent.com/OCA/web/12.0/web_widget_one2many_product_picker/static/img/product_picker.gif" src="https://raw.githubusercontent.com/OCA/web/12.0/web_widget_one2many_product_picker/static/img/product_picker.gif" />
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="known-issues-roadmap">
|
||||
<h1><a class="toc-backref" href="#id5">Known issues / Roadmap</a></h1>
|
||||
<h1><a class="toc-backref" href="#id10">Known issues / Roadmap</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Translations in the xml ‘options’ attribute of the field that use the widget can’t be exported automatically to be translated</li>
|
||||
<li>The product card animations can be improved. Currently the card is recreated, so we lost some states to apply correct effects.</li>
|
||||
<li>The product card animations can be improved. Currently the card is recreated, so we lost some elements to apply correct effects.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="bug-tracker">
|
||||
<h1><a class="toc-backref" href="#id6">Bug Tracker</a></h1>
|
||||
<h1><a class="toc-backref" href="#id11">Bug Tracker</a></h1>
|
||||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/web/issues">GitHub Issues</a>.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
|
@ -490,15 +665,15 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
|
|||
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
||||
</div>
|
||||
<div class="section" id="credits">
|
||||
<h1><a class="toc-backref" href="#id7">Credits</a></h1>
|
||||
<h1><a class="toc-backref" href="#id12">Credits</a></h1>
|
||||
<div class="section" id="authors">
|
||||
<h2><a class="toc-backref" href="#id8">Authors</a></h2>
|
||||
<h2><a class="toc-backref" href="#id13">Authors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Tecnativa</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="contributors">
|
||||
<h2><a class="toc-backref" href="#id9">Contributors</a></h2>
|
||||
<h2><a class="toc-backref" href="#id14">Contributors</a></h2>
|
||||
<ul>
|
||||
<li><p class="first"><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:</p>
|
||||
<blockquote>
|
||||
|
@ -512,7 +687,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
|
|||
</ul>
|
||||
</div>
|
||||
<div class="section" id="maintainers">
|
||||
<h2><a class="toc-backref" href="#id10">Maintainers</a></h2>
|
||||
<h2><a class="toc-backref" href="#id15">Maintainers</a></h2>
|
||||
<p>This module is maintained by the OCA.</p>
|
||||
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
|
||||
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
|
|
|
@ -259,7 +259,6 @@ odoo.define("web_widget_one2many_product_picker.ProductPickerQuickCreateFormView
|
|||
this._updateButtons();
|
||||
} else {
|
||||
this.update({}, {reload: false}).then(function(){
|
||||
debugger;
|
||||
self.model.unsetDirty(self.handle);
|
||||
self.trigger_up("restore_flip_card");
|
||||
self._updateButtons();
|
||||
|
|
|
@ -13,8 +13,6 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
|||
var tools = require("web_widget_one2many_product_picker.tools");
|
||||
var ProductPickerQuickModifPriceForm = require(
|
||||
"web_widget_one2many_product_picker.ProductPickerQuickModifPriceForm");
|
||||
var ProductPickerQuickCreateForm = require(
|
||||
"web_widget_one2many_product_picker.ProductPickerQuickCreateForm");
|
||||
|
||||
var qweb = core.qweb;
|
||||
|
||||
|
|
|
@ -302,6 +302,7 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
|
|||
var soptions = options || {};
|
||||
var context = _.extend({
|
||||
'active_search_group_name': this._activeSearchGroup.name,
|
||||
'active_search_involved_fields': this._searchContext.involvedFields,
|
||||
},this.state.data[this.name].getContext());
|
||||
|
||||
return $.Deferred(function (d) {
|
||||
|
@ -420,6 +421,7 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
|
|||
*/
|
||||
_getFullSearchDomain: function (domain) {
|
||||
var sdomain = _.clone(domain);
|
||||
this._searchContext.involvedFields = [];
|
||||
if (!sdomain) {
|
||||
sdomain = _.clone(this._searchContext.domain) || [];
|
||||
if (this._searchContext.text) {
|
||||
|
@ -427,6 +429,7 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
|
|||
if (!(search_domain[0] instanceof Array)) {
|
||||
search_domain = search_domain[this._searchMode].domain;
|
||||
}
|
||||
var involved_fields = [];
|
||||
// Iterate domain triplets and logic operators
|
||||
for (var index in search_domain) {
|
||||
var domain = _.clone(search_domain[index]);
|
||||
|
@ -435,12 +438,23 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
|
|||
// Replace right leaf with the current value of the search input
|
||||
if (domain[2] === "$number_search") {
|
||||
domain[2] = Number(this._searchContext.text);
|
||||
involved_fields.push({
|
||||
type: 'number',
|
||||
field: domain[0],
|
||||
oper: domain[1],
|
||||
});
|
||||
} else if (typeof(domain[2]) === "string" && domain[2].includes("$search")) {
|
||||
domain[2] = domain[2].replace(/\$search/, this._searchContext.text)
|
||||
domain[2] = domain[2].replace(/\$search/, this._searchContext.text);
|
||||
involved_fields.push({
|
||||
type: 'text',
|
||||
field: domain[0],
|
||||
oper: domain[1],
|
||||
});
|
||||
}
|
||||
}
|
||||
sdomain.push(domain);
|
||||
}
|
||||
this._searchContext.involvedFields = involved_fields;
|
||||
}
|
||||
}
|
||||
return sdomain || [];
|
||||
|
|
Loading…
Reference in New Issue