Two rules for one model - odoo

I need to apply two rules on res_partner table using two groups
Groups: Staff and Manager
Menuitems: Customer and 'Staff'
Model : res_partner for both views.
Users in group Staff can only see staff menu details (read access only)
But they need to have full access to Customer ( read,write,create and unlink)
users in Manager should have full access to both views.
I tried below code
<record model="ir.rule" id="staff_staff_rule">
<field name="name">Readonly for staff</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="domain_force">[(1,'=',1)]</field>
<field name="perm_create" eval="False"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_unlink" eval="False"/>
<field name="groups" eval="[(4, ref('appartment.group_appartment_staff'))]"/>
</record>
But users still can create,edit,read, and delete records from staff groups.
How can i achieve this.

you should give the right domain that show only staff. when you put the
a domain you indicate that this group is allawed to read only this records.
<record model="ir.rule" id="staff_staff_rule">
<field name="name">Readonly for staff</field>
<field name="model_id" ref="base.model_res_partner"/>
<!-- put the right domain -->
<field name="domain_force">[('partner_type','=', 'staff')]</field>
<field name="perm_create" eval="False"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_unlink" eval="False"/>
<field name="groups" eval="[(4, ref('appartment.group_appartment_staff'))]"/>
</record>

I think it will be done easily using csv (security access file).
You can manage this kind of situation directly from the csv file and that file you need to add into the openerp.py / manifest.py file.
CSV file example
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_res_partner,res_partner_user_access,model_res_partner,appartment.group_appartment_staff,1,0,0,0
access_manager_res_partner,res_partner_manager_access,model_res_partner,appartment.group_appartment_manager,1,1,1,1
Rules
Rules are used to applied conditions on each records while they have
been trying to access.
Access Control List
ir.model.access / Access control list is used to manage permissions
(only model access whether user can read / write / create / delete or
not).
#Cherif Odoo has explained rules and here is the access control list. By these two way odoo manage securities.

Related

How can add a Custom filter / Custom search field to Sale Order view based on a field in the partner form

I have a field card_customer in partner form. What i need is i have to add a custom filter for sale orders based on the field card_customer. When choosing this filter i need the sale orders, which have customers with card_customer field equaling True.
That's possible by creating the filter "technically". A normal user can't do that in vanilla Odoo sofar. Hopefully that feature will come one day.
"Technically" means either in a custom module or by using the debug mode in the client. Odoo can use dot-Notation in domains on such filters. And an admin can use this to create a custom filter directly in the client.
Creating in debug mode
active the debug mode
either go to Settings/Technical/user-defined filters OR open "Manage filters" in the debug context menu in the sales order list view
create the filter
Create a filter in custom module
<record id="my_customer_filter" model="ir.filters">
<field name="action_id" eval="False"/>
<field name="active" eval="True"/>
<field name="context">{}</field>
<field name="domain">[["partner_id.card_customer","=",True]]</field>
<field name="is_default" eval="True"/>
<field name="model_id">sale.order</field>
<field name="name">cart_customer is true</field>
<field name="sort">[]</field>
</record>
Create a filter in search view in a custom module
<record id="view_sales_order_filter" model="ir.ui.view">
<field name="name">sale.order.list.select</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_sales_order_filter" />
<field name="arch" type="xml">
<filter name="need_message" position="after">
<filter name="filter_card_customer_true" string="card_customer is true"
domain="[('partner_id.card_customer','=',True)]" />
</filter>
</field>
</record>
You can create a filter in search view, by inheriting the base search view of sale order ,and create a new view.
<data>
<record id="sale_order_search_inherit_receipt" model="ir.ui.view">
<field name="name">sale.order.search.receipt</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.sale_order_view_search_inherit_quotation"/>
<field name="arch" type="xml">
<xpath expr="//filter[#name='order_confirmed']" position="after"> // Adding the filter after existing filter 'Confirmed Orders'
<separator/>
<filter string="Card Customer" name="is_card_customer" domain="[('partner_id.card_customer','=', True)]"/>
<separator/>
</xpath>
</field>
</record>
</data>

Way to get specific user's ID

There is a self-made timesheet module.
We are using few digital signatures (tableman, division boss, accountants and so on) to sign timesheets. Only users with their respective roles can see timesheets of the specific states (unsigned, signed, signed by division boss and so on).
As for now, accountants are making some timesheets for tablemen, who went on vacation. But due to restriction rules, after returning, tablemen can't see timesheets of their divisions, made by accountants.
Is there a way to get an ID of some specific user? So I can add accountant's ID to domain_force to make his timesheets visible for the respective division's tablemen. As I know, admin's ID = 0, but what about the rest?
That's how it looks now:
<record id="inf3" model="ir.rule">
<field name="name">Tableman can do anything with 'unsigned' documents, made by himself or admin (0)</field>
<field name="model_id" ref="model_tabel_tabel"/>
<field name="groups" eval="[(4, ref('tabel_inf_division'))]"/>
<field name="perm_read" eval="1"/>
<field name="perm_write" eval="1"/>
<field name="perm_create" eval="1"/>
<field name="perm_unlink" eval="1"/>
<field name="domain_force">
[('state','not in',['signed','signed2','done']),('create_uid' ,'in',[user.id,0])]
</field>
</record>

Odoo - how to make mutually exclusive user groups

