15

I have several organization types with a many2many relation describing which types that may be parent to other types (e.g. department can be parent to sub-department and working group). It's NOT a strict hierarchy (working group can be parent to other working groups), hence the many2many relation.

I have two fields on my organization_type object: allowed_parent_type_ids and the inverse allowed_children_type_ids.

Now I want to restrict the organization type field on my organization object depending on it's parent, so a child of a "department" can only select the organization types allowed to be children of departments and so on.

In my form view, I tried:

<field
    name="organization_type_id"
    domain="[('id', 'in', parent_id.organization_type_id.allowed_children_ids)]"
    />

I also tried to put a related field with allowed types on my organization object, but I always ends up with an error message. My last attempt was:

domain=[('id', 'in', allowed_type_ids)]

That gives an error message:

TypeError: not all arguments converted during string formatting

The client actually fetches a JSON object like "allowed_type_ids" = [0,1,2] and if I replace allowed_type_ids in the domain expression with [0,1,2] there are no errors and I get the three organization types in my selection...

Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
cgs
  • 322
  • 1
  • 4
  • 15

2 Answers2

8

Try this:

<field
    name="organization_type_id"
    domain="[('id', 'in', parent_id.organization_type_id.allowed_children_ids.ids)]"
    />

While allowed_children_ids is a set of records, allowed_children_ids.ids is a list of ids of those records.

You can also approach this from the other side. This should work and be event faster:

<field
    name="organization_type_id"
    domain="[('allowed_parent_type_ids', '=', parent_id.organization_type_id)]"
    />
Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
Ludwik Trammer
  • 24,602
  • 6
  • 66
  • 90
  • 1
    I couldn't get the first solution to work (I had tried something similar), but the second approach worked. I used 'in' as operator. It doesn't seem logic to have "ids in id", but it works... – cgs Aug 26 '15 at 13:42
5

EDIT: This trick doesn't work anymore in 9.0 and 10.0 even at the time I posted the message if your Odoo codebase was up to date see https://github.com/odoo/odoo/issues/16072 for more details.

For an alternative you can give a try to web_domain_field module. It is currently here: https://github.com/OCA/web/pull/567


Former answer:

To have a domain on a Many2many you will find a good answer from Olivier Dony on the Odoo FAQ: https://www.odoo.com/fr_FR/forum/aide-1/question/complex-many2many-domains-in-views-41777#answer_41784

In short, you need to adress the correct values as the Many2many value is a list of tuple like [(6, 0, ids)].

Thus you need to create a domain like this to compare ids:

domain=[('id', 'in', allowed_type_ids[0][2])]

Warning, this might not work on Odoo 9.0 in the case your many2many field is empty.

Yannick
  • 102
  • 1
  • 6
  • 1
    I believe you ment allowed_type_ids[0][2] (2 instead of 6 in the last brackets)? - And maybe it should be "allowed_type_ids and allowed_type_ids[0][2]" to make sure the list is valid. Anyway, neat little trick. ;-) – cgs Mar 27 '16 at 15:37
  • Do you know if this has recently changed? I swear this had been working for me up until the last couple of days. Now all of a sudden when I view the output from the server in my view, my custom many2many field does not show `x_my_field: [[6, 0, [id1,id2]]` like it used to. It now either shows simply an array of ids, or sometimes it shows an array of other many2many commands, like [[5], [1, id1, {}], [1, id2, {}]]`. Has something changed? I'm using Odoo 10 Saas. – flyingL123 Mar 30 '17 at 23:30
  • @flyingL123 Yes something changed. And it not possible to use it this way with last version of Odoo. What you might want is to have a look at this module: web_domain_field https://github.com/OCA/web/pull/567 It allows you to create a field to compute the domain and reuse this field as the domain for your filtering. – Yannick Aug 25 '17 at 17:34
  • I updated my answer as this solution won't work anymore – Yannick Aug 25 '17 at 17:44