Importer des employés via csv avec OpenERP V7
Tout ce qui est indiqué dans cet article a été testé avec OpenERP 7.0.
- Description des objets en jeu
- Utilisateur
- Exemple CSV minimal (Sans info partenaire), utilisateur_minimal.csv
- Note
- Partenaire
- Note
- Exemple partenaire.csv
- Utilisateur + Partenaire
- Exemple utilisateur_complet.csv
- Départememts
- Exemple departement.csv
- Postes
- Exemple poste.csv
- Employé
- Exemple employe.csv
- Exemple d’import des employés au format CSV
- À propos des formats de fichiers
- utilisateur_complet.csv
- partenaire.csv
- departement.csv
- poste.csv
- employe.csv
- Détails techniques pour l’import csv
- À propos de l’extraction de données
- Le problème des champs liés
- Le mode développeur à la rescousse
- Découvrir les types de champs
- Liste déroulante simple (selection)
- Liste déroulante avancée (many2one)
- Champs many2many
- Champs one2many
- Champs Date
- Champs DateTime
- Pour aller plus loin
Le but de cet article est de pouvoir importer facilement et en masse des employés liés à un compte utilisateur OpenERP.
Pour cela au moins cinq fichiers et étapes d’import sont nécessaire :
- Import des utilisateurs
- Import des partenaires
- Import des départements
- Import des postes
- Import des employés (l’employé est lié à un utilisateur, à un département, et à un ou deux partenaires pour représenter ses adresses professionnelle et personnelle.)
Description des objets en jeu
Utilisateur
L’utilisateur au sens compte utilisateur, c’est-à-dire ce qui est nécessaire pour se connecter au serveur avec un identifiant. login:Identifiantactive:True, False (active ou pas le compte)email:Courrielname:Prénom Nomcompany_id/id:base.main_company (base.main_company permet de rattacher à la société configurée par défaut dans OpenERP)tz:Fuseau horaire (Europe/Paris pour la France)lang:Langue (fr_FR, pour le français, code ISO)notification_email_send:Incoming Emails and Discussions (mode de notification)groups_id/id:Les groupes de droits à affecter à cet utilisateur. Pour un employé standard nous indiquerons “base.group_user,base.group_hr_user”
Attention lors de la création de l’utilisateur, OpenERP créé automatiquement un partenaire (voir plus bas). C’est donc plus judicieux d’ajouter dans le même fichier les champs relatifs au partenaire afin d’éviter de se retrouver avec plus de partenaires que souhaité. Nous allons voir plus bas les détails des champs pour définir un partenaire et en suivant un exemple pour définir à la fois un utilisateur et un partenaire associés dans un seul fichier.
Exemple CSV minimal (Sans info partenaire), utilisateur_minimal.csv
Exemple:"login","name","active","email","company_id/id","tz","lang","notification_email_send","groups_id/id""pierre_martin","Pierre Martin","True","pierre.martin@company.fr","base.main_company","Europe/Paris","fr_FR","Incoming Emails and Discussions","base.group_user,base.group_hr_user"
Note
Attention si l’email est saisi et qu’il n’y a pas de serveur SMTP configuré, l’import sera en échec et vous aurez un message semblable à celui-ci :Erreur:Impossible d’envoyer des courriels : aucun serveur de courriel sortant n’est configuré. Vous pouvez le configurer dans : Configuration/Paramètres généraux.
L’astuce quand on développe en local est de lancer un serveur SMTP de test :Terminal:sudo python -m smtpd -n -c DebuggingServer localhost:25
En production il faut s’assurer d’avoir un serveur SMTP configuré et de correctement renseigner les paramètres SMTP dans “Configuration / Configuration / Paramètres généraux / Courriel” de manière à ce que le serveur OpenERP puisse envoyer des e-mails.
Partenaire
La gestion des contacts dans OpenERP est faite au travers des objets “partner”. Un partenaire peut être une entité juridique ou une personne physique, à laquelle est attachée une adresse, des informations de contact, ainsi que d’autres informations relatives à la relation commerciale et la comptabilité.
Le partenaire que nous voulons créer ici correspondant à un employé, ce n’est ni un client, ni un fournisseur. Nous avons besoin de cet objet partenaire pour stocker les adresses professionnelle et personnelle de chaque employé. name:Prénom, Nomtitle/id:Titre (Monsieur, Madame, etc) les valeurs possibles par défaut sont base.res_partner_title_doctor, base.res_partner_title_ltd, base.res_partner_title_madam, base.res_partner_title_miss, base.res_partner_title_mister, base.res_partner_title_prof, base.res_partner_title_pvt_ltd, base.res_partner_title_siractive:True, False (active ou pas le partenaire)type:Le type d’adresse, peut prendre les valeurs suivantes, default, invoice, delivery, contact ou other. Pour l’adresse d’un employé nous utiliserons contactis_company:True, False (si le partenaire est une entreprise. False pour un employé)customer:True, False (si le partenaire est un client. False pour un employé)supplier:True, False (si le partenaire est un fournisseur. False pour un employé)employee:True, False (si le partenaire est un employé. False pour un employé. Ce champ est à priori inutile et sa valeur n’a pas d’incidence à ce jour)vat_subjected:True, False (True si le partenaire est assujetti à la TVA, False pour un employé)tz:Fuseau horaire du partenaire (Europe/Paris pour la France)lang:La langue du partenaire (fr_FR pour un français)email:Courrier électroniquestreet:Ruestreet2:Champ pour complémentaire pour désigner la rue/étage/portezip:Code postalcity:Villephone:Téléphone fixemobile:Téléphone mobilefax:Faxref:Permet de définir une référencewebsite:Url du site Internet du partenaireuse_parent_address:True, False (si le partenaire a la même adresse qu’une partenaire parent auquel il serait attaché)
Note
Attention, il y a un champ booléen “employee” dans la table partner. A priori ce champ n’est plus utilisé ni visible dans les interfaces standard. Utilité à vérifier.
Exemple partenaire.csv
Exemple:"name","title/id","active","type","is_company","customer","supplier","employee","vat_subjected","tz","lang","email","street","street2","zip","city","phone","mobile","fax","ref","website","use_parent_address" "Pierre Martin (Perso)","base.res_partner_title_mister","True","Contact","False","False","False","False","False","Europe/Paris","fr_FR","pierre.martin@perso.com","200 rue du sentier",,75000,"Paris",0504030201,0708090001,0102030406,"PMARTIN",,"False"
Notez bien que j’ai défini ici comme valeur de “name”, “Pierre Martin (Perso)”, ceci afin de distinguer l’adresse personnelle de l’adresse professionnelle. Il serait plus intéressant pour cela d’utiliser le système de catégorisation ou de tags mais nous verrons dans la dernière partie de l’article que dans le cas de notre exemple il est nécessaire de distinguer les deux.
Utilisateur + Partenaire
Comme indiqué plus haut il est possible de définir à la fois un utilisateur et un partenaire lié en un seule importation. Dans notre exemple nous voulons créer un employé. Nous verrons qu’a minima un employé a deux adresses liées, une professionnelle et une personnelle. Nous allons également considérer que le partenaire défini dans ce fichier aura le rôle d’adresse professionnelle pour l’employé.
Exemple utilisateur_complet.csv
Exemple:"login","name","active","email","company_id/id","tz","lang","notification_email_send","groups_id/id","title/id","active","type","is_company","customer","supplier","employee","vat_subjected","tz","lang","street","street2","zip","city","phone","mobile","fax","ref","website","use_parent_address" "pierre_martin","Pierre Martin","True","pierre.martin@company.fr","base.main_company","Europe/Paris","fr_FR","Incoming Emails and Discussions","base.group_user,base.group_hr_user", "base.res_partner_title_mister","True","Contact","False","False","False","False","False","Europe/Paris","fr_FR","1 rue des chemins",,"75001","Paris","0102030405","0607080900","0109080706",,,"False"
Départememts
Les départements dans OpenERP permettent de définir la structure des différents services de la société. Pour chaque département on peut définir un responsable, mais celui-ci doit être un employé existant. Chaque employé pouvant appartenir à un département, il faut ici prendre une décision.
Nous préférons pour l’exemple définir quels seront les départements de chaque employé plutôt que de définir les responsables de département. Il faudra dans ce cas une fois que toutes les données d’employés seront importées, définir les responsables de département “à la main”.
Nous nous limiterons donc aux champs suivants pour la définition des départements : id:Une référence unique utilisée dans ce cas pour permettre de définir des départements parentsname:Le nom du départementparent_id/id:Département parentnote:Description du département
Exemple departement.csv
Exemple:"id","parent_id/id","name","note" "departement_principal",,"département principal", "sous_departement_01","departement_principal","Sous département 01", "sous_departement_02","departement_principal","Sous département 02",
Postes
Les postes dans OpenERP permettent de définir la nature du travail de l’employé en précisant fiche de poste, département d’attachement, et pré-requis / compétences.
Ils peuvent également être utilisés pour formaliser les objectifs d’une campagne de recrutement (Voir le module “Processus de recrutement”, hr_recruitment)
Enfin, un poste peut être attaché à un département. name:Intitulé du postedepartment_id:Département lié (La valeur doit correspondre à la valeur ‘name’ de l’adresse d’un département existant)description:Description du posterequirements:Pré-requis / Compétences
Exemple poste.csv
Exemple:"name","department_id","description","requirements""Secrétaire","Sous département 01","Description du poste de secrétaire","Accueil téléphonique, prise de rendez-vous""Comptable","Sous département 02","Description du poste de Comptable","Comptabilité générale et financière, gestion de portefeuille client"
Employé
Un employé de la compagnie principale. Son adresse professionnelle peut être soit celle de la société à laquelle il est rattaché, soit une nouvelle adresse. Son adresse personnelle est également nécessaire. Elle est utilisée par exemple pour le paiement des notes de frais, contrat de travail, etc... name:Le nom de l’employéaddress_id:L’adresse professionnelle de l’employé (La valeur doit correspondre à la valeur ‘name’ de l’adresse d’un partenaire existant)address_home_id:L’adresse personnelle de l’employé (La valeur doit correspondre à la valeur ‘name’ de l’adresse d’un partenaire existant)user_id:L’utilisateur lié à l’employé (La valeur doit correspondre à la valeur ‘name’ d’un utilisateur existant)department_id:Le département de l’utilisateur. (La valeur doit correspondre à l’id d’un département existant comme défini dans l’exemple précédent, “sous_departement_01” par exemple)ssnid:Numéro de sécurité socialesinid:Numéro de contrat d’assuranceidentification_id:Numéro d’identification (peut être utilisé pour un numéro de carte d’identité par exemple)passport_id:Numéro de passeportotherid:Autre identifiant uniquebirthday:Date de naissancecountry_id/id:Nationalitégender:Genre (Male, Female)marital:Statut marital (Single, Married, Widower, Divorced). Widower signifie veuf/veuvework_email:Courrier électronique professionnel (ce champ n’est actuellement utilisé que par le module hr_evaluation. Cette valeur est automatiquement renseigné par la valeur de l’email de l’utilisateur lié si ce dernier change)work_phone:Numéro de téléphone professionnel (ce champ n’est actuellement pas utilisé. Cette valeur est automatiquement renseigné par la valeur du téléphone du partenaire lié si le partenaire change. Nous parlons ici du partenaire correspondant à l’adresse professionnelle de l’employé)mobile_phone:Numéro de téléphone mobile professionnel (Même remarque que précédemment sur son usage)work_location:Numéro de bureau de l’employéparent_id:Manager, le responsable de l’employé (La valeur doit correspondre à la valeur ‘name’ d’un employé existant)coach_id:Coach, le coach de l’employé (La valeur doit correspondre à la valeur ‘name’ d’un employé existant)job_id:Poste, correspond (La valeur doit correspondre à la valeur ‘name’ d’un poste existant)notes:Notes
Exemple employe.csv
Exemple:"name","address_id","address_home_id","user_id","department_id","ssnid","sinid","identification_id","passport_id","otherid","birthday","country_id/id","gender","marital","work_email","work_phone","mobile_phone","work_location","parent_id","coach_id","job_id","notes" "Pierre Martin","Pierre Martin","Pierre Martin (Perso)","Pierre Martin","Sous département 01","123VVV","123WWW","123XXX","123YYY","123ZZZ","01/01/70","base.fr","Male","Married",,,,"A101",,,"Comptable",
Exemple d’import des employés au format CSV
À présent il faut importer dans le bon ordre les fichiers CSV.
Pour importer de nouveaux enregistrements, il suffit de se rendre dans la page affichant la liste des objets que l’on souhaite importer. Par exemple pour importer des utilisateurs, via le menu “Configuration / Utilisateurs / Utilisateurs” en mode liste, cliquez sur le lien “Importer” à côté du bouton “Créer”. Attention si vous n’êtes pas “admin” et que vous ne voyez pas le lien “Importer”, il faudra configurer votre compte utilisateur pour qu’il puisse accéder aux fonctions d’import/export.
Pour certains objets la vue par défaut est kanban. Passez en vue liste si vous voulez importer.
Pour créer notre nouvel employé, nous allons importer les fichiers dans l’ordre suivant :
Pour chaque import le processus sera le même :
- Import du fichier
- Vérification du mapping (liaison entre les en-têtes de colonnes du csv et les propriétés de l’objet OpenERP correspondant) en cliquant sur valider
- Si tout est valide, import des enregistrements
À propos des formats de fichiers
Le système d’import d’OpenERP est assez évolué pour détecter le format de fichier, son encodage, les séparateurs de champs... Vous pouvez lors de l’import ajuster les “File format options”.
utilisateur_complet.csv
À validation, “tout semble correct”. Cela signifie que pour les premières lignes analysées, les valeurs des champs correspondent bien au type attendu.
Si tout convient à ce point, on peut importer, sinon il faut corriger son fichier CSV.
Notre nouvel utilisateur “Pierre Martin” a bien été créé.
partenaire.csv
Via le menu “Messagerie / Agenda / Contact” on importe le fichier partenaire.csv
Au final nous avons bien nos deux adresses.
departement.csv
Via le menu “Ressources humaines / Configuration / Département” on importe le fichier departement.csv
On voit ici la liaison id/parent id qui est validée.
Les départements sont bien importés.
poste.csv
Via le menu “Ressources humaines / Configuration / Postes” on importe le fichier poste.csv
employe.csv
Via le menu “Ressources humaines / Employés” importez le fichier employe.csv
Détails techniques pour l’import csv
À propos de l’extraction de données
Il peut être judicieux lorsque l’on veut importer des données, de passer par une phase d’extraction préalable, pour voir notamment quels sont les champs qu’il est possible de définir pour un objet.
Pour cela, dans la vue liste une fois les enregistrements à exporter sélectionnés, dans la liste déroulante “Autres options”, sélectionnez “exporter”.
Dans la fenêtre d’export les champs en bleu correspondent aux champs requis du modèle. Il faut obligatoirement les sélectionner à l’import.
Le problème des champs liés
Ensuite il faut faire attention à une chose, et il faut avouer que pour le moment ce cas est encore difficile à appréhender pour des utilisateurs non techniciens.
Comme nous l’avons vu dans notre exemple il est possible de définir et de renseigner des champs liés. Lors de l’export, l’interface propose tous les champs liés possibles pour le modèle, et parfois le nombre de champs possibles est très grand.
Par exemple si l’on prend l’export des utilisateurs, il n’y a pas moins d’un millier de champs proposés à l’extraction. Ce nombre dépend des modules installés. Si vous avez par exemple tous les modules standards installés et que vous souhaitez exporter tous les champs de l’objet utilisateurs, vous ne pourrez pas car la quantité de colonnes est supérieure à 1024 ce qui est la limite dans la plupart des tableurs, notamment Libre Office Calc.
Dans la majorité des cas les champs liés proposés ne seront pas facilement importable, et nécessiteront de toutes façons de découper en plusieurs fichiers l’import comme nous l’avons fait dans l’exemple afin de créer dans le bonne ordre les enregistrements d’objets qui pourraient être référencés par la suite dans un autre CSV.
La méthode pour s’y retrouver est alors de regarder pour chaque objet quels sont les champs qui s’affichent. Si ces champs ne sont pas des listes vers d’autres objets OpenERP, pas de risques. Si c’est le cas il faut aller voir dans l’objet correspondant quels sont les champs et évaluer s’il vaut mieux découper notre import en plusieurs fichiers ou si on peut faire l’opération avec un seul fichier.
Dans notre exemple, c’est le cas avec utilisateur_complet.csv où nous créons un utilisateur et un partenaire avec une seule ligne dans un seul fichier.
Le mode développeur à la rescousse
Pour retrouver facilement, le nom des champs dans une interface, le plus simple est d’activer le mode développeur, en cliquant en haut à droite sur votre nom d’utilisateur / À propos de OpenERP.
Il suffit ensuite de survoler un label pour voir quelles sont les informations techniques du champ. Ici pour le modèle “res.user”, c’est à dire Utilisateur, le champ “Name” ou “Nom” en français correspond au champ “name”. “name” sera alors un nom d’en-tête correct pour un colonne du fichier CSV pour définir de nouveaux utilisateurs. Le type de ce champ étant “char”, tout caractère alpha-numérique sera accepté.
Découvrir les types de champs
Nous venons de voir un champ de type “char” avec le champ name de l’utilisateur. Mais qu’en est-il des autres types de champs ?
Liste déroulante simple (selection)
Prenons le champ “langue” d’un utilisateur.
le nom du champ est “lang”, son type est “selection”, les valeurs possibles sont indiquées entre crochets [en_US] - English et [fr_FR] Français. Les valeurs possibles dans notre CSV seront donc “en_US” ou “fr_FR” pour la colonne “lang”
Liste déroulante avancée (many2one)
Prenons le champ “société” d’un utilisateur.
Le nom du champ est “company_id”, son type est “many2one”, qui établit une relation vers l’objet “res.company”.
Lors de l’import, il peut y avoir plusieurs types de valeurs attendues dans ce champ, en fonction de comment est défini l’en-tête de la colonne du fichier ”.csv”.
Le plus simple ; et c’est une nouveauté de OpenERP 7 ; est d’utiliser le name_search. La valeur sera utilisée pour tenter de trouver un enregistrement correspondant en cherchant sur le champ name de l’objet relié. Dans ce cas la recherche portera sur res.company.name. “company_id”:Si le champ spécifié est le champ relationnel lui-même (m2o), la valeur est utilisée dans un name_search. Le premier enregistrement renvoyé par le name_search est utilisé comme la valeur du champ.
Si le name_search ne trouve pas de valeur, une erreur est générée. Si le name_search trouve plusieurs valeurs, un avertissement est généré pour avertir l’utilisateur des collisions du name_search. Dans l’exemple ci-dessous, la valeur du champ est “Your company” qui correspond au nom de la compagnie par défaut dans OpenERP.
Exemple many2one “company_id”:"login","name","active","email","company_id""pierre_martin","Pierre Martin","True","pierre.martin@company.fr","Your Company" “company_id/id”:Si le champ spécifié est un identifiant externe (m2o/id), l’enregistrement correspondant est recherché dans la base de données et utilisé comme valeur du champ .
Si aucun enregistrement correspondant à l’ID externe fourni n’est trouvé, une erreur est générée. C’est le type que nous avons employé dans notre exemple “utilisateur_minimal.csv”, pour laquelle la valeur est “base.main_company”.
Exemple many2one “company_id/id”:"login","name","active","email","company_id/id""pierre_martin","Pierre Martin","True","pierre.martin@company.fr","base.main_company" “company_id/.id”:Si le champ spécifié est un ID de base de données (m2o/.id), le processus est le même que pour les identifiants externes (mais cette fois sur les identifiants de la base de données).
Dans l’exemple ci-dessous, la valeur du champ est 0 qui correspond à l’id en de base de donnée de la compagnie par défaut dans OpenERP.
Exemple many2one “company_id/.id”:"login","name","active","email","company_id/.id""pierre_martin","Pierre Martin","True","pierre.martin@company.fr",1
Champs many2many
Prenons le champ “Etiquettes” d’un employé. C’est un système de tags pratique pour assigner des informations de classification supplémentaire sur une fiche employé.
Le nom du champ est “category_ids”, son type est “many2many”, qui établit une relation vers “hr.employee.category”. “category_ids”:La valeur du champ est interprétée comme une liste de noms, identifiants externes ou les identifiants de base de données séparées par des virgules. Pour chacun d’eux, le processus déjà utilisé pour les many2one est appliqué.
Comme précédemment les valeurs doivent exister avant d’être référencées. Dans l’exemple nous utilisons le name_search pour les 3 valeurs “Temps complet, Clients France, Pme”, séparées par des virgules.
Exemple many2many “category_ids”:"name","address_id","address_home_id","user_id","country_id/id","category_ids""Pierre Martin","Pierre Martin","Pierre Martin (Perso)","Pierre Martin","Sous département 01","123VVV","123WWW","123XXX","123YYY","123ZZZ","1970-01-01","base.fr","Temps complet, Clients France, Pme"
Champs one2many
La gestion de l’import de champs “one2many” a également été grandement améliorée avec la version 7 d’OpenERP. Il est maintenant possible dans un seul fichier d’indiquer plusieurs enregistrements liés à l’objet courant, si ces enregistrements n’existent pas ils seront créés automatiquement. Par exemple si nous voulons associer plusieurs comptes bancaires à un nouveau partenaire, nous pourrons définir directement ces comptes bancaires dans le fichier CSV de définition du partenaire.
“bank_ids”:Pour chaque enregistrement o2m extrait, si l’enregistrement a un nom, un ID externe ou ID de base de données, l’ID de base de données est recherché et vérifié par le même processus que pour les champs de m2o.
Si un ID de base de données a été trouvé, une commande link_to est émise, suivi d’un UPDATE avec les valeurs non-db pour le champ relationnel. Sinon une commande CREATE est émise.
Come on le voit ici, la première ligne correspond à l’enregistrement “partner” avec une première banque. La deuxième ligne, vide de toute informations partenaire, contient les informations d’un deuxième enregistrement “banque”, lié au partenaire de la ligne précédente.
Exemple one2many “bank_ids”:"name","title/id","active","type","is_company","customer","supplier","employee","vat_subjected","tz","lang","bank_ids/name","bank_ids/acc_number","bank_ids/bank_bic","bank_ids/state","email","street","street2","zip","city","phone","mobile","fax","ref","website","use_parent_address" "Pierre Martin (Perso)","base.res_partner_title_mister","True","Contact","False","False","False","False","False","Europe/Paris","fr_FR","Ma banque 1",1234567890,"BB888899JJ8UU","bank","pierre.martin@perso.com","200 rue du sentier",,75000,"Paris",504030201,708090001,102030406,"PMARTIN",,"False" ,,,,,,,,,,,"Ma banque 2",9996663330,"BB888899JJ8UK","bank",,,,,,,,,,,
partenaire_avec_banque.csv
Champs Date
Le format de la valeur est comparé à DEFAULT_SERVER_DATE_FORMAT, une erreur est générée si elle ne correspond pas au format indiqué.La valeur par défaut de DEFAULT_SERVER_DATE_FORMAT = “%Y-%m-%d”, dans ce cas, le format attendu pour le csv est le suivant :“1970-01-01” pour le 1er Janvier 1970, soit “YEAR-MONTH-DAY”
Champs DateTime
C’est sensiblement la même chose que pour le cas précédent, avec l’heure en plus.
DEFAULT_SERVER_DATETIME_FORMAT = “%Y-%m-%d %H:%M:%S”, exemple de valeur “1970-01-01 14:30:10” pour le 1er Janvier 1970, 14 heures, 30 secondes et 10 secondes.
Le format de la valeur est comparé à DEFAULT_SERVER_DATETIME_FORMAT, une erreur est générée si elle ne correspond pas. La valeur est alors interprétée comme une date-heure dans le fuseau horaire de l’utilisateur. Le fuseau horaire est précisé ainsi:
- Si le contexte d’import contient une clé de tz avec un nom de fuseau horaire valide, c’est le fuseau horaire de la date et l’heure.
- Sinon, si l’utilisateur effectuant l’import a un attribut tz défini avec un nom de fuseau horaire valide, ce dernier sera utilisé.
- Dans le cas contraire, la date et l’heure sont intépretés comme étant dans le fuseau horaire UTC.
Pour aller plus loin
Vous pouvez trouver des compléments d’information dans la documentation officielle Bulk Import sinon lisez le code ;-)