Tutorial Openerp Basic Code

  • Home
  • About
  • Template
  • Design
  • Blogger
  • Tips Tricks

Create Menu on Openerp

Create Menu on Openerp
Menus are records in the ir.ui.menu table. In order to create a new menu entry, you can directly create a record using the record tag.
<record id="menu_xml_id" model="ir.ui.menu">
  <field name="name">My Menu</field>
  <field name="action" ref="action_xml_id"/>
  <field name="sequence" eval="<integer>"/>
  <field name="parent_id" ref="parent_menu_xml_id"/>
</record>
There is a shortcut by using the menuitem tag that you should use preferentially. It offers a flexible way to easily define the menu entry along with icons and other fields.
<menuitem id="menu_xml_id"
    name="My Menu"
    action="action_xml_id"
    icon="NAME_FROM_LIST"
    groups="groupname"
    sequence="<integer>"
    parent="parent_menu_xml_id"
/>
Where
  • id specifies the xml identifier of the menu item in the menu items table. This identifier must be unique. Mandatory field.
  • name defines the menu name that will be displayed in the client. Mandatory field.
  • action specifies the identifier of the attached action defined in the action table (ir.actions.act_window). This field is not mandatory : you can define menu elements without associating actions to them. This is useful when defining custom icons for menu elements that will act as folders. This is how custom icons for “Projects” or “Human Resources” in OpenERP are defined).
  • groups specifies which group of user can see the menu item. (example : groups=”admin”). See section ” Management of Access Rights” for more information. Multiple groups should be separated by a ‘,’ (example: groups=”admin,user”)
  • sequence is an integer that is used to sort the menu item in the menu. The higher the sequence number, the downer the menu item. This argument is not mandatory: if sequence is not specified, the menu item gets a default sequence number of 10. Menu items with the same sequence numbers are sorted by order of creation (_order = "*sequence,id*").
The main current limitation of using menuitem is that the menu action must be an act_window action. This kind of actions is the most used action in OpenERP. However for some menus you will use other actions. For example, the Feeds page that comes with the mail module is a client action. For this kind of menu entry, you can combine both declaration, as defined in the mail module :
<!-- toplevel menu -->
<menuitem id="mail_feeds_main" name="Feeds" sequence="0"
    web_icon="static/src/img/feeds.png"
    web_icon_hover="static/src/img/feeds-hover.png" />
<record id="mail_feeds_main" model="ir.ui.menu">
    <field name="action" ref="action_mail_all_feeds"/>
</record>

Actions

The actions define the behavior of the system in response to the actions of the users ; login of a new user, double-click on an invoice, click on the action button, ...
There are different types of simple actions:
  • Window: Opening of a new window
  • Report: The printing of a report
    o Custom Report: The personalized reports o RML Report: The XSL:RML reports
  • Execute: The execution of a method on the server side
  • Group: Gather some actions in one group
The actions are used for the following events:
  • User connection,
  • The user clicks on a menu,
  • The user clicks on the icon ‘print’ or ‘action’.

Opening of the menu

When the user open the option of the menu “Operations > Partners > Partners Contact”, the next steps are done to give the user information on the action to undertake.
  1. Search the action in the IR.
  2. Execution of the action
    1. If the action is the type Opening the Window; it indicates to the user that a new window must be opened for a selected object and it gives you the view (form or list) and the filed to use (only the pro-forma invoice).
    2. The user asks the object and receives information necessary to trace a form; the fields description and the XML view.

User connection

When a new user is connected to the server, the client must search the action to use for the first screen of this user. Generally, this action is: open the menu in the ‘Operations’ section.
The steps are:
  1. Reading of a user file to obtain ACTION_ID
  2. Reading of the action and execution of this one

The fields

Action Name
The action name
Action Type
Always ‘ir.actions.act_window’
View Ref
The view used for showing the object
Model
The model of the object to post
Type of View
The type of view (Tree/Form)
Domain Value
The domain that decreases the visible data with this view

The view

