jeudi 23 octobre 2014

Openerp Module Development .

Un module openerp est généralement composé de fichiers et repertoires suivants.
 module_name/
    ├── module_name.py
    ├── module_name_view.xml
    ├── __init__.py
    ├── __openerp__.py
    ├── reports
    ├── wizards
    └── workflows
init : Indique que le dossier est un package
module_name.py : Il contient les objects de votre module
module_name_view.xml : Gere les donnees via une definition d'interface (view, les menu, les interactions ...)
openerp : Decrit le module (nom , version, auteur, dependances,...)
reports : Dossier contenant les objest et fichiers lies au reporting
wizards : Dossier contenant les objets definissant les interactions client-server (voir)
workflow : Dossier contenant la definition d'un workflow (voir)

A- Un hello world

Pour notre hello world j'ai pensé à un module nous permettant d'enregistrer une famille et ses membres .
A vos terminaux !!!
Creer un dossier family dans votre espace de travail avec les fichier suivants :
1- openerp.py dont le contenu est le suivant :
{
    "name":"family", # le nom du module, il apparait dans la liste des modules
    "version":"1.0", # la version
    "author":"Josue", # l'auteur
    "website":"none", # site web
    "category":"Generic Modules/Others", # category du module
    "depends":["base"], # liste des modules de dependances
    "description":"Simple module permettant d'enregistrer une famille est ses memebres",
    "update_xml":["family_view.xml"], #liste des vue, dans notre cas family_view.xml
    "demo_xml":[],
    "init_xml":[],
    "active":False,
    "installable":True,
}
NB : Tous les modules dependent de base .
2- init.py contenant ceci :
import family
Simple importation d'un module python
3- family.py
from osv import osv, fields

class family_family(osv.osv):
    _name = 'family.family'
    _columns = {
        'name': fields.char('Family Name',size=128),
        'member_ids': fields.one2many('family.member','family_id','Members'),
    }


family_family()

class family_member(osv.osv):
    _name = 'family.member'
    _columns = { # dictionnaire des champs de l'object
        'firstname': fields.char('FirstName',size=128),
        'lastname': fields.char('LastName',size=128),
        'family_id': fields.many2one('family.family','Family',ondelete='cascade'),
        'gender': fields.selection(  # definition d'un champ de selection
            [('male','Male'),
            ('female','Female'),
            ],'Gender',readonly=False,select=True),
    }
    # default : dictionnaire des valeurs par defaut
    _defaults = {
        'lastname' : lambda self, cr, uid, context : self.pool.get('family.family').browse(cr, uid, context['family_id']).name if context and 'family_id' in context else None,
        'gender' : lambda *a: 'male', # "male" sera la valeur par defaut du champ "gender"
    }

family_member() #instanciation de la classe , __N'oubliez jamais de le faire__
Ce fichier decrit les objects du modules et leur caracteristiques
Documentation sur l'objet osv
Documentation sur l'objet fields

explications :

_defaults['lastname'], j'ai utilisé une fonction lambda afin de permettre que le champ lastname soit automatiquement rempli en se servant du context family_id definit dans le fichier family_view.xml au sein de l'objet family. Mais cela ne se fera que dans la condition ou un membre sera crée à partir du menu(vue,interface) d'une famille.
4- family_view.xml
<?xml version="1.0" ?>

<openerp>
        <data>

    <menuitem id="family" name="Family" />

    <!--Family-->
    <record model="ir.ui.view" id="family_form"> <!-- definition d'une vuew dont l'id est "family_form"--> 
        <field name="name">family.form</field> <!-- nom de la vue -->
        <field name="model">family.family</field> <!-- classe sur laquelle on se base pour creer la vue (une des classes de "family.py", dans notre cas "family.family")-->
        <field name="type">form</field> <!--type de vue : form/tree/graph -->
        <field name="arch" type="xml">
            <form string="Family" > <!-- declaration d'un formulaire -->
                <field name="name"/>  <!-- declaration d'un champ -->
                <notebook colspan="4"> 
                    <page string="Members">
                        <field name="member_ids" domain="[('family_id','=',active_id)]" context="{'family_id':active_id}"/> <!-- definition d'un context -->
                    </page>
                </notebook>
            </form>
        </field>
    </record>

    <record model="ir.ui.view" id="family_tree">
        <field name="name">family.tree</field>
        <field name="model">family.family</field>
        <field name="type">tree</field> <!--type de vue : tree, correspond a l'affichage en liste d'elements --> 
        <field name="arch" type="xml">
            <tree string="Family" > <!-- on declare "tree" cette fois ci et non un "form"-->
                <field name="name"/>
                <field name="member_ids"/> <!-- declaration des champs -->
            </tree>
        </field>
    </record>

    <!-- Notez que tous les champs declarés ici sont dans family.py, sinon une erreur sera levée -->

    <!--Definition d'une action -->

    <record model="ir.actions.act_window" id="action_family"> <!-- le model est bien différent : "ir.actions" et non "ir.ui.view" -->
        <field name="name">Family</field> <!-- nom de l'action -->
        <field name="res_model">family.family</field> <!-- model sur lequel se base l'action -->
        <field name="view_type">form</field> 
        <field name="view_mode">tree,form</field>
    </record>

    <!-- Declaration d'un menu -->
    <menuitem id="family_menu" name="Family" parent="family" action="action_family"/>
    <!--
        id : identifiant du menu
        name : nom du menu
        parent : le menu dont depend celui-ci, il sera donc un sous-menu 
        action : action relier au menu
    -->
    <!-- "action_family" correspond à l'id de l'acton déclarée pécedement -->


    <!--Members-->

    <record model="ir.ui.view" id="member_form">
        <field name="name">member.form</field>
        <field name="model">family.member</field>
        <field name="type">form</field>
        <field name="arch" type="xml">
            <form string="Member" >
                <field name="firstname"/>
                <field name="lastname"/>
                <field name="gender" />
                <field name="family_id"/>
            </form>
        </field>
    </record>

    <record model="ir.ui.view" id="member_tree">
        <field name="name">member.tree</field>
        <field name="model">family.member</field>
        <field name="type">tree</field>
        <field name="arch" type="xml">
            <tree string="Member" >
                <field name="firstname"/>
                <field name="lastname"/>
                <field name="gender" />
                <field name="family_id"/>
            </tree>
        </field>
    </record>

    <record model="ir.actions.act_window" id="action_member">
        <field name="name">Member</field>
        <field name="res_model">family.member</field>
        <field name="view_type">form</field>
        <field name="view_mode">tree,form</field>
    </record>

    <menuitem id="member_menu" name="Members" parent="family" action="action_member"/>

    </data>
</openerp>

Aucun commentaire:

Enregistrer un commentaire