# Write Access rules to group depending on a field

**URL:** <https://discuss.tryton.org/t/write-access-rules-to-group-depending-on-a-field/4016>\
**Category:** Developer\
**Created:** [April 7, 2021, 1:49pm UTC](https://discuss.tryton.org/t/write-access-rules-to-group-depending-on-a-field/4016 "2021-04-07T13:49:59Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![maxx](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/maxx/32/2320_2.png) [@maxx](https://discuss.tryton.org/u/maxx)\
**Post date:** [April 7, 2021, 1:50pm UTC](https://discuss.tryton.org/t/write-access-rules-to-group-depending-on-a-field/4016/1 "2021-04-07T13:50:00Z")

</div>

Hi,

For some models, we allow “admin rights” to users. For instance, creating products for opportunities.  
But, if we intend to sell those products, we need to validate some details (accounting, customs, measurements) and then prevent user to update data once the product is validated. In this case, we use the nan-tic module [GitHub - NaN-tic/trytond-product\_validate](https://github.com/NaN-tic/trytond-product_validate) which add a “validate” boolean field on the template form. This field is only writeable by a specific group “product\_validation”.  
Once a product is validated, users having “product admin” rights should not update this product. This could only be done by user in “product\_validation” group.

So i add this rule to prevent users in “product\_admin” group to write in product model if field “validated” is true:

```auto
        <record model="ir.rule.group" id="rule_group_product_validated">
           <field name="name">Product Validated</field>
           <field name="model" search="[('model', '=', 'product.template')]"/>
           <field name="global_p" eval="False"/>
           <field name="default_p" eval="False"/>
           <field name="perm_read" eval="True"/>
           <field name="perm_write" eval="False"/>
           <field name="perm_create" eval="False"/>
           <field name="perm_delete" eval="False"/>
       </record>
       <record model="ir.rule" id="rule_product_validated">
           <field name="domain" eval="[('validated', '=', True)]" pyson="1"/>
           <field name="rule_group" ref="rule_group_product_validated"/>
       </record>
       <record model="ir.rule.group-res.group" id="rule_group_product_validated_group_product_admin">
           <field name="rule_group" ref="rule_group_product_validated"/>
           <field name="group" ref="product.group_product_admin"/>
       </record>

```

With this rule, i only see validated products and i can’t write them which is correct.  
But my products which are not validated are not displayed !

So i’ve 2 groups:

- product\_admin
- product\_validation

Product\_admin has the default rights to create, update, delete product but can’t “validate” a product. Once a product is validated, product\_admin can no more update product.

Product\_validation group has all rights on product (validate, and also updating a validated product).

Need some help to set correct rules depending of this behaviour. Thanks!

---

<div class="post-metadata">

**Author:** ![ced](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/ced/32/1237_2.png) [@ced](https://discuss.tryton.org/u/ced)\
**Post date:** [April 7, 2021, 2:13pm UTC](https://discuss.tryton.org/t/write-access-rules-to-group-depending-on-a-field/4016/2 "2021-04-07T14:13:01Z")

</div>

In contrary to other access rights, the Rules are removing access instead of giving (it is a kind of filter).  
So your rule limit the read access for the group to only product validated.

Instead you must reverse the rules to give write access to only non-validated products.

---

<div class="post-metadata">

**Author:** ![maxx](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/maxx/32/2320_2.png) [@maxx](https://discuss.tryton.org/u/maxx)\
**Post date:** [April 7, 2021, 2:20pm UTC](https://discuss.tryton.org/t/write-access-rules-to-group-depending-on-a-field/4016/3 "2021-04-07T14:20:47Z")

</div>

I applied this way:

```auto
        <record model="ir.rule.group" id="rule_group_product_validated">
           <field name="name">Product Validated</field>
           <field name="model" search="[('model', '=', 'product.template')]"/>
           <field name="perm_write" eval="True"/>
       </record>
       <record model="ir.rule" id="rule_product_validated">
           <field name="domain" eval="[('validated', '=', False)]" pyson="1"/>
           <field name="rule_group" ref="rule_group_product_validated"/>
       </record>
       <record model="ir.rule.group-res.group"
           id="rule_group_product_validated_group_product_admin">
           <field name="rule_group" ref="rule_group_product_validated"/>
           <field name="group" ref="product.group_product_admin"/>
       </record>

```

but in this case, i don’t see anymore validated products. It’s only displaying not validated products (and i can update them).

---

<div class="post-metadata">

**Author:** ![ced](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/ced/32/1237_2.png) [@ced](https://discuss.tryton.org/u/ced)\
**Post date:** [April 7, 2021, 2:22pm UTC](https://discuss.tryton.org/t/write-access-rules-to-group-depending-on-a-field/4016/4 "2021-04-07T14:22:36Z")

</div>

I guess the rule is not correctly updated.  
Removing a `<field/>` does not change its value.

---

<div class="post-metadata">

**Author:** ![maxx](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/maxx/32/2320_2.png) [@maxx](https://discuss.tryton.org/u/maxx)\
**Post date:** [April 7, 2021, 2:25pm UTC](https://discuss.tryton.org/t/write-access-rules-to-group-depending-on-a-field/4016/5 "2021-04-07T14:25:49Z")

</div>

Is this a bug ? How correctly update the rule ?  
Or should i add other perm too ?

---

<div class="post-metadata">

**Author:** ![ced](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/ced/32/1237_2.png) [@ced](https://discuss.tryton.org/u/ced)\
**Post date:** [April 7, 2021, 2:32pm UTC](https://discuss.tryton.org/t/write-access-rules-to-group-depending-on-a-field/4016/6 "2021-04-07T14:32:37Z")

</div>

To ensure the value of a `<field/>` through update, you must always have it declared.  
Removing a `<field/>` from the XML means that you do not care anymore of its value.

---

<div class="post-metadata">

**Author:** ![maxx](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/maxx/32/2320_2.png) [@maxx](https://discuss.tryton.org/u/maxx)\
**Post date:** [April 8, 2021, 12:16pm UTC](https://discuss.tryton.org/t/write-access-rules-to-group-depending-on-a-field/4016/7 "2021-04-08T12:16:12Z")

</div>

Still struggling with rules…

So i define a group product\_management similar to product\_admin.  
Only group product\_admin can write boolean field “validate” on product template.  
Product\_management group can not update nor delete product template having field validate = ‘True’  
I define a rule to allow write/delete permission on group product\_management when validated field is False.

Products with validated field = True are not visible… even for admin (But i need to see all products!)  
As admin, i can’t save a template with validated=True (not allowed to write records… because of my rule).

Need some help to understand…

Here’s a part of my code:

```auto
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
     copyright notices and license terms. -->
<tryton>
    <data>
        <record model="res.group" id="group_product_management">
            <field name="name">Product Management</field>
        </record>
        <record model="ir.model.access" id="access_product_management">
            <field name="model" search="[('model', '=', 'product.product')]"/>
            <field name="group" ref="group_product_management"/>
            <field name="perm_read" eval="True"/>
            <field name="perm_write" eval="True"/>
            <field name="perm_create" eval="True"/>
            <field name="perm_delete" eval="True"/>
        </record>
        <record model="ir.model.access" id="access_product_template_management">
            <field name="model" search="[('model', '=', 'product.template')]"/>
            <field name="group" ref="group_product_management"/>
            <field name="perm_read" eval="True"/>
            <field name="perm_write" eval="True"/>
            <field name="perm_create" eval="True"/>
            <field name="perm_delete" eval="True"/>
        </record>

        <record model="ir.model.field.access"
                id="model_field_access_product_validated">
            <field name="field"
                search="[('model.model', '=', 'product.template'), ('name', '=', 'validated')]"/>
            <field name="perm_read" eval="True"/>
            <field name="perm_write" eval="False"/>
        </record>
        <record model="ir.model.field.access"
                id="model_field_access_product_validated_group_product_admin">
            <field name="field"
                search="[('model.model', '=', 'product.template'), ('name', '=', 'validated')]"/>
            <field name="group" ref="product.group_product_admin"/>
            <field name="perm_read" eval="True"/>
            <field name="perm_write" eval="True"/>
        </record>

        <record model="ir.rule.group" id="rule_group_product_not_validated">
           <field name="name">Product Not Validated</field>
	   <field name="model" search="[('model', '=', 'product.template')]"/>
	   <field name="perm_write" eval="True"/>
	   <field name="perm_delete" eval="True"/>
       </record>
       <record model="ir.rule" id="rule_product_not_validated">
           <field name="domain" eval="[('validated', '=', False)]" pyson="1"/>
           <field name="rule_group" ref="rule_group_product_not_validated"/>
       </record>
       <record model="ir.rule.group-res.group"
           id="rule_group_product_not_validated_group_product_management">
           <field name="rule_group" ref="rule_group_product_not_validated"/>
           <field name="group" ref="group_product_management"/>
       </record>
...

```

---

<div class="post-metadata">

**Author:** ![pokoli](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/pokoli/32/22_2.png) [@pokoli](https://discuss.tryton.org/u/pokoli)\
**Post date:** [April 8, 2021, 12:32pm UTC](https://discuss.tryton.org/t/write-access-rules-to-group-depending-on-a-field/4016/8 "2021-04-08T12:32:52Z")

</div>

> [@maxx](#):
>
> Products with validated field = True are not visible… even for admin (But i need to see all products!)  
> As admin, i can’t save a template with validated=True (not allowed to write records… because of my rule).

There is no special rule for admin. So if you create a new group you should assign it to the admin user so he is able to perform this operation also. As the admin user is created with an xml record, you can assign the group on your xml group so this is automatically done when updating your module. You can have a look at the [account module to see how it’s done](https://hg.tryton.org/modules/account/file/100594419a86/account.xml#l13).

---

<div class="post-metadata">

**Author:** ![maxx](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/maxx/32/2320_2.png) [@maxx](https://discuss.tryton.org/u/maxx)\
**Post date:** [April 8, 2021, 12:41pm UTC](https://discuss.tryton.org/t/write-access-rules-to-group-depending-on-a-field/4016/9 "2021-04-08T12:41:23Z")

</div>

> [@pokoli](#):
>
> There is no special rule for admin. So if you create a new group you should assign it to the admin user so he is able to perform this operation also. As the admin user is created with an xml record, you can assign the group on your xml group so this is automatically done when updating your module. You can have a look at the [account module to see how it’s done](https://hg.tryton.org/modules/account/file/100594419a86/account.xml#l13).

I don’t want admin user to be part of this new group ‘product\_management’. Admin is part of group “product\_admin” with all the rights on products. Product\_management group will be similar of group “product\_admin” except i don’t want people of this group could update or delete products having “validated” field = True.  
So i try to define a rule for this: Everybody can see all products, product\_admin can do anything, product\_management can do anything except updating or deleting validated products.

---

<div class="post-metadata">

**Author:** ![edbo](https://discuss-cdn.tryton.org/letter_avatar_proxy/v4/letter/e/f14d63/32.png) [@edbo](https://discuss.tryton.org/u/edbo)\
**Post date:** [April 8, 2021, 1:35pm UTC](https://discuss.tryton.org/t/write-access-rules-to-group-depending-on-a-field/4016/10 "2021-04-08T13:35:04Z")

</div>

Nice question 😄 I’m always in for a challenge so I fiddled around a bit.

I’ve tried your idea on the trunk version of Tryton, so no idea if it will work with your version of Tryton. Also I made a small change to your idea, I used the `salable` field and made the rules in the GUI rather then in XML. I will leave that to you.

> [@maxx](#):
>
> Everybody can see all products

I’ve created a record rule with an empty domain.

- model: product.template
- only ‘read’ access
- both ‘global’ and ‘default’ unchecked
- domain, leave it empty or add `'[]'`

> [@maxx](#):
>
> product\_admin can do anything

Just create a special group for them and add the empty rule, but also add all the rights on the product.template model on the model access tab

> [@maxx](#):
>
> product\_management can do anything except updating or deleting validated products

Create a new record rule with `[["salable", "=", True"]]` as domain

- model: product.template
- all access
- both ‘global’ and ‘default’ unchecked

Create a new group, and add all access on the product.template model like the group above. Also add the two newly created record rules to the group.

It’s very rough but hopefully it will help you a bit.

---

<div class="post-metadata">

**Author:** ![maxx](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/maxx/32/2320_2.png) [@maxx](https://discuss.tryton.org/u/maxx)\
**Post date:** [April 8, 2021, 1:38pm UTC](https://discuss.tryton.org/t/write-access-rules-to-group-depending-on-a-field/4016/11 "2021-04-08T13:38:40Z")

</div>

I think i found a solution 🙂  
Thanks to all! Don’t hesitate to comment if this could be improved.

I seems working with this code:

```auto
...
        <record model="ir.rule.group" id="rule_group_product_not_validated">
           <field name="name">Product Not Validated</field>
		   <field name="model" search="[('model', '=', 'product.template')]"/>
		   <field name="global_p" eval="False"/>
		   <field name="default_p" eval="False"/>
		   <field name="perm_read" eval="False"/>
		   <field name="perm_write" eval="True"/>
		   <field name="perm_delete" eval="True"/>
       </record>
       <record model="ir.rule" id="rule_product_not_validated">
           <field name="domain" eval="[('validated', '=', False)]" pyson="1"/>
           <field name="rule_group" ref="rule_group_product_not_validated"/>
       </record>
       <record model="ir.rule.group-res.group"
           id="rule_group_product_not_validated_group_product_management">
           <field name="rule_group" ref="rule_group_product_not_validated"/>
           <field name="group" ref="group_product_management"/>
       </record>

        <record model="ir.rule.group" id="rule_group_product_admin_all_perm">
           <field name="name">Product All Perm Admin</field>
           <field name="model" search="[('model', '=', 'product.template')]"/>
	       <field name="global_p" eval="False"/>
	       <field name="default_p" eval="False"/>
           <field name="perm_read" eval="True"/>
           <field name="perm_write" eval="True"/>
           <field name="perm_create" eval="True"/>
           <field name="perm_delete" eval="True"/>
        </record>
       <record model="ir.rule.group-res.group"
           id="rule_group_product_admin_all_perm_group_product_admin">
           <field name="rule_group" ref="rule_group_product_admin_all_perm"/>
           <field name="group" ref="product.group_product_admin"/>
       </record>
...

```

---

<div class="post-metadata">

**Author:** ![maxx](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/maxx/32/2320_2.png) [@maxx](https://discuss.tryton.org/u/maxx)\
**Post date:** [April 20, 2021, 2:26pm UTC](https://discuss.tryton.org/t/write-access-rules-to-group-depending-on-a-field/4016/12 "2021-04-20T14:26:53Z")

</div>

Since my last post, i met some problem with field access rules to duplicate a record. (Setting perm\_write=False to a field doesn’t allow to duplicate a record). So i update my code to set field ‘readonly’ depending on field state attribute instead on field access rules.

To resume, i need to allow some users to have some rights to manage products but they are not product\_admin.  
So, i’ve defined a new group product\_management similar to product\_admin.  
I’ve added a boolean field “Validated” on product template. Only group product\_admin can write boolean field “validate” on product template.  
Product\_management group can not update nor delete product template once field validate is ‘True’.

Here’s my code:

product.py

```auto
from trytond.model import fields
from trytond.pool import PoolMeta
from trytond.pyson import Eval, Id

class Template(metaclass=PoolMeta):
    __name__ = 'product.template'

    validated = fields.Boolean('Validated',
        states={
            'readonly': ~Id('product', 'group_product_admin').in_(
                Eval('context', {}).get('groups', [])),
            })

    @classmethod
    def default_validated(cls):
        return False

    @classmethod
    def copy(cls, templates, default=None):
        if default is None:
            default = {}
        else:
            default = default.copy()
        default.setdefault('validated', False)
        return super().copy(templates, default=default)

```

product.xml

```auto
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
     copyright notices and license terms. -->
<tryton>
    <data>
        <record model="res.group" id="group_product_management">
            <field name="name">Product Management</field>
        </record>
        <record model="ir.model.access" id="access_product_management">
            <field name="model" search="[('model', '=', 'product.product')]"/>
            <field name="group" ref="group_product_management"/>
            <field name="perm_read" eval="True"/>
            <field name="perm_write" eval="True"/>
            <field name="perm_create" eval="True"/>
            <field name="perm_delete" eval="True"/>
        </record>
        <record model="ir.model.access" id="access_product_template_management">
            <field name="model" search="[('model', '=', 'product.template')]"/>
            <field name="group" ref="group_product_management"/>
            <field name="perm_read" eval="True"/>
            <field name="perm_write" eval="True"/>
            <field name="perm_create" eval="True"/>
            <field name="perm_delete" eval="True"/>
        </record>
        <record model="ir.ui.view" id="product_template_view_form">
            <field name="model">product.template</field>
            <field name="inherit" ref="product.template_view_form"/>
            <field name="name">product_template_form</field>
        </record>

        <record model="ir.rule.group" id="rule_group_product_not_validated">
            <field name="name">Product Not Validated</field>
            <field name="model" search="[('model', '=', 'product.template')]"/>
            <field name="global_p" eval="False"/>
            <field name="default_p" eval="False"/>
            <field name="perm_read" eval="False"/>
            <field name="perm_write" eval="True"/>
            <field name="perm_delete" eval="True"/>
        </record>
        <record model="ir.rule" id="rule_product_not_validated">
            <field name="domain" eval="[('validated', '=', False)]" pyson="1"/>
            <field name="rule_group" ref="rule_group_product_not_validated"/>
        </record>
        <record model="ir.rule.group-res.group"
            id="rule_group_product_not_validated_group_product_management">
            <field name="rule_group" ref="rule_group_product_not_validated"/>
            <field name="group" ref="group_product_management"/>
        </record>

        <record model="ir.rule.group" id="rule_group_product_all_perm_admin">
            <field name="name">Product All Perm Admin</field>
            <field name="model" search="[('model', '=', 'product.template')]"/>
            <field name="global_p" eval="False"/>
            <field name="default_p" eval="False"/>
            <field name="perm_read" eval="True"/>
            <field name="perm_write" eval="True"/>
            <field name="perm_create" eval="True"/>
            <field name="perm_delete" eval="True"/>
        </record>
        <record model="ir.rule.group-res.group"
            id="rule_group_product_all_perm_admin_group_product_admin">
            <field name="rule_group" ref="rule_group_product_all_perm_admin"/>
            <field name="group" ref="product.group_product_admin"/>
        </record>
    </data>
</tryton>

```

view/template\_form.xml

```auto
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
     copyright notices and license terms. -->
<data>
    <xpath expr="/form/notebook" position="before">
        <label name="validated"/>
        <field name="validated"/>
    </xpath>
</data>

```

Feel free to comment…

---

<div class="post-metadata">

**Author:** ![ced](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/ced/32/1237_2.png) [@ced](https://discuss.tryton.org/u/ced)\
**Post date:** [April 20, 2021, 2:29pm UTC](https://discuss.tryton.org/t/write-access-rules-to-group-depending-on-a-field/4016/13 "2021-04-20T14:29:36Z")

</div>

For the record, this works because `readonly` is not yet enforced on the server side [Enforce readonly on field (#4207) · Issues · Tryton / Tryton · GitLab](https://bugs.tryton.org/issue4207)

---

<div class="post-metadata">

**Author:** ![system](https://discuss-cdn.tryton.org/uploads/default/original/1X/c6f8ec0a40525cdcd50058c734283450a4b3d38b.png) [@system](https://discuss.tryton.org/u/system)\
**Post date:** [May 20, 2021, 2:29pm UTC](https://discuss.tryton.org/t/write-access-rules-to-group-depending-on-a-field/4016/14 "2021-05-20T14:29:39Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