The view describes how the edition form or the data tree/list appear on screen. The views can be of ‘Form’ or ‘Tree’ type, according to whether they represent a form for the edition or a list/tree for global data viewing.
A form can be called by an action opening in ‘Tree’ mode. The form view is generally opened from the list mode (like if the user pushes on ‘switch view’).

The domain

This parameter allows you to regulate which resources are visible in a selected view.(restriction)
For example, in the invoice case, you can define an action that opens a view that shows only invoices not paid.
The domains are written in python; list of tuples. The tuples have three elements;
  • the field on which the test must be done
  • the operator used for the test (<, >, =, like)
  • the tested value
For example, if you want to obtain only ‘Draft’ invoice, use the following domain; [(‘state’,’=’,’draft’)]
In the case of a simple view, the domain define the resources which are the roots of the tree. The other resources, even if they are not from a part of the domain will be posted if the user develop the branches of the tree.

Window Action

Actions are explained in more detail in section “Administration Modules - Actions”. Here’s the template of an action XML record :
<record model="ir.actions.act_window" id="action_id_1">
    <field name="name">action.name</field>
    <field name="view_id" ref="view_id_1"/>
    <field name="domain">["list of 3-tuples (max 250 characters)"]</field>
    <field name="context">{"context dictionary (max 250 characters)"}</field>
    <field name="res_model">Open.object</field>
    <field name="view_type">form|tree</field>
    <field name="view_mode">form,tree|tree,form|form|tree</field>
    <field name="usage">menu</field>
    <field name="target">new</field>
</record>
Where
  • id is the identifier of the action in the table “ir.actions.act_window”. It must be unique.
  • name is the name of the action (mandatory).
  • view_id is the name of the view to display when the action is activated. If this field is not defined, the view of a kind (list or form) associated to the object res_model with the highest priority field is used (if two views have the same priority, the first defined view of a kind is used).
  • domain is a list of constraints used to refine the results of a selection, and hence to get less records displayed in the view. Constraints of the list are linked together with an AND clause : a record of the table will be displayed in the view only if all the constraints are satisfied.
  • context is the context dictionary which will be visible in the view that will be opened when the action is activated. Context dictionaries are declared with the same syntax as Python dictionaries in the XML file. For more information about context dictionaries, see section ” The context Dictionary”.
  • res_model is the name of the object on which the action operates.
  • view_type is set to form when the action must open a new form view, and is set to tree when the action must open a new tree view.
  • view_mode is only considered if view_type is form, and ignored otherwise. The four possibilities are :
    • form,tree : the view is first displayed as a form, the list view can be displayed by clicking the “alternate view button” ;
    • tree,form : the view is first displayed as a list, the form view can be displayed by clicking the “alternate view button” ;
    • form : the view is displayed as a form and there is no way to switch to list view ;
    • tree : the view is displayed as a list and there is no way to switch to form view.
(version 5 introduced graph and calendar views)
  • usage is used [+ *TODO* +]
  • target the view will open in new window like wizard.
  • context will be passed to the action itself and added to its global context
    <record model="ir.actions.act_window" id="a">
        <field name="name">account.account.tree1</field>
        <field name="res_model">account.account</field>
        <field name="view_type">tree</field>
        <field name="view_mode">form,tree</field>
        <field name="view_id" ref="v"/>
        <field name="domain">[('code','=','0')]</field>
        <field name="context">{'project_id': active_id}</field>
    </record>
    
They indicate at the user that he has to open a new window in a new ‘tab’.
Administration > Custom > Low Level > Base > Action > Window Actions

Examples of actions

This action is declared in server/bin/addons/project/project_view.xml.
<record model="ir.actions.act_window" id="open_view_my_project">
    <field name="name">project.project</field>
    <field name="res_model">project.project</field>
    <field name="view_type">tree</field>
    <field name="domain">[('parent_id','=',False), ('manager', '=', uid)]</field>
    <field name="view_id" ref="view_my_project" />
</record>
This action is declared in server/bin/addons/stock/stock_view.xml.
<record model="ir.actions.act_window" id="action_picking_form">
    <field name="name">stock.picking</field>
    <field name="res_model">stock.picking</field>
    <field name="type">ir.actions.act_window</field>
    <field name="view_type">form</field>
    <field name="view_id" ref="view_picking_form"/>
    <field name="context">{'contact_display': 'partner'}</field>
