I added the following filter to the line item list of the Sale Order form to show only products appropriate for the selected customer:
<xpath expr="//field[@name='order_line']/tree//field[@name='product_id']" position="attributes"><attribute name="domain">[('id','in',parent.product_ids and parent.product_ids[0][2]),('sale_ok','=',True)]</attribute></xpath>
product_ids is a related field to a many2many list of products the customer has approved:
product_ids = fields.Many2many(related='partner_id.product_ids', string="Approved Products")
This works fine when a customer is selected and the customer's approved products list is not empty, but I get the following javascript error when I try to select a product in the line item and either no customer is selected or the approved products list is empty for that customer:
Error: No conversion for undefined
http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:3048 Traceback: wrap@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:3048:44 wrapping_list<.__getitem__@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:3053:293 py.PY_getItem@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:2834:9 py.evaluate@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:2917:1 py.evaluate@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:2917:85 py.evaluate@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:2916:108 py.evaluate@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:2918:96 py.eval@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:2923:281 eval_domains/<@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:3062:120 _.forEach@http://127.0.0.1:8069/web/content/249-ee9a491/web.assets_common.js:12:558 _.mixin/</_.prototype[name]@http://127.0.0.1:8069/web/content/249-ee9a491/web.assets_common.js:69:521 eval_domains@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:3061:136 eval_domains/<@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:3062:301 _.forEach@http://127.0.0.1:8069/web/content/249-ee9a491/web.assets_common.js:12:558 _.mixin/</_.prototype[name]@http://127.0.0.1:8069/web/content/249-ee9a491/web.assets_common.js:69:521 eval_domains@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:3061:136 eval_domains/<@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:3062:301 _.forEach@http://127.0.0.1:8069/web/content/249-ee9a491/web.assets_common.js:12:558 _.mixin/</_.prototype[name]@http://127.0.0.1:8069/web/content/249-ee9a491/web.assets_common.js:69:521 eval_domains@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:3061:136 pyeval@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:3072:24 eval_arg@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:3075:61 ensure_evaluated@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:3078:11 .call@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:2945:1 DataSet<.name_search@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:3199:1038 CompletionFieldMixin.get_search_result@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:3616:25 FieldMany2One<.render_editable/<.source@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:3717:103 ._search@http://127.0.0.1:8069/web/content/249-ee9a491/web.assets_common.js:1588:142 $.widget/</proxiedPrototype[prop]</<@http://127.0.0.1:8069/web/content/249-ee9a491/web.assets_common.js:1124:328 .search@http://127.0.0.1:8069/web/content/249-ee9a491/web.assets_common.js:1588:8 $.widget/</proxiedPrototype[prop]</<@http://127.0.0.1:8069/web/content/249-ee9a491/web.assets_common.js:1124:328 $.widget.bridge/$.fn[name]/<@http://127.0.0.1:8069/web/content/249-ee9a491/web.assets_common.js:1129:13 .each@http://127.0.0.1:8069/web/content/249-ee9a491/web.assets_common.js:473:758 jQuery.prototype.each@http://127.0.0.1:8069/web/content/249-ee9a491/web.assets_common.js:461:636 $.widget.bridge/$.fn[name]@http://127.0.0.1:8069/web/content/249-ee9a491/web.assets_common.js:1126:342 FieldMany2One<.render_editable/<@http://127.0.0.1:8069/web/content/362-dbba6fb/web.assets_backend.js:3712:1057 jQuery.event.dispatch@http://127.0.0.1:8069/web/content/249-ee9a491/web.assets_common.js:740:378 jQuery.event.add/elemData.handle@http://127.0.0.1:8069/web/content/249-ee9a491/web.assets_common.js:713:151
I thought parent.product_ids on the left-hand side of the and expression in the domain would check for an empty list and shortcut the boolean expression, but obviously, that doesn't work.
What is the correct way to write the domain so that the filter works as intended but also gracefully handles an empty m2m list?
I was able to workaround this issue by specifying the domain dynamically in an onchange event handler. More details about domains and many2many fields can be found in this post: https://www.odoo.com/nl_NL/forum/help-1/question/complex-many2many-domains-in-views-41777