Thursday, January 7, 2010

Evénements du mois de Janvier

CRM avec OpenERP : Le 14/01/2010

Séminaire en ligne gratuit pour vous présenter un cas typique d'utilisation de OpenERP pour pour la gestion de la relation client (avant-vente et après-vente).

GPAO avec OpenERP : Le 20/01/2010
Séminaire en ligne gratuit pour vous présenter un cas typique d'utilisation de OpenERP dans un contexte de gestion des approvisionnement au travers de nomenclatures et de gammes.




Configuration et administration de OpenERP : Le 27/01/2010

Séminaire en ligne gratuit pour vous présenter les méthodes de gestion et de configuration de OpenERP :
- Gestion des droits
- Design des écrans
- Gestion des traduction
- Modifications des processus




Vous pouvez recevoir une invitation en contactant : info@open-net.ch .






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?