</record>

Url Action

Report Action

Report declaration

Reports in OpenERP are explained in chapter “Reports Reporting”. Here’s an example of a XML file that declares a RML report :
<?xml version="1.0"?>
<openerp>
    <data>
    <report id="sale_category_print"
            string="Sales Orders By Categories"
            model="sale.order"
            name="sale_category.print"
            rml="sale_category/report/sale_category_report.rml"
            menu="True"
            auto="False"/>
     </data>
</openerp>
A report is declared using a report tag inside a “data” block. The different arguments of a report tag are :
  • id : an identifier which must be unique.
  • string : the text of the menu that calls the report (if any, see below).
  • model : the OpenERP object on which the report will be rendered.
  • rml : the .RML report model. Important Note : Path is relative to addons/ directory.
  • menu : whether the report will be able to be called directly via the client or not. Setting menu to False is useful in case of reports called by wizards.
  • auto : determines if the .RML file must be parsed using the default parser or not. Using a custom parser allows you to define additional functions to your report.

Action creation

Linking events to action

The available type of events are:
  • client_print_multi (print from a list or form)
  • client_action_multi (action from a list or form)
  • tree_but_open (double click on the item of a tree, like the menu)
  • tree_but_action (action on the items of a tree)
To map an events to an action:
<record model="ir.values" id="ir_open_journal_period">
    <field name="key2">tree_but_open</field>
    <field name="model">account.journal.period</field>
    <field name="name">Open Journal</field>
    <field name="value" eval="'ir.actions.wizard,%d'%action_move_journal_line_form_select"/>
    <field name="object" eval="True"/>
</record>
If you double click on a journal/period (object: account.journal.period), this will open the selected wizard. (id=”action_move_journal_line_form_select”).
You can use a res_id field to allow this action only if the user click on a specific object.
<record model="ir.values" id="ir_open_journal_period">
    <field name="key2">tree_but_open</field>
    <field name="model">account.journal.period</field>
    <field name="name">Open Journal</field>
    <field name="value" eval="'ir.actions.wizard,%d'%action_move_journal_line_form_select"/>
    <field name="res_id" eval="3"/>
    <field name="object" eval="True"/>
</record>
The action will be triggered if the user clicks on the account.journal.period n°3.
When you declare wizard, report or menus, the ir.values creation is automatically made with these tags:
  • <menuitem... />
  • <report... />
So you usually do not need to add the mapping by yourself.
0
Komentar
f
Share
t
Tweet
g+
Share
?
Unknown
18.11

Functional Fields On Openerp

Functional Fields On Openerp
A functional field is a field whose value is calculated by a function (rather than being stored in the database).
Parameters:
fnct, arg=None, fnct_inv=None, fnct_inv_arg=None, type="float",
    fnct_search=None, obj=None, method=False, store=False, multi=False
where
  • fnct is the function or method that will compute the field value. It must have been declared before declaring the functional field.
  • fnct_inv is the function or method that will allow writing values in that field.
  • type is the field type name returned by the function. It can be any field type name except function.
  • fnct_search allows you to define the searching behaviour on that field.
  • method whether the field is computed by a method (of an object) or a global function
  • store If you want to store field in database or not. Default is False.
  • multi is a group name. All fields with the same multi parameter will be calculated in a single function call.

fnct parameter

If method is True, the signature of the method must be:
def fnct(self, cr, uid, ids, field_name, arg, context):
otherwise (if it is a global function), its signature must be:
def fnct(cr, table, ids, field_name, arg, context):
Either way, it must return a dictionary of values of the form {id’_1_’: value’_1_’, id’_2_’: value’_2_’,...}.
The values of the returned dictionary must be of the type specified by the type argument in the field declaration.
If multi is set, then field_name is replaced by field_names: a list of the field names that should be calculated. Each value in the returned dictionary is also a dictionary from field name to value. For example, if the fields ‘name’, and ‘age’ are both based on the vital_statistics function, then the return value of vital_statistics might look like this when ids is [1, 2, 5]:
{
    1: {'name': 'Bob', 'age': 23},
    2: {'name': 'Sally', 'age', 19},
    5: {'name': 'Ed', 'age': 62}
}

fnct_inv parameter

If method is true, the signature of the method must be:
def fnct(self, cr, uid, ids, field_name, field_value, arg, context):
otherwise (if it is a global function), it should be:
def fnct(cr, table, ids, field_name, field_value, arg, context):

fnct_search parameter

If method is true, the signature of the method must be:
def fnct(self, cr, uid, obj, name, args, context):
otherwise (if it is a global function), it should be:
def fnct(cr, uid, obj, name, args, context):
The return value is a list containing 3-part tuples which are used in search function:
return [('id','in',[1,3,5])]
obj is the same as self, and name receives the field name. args is a list of 3-part tuples containing search criteria for this field, although the search function may be called separately for each tuple.

Example

Suppose we create a contract object which is :
class hr_contract(osv.osv):
    _name = 'hr.contract'
    _description = 'Contract'
    _columns = {
        'name' : fields.char('Contract Name', size=30, required=True),
        'employee_id' : fields.many2one('hr.employee', 'Employee', required=True),
        'function' : fields.many2one('res.partner.function', 'Function'),
    }
hr_contract()
If we want to add a field that retrieves the function of an employee by looking its current contract, we use a functional field. The object hr_employee is inherited this way:
class hr_employee(osv.osv):
    _name = "hr.employee"
    _description = "Employee"
    _inherit = "hr.employee"
    _columns = {
        'contract_ids' : fields.one2many('hr.contract', 'employee_id', 'Contracts'),
        'function' : fields.function(
            _get_cur_function_id,
            type='many2one',
            obj="res.partner.function",
            method=True,
            string='Contract Function'),
    }
hr_employee()
Note
three points
  • type =’many2one’ is because the function field must create a many2one field; function is declared as a many2one in hr_contract also.
  • obj =”res.partner.function” is used to specify that the object to use for the many2one field is res.partner.function.
  • We called our method _get_cur_function_id because its role is to return a dictionary whose keys are ids of employees, and whose corresponding values are ids of the function of those employees. The code of this method is:
def _get_cur_function_id(self, cr, uid, ids, field_name, arg, context):
    for i in ids:
        #get the id of the current function of the employee of identifier "i"
        sql_req= """
        SELECT f.id AS func_id
        FROM hr_contract c
          LEFT JOIN res_partner_function f ON (f.id = c.function)
        WHERE
          (c.employee_id = %d)
        """ % (i,)

        cr.execute(sql_req)
        sql_res = cr.dictfetchone()

        if sql_res: #The employee has one associated contract
            res[i] = sql_res['func_id']
        else:
            #res[i] must be set to False and not to None because of XML:RPC
            # "cannot marshal None unless allow_none is enabled"
            res[i] = False
    return res
The id of the function is retrieved using a SQL query. Note that if the query returns no result, the value of sql_res[‘func_id’] will be None. We force the False value in this case value because XML:RPC (communication between the server and the client) doesn’t allow to transmit this value.

store Parameter

It will calculate the field and store the result in the table. The field will be recalculated when certain fields are changed on other objects. It uses the following syntax:
store = {
    'object_name': (
            function_name,
            ['field_name1', 'field_name2'],
            priority)
}
It will call function function_name when any changes are written to fields in the list [‘field1’,’field2’] on object ‘object_name’. The function should have the following signature:
def function_name(self, cr, uid, ids, context=None):
Where ids will be the ids of records in the other object’s table that have changed values in the watched fields. The function should return a list of ids of records in its own table that should have the field recalculated. That list will be sent as a parameter for the main function of the field.
Here’s an example from the membership module:
'membership_state':
    fields.function(
        _membership_state,
        method=True,
        string='Current membership state',
        type='selection',
        selection=STATE,
        store={
            'account.invoice': (_get_invoice_partner, ['state'], 10),
            'membership.membership_line': (_get_partner_id,['state'], 10),
            'res.partner': (
                lambda self, cr, uid, ids, c={}: ids,
                ['free_member'],
                10)
        }),

Property Fields

Declaring a property

A property is a special field: fields.property.
class res_partner(osv.osv):
    _name = "res.partner"
    _inherit = "res.partner"
    _columns = {
                'property_product_pricelist':
                                            fields.property(
                                'product.pricelist',
                        type='many2one',
                        relation='product.pricelist',
                        string="Sale Pricelist",
                                method=True,
                                group_name="Pricelists Properties"),
    }
Then you have to create the default value in a .XML file for this property:
<record model="ir.property" id="property_product_pricelist">
    <field name="name">property_product_pricelist</field>
    <field name="fields_id" search="[('model','=','res.partner'),
      ('name','=','property_product_pricelist')]"/>
    <field name="value" eval="'product.pricelist,'+str(list0)"/>
</record>
Tip
if the default value points to a resource from another module, you can use the ref function like this:
<field name=”value” eval=“‘product.pricelist,’+str(ref(‘module.data_id’))”/>
Putting properties in forms
To add properties in forms, just put the <properties/> tag in your form. This will automatically add all properties fields that are related to this object. The system will add properties depending on your rights. (some people will be able to change a specific property, others won’t).
Properties are displayed by section, depending on the group_name attribute. (It is rendered in the client like a separator tag).
How does this work ?
The fields.property class inherits from fields.function and overrides the read and write method. The type of this field is many2one, so in the form a property is represented like a many2one function.
But the value of a property is stored in the ir.property class/table as a complete record. The stored value is a field of type reference (not many2one) because each property may point to a different object. If you edit properties values (from the administration menu), these are represented like a field of type reference.
When you read a property, the program gives you the property attached to the instance of object you are reading. If this object has no value, the system will give you the default property.
The definition of a property is stored in the ir.model.fields class like any other fields. In the definition of the property, you can add groups that are allowed to change to property.
Using properties or normal fields
When you want to add a new feature, you will have to choose to implement it as a property or as normal field. Use a normal field when you inherit from an object and want to extend this object. Use a property when the new feature is not related to the object but to an external concept.
Here are a few tips to help you choose between a normal field or a property:
Normal fields extend the object, adding more features or data.
A property is a concept that is attached to an object and have special features:
  • Different value for the same property depending on the company
  • Rights management per field
  • It’s a link between resources (many2one)
Example 1: Account Receivable
The default “Account Receivable” for a specific partner is implemented as a property because:
  • This is a concept related to the account chart and not to the partner, so it is an account property that is visible on a partner form. Rights have to be managed on this fields for accountants, these are not the same rights that are applied to partner objects. So you have specific rights just for this field of the partner form: only accountants may change the account receivable of a partner.
  • This is a multi-company field: the same partner may have different account receivable values depending on the company the user belongs to. In a multi-company system, there is one account chart per company. The account receivable of a partner depends on the company it placed the sale order.
  • The default account receivable is the same for all partners and is configured from the general property menu (in administration).
Note
One interesting thing is that properties avoid “spaghetti” code. The account module depends on the partner (base) module. But you can install the partner (base) module without the accounting module. If you add a field that points to an account in the partner object, both objects will depend on each other. It’s much more difficult to maintain and code (for instance, try to remove a table when both tables are pointing to each others.)
Example 2: Product Times
The product expiry module implements all delays related to products: removal date, product usetime, ... This module is very useful for food industries.
This module inherits from the product.product object and adds new fields to it:
class product_product(osv.osv):

    _inherit = 'product.product'
    _name = 'product.product'
    _columns = {

        'life_time': fields.integer('Product lifetime'),
        'use_time': fields.integer('Product usetime'),
        'removal_time': fields.integer('Product removal time'),
        'alert_time': fields.integer('Product alert time'),
        }

product_product()
This module adds simple fields to the product.product object. We did not use properties because:
  • We extend a product, the life_time field is a concept related to a product, not to another object.
  • We do not need a right management per field, the different delays are managed by the same people that manage all products.


0
Komentar
f
Share
t
Tweet
g+
Share
?
Unknown
18.09

Relational Types on Openerp

Relational Types on Openerp
one2one:
A one2one field expresses a one:to:one relation between two objects. It is deprecated. Use many2one instead.
Syntax:
fields.one2one('other.object.name', 'Field Name')
many2one:
Associates this object to a parent object via this Field. For example Department an Employee belongs to would Many to one. i.e Many employees will belong to a Department
Syntax:
fields.many2one(
        'other.object.name',
        'Field Name',
        optional parameters)
Optional parameters:
  • ondelete: What should happen when the resource this field points to is deleted.
    • Predefined value: “cascade”, “set null”, “restrict”, “no action”, “set default”
    • Default value: “set null”
  • required: True
  • readonly: True
  • select: True - (creates an index on the Foreign Key field)
Example
'commercial': fields.many2one(
        'res.users',
        'Commercial',
        ondelete='cascade'),
one2many:
TODO
Syntax:
fields.one2many(
        'other.object.name',
        'Field relation id',
        'Fieldname',
        optional parameter)
Optional parameters:
  • invisible: True/False
  • states: ?
  • readonly: True/False
Example
'address': fields.one2many(
        'res.partner.address',
        'partner_id',
        'Contacts'),
many2many:
TODO
Syntax:
fields.many2many('other.object.name',
                 'relation object',
                 'actual.object.id',
                 'other.object.id',
                 'Field Name')
Where:
  • other.object.name is the other object which belongs to the relation
  • relation object is the table that makes the link
  • actual.object.id and other.object.id are the fields’ names used in the relation table
Example:
'category_ids':
   fields.many2many(
    'res.partner.category',
    'res_partner_category_rel',
    'partner_id',
    'category_id',
    'Categories'),
To make it bidirectional (= create a field in the other object):
class other_object_name2(osv.osv):
    _inherit = 'other.object.name'
    _columns = {
        'other_fields': fields.many2many(
            'actual.object.name',
            'relation object',
            'actual.object.id',
            'other.object.id',
            'Other Field Name'),
    }
other_object_name2()
Example:
class res_partner_category2(osv.osv):
    _inherit = 'res.partner.category'
    _columns = {
        'partner_ids': fields.many2many(
            'res.partner',
            'res_partner_category_rel',
            'category_id',
            'partner_id',
            'Partners'),
    }
res_partner_category2()
related:
Sometimes you need to refer to the relation of a relation. For example, supposing you have objects: City -> State -> Country, and you need to refer to the Country from a City, you can define a field as below in the City object:
'country_id': fields.related(
    'state_id',
    'country_id',
    type="many2one",
    relation="res.country",
    string="Country",
    store=False)
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.
0
Komentar
f
Share
t
Tweet
g+
Share
?
Unknown
18.07
Postingan Lama Beranda
Langganan: Komentar (Atom)
Find Us :

Entri Populer

  • Functional Fields On Openerp
    A functional field is a field whose value is calculated by a function (rather than being stored in the database). Parameters: fnct, ar...
  • Relational Types on Openerp
    one2one: A one2one field expresses a one:to:one relation between two objects. It is deprecated. Use many2one instead. Syntax: fields ...
  • Basic Type Fields On Openerp
    boolean: A boolean (true, false). Syntax: fields.boolean('Field Name' [, Optional Parameters]), integer: An integer. S...
  • Create Menu on Openerp
    Menus are records in the ir.ui.menu table. In order to create a new menu entry, you can directly create a record using the record tag. ...
  • Predefined fields in Openerp
    _auto Determines whether a corresponding PostgreSQL table must be generated automatically from the object. Setting _auto to False can be u...
  • Fields Introduction on Openerp
    Here’s the header of the initialization method of the class any field defined in OpenERP inherits (as you can see in server/bin/osv/fields.p...

Mengenai Saya

Unknown
Lihat profil lengkapku
Diberdayakan oleh Blogger.
Copyright 2013 Tutorial Openerp Basic Code - All Rights Reserved
Design by Download software Articel and game free