Why isn't my act_window with views= definition and using act_window.view equivalent? - odoo

Say I have this:
<record id="mrp_bom_form_action_master_products" model="ir.actions.act_window">
<field name="name">Master Bill of Materials</field>
<field name="res_model">mrp.bom</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" eval="False"/>
<field name="views" eval="[(False, 'tree'), (ref('mrp_bom_form_view_master'), 'form')]"/>
<field name="search_view_id" ref="mrp.view_mrp_bom_filter"/>
</record>
According to the docs:
views
a list of (view_id, view_type) pairs. The second element of each pair is the category of the view (tree, form, graph, ...) and the first is an optional database id (or False). If no id is provided, the client should fetch the default view of the specified type for the requested model (this is automatically done by fields_view_get()). The first type of the list is the default view type and will be open by default when the action is executed. Each view type should be present at most once in the list
But it doesn't work. Instead I've done this:
<record model="ir.actions.act_window.view"
id="mrp_bom_form_view_master_form">
<field name="sequence" eval="1"/>
<field name="view_mode">tree</field>
<field name="act_window_id" ref="mrp_bom_form_action_master_products"/>
</record>
<record model="ir.actions.act_window.view"
id="mrp_bom_form_view_master_tree">
<field name="sequence" eval="2"/>
<field name="view_mode">form</field>
<field name="view_id" ref="mrp_bom_form_view_master"/>
<field name="act_window_id" ref="mrp_bom_form_action_master_products"/>
</record>
Which works, but I don't understand why the first case doesn't.

The views field on the ir.actions.act_window model is a non-stored computed field, without an inverse function. In other words it's read-only and is not even stored in the database. That's why when you create a new action with this field, it is not saved and just gets ignored.
The documentation is a little confusing (I also had a hard time orginaly figuring this out), but not technically wrong. This field is indeed a list of (view_id, view_type) pairs, you just can't change it directly when dealing with actions stored in database. It is generated automatically, based on view_id and view_ids fields.
You can however use the field directly with actions that are not stored in the database, but returned from the python code instead. Here's an example taken from the account_payment module:
return {
'name': _('Entry Lines'),
'context': context,
'view_type': 'form',
'view_mode': 'form',
'res_model': 'payment.order.create',
'views': [(resource_id,'form')],
'type': 'ir.actions.act_window',
'target': 'new',
}

Related

How to change selection fields with filters search in odoo? [Odoo 9]

I have created a state on models
state = fields.Selection([
('new', 'New'),
('draft', 'Draft'),
('approved', 'Approved')
],default='new')
I make menuitems that are different for user and admin. But in the admin groups, i get an error after adding filters search.
<record id="view_admin_filter" model="ir.ui.view">
<field name="name">Admin</field>
<field name="model">mymodels</field>
<field name="arch" type="xml">
<search string="Admin">
<filter string="Draft" name="state" domain="[('state','=','draft')]"/>
</search>
</field>
</record>
and
<record id="open_module_tree_admin" model="ir.actions.act_window">
<field name="name">Admin</field>
<field name="res_model">mymodels</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="context">{
"search_default_state": 1,
"default_state": 1}
</field>
<field name="domain">[]</field>
<field name="view_ids" eval="[(5, 0, 0),
(0, 0, {'view_mode': 'tree', 'view_id': ref('view_admin_tree')}),
(0, 0, {'view_mode': 'form', 'view_id': ref('view_admin_form')})]"/>
<field name="search_view_id" ref="view_admin_filter"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create.
</p>
</field>
</record>
I found an error like this
ValueError: Wrong value for mail.mail.state: 1
I have tried to replace it like this
"search_default_state": 'draft',
"default_state": 'draft'}
but it still doesn't work and getting error
ValueError: Wrong value for mail.mail.state: u'draft'
how should I fix it?
From what you said you are setting a default value for state some where in your code
with a value that is not in selection.
like for example when you did this:
"default_state": 1
This will cause this error to happen because I'm sure that 1 is not valid value
instead doing this is correct.
"default_state": 'draft'
But only if your selection has this value 'draft'.
One thing you should know in XML removing the code of the context from the action
definition will not remove it from the data base (you will keep having the same problem).
To fix this problem remove this default values from your code then do it again step by step
and make sure you upgrade the moduel and restart the server.
<record id="open_module_tree_admin" model="ir.actions.act_window">
<field name="name">Admin</field>
<field name="res_model">mymodels</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="context">{}</field> <!-- this will update the context to {} -->
.....
....
and check your python code for default value or onchange event make sure your not setting
the state field to a wrong value.
fields.Selection(.... default='draft')
Hope this helps you
And for your filter don't give them names like your fields names
<filter string="Draft" name="draft_state" domain="[('state','=','draft')]"/>
This way you can apply this filter in the context of the action like this:*
{'search_default_draft_state': 1}
I think it's safer.

Odoo 9 Is there a way to handle authorization with different groups on a certain field in form view?

I'm trying to create a form view.
<field name="is_positive" attrs="{'readonly':[('state','==','final')]}"/>
However there is many attributes like groups and invisible related to authorization so that certain group of people can see the field.
groups="base.group_hr_user"
But Is there a way for certain group can edit the field and the other group cannot?
add a new field to check whether the user is manager or user.
New Api Method
check_user = fields.Boolean(string='user',compute='_compute_user_check')
#api.multi
def _compute_user_check(self):
if self.user_has_groups('purchase.group_purchase_manager'):
self.check_user =True
In view
<field name="is_positive" attrs="{'readonly':[('check_user','=','True')]}"/>
First of all, you cannot use a domain like this one
<field name="is_positive" attrs="{'readonly':[('state','==','final')]}"/>
There is not a '==' operator, use = instead.
Now, to answer your question, if you want to create a special view for another group in which some elements are readonly for one group, and editable in the other, you have to it this way.
For the default view :
<record id="some_model_view" model="ir.ui.view">
<field name="name">some.model.form</field>
<field name="model">some.model</field>
<field name="arch" type="xml">
<form>
<field name="some_field" readonly="1"/>
</form>
<field/>
</record>
For a certain group :
<record id="some_model_view_for_other_group" model="ir.ui.view">
<field name="name">some.model.form</field>
<field name="model">some.model</field>
<field name="inherit_id" ref="my_module.some_model_view"
<field name="groups_id" eval="[(6, 0, [ref('some.first_group')])]" />
<field name="arch" type="xml">
<field name="some_field" position="attributes">
<attribute name="readonly">0</attribute>
</field>
<field/>
</record>
I will show one example to how this functionality works in sale group.
I make the unit price field in the sale order line makes readonly we select the user group user:own documents only The field is editable for other 2 groups user:All documets and manager
Firstly I create a boolean field for checking the user belongs to which group
is_own_user = fields.Boolean(string="Own user", compute='compute_own_user')
Then assigns the boolean field is True when the user belongs the group user:own documents only otherwise assigns to False
#api.depends('product_id')
def compute_own_user(self):
res_user_id = self.env['res.users'].search([('id', '=', self._uid)])
for rec in self:
if res_user_id.has_group('sales_team.group_sale_salesman') and not res_user_id.has_group('sales_team.group_sale_salesman_all_leads'):
rec.is_own_user = True
else:
rec.is_own_user = False
in xml make is_own_user invisible and replaces the unit price field
<xpath expr="//notebook/page/field[#name='order_line']/tree/field[#name='price_unit']" position="replace">
<field name="price_unit" attrs="{'readonly': [('isown_user', '=', True)]}" />
</xpath>

How to set default field value from xml code in odoo?

In sales order module I have created a new customised form view, in sale.py file I have created a new field 'is_sample'
'is_sample': fields.boolean("Specimen Order", store=False),
I want to set its default value from xml code so that it doesn't get affected in default form view. I have tried in four ways,
1)<field name="is_sample" eval="True"/>
2)<field name="is_sample" domain="[('is_sample','=',True)]"/>
3)<record id="action_specimen_orders" model="ir.actions.act_window">
<field name="type">ir.actions.act_window</field>
<field name="context">{'is_sample': 'True'}</field>
...
4)<record id="action_specimen_orders" model="ir.actions.act_window">
<field name="type">ir.actions.act_window</field>
<field name="domain">[('is_sample','=','True')]</field>
...
There is an easiest way to set default value from the xml, generally you can it for all those fields of the model. For that you need to add dictionary key/value pair to set default value for any field.
General syntax
default_field_name : default_value
To set default value you need to pass context with window action in which you need to set one key/value pair in context as shown in syntax. default_ is the prefix which needs to be set with field name as key.
Try following:
<record id="action_specimen_orders" model="ir.actions.act_window">
<field name="type">ir.actions.act_window</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="context">{'default_is_sample': True}</field>
</record>
If you want your product must be available in POS, you have to do like:
<record id="module_name.action_name" model="ir.actions.act_window">
<field name="name">My Menu</field>
<field name="res_model">object.name</field>
<field name="context">{'default_available_in_pos':1}
</field>
</record>

What is the right odoo 8 XML syntax for view_ids field

I am trying to customize the crm lead object. Class is defined this way
class yvleads(models.Model):
_inherit = 'crm.lead'
_name = 'crm.lead'
Now I added a menu item to display the added elements for which I have both a tree view and a form view. I have added a lett menu item referening a ir.actions.act_window. When this action is defined as
<record model="ir.actions.act_window" id="yvleads_mgt">
<field name="name">Leads Yves</field>
<field name="res_model">crm.lead</field>
<field name="view_type">form</field>
<field name="view_mode">form,tree</field>
<field name="view_id" ref="tree_view_yves_leads"/>
</record>
this works fine for the list-tree view but when I click on any item or the create button, I get the default form view for crm.
To add my customized view for form also, my understanding of odoo documentation is that I should use view_ids element but I was not able to get it right
I have tried several syntaxes with/without brackets, using eval="" or inside the xml definition but with no success. Searching this forum for string name="view_ids" was not very helfull, may be it is not the best practice to do that? any help appreciated
<record model="ir.actions.act_window" id="yvleads_mgt">
<field name="name">Leads Yves</field>
<field name="res_model">crm.lead</field>
<field name="view_type">form</field>
<field name="view_mode">form,tree</field>
<field name="view_ids">(tree,tree_view_yves_leads),(form,form_view_yves_leads)</field>
</record>
this is the right syntax :
<field name="view_ids"
eval="
[
(5, 0, 0),
(0, 0, {'view_mode': 'tree', 'view_id': ref('tree_external_id')}),
(0, 0, {'view_mode': 'form', 'view_id': ref('form_external_id')}),
]"
/>
The view_id you used in your action is valid only when you click on the menu connected to that action.
What you need to use is view inheritance, i.e. you need to redefine the existing views:
<record id="new_view" model="ir.ui.view">
<field name="name">new view</field>
<field name="model">crm.lead</field>
<field name="inherit_id" ref="crm_lead.existing_view_id"/>
<field name="arch" type="xml">
<data>
...
</data>
</field>
</record>
inside the data tag you can accomplish the modifications you need following the instructions in the provided link.
In theory you could also change the whole view, but this could ba problematic if other modules inherits that same view.
This way every time you open crm.lead model in any way, your view is used.
Btw the correct syntax for view_ids would be:
<field name="view_ids" eval="[(6, False, [ref('view_id_1'), ref('view_id_2')])]">
I think very useful for this link so please check it.
https://www.odoo.com/forum/help-1/question/for-which-reason-can-i-add-a-value-to-view-ids-of-a-window-action-97682

how can i use onchange from product field to one2many field of purchase order line odoo

Like i have one field in product.template with the field name squ_meter which i need to copy this value in custom field of purchase order line with same field name i.e squ_meter and i want to apply onchange on purchase order line field
Any kind of help would be much appreciated. Thanks in advance
Here's my code
class purchase_order_line(osv.osv):
_inherit = 'purchase.order.line'
_columns ={'squ_meter' : fields.float('Square Meter'),
}
purchase_order_line.xml
<field name="name">purchase.order.inherit</field>
<field name="model">purchase.order</field>
<field name="inherit_id" ref="purchase.purchase_order_form"/>
<field name="arch" type="xml">
<xpath expr="//page[#string='Products']//field[#name='order_line']//field[#name='product_qty']" position="after">
<field name="squ_meter"/>
</xpath>
</field>
Related Fields
Related field is useful when you want to keep the values of any relational fields except it's reference then it would be easier way to do it.
OLD API
_columns ={
'squ_meter': fields.related('product_id','squ_meter', type='float', relation='product.product', string='Square Meter', readonly=True),
}
Where:
The first set of parameters are the chain of reference fields to
follow, with the desired field at the end.
type is the type of that desired field.
Use relation if the desired field is still some kind of reference. relation is the table to look up that reference in.
NEW API
There is not anymore fields.related fields.
Instead you just set the name argument related to your model:
squ_meter = Fields.Float(string='Square Meter', related='product_id.squ_meter' , readonly=True)
purchase_order_line.xml
<field name="name">purchase.order.inherit</field>
<field name="model">purchase.order</field>
<field name="inherit_id" ref="purchase.purchase_order_form"/>
<field name="arch" type="xml">
<xpath expr="//page[#string='Products']//field[#name='order_line']//field[#name='product_qty']" position="after">
<field name="squ_meter" readonly="1" />
</xpath>
</field>