When you go to configuration->users in odoo as administrator, you see two groups under the category administration: Settings and Access rights. Since one of these groups are selected from a combo box, it seems to me like these groups are mutually exclusive, that is that a user can't be a member of both groups.
I need to do exactly the same with two groups under a custom category which I have created with the following data file:
<record id="FVO" model="ir.module.category">
<field name="name"> FVO </field>
</record>
<record id="FVO_nuova" model="res.groups">
<field name="name">FVO - nuova vista</field>
<field name="category_id" ref="FVO"/>
</record>
<record id="FVO_vecchia" model="res.groups">
<field name="name">FVO - vecchia vista</field>
<field name="category_id" ref="FVO"/>
</record>
But in the users form, they appear as two check boxes, which means that the user could be member of both groups.
Now I've studied both of these groups, and it's category, inspecting also the tables in which they are stored, to try to find out which flag they have so that Settings and Access rights can't be applied to one user at the same time, but for the life of me, I can't find anything special nor in the record for the group, nor in the record for the category.
Is someone able to point out what I'm missing?
I don't know the meaning of vecchia vista and nuova vista so i cannot understand if they are cascade or not, if they are cascade (inherited) rights (like 'see_own_leads' and 'see_all_leads'), you should use
<field name="implied_ids" eval="[(4, ref('FVO_nuova'))]"/> in your FVO_vecchia group so odoo will understand the user should select one of your groups not both of them.
If your groups are not meant to be cascade, i should define 3 groups like this:
`
<record id="FVO_none" model="res.groups">
<field name="name">FVO - no access</field>
<field name="category_id" ref="FVO"/>
</record>
<record id="FVO_nuova" model="res.groups">
<field name="name">FVO - nuova vista</field>
<field name="implied_ids" eval="[(4, ref('FVO_none'))]"/>
<field name="category_id" ref="FVO"/>
</record>
<record id="FVO_vecchia" model="res.groups">
<field name="name">FVO - vecchia vista</field>
<field name="implied_ids" eval="[(4, ref('FVO_none'))]"/>
<field name="category_id" ref="FVO"/>
</record>
`

OpenERP - field not showing in a tree view

Here is my XML file. For some reason the field "product_uom" is not showing in view's tree view. Any insights why it is happening and how I can make it show?
<tree string="Components" editable="bottom">
<field name="sequence" widget="handle"/>
<field name="product_id" on_change="onchange_product_id(product_id,
product_qty)"/>
<field name="type"/>
<field name="product_qty"/>
<field name="product_uom" on_change="onchange_uom(product_id,
product_uom)" groups="product.group_uom"/>
<field name="product_rounding"/>
<field name="product_efficiency"/>
<field name="date_start"/>
<field name="date_stop"/>
<field name="attribute_value_ids" widget="many2many_tags" domain="
[('product_ids.product_tmpl_id', '=', parent.product_tmpl_id)]"/>
</tree>
The product_uom field has a groups="product.group_uom" attribute.
This makes it visible only to the users in that Group.
Either remove it from the tree definition, or make sure your user in in that group.
Probably what you need is just to activate the "Allow using different units of measures" feature on Settings / Configuration / Sales, Product Features section. Behind the scenes this activates the group_uom for all users.

How to make field readonly based on group and status?

I want to make field readonly based on group, and status. Like I have two groups:
Manager Group
User Group
If I give User Group to any user and then change Status to Done, then field will be readonly for this user.
Hope I was able to make it clear to understand. Thanks.
Create a functional field of type boolean. If the logged in user is under user group and state is done, then return true. Then in the view, specify attrs="{'readonly':[('boolean_field_name','=',True)]}"
OR
First create your form view. Then inherit the view also specify the groups. for example in sale order form view, i want to make the customer reference field readonly for group user when state is not in draft or sent.
<record id="view_order_form_cust_ref_readonly" model="ir.ui.view">
<field name="name">sale.order.form.readonly.cust</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="groups_id" eval="[(6, 0, [ref('base.group_user') ])]"/>
<field name="arch" type="xml">
<field name='client_order_ref'" position="attributes">
<attribute name="attrs">{'readonly':[('state','not in',['draft','sent'])]}</attribute>
</field>
</field>
</record>
you can apply access rule on field level in OpenERP, like in py
'name': fields.char('Name', size=128, required=True, select=True,
read=['base.group_user'] ),
And for status in xml:
<field name="name " attrs="{'readonly': [('state','=','done')]}"/>
There is another sweet way to achieve this. Create one functional field and in that check for group assigned to that user and do not store that field. In View use that field in attrs.
Let say in product you don't want to allow any user to modify Internal Reference if user does not belongs to Product Modify group.
Create one group.
<data noupdate="1" >
<record model="res.groups" id="group_product_modify">
<field name="name">Product Modify</field>
<field name="users" eval="[(4, ref('base.user_root'))]"/>
</record>
</data>
Python file
class product_template(models.Model):
_inherit="product.template"
#api.one
def set_access_for_product(self):
self.able_to_modify_product = self.env['res.users'].has_group('product_extended_ecom_ept.group_product_modify')
able_to_modify_product = fields.Boolean(compute=set_access_for_product, string='Is user able to modify product?')
XMl file should be looking like,
<record model="ir.ui.view" id="product_template_update_internal_code_ept">
<field name="name">Product Template extension</field>
<field name="inherit_id" ref="product.product_template_only_form_view"/>
<field name="model">product.template</field>
<field name="priority" eval="50" />
<field name="arch" type="xml">
<field name="default_code" position="before">
<field name="able_to_modify_product" invisible="1" />
</field>
<field name="default_code" position="attributes">
<attribute name="attrs">{'readonly' : [('able_to_modify_product','=',False)]}</attribute>
</field>
</field>
</record>
In case if you are using Odoo web client(GUI) instead of code then there is a bit unorthodox way to do it.
Just make a copy of the field which will contain same value as the original one(giving original field name in Related Field under Advanced Properties) and mark it as read-only.
Then you can hide original field from the users which cannot edit that field and hide the copy field from those who can edit by using groups attribute.