Monday, December 21, 2009

La gestion des rapports

Introduction:

* Il existe 3 méthodes pour gérer des rapports dans OpenERP:

● Les rapports OpenOffice .
● Les rapports XML et XLS:RML .
● Les rapports colonnes créés directement dans le client OpenERP .
Nous nous intéresserons à la première méthode qui est à la fois la plus
simple et la plus fléxible .

* Le processus de création d'un nouveau :

OpenERP propose une intégration des rapports avec OpenOffice.Il est ainsi possible de faire la mise en page d'un rapport dans OpenOffice puis de l'importer dans OpenERP.
OpenERP utilise un 'dialecte' XML pour définir les rapports, le "RML". Les fichiers RML décrivent la structure du document ainsi que les expressions et les champs à inclure.
Il est bien sûr possible de modifier directement un rapport au travers de l'édition de son fichier RML, mais alors la possibilité de mise en page ultérieure avec OpenOffice est perdue .

* Exemple Création du report PDF de commande :

OpenERP possède une structure complètement modulaire, chaque module se trouve dans un
répertoire /addons/ qui contient le code source de définition des classes, des écrans et des rapports .
Le report de commande doit faire partie du module 'mon_module', il se trouvera donc dans bin/addons/mon_module/report/ .
Dans ce répertoire, le fichier rml génère le formulaire pdf tandis que le fichier sxw est capable de regénérer le fichier rml. Ce fichier sxw est éditable par Open Office (version 2.x ou 3.x), vous pouvez le télécharger à partir de ce lien OpenOffice .

* Etapes de création du fichier .RML :

1. Editer le fichier commande avec Open Office (enregistrez le au format .swx) .

2. Uploader le fichier commande.swx créé dans votre compte sur le serveur .

3. Déplacer vous dans le répertoire ou se trouve le script tiny_sxw2rml.py .

4. Lancer la conversion d'un rapport en rml avec la commande suivante:
tiny_sxw2rml.py file.sxw >file.rml .
tiny_sxw2rml.py commande.sxw >commande.rml .

* Construction d'un rapport :

Chaque rapport est construit sur la base d'un objet [[o]] et des attributs de cet objet. Par exemple, la description de la commande achat (order) est représentée par l'expression suivante: [[ o.name ]] .L'objet 'order' est relié à l'objet
'res.partner' par le champ many2one 'partner_id'. Il est donc possible d'afficher le
nom du partenaire en utilisant le code suivant: [[o.partner_id.name]] . L'objet 'order' possède un objet 'line', c'est à dire qu'un order est composé d'une ou de plusieurs lignes de commande .
Il est possible d'accéder à ces lignes de commandes par la fonction:
"[[ repeatIn(o.line_ids,'line') ]]" qui nous fournit un nouvel objet
'line' contenant les attributs de chaque ligne de commande. Par exemple "[[line.quantity]]" affiche la quantité commandée .
Order line possède un attribut 'product_id' qui est une relation many2one avec l'objet 'product' . L'objet product possède un attribut 'name'.
Nous pouvons donc écrire [[ line.product_id and line.product_id.name]] . Après avoir éditer le fichier commande.sxw, on procéde à sa converssion du sxw en rml via le
programme : tiny_sxw2rml.py Le fichier commande.rml ainsi converti doit se trouvé dans le dossier: addons\mon_module\report .
Dans le fichier __init__.py qui va appeller les fonctions nécessaires ajouter la fonction suivante: import report .
Puis ajouter le dossier report qui contiendra le fichier commande.rml .
Ensuite dans le fichier __terp__.py qui va permettre de déclarer le report, modifier la ligne update_xml :
"update_xml" : ["tiny_purchase_view.xml”,"tiny_purchase_report.xml”] .
La définition du report se trouvera dans le fichier : (mon_module_report.xml).

Editer un fichier xml correspondant au report: mon_module_report.xml .


< ?xml version="1.0"? >
<>
<>
< id="report.order" string="Order" model="mon_module.order" name="commande" rml="mon_module/report/commande.rml">
< /data >
< /openerp >


name="commande", "commande" : est un nom interne donné au report
rml="tiny_purchase/report/commande.rml" .
L'exécution est très simple : faites une mise à jour du module et c'est tout :) !

Dans le cas où le report contient un champs ne se trouvant pas dans l'objet en
question, alors il faut définir une classe spécifique à ce report contenant la
définition du champs en question, Par exemple le total de la commande ne
se trouve nul part dans l'objet order.
Dans ce cas, nous devons définir la classe commande de la façon suivante :


from report import report_sxw
class commande(report_sxw.rml_parse):
def __init__(self, cr, uid, name, context):
super(commande, self).__init__(cr, uid, name, context)
self.localcontext.update({
'time': time,
'total': self.total,
})
def total(self, lines):
res=0
for i in lines:
res += i.price
return res
report_sxw.report_sxw('report.commande','tiny_purchase.order','addons/tiny_purc
hase/report/commande.rml', parser=commande)


Dans le fichier mon_module_report.xml on doit ajouter le paramètre auto:
auto=”False” si le report utilise des champs définis par un code.
auto=”True” si le report n'utilise que les champs définis dans la base de donnée (valeur par défaut=True) .
Enrégistrer cette déclaration dans le fichier : commande.py
puis ajouter un fichier init.py dans le dossier addons\mon_module\report
qui appellera commande.py : import commande .

Monday, December 14, 2009

Le worflow

On appelle workflow la modélisation et la gestion informatique de l'ensemble des tâches à accomplir et des différents acteurs impliqués dans la réalisation d'un processus métier (aussi appelé processus opérationnel ou bien procédure d'entreprise). Le terme de « workflow » pourrait donc être traduit en français par « gestion électronique des processus métier ». De façon plus pratique, le workflow décrit le circuit de validation, les tâches à accomplir entre les différents acteurs d'un processus, les délais, les modes de validation, et fournit à chacun des acteurs les informations nécessaires pour la réalisation de sa tâche. Pour un processus de publication en ligne par exemple, il s'agit de la modélisation des tâches de l'ensemble de la chaîne éditoriale.

Il permet généralement un suivi et identifie les acteurs en précisant leur rôle et la manière de le remplir au mieux.

1 - Définir un worflow :
* name: nom du workflow .
* osv: nom de l'objet .
* on_create: instancie en création .

2 - Définier une liste de noeuds :
* wkf_id
* flow_start
* flow_stop
* kind
- dummy (ne fait rien)
- function (appelle une methode objet )
- subflow (appelle un subworkflow)
* Action (= nom de methode)
- si kind est une “function” ou un “subflow”
* subflow_id
- si kind = “subflow”
- < name="subflow_id" search="[('name','=','account.invoice.basic')]">

3 - Définier une liste de transactions :
* Champs :
- act_from: id de l'activité source .
- act_to: id de activité destination .
- condition: expression python .
- signal: nom d'un bouton attendu .
- role_id: role necessaire pour l'execution de la transition .

** Exemple :
Commencez par créer un fichier nom_module_worflow.xml dans le dossier qui contient les .py et les vues que vous avez créer déja .
Dans la partie qui suit, on déclare les activités workflow où on spécifie l'id du workflow, la nature de l'activité ainsi que l'action qui doit s'exécuter .

< record model="workflow" id="account">
< field name="name">budget.account.basic< /field>
< field name="osv">budget.account< /field>
< field name="on_create">True< /field>
< /record>
< record model="workflow.activity" id="retour">
< field name="wkf_id" ref="account">
< field name="flow_start">True< /field>
< field name="name">draft< /field>
< field name="kind">function< /field>
< field name="action">budget_confirm()< /field>
< /record>


Ensuite on déclare les transactions, c'est ici que se manifeste le fonctionnement du workflow .

< record model="workflow.transition" id="valide_account">
< field name="act_from" ref="non_valide"/ >
< field name="act_to" ref="valide"/ >
< field name="signal">valider< /field>
< /record>


Dans la partie act_from, on mets l'activité à partir de laquelle le flux commence, et dans act_to ç'est là où mène le flux .

Enfin, voici un petit shéma explicatif qui résume le fonctionnement d'un workflow au sein d'une opération sur OpenERP .

Tuesday, December 8, 2009

Les objets en détails

Dans cette partie, on verra d'autres types de champs qu'on utilise souvent dans la programmation pour OpenERP .

* Les champs complexes :

1- function (nom_methode, type_methode, ...) : Un champs de type fonction est un champs dont la valeur est calculée par une fonction (plutôt que étant stockées dans la base de données).

def essai(self, cr, uid, ids,field_name=None,arg=None,context={}):
res = {}
for m in ...
res[m.id] = ...
return res

'a': fields.function(essai, method=True, string='A',type='char').

On a définie la fonction essai ayant comme paramètres :
- self : l'objet courant .
- cr : le curesseur courant (base de données ouverte) .
- uid : l'identifiant du user connecté .
- ids : les identifiants de l'objet courant .
Le champs a est du type function .
La fonction est essai .

2- Les selections : selection (options_possibles, ...)
* Exemple:
'state': fields.selection (('e','encours'),('c','confirme'), 'Etat', required = True).

* Les champs relation :

1- many2one (obj, ...) :
* Exemple :
'service': fields.many2one('ir.module.category', 'Service Demandeur') .

2- one2many (obj, field_id, ...) :
* Exemple :
'addresse': fields.one2many('res.partner.address', 'partner_id', 'Contacts') .

L'attribut "_defaults" permet de définir des valeurs par défaut pour un ou plusieurs champs simples d'un objet .
Puisque les valeurs par défaut ne doivent pas être statiques (elles peuvent , par exemple, dependre des valeurs des resources déjà créés), vous devez définir les fonctions de valeurs par défaut et pas des simples valeurs constantes .
Pour définir les valeurs par défaut pour des champs d'un objet , vous devez definir un dictionaire de la forme: {'nom_du_champs': function, ...} .

* Syntax:
_defaults = {
'nom_champs': function,
...
}

* Exemple
_defaults = {
'etat': lambda *a: 'engage'
}

Python permet une syntaxe intéressante qui vous laisse définir des minifonctions d’une ligne à la volée. Empruntées à Lisp, ces fonctions dites lambda peuvent être employées partout où une fonction est nécéssaire .

g = lambda x: x*2
g(7)
14

La fonction lambda fait la même chose qu'une fonction ordinaire . Notez la syntaxe condensée : il n’y a pas de parenthèses autour de la liste d’arguments et le mot
clé return est manquant (il est implicite, la fonction complète ne pouvant être qu’une seule expression). Remarquez aussi que la fonction n’a pas de nom, mais qu’elle peut être appelée à travers la variable à laquelle elle est assignée, c'est un peu étrange mais très intéressant :) .

* Méthodes prédéfinies des objets :

1- Create :
- Description : Créer une nouvelle ressource
- Signature : def create(self, cr, uid, vals, context={})
Retourne le id de la ressource créée
- Parametres :
● vals: Un dictionnaire de valeurs pour les champs. Ce dictionnaire doit avoir la forme suivante: {'nom_du_champs': valeur, ...}
● context (optionel): Le contexte actuel.

2- Search :
- Description : Cherche toutes les ressources satisfaisant certains critéres .
- Signature :
def search(self, cr, uid, args, offset=0, limit=2000)
args = [('field_name', 'operator', value), ...] .
Elle retourne une liste de ids .

3- Read :
- Description: Liste des valeurs de champs .
- Signature :
def read(self, cr, uid, ids, fields=None, context={})
- Parametres :
● ids: liste des identifients des ressources à lire .
● fields (optionel): la liste des champs spécifiques. Si nous n'introduisons pas ce parmétre, la fonction contrôle tous les champs.
● context (optionel): le contexte actuel.
Elle retourne une liste de dictionaires (un dictionaire par resource intérrogé) de la forme: [{'field_name': value}] .

4- Write :
- Description :
Elle écrit des valeurs sur un ou plusieurs champs d'une ou plusieurs ressources .
- Signature :
def write(self, cr, uid, ids, vals, context={})
vals = {'field_name': value, ...}
retourne True .

5- Unlink :
- Description :
Supprime une ou plusieurs ressources
- Signature :
def unlink(self, cr, uid, ids)
retourne True .

6- Browse :
- Description: Retourne une ou plusieurs ressources d'un objet.
def browse(self, cr, uid, ids, offset=0, limit=2000)
- Signature :
addr_obj = self.pool.get('res.partner.address').browse(cr, uid, contact_ids)
contact_name = addr_obj.name
contact_bank = addr_obj.partner_id.bank .

Je mettrai à votre disposition un exemple bien détaillé englobant tout ce qu'on a vu dans la partie administration, que vous pouvez intégrer facilement sous OpenERP, tester et meme y faire des modifictions et personnaliser ;) .

Les vues (Partie 2)

Dans cette partie, on va voir comment personnaliser la vue dans OpenERP :

* Les attributs pour le tag des champs :
select="1" .
colspan="2" .
string="Nom libellé" .
readonly="1" .
nolabel="1" .
required="1" .
on_change:
- Exemple:
on_change = ''_onchange_partner_id(type,partner_id)'' .
Signature
- def _onchange_partner_id(self, cr, uid, ids, type, partner_id) :
Return value :
{
'value': {'field_name': value}
}

Citant maintenant d'autres tags pour les vues :

- < form string="Sale Order" >
- < tree string="" sale="" order="" >
- < sparator string="Links" colspan="4"/ > : Il sert à mettre un separateur entre deux parties, par exemple entre zones de formulaires .


- < notebook >
< page string="Order Line">
...
< /page >
< /notebook >

La partie encadrée en noir s'appelle "page" et le notebook regroupe plusieurs pages comme le montre la figure ci-dessous :) .

- < newline/ > : Sert à sauter une ligne .

- < group colspan="4" col="6"> : Sert à regrouper plusieurs champs :

< group colspan="4" col="7">
< field name="amount_untaxed" sum="Untaxed amount"/ >
< field name="amount_tax"/ >
< /group >

- < label string="Test"> : Libellé du champs .

- < button > : Il sert à déclarer un bouton dans la vue .
string: libellé du bouton
*type:
- "workflow" (valeur par défaut) : Transition du workflow.
- "object": Appelle une méthode dans un objet.
- "action": Appelle une action (imprimer, ouvrir une vue, wizard).
*name : Nom de la transition workflow , methode de l'objet ou une action à appeler .
*Signature de la method objet : method_name(cr, uid, ids, *args).
*states: Liste des états pour lesquels le bouton est visible .
**Exemple:
< button string="''Press" type="''object''" name="''method_name''">
< /button >



Friday, December 4, 2009

Les vues (Partie 1)

*Introduction au fichiers XML dans OpenERP :

Dans OpenEPR, les fichiers XML servent pour :
- Definir les views (modulename_view.xml)
- Definir les workflow (modulename_workflow.xml)
- Declarer les reports (modulename_report.xml)
- Declarer les wizards (modulename_wizard.xml)
- Importer des données (modulename_data.xml)
- Importer des donées de demonstration (modulename_demo.xml) .

* La structure des fichiers XML dans OpenERP :

1- < openerp >
2- < data >
3- < record model="object_name" id="record_id">
4- < field name="field_name">field_value< /field >
5- < /record >
6- < record model="other_object_name" id="other_record_id">
7- < field name="relation_field_name" ref="”record_id”/">< /field >
8- < /record >
9- < /data >
10-< /openerp >


Prenons un petit exemple concret :

1- < openerp >
2- < data >
3- < record model="account.currency" id="EUR">
4- < field name="name">EUR< /field >
5- < field name="rate">1.0< /field >
6- < field name="digits">2< /field >
7- < field name="accuracy">4< /field >
8- < field name="priority">1< /field >
9- < /record >
10- < record model="account.account" id="a0" >
11- < field name="name">Account chart< /field >
12- < field name="type">view< /field >
13- < field name="currency_id" ref="EUR"/ >
14- < field name="code">0< /field >
15- < /record >
16- < /data >
17-< /openerp >

*Les vues :

Les Vues définissent comment le client affiche les objets. Il peut y avoir plusieurs vues pour le même objet .
- Les differents types de vues :
- Form
- Tree
- Actions
- Ouvrir une fenêtre (form ou tree)
- Imprimer un raport
- Executer un wizard
- Menu items .

* En ce qui concerne la syntaxe des vues, elle est de la forme suivante :


1- < record model="ir.ui.view" id="id_vue">
2- < field name="name">view_name< /field >
3- < field name="model">view_object< /field >
4- < field name="type">form< /field >
5- < field name="arch" type="xml">
6- < form string="libellé de la vue">
7- < field name="fields_name">
...
8- < /field >
9- < /form >
10- < /field >
11-< /record >
Le "ir.ui.view est l'objet qui contient les vues (views).

Commencez par créer un fichier XML budget.xml dans le dossier addons/budget et mettez-y le code suivant :

1- < record model="ir.ui.view" id="line.form" >
2- < field name="name">budget.account.form< /field >
3- < field name="model">budget.account< /field >
4- < field name="type">form< /field >
5- < field name="arch" type="xml" >
6- < form string="Budget" >
7- < field name="name"/ >
8- < field name="code_economique"/ >
9- < field name="ref"/ >
10- < /form >
11- < /field >
12-< /record >


Comme on le constate dans l'exemple ci-dessus, dans chaque fichier XML de la vue, on doit déclarer le modèle (model) suivi de l'id qu'on utilisera après dans l'appel de la vue (form ou tree ou les deux) . Pour la déclaration des champs, on doit les écrire tels qu'ils sont déclarés dans la classe mère (le fichier budget.py) :) .

* Passons maintenant à une partie qui est pas mal intéressante que les autres, c'est la déclaration des action window et du menu item .

C'est tout un petit paragraphe de codes qu'on ajoute après la partie précédente de la vue et où on déclare l'id du record, le nom de la page, le nom du modèle (model) et le type de la vue (form, tree, ...).


1- < record model="ir.actions.act_window" id="action_id" >
2- < field name="name">action_name< /field >
3- < field name="res_model">object_name< /field >
4- < field name="view_type">form< /field >
5- < /record >
6- < menuitemname="Outil/Tiny Purchase" action="action_id">
7- < /menuitem >


Pour la dernière ligne, il s'agit du menu qui apparaitera dans la page .

N.B :
Si on utilise "form" pour le type de la vue, on aura des formulaires à remplir .
Si on utilise "tree" pour le type de la vue, on aura un tableau affichant les données de la table concernée (ici abudget.accoun , c-à-d la table des comptes budgets ) .

Vous pouvez faire des améliorations sur ces codes de sorte de rendre votre interface plus riche et plus belle ;) .

Thursday, December 3, 2009

Les données OpenERP sur Google Map !

Il existe un nouveau module très intéressant OpenERP qui importe des données OpenERP dans Google Map. simple and really interesting."> Ce module crée un fichier. KML avec tous les partenaires et les données de chiffre d'affaires des partenaires, qui pourraient être importés dans Google Maps. Résultat : simple et vraiment intéressant. Comment ça se fait ?? La vidéo ci-dessous vous explique !



--> Deux questions se posent après :

* Qui est le propriétaire des données?
* Est-ce vraiment une bonne idée de mettre les données financières (qui doivent être tenues secrètes) dans google map?


Wednesday, December 2, 2009

Création d'un module (partie 2)

Toutes les données OpenERP sont accessibles à travers des "objets". Par exemple,
il y a un objet res.partner qui accéde aux données du partenaire , un objet account.invoice concernant les données factures, etc... .
Pour définir un nouvel objet, on doit définir une nouvelle classe dans Python puis l'instantier. Cette classe doit hériter de la classe osv module osv.Le fichier: addons/module_name/module_name.py :

1- class object_name(osv.osv):
2- _name = "module_name.object_name"
3- _columns = {
4- 'field_name': fields.field_type('Libellé du champs', ...),
5- 'other_field_name' : fields.other_field_type(...),
6- }
7- object_name()

Exemple :

1- class res_partner_address(osv.osv):
2- _name = 'res.partner'
3- _columns = {
4- 'name': fields.char('Name', size=128, required=True, select=True),
5- 'date': fields.date('Date'),
6- 'ref': fields.char('Code', size=64),
7- }
8- res_partner()




* Deux sont obligatoires(_name et _columns), le reste est optionel.

Les noms des champs doivent respecter les normes suivantes :
- Tout doit etre minuscule.
- Pas d'espace.
- Pas de caractéres spéciaux.

* Types simples de champs :

- Boolean : un booléen (true, false).
* Syntax : fields.boolean('Nom du champ' [, Parametres Optionels]),
- Integer :
* Syntax : fields.integer('Nom du champ' [, Parametres Optionels]),
- float :
* Le paramètre digits est optionnel.
Exemple : 'credit_limit': fields.float(string='Credit Limit', digits=(12,6))
- char :
* Paramétre size
Exemple : 'ref': fields.char('Code', size=64),
- text : champs texte de longueur illimité.
* Syntax : fields.text('Nom du champ' [, Parametres Optionels]),
- date : Une date.
* Syntax : fields.date('Nom du champ' [, Parametres Optionels]),
- datetime : Pemet de stocker une date et l'heure de la journée dans le même champs.
* Syntax : fields.datetime('Nom du champ' [, Parametres Optionels]),

** Voici un petit exemple d'un module standard qui vous aidera à mieux comprendre comment ça marche :) :

Créer le dossier budget dans \server\bin\addons
● Créer le fichier __init__.py dans le dossier
budget
Ce fichier contiendra l'instruction suivante:
import budget
● Cette instruction permet d'importer le module
budget
● Créer le fichier __terp__.py dans le dossier
budget qui correspond au fichier config de module :


1- {
2- "name": "Budget",
3- "version": "0.1",
4- "author" : "iGenius",
5- "depends": ['base',],
6- "init_xml": [],
7- "update_xml": [],
8- "active": False,
9- "installable": True,
9- }


Créer le fichier budget.py dans le dossier budget :
● Ce fichier contiendra toutes les classes du module .
● On commence par une classe permettant de gérer les comptes des budgets :


1- class budget_account(osv.osv):
2- _name = "budget.account"
3- _description = "Budget Account"
4- _columns = {
5- 'name': fields.char('Intitule du compte', size=128, ),
6- 'code_economique': fields.char('Code economique', size=10, ),
7- 'chapitre': fields.char('Chapitre', size=10, ),
8- 'article': fields.char('Article', size=10, ),
9- }
10- budget_account()





Après avoir mis à jour la liste des modules, on doit trouver nouveau module ajouté dans la liste des modules non installés .


On l'installe et voilà !! Notre module est prêt à l'emploi :) .




Sunday, November 29, 2009

Création d'un module (Partie 1)

Les modules sur OpenERP se trouvent dans le dossier server/bin/addons/ , un dossier par module :
✔ base
✔ account
✔ product
✔ crm
✔ stock
✔ sale
✔ purchase
✔ marketing
✔ project
✔ ...

Les étapes suivantes sont indispensables pour créer un nouveau module:
● créer un sous répertoire dans server/bin/addons
● créer un fichier de description du module : __terp__.py
● créer un fichier Python contenant les objets
● créer les fichiers .xml qui chargent les données (vues, menu , données de demo , ...)
● optionnellement créer les reports, wizards ou workflows.

Le contenu du dossier d'un module (addons/module_name) :
✔ __terp__.py.

* Objets:
✔ modulename.py, autres possibilités :
✔ __init__.py.

* Les fichiers XML :
✔ modulename_view.xml.
✔ modulename_workflow.xml (optional).
✔ modulename_report.xml (optional).
✔ modulename_wizard.xml (optional).
✔ modulename_data.xml (optional).
✔ modulename_demo.xml (optional).

* report/sous dossier :
✔ report_name.xml.
✔ report_name.xsl.
ou
✔ report_name.rml.
✔ report_name.sxw.
✔ report_name.py (optional).

* wizard/sous dossier
✔ __init__.py
✔ wizard_name.py

* Étape 1 - création du fichier de description du module : __terp__.py :

Dans le dossier du module créé, vous devez ajouter un fichier __terp__.py .
Ce fichier , qui doit être écrit sous Python , est responsable de :
● déterminer les fichiers XML qui doivent être analysés durant l'initialisation du serveur.
● déterminer les dépendances du module créé.
✔ Le fichier doit contenir un dictionnaire Python avec les valeurs suivantes:

✔ name : Le nom du module.
✔ version : La version du module.
✔ depends : Liste des modules dont dépend le module. Le module base est presque toujours dans les dépendances car des données indisponsables pour les vues, reports, ... sont dans le module base .
✔ init_xml : Liste de fichiers .xml à charger quand le serveur est
lancé avec l'argument "init=
module".
✔ update_xml : Liste de fichiers .xml à charger quand le serveur est
lancé avec l'argument "update= module" .
✔ active : True or False. Détermine si le module est actif ou non en utilisant le client.
✔ Installable : True or False. Détermine si le module est installable ou non. Si le module n'est pas
installable, il n'est pas possible de l'activer en utilisant le client.

Prenons cet exemple :

{
"name" : "Mon Module",
"version" : "1.0",
"depends" : ['base'],
"init_xml": [],
"update_xml": ["mon_module_view.xml",
mon_module_report.xml"],
"active": True
"installable": True,
}

✔ init_xml & update_xml sont équivalent.
* additional keys:
✔ "author" : "iGENIUS",
✔ "website" : "igenius.com",
✔ "category" : "Generic Modules/Mon module",
✔ "translations" :
{
"fr": "i18n/french_fr.csv"
},

* Le fichier __init__.py est comme tout module Python , exécute au démarrage du programme. Il a besoin d'importer les fichiers Python pour être chargés.
Ainsi, si vous crééez le fichier "module.py", contenant la description de vos objets, vous devez écrire une ligne dans __init__.py: import module .

Architecture technique et modulaire

Avant d'entamer la partie 'Administration de OpenERP', il me semble nécessaire de faire un petit aperçu sur le langage de programmation 'Python' avec lequel est programmé OpenERP .
Pour cela, je vous invite à faire une petite balade sur le tutoriel présent sur ce lien http://python.developpez.com/cours/TutoSwinnen/ .

* L’architecture technique

* Architecture client/serveur :

OpenERP est basé sur une architecture client/serveur comme le décrit le schéma ci-dessous:




L’OpenERP est couplé à une base de données PostgreSQL. De plus, il est compatible au pack Open Office, et aussi avec des outils de reporting (Open Report) pour produire des rapports en PDF ou en HTML.
Le serveur et le client communiquent entre eux en utilisant le protocole XML­RPC.
La logique du OpenERP (TinyERP) est entièrement du côté serveur. Le client est simple; sa tâche est de demander les données (formulaire ou listes) au serveur et de les renvoyer. Avec cette approche, presque tout le développement est fait du côté serveur. Ce qui rend OpenERP plus simple au développement et à la maintenance.
L'opération client est très simple; Quand un utilisateur exécute une action (sauvegarder une forme, ouvrir un menu, imprimer, ...) il envoie cette action au serveur. Le serveur envoi alors la nouvelle action pour s'exécuter au client.
Il y a trois types d'actions :
• Ouvrir une fenêtre (formulaire, listes)
• Imprimer un document
• Exécuter un wizard

*MVC modèle dans la théorie classique de la POO :

Un (MVC) est une architecture de modèles utilisée en génie logiciel. Dans des applications complexes qui présentent des lots de données aux utilisateurs, on souhaite souvent séparer les données (modèle) et l'interface utilisateur (vue), de sorte que les changements à l'interface utilisateur n'affectent pas le traitement des données, et que les données peuvent être réorganisées sans changer l'interface utilisateur.

Le MVC résout ce genre de problème en découplant l'accès des données et la logique des applications de la présentation des données et de l'interaction utilisateur, en introduisant un composant intermédiaire : « le contrôleur ».

Dans OpenERP, on peut appliquer cette sémantique de model­view­controller avec :
Modele : les modèles sont les objets déclarés dans OpenERP. Ils sont également des tables PostgreSQL.
view : les vues sont définies en fichiers XML dans OpenERP.
• contrôleur : le contrôleur est Python qui contrôle OpenERP.

* L’architecture modulaire:

Comme il est déjà cité que le principe fondateur du OpenERP est de construire des applications informatiques de manière modulaire (modules indépendants entre eux) tout en partageant une base de données unique et commune. Cela crée une différence importante avec la situation préexistante (les applications sur mesure existant avant les ERP) car les données sont désormais supposées standardisées et partagées, ce qui élimine les saisies multiples et évite l'ambiguïté
des données multiples de même nature donc OpenERP est un ensemble dont toutes les parties fonctionnent les unes avec les autres d'où l'ergonomie et l'unicité des informations et donc la cohérence du système informatique.