What is the right odoo 8 XML syntax for view_ids field - odoo

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

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>

Odoo header buttons missing

I'm having a problem with the create button appearing in tree view. Neither does the next or previous buttons appear in the form view. However, the data is being retrieved from the database.
Tree form with missing buttons
The module I'm trying to make is an extended module of the human resource module, like the included HR attendance module. The extended module doesn't inherit anything and security hasn't been added yet. Only a menu item is added to the main module.
A module I previously created by inheriting the main HR module created the buttons as expected.
Expected outcome(different module)
training.py:
from openerp import fields, models, api
class ew_training(models.Model):
_name = 'hr.training'
var = fields.Char( string='variable')
training_view.xml:
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Main Submenu -->
<menuitem id="menu_training_tree" action="action_view_training"
parent="hr.menu_hr_main" sequence="6"/>
<record id="action_view_training" model="ir.actions.act_window">
<field name="name">Training</field>
<field name="res_model">hr.training</field>
<field name="view_type">tree</field>
<field name="view_mode">tree,form</field>
</record>
<record id="view_training_tree" model="ir.ui.view">
<field name="name">hr.training.tree</field>
<field name="model">hr.training</field>
<field name="arch" type="xml">
<tree>
<field name="var"/>
</tree>
</field>
</record>
<record id="view_training_form" model="ir.ui.view">
...
</record>
</data>
</openerp>
Please try avoid using the old API
EDIT
This should be work if you are trying to call differents views in differents actions.
The problem is not the button create, the problem is that you are not calling the tree view on your action action_view_training, try adding this line after view_mode:
<field name="view_id" ref="view_training_tree"/>
EDIT
To solve your case you only need to change in the view_type, you should use form:
<record id="action_view_training" model="ir.actions.act_window">
<field name="name">Training</field>
<field name="res_model">hr.training</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
It should be work perfectly!!! I hope this could be helpful for you.
Just for Information.
in action view_type tree can be used when you want to create hierarchical view, It will not give you ability to create or update record. view of company structure in Odoo is the example of view type tree.
and view_type to form in action will allow you to create normal tree, form view with ability to Create, Update, Duplicate, Delete.
Hope this helps.

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

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',
}

How do I get the value from a form field using Odoo?

I have this field in a form view:
<field name="value"/>
I want to get the value from the field when someone wants to add a new value, the way that I might do $_GET['value'] in PHP.
Simple example:
I want, when the user inserts a value, for the program to check if it is greater than sum of all values and print an error message like:
Cannot add the value because it is greater than the sum of all values
I've written this so far:
view.xml
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="action_test" model="ir.actions.act_window">
<field name="name">Insert</field>
<field name="res_model">test.odoo</field>
<field name="view_mode">form,tree</field>
</record>
<record id="view_tree_test" model="ir.ui.view">
<field name="name">Inset.tree</field>
<field name="model">test.odoo</field>
<field name="arch" type="xml">
<tree string="T">
<field name="create_uid"/>
<field name="value" sum="Total Sum"/>
</tree>
</field>
</record>
<record id="view_from_test" model="ir.ui.view">
<field name="name">Inset.form</field>
<field name="model">test.odoo</field>
<field name="arch" type="xml">
<form string="T_Form">
<group>
<field name="value"/>
</group>
</form>
</field>
</record>
<menuitem name="Test Module" id="main_menu_test" sequence="3"/>
<menuitem name="TEST" id="sub_menu" parent="main_menu_test"/>
<menuitem action="action_test" id="action_menu" parent="sub_menu" />
</data>
</openerp>
test.py
from openerp import models
from openerp import fields
class test(models.Model):
_name = "test.odoo"
value = fields.Integer()
You cannot think about form view in odoo in isolation from the database layer.
The data from the form is immediately (and automatically) saved in the database. You can later access it using the ORM methods.
I don't know what exactly you want to achieve, so it's hard for me to give you a concrete example. Every form view is associated with a single ORM model. If you want to do do something with the data immediately before/after it is saved, you would usually subclass the ORM model and overwrite one of its methods.
class Foo(models.Model):
_inherit = 'other.foo'
#api.model
def create(self, vals):
record = super(Foo, self).create(vals)
print "A new Foo with name={} and bar={} has been created!".format(
record.name,
record.bar,
)
return record
This is how you validate a form:
from openerp import models, fields, api, exceptions
class test(models.Model):
_name = 'test.odoo'
value = fields.Integer()
#api.one
#api.constrains('value')
def _check_value(self):
if self.value > 25:
raise exceptions.ValidationError("The value is too large!")