Stage à Self Signal

Du 5 juin au 7 juillet 2023
L’entreprise Self Signal est spécialisée dans la conception et la fabrication d’un large panel de dispositifs de signalisation, des marquages au sol et autres mobiliers urbains aux enseignes de marque en passant par les panneaux de signalisation (chantiers, routes).

Les activités de Self Signal sont réparties dans trois secteurs

Self Signal signalisation s’occupe de la signalisation temporaire et permanente (panneaux de chantier, signalisation de police et directionnelle, mobilier urbain…) 

Self Signal communication s’occupe de la conception, fabrication et pose de matériel de communication visuelle et d’enseignes sur-mesure pour tout type d’organisation. 

En complément de ces deux entités de fabrication, Self Services 35 vient compléter le groupe en proposant des activités de service dont du marquage au sol et de la pose en Ille-et-Vilaine et dans ses départements limitrophes. 

 

Durant mon stage au sein du service informatique, j’ai effectué des missions de développement informatique confiées par M. Lizot, développeur et technicien systèmes et réseaux, le tout sous la surveillance de M. Scraigne, responsable informatique.

On m’a fourni un poste et les accès nécessaires à la bonne exécution de mes missions. En ce qui concerne la planification du travail et la gestion de projet, M. Lizot privilégie la méthode agile : je lui rendais compte régulièrement de mon avancée dans mes missions puis il faisait des remarques et me donnait des conseils et des informations sur la marche à suivre et les nouvelles étapes du projet.

Mission 1 – semaine du 5 au 9 juin

Évolution de script python (Cegid-python)

Contexte

Afin de répondre aux besoins des organisations clientes, l’entreprise effectue de nombreuses commandes auprès de fournisseurs (matériaux). 

Toutes les commandes (clients, fournisseurs, ordres de fabrication) sont stockées et gérées dans des bases de données consultables sur le PGI (ou ERP) utilisé par Self Signal : Windows Dynamics AX. Le service de comptabilité utilise un logiciel édité par Cegid afin de générer des informations exploitables par le service grâce à l’intervention d’un script .bat qui se connecte au logiciel et exécute une commande (script écrit par le directeur financier). Les données générées sont ensuite écrites dans des fichiers .TRA (transfert). En effet, la comptabilité est gérée par un logiciel indépendant (Cegid) mais le SI a besoin de certaines informations pour effectuer des analyses via l’ERP. 

L’objectif est de récupérer ces fichiers .TRA grâce à un script python qui analyse le contenu de ces fichiers et en extrait les informations utiles avant de les insérer dans une base de données (SQL server) qui sera lu par l’ERP.

Réalisation

Renaud LIZOT, développeur et technicien systèmes et réseaux au sein de l’entreprise, m’a demandé de faire évoluer ce script en ajoutant une fonctionnalité d’envoi du journal de logs par mail. 

Ce journal de logs regroupe toutes les opérations effectuées par le script ainsi que les configurations initiales et les éventuelles erreurs rencontrées (ici, il est en mode debug donc les opérations sont annulées). 

J’ai trouvé un module python qui permet l’envoi de mail, SMTPLib, que j’ai donc ajouté au script.

J’ai défini une fonction d’envoi de ce journal de logs par mail (en pièce jointe du mail, formaté en HTML).

Je me suis ensuite attelé au développement d’une méthode permettant de générer un corps de mail résumant ce qui est écrit dans le journal de logs. Le module re (regular expressions) de python a été particulièrement utile ici pour chercher des sous-chaînes de caractères dans des lignes à l’intérieur des fichiers de logs.

Enfin, la fonction d’envoi par mail appellera cette fonction afin de générer un corps de mail correspondant.

Voici le résultat de l’ajout de la fonctionnalité d’envoi par mail.

Il ne me restait plus qu’à déployer mon travail sur le projet Gitlab correspondant.

Compétences mobilisées pour la réalisation de cette mission

B1.2 : répondre aux incidents et aux demandes d’assistance et d’évolution
B1.5 : mettre à disposition des utilisateurs un service informatique
B2.2 : assurer la maintenance corrective ou évolutive d’une solution applicative

Lien vers la production

(accès restreint)

Mission 2 – semaine du 12 au 16 juin

Développement de script python (Rapport-AX)

Contexte

Afin d’organiser et actualiser tous les fichiers contenant les commandes, devis, factures et autres récapitulatifs et informations, de nombreux scripts sont exécutés par le service informatique afin de faciliter tout le processus.

Ces scripts .bat vont eux-mêmes exécuter des scripts .vbs qui sont chargés d’ouvrir les fichiers Excel (.xls et .xlsx), contenant toutes les informations importantes, et les actualiser. Le script .bat va ensuite envoyer le rapport de l’opération par mail avec les fichiers Excel actualisés en pièce jointe, afin de tenir les destinataires à jour, tandis que le service informatique en reçoit les logs

Mais leur gestion n’est pas évidente car ils sont exécutés individuellement et tout est placé dans le même fichier (scripts .bat, scripts .vbs, fichiers Excel, fichiers de logs…), difficile donc de s’y retrouver. (voir ci-dessous)

Un beau bazar

Réalisation

L’objectif derrière cette deuxième mission, qui s’étale sur toute la semaine, est donc de faciliter l’exécution de tous ces scripts et ainsi d’y voir plus clair, car tout sera centralisé et géré par un seul script python. 

Pour ce faire, il faut donc créer un script python capable de faire ce que faisaient initialement les scripts .bat, d’envoyer par mail les fichiers Excel actualisés et de générer un journal de logs spécifique indiquant si :  

  • Le ou les scripts .vbs se sont bien exécutés 
  • Le ou les fichiers Excel ont bien été actualisés 

Cette fois-ci, je dois créer le script à partir de rien, contrairement à la première mission qui consistait à répondre à une demande d’évolution de script. 

Avant de m’attaquer au développement du script, j’ai listé tous les scripts .bat à récupérer et pour chacun d’entre eux, le ou les scripts .vbs exécutés et les fichiers Excel actualisés, dans un fichier texte (bloc note) afin d’avoir une vision globale de tous les fichiers à copier localement pour effectuer mes tests.

Ensuite, j’ai débuté le développement.
Ma première piste était
de définir une fonction python par script .bat, chacune effectuant ce que faisait un script .bat

J’ai donc commencé par la première fonction, pour le premier script .bat (une fonction pour un seul script .bat)

Mais je me suis vite rendu compte que cela prendrait beaucoup de temps, tout ça pour créer autant de fonctions qu’il n’y a de scripts .bat. J’ai donc décidé de rendre cette fonction totalement adaptable à chaque script .bat.
Cette fonction prendrait en paramètre toutes les données d’un script
 (scripts vbs exécutés, fichiers Excel actualisés, journal de logs généré…) pour exécuter toutes les opérations auparavant gérées par ce script. 

Désormais, les données spécifiques de chaque script ne seraient plus stockées à l’intérieur de la fonction mais dans une variable qui pourrait être entrée en paramètre de cette fonction. Il y aurait donc autant de variables que d’anciens scripts .bat, mais une seule fonction (voir exemple ci-dessous).

Il restait encore à vérifier que la méthode fonctionnait pour toutes les variables, et c’était loin d’être le cas.  

Il faut savoir que les scripts .bat génèrent un journal de logs dans lequel un rapport de tâche est écrit et envoyé par mail à plusieurs employés de Self Signal avec le(s) fichier(s) Excel actualisé(s) en pièce jointe. Les scripts vbs aussi génèrent un journal de logs indiquant les résultats des opérations, mais ce journal de logs peut avoir un nom différent du journal de logs généré par les scripts .bat.

Exemple avec un script .bat
Et le script .vbs correspondant

Résultat : pour plusieurs d’entre eux, la fonction renvoyait un journal de logs ne contenant pas ce qu’écrivaient les scripts vbs car ceux-ci allaient l’écrire dans un autre journal de logs que celui renseigné (càd celui du script .bat correspondant). De plus, certains scripts ne fonctionnaient pas très bien et ne renvoyaient parfois aucune réponse même s’ils actualisaient bien leur fichier Excel. Exemple (ici, j’ai renseigné le nom de journal de log indiqué dans le script .bat) :

J’ai donc pris du temps pour corriger les données renseignées dans chaque variable et également ajuster quelques scripts vbs afin qu’ils renvoient un résultat récupérable par le script python.  

Résultat (j’ai modifié le nom de journal de log renseigné par celui indiqué dans le script .vbs)

Maintenant que (presque) tous les scripts vbs renvoient des résultats récupérables par le script python, la génération du journal de logs est presque complète. Il reste alors à finaliser les fonctions d’envoi par mail afin que :  

  • Le journal de logs soit envoyé par mail au service informatique, qu’il y ait ou non une erreur. 
  • Les fichiers Excel actualisés soient envoyés à plusieurs destinataires extérieurs au service informatique. 

Et voilà le résultat final : 

Compétences mobilisées pour la réalisation de cette mission

B1.2 : répondre aux incidents et aux demandes d’assistance et d’évolution
B1.5 : mettre à disposition des utilisateurs un service informatique
B2.2 : assurer la maintenance corrective ou évolutive d’une solution applicative

Lien vers la production

(accès restreint)

Mission 3 – semaines du 19 au 30 juin

Évolution de script python (Rapport-AX)

Contexte – semaine 3 (du 19 au 23 juin)

Dans la continuité de mon travail sur le développement d’un script python permettant d’exécuter ce que faisaient jusqu’ici une dizaine de scripts .bat -à savoir exécuter des scripts vbs d’actualisation de fichiers Excel puis envoyer les fichiers actualisés en pièce jointe par mail – M. Lizot m’a indiqué la nouvelle étape qui facilitera l’utilisation du script. 

En effet, il s’agira maintenant de rendre le script capable de lire des fichiers .json ou .ini (ou autre format comme .txt) contenant les informations nécessaires à un traitement des données plus personnalisé :  

  • Les adresses mail des destinataires du rapport de tâche (avec fichiers Excel) 
  • Les fichiers Excel à actualiser 
  • D’autres informations si besoin (scripts .vbs à exécuter, destinataires des logs…) 

Il a également évoqué la mise en place d’une interface sur laquelle on pourrait entrer ces données avant de valider le lancement du script avec ces données. 

Réalisation

Je suis directement parti sur l’idée de l’interface, sans pour autant abandonner la fonction de lecture de fichier. En effet, l’interface permettrait également de déposer directement un fichier de ce type afin que le script puisse le lire et s’exécuter après avoir récupéré les données (ce qui nécessitera la création d’une nouvelle fonction de lecture de fichier) 

L’idée de départ était qu’un utilisateur ait simplement à sélectionner les noms de fichiers Excel qu’il veut actualiser d’un côté et qu’il entre les adresses mail des destinataires voulus de l’autre. 

Pour cela, il fallait d’abord faire en sorte que le script puisse exécuter les bons scripts vbs et écrire dans les bons fichiers de logs en fonction des fichiers Excel sélectionnés. Il y a donc toujours besoin de tableaux de données mais cette fois-ci, c’est pour faire correspondre les noms de fichier Excel aux scripts vbs / noms de fichier de logs / sujets de mail correspondants. 

Le script python va ensuite chercher dans ces tableaux les noms de fichier Excel entrés en paramètre et récupérer les données qui correspondent. 

Il reste maintenant à travailler sur la préparation de l’interface et la façon dont les données seront gérées pour être ensuite stockées dans des variables (destinataires et fichiers Excel) qui seront entrées en paramètre de la fonction d’actualisation.

Contexte – semaine 4 (du 26 au 30 juin)

Dans un souci de faciliter au maximum l’utilisation du script et d’offrir un choix de personnalisation plus étendu concernant les fichiers à actualiser et les destinataires de ces fichiers*, j’ai décidé de développer une interface utilisateur 

Combiné au script python, ce projet mènera donc à une mini application suffisamment intuitive pour être utilisé par tout le monde (même si son utilisation ne risque pas de sortir du service informatique, ce sera toujours plus agréable à utiliser). 

*Jusqu’ici, pour actualiser un fichier Excel, il fallait exécuter un script .bat qui exécutait lui-même un script .vbs qui s’occupait de l’actualisation du fichier. Il fallait donc exécuter presque autant de scripts .bat que l’on voulait actualiser de fichiers Excel (un seul script .bat permettait l’actualisation de 4 fichiers Excel, mais le reste n’en actualisait qu’un seul), et ce avec une liste d’adresses mail définie par script .bat (pas les mêmes destinataires selon le fichier Excel à envoyer). 

Désormais, il sera possible de choisir les fichiers Excel à actualiser, les adresses mail à qui envoyer les fichiers et ce, sur une seule et même interface. On peut parler de menu à la carte. 

Le projet de script s’intitulant “Self Rapport AX”, j’ai temporairement nommé ce projet d’interface “Mon rapport AX personnalisé” 

Réalisation

J’ai commencé à travailler sur cette interface, ou plutôt à la préparation du développement de cette interface (adaptation du script à une nouvelle entrée de données en paramètres) dès la deuxième moitié de la semaine précédente, mais c’est cette semaine que je me suis attaqué au plus important.

Pour développer l’interface j’ai utilisé le module python TKinter, une bibliothèque libre pour python permettant la création d’interfaces graphiques.

D’abord, j’ai créé la fenêtre principale à laquelle j’ai ajouté les boutons correspondants aux fichiers Excel à actualiser (il y en a 17) et je les ai reliés à une fonction permettant l’ajout de chaque fichier à une liste affichée directement sur l’interface (excel_files_list) et aussi une liste excel_files en arrière-plan qui servira de premier paramètre à la fonction d’actualisation.

Ensuite, j’ai ajouté une case dans laquelle écrire les adresses mail et un bouton “Ajouter” qui permet l’ajout de l’adresse mail, écrite dans la case, à une liste affichée directement sur l’interface (receiver_list) et aussi une liste receivers en arrière-plan qui servira de second paramètre à la fonction d’actualisation. J’ai également ajouté un bouton “Supprimer” qui permet, après avoir sélectionné une adresse mail dans la liste, de la supprimer en cliquant sur le bouton.

Enfin, j’ai ajouté un bouton “Valider” relié à une fonction on_valider_click qui lance le script d’actualisation avec excel_files et receivers en paramètre.

J’avais la première version de mon interface.

Je devais aussi ajouter la fonction de dépôt de fichier dont M. Lizot m’avait parlé. Cette fonction permettrait de récupérer des adresses mail en lisant des fichiers texte (.txt, .json, .ini) puis de les rajouter à la liste receivers. Ce serait également beaucoup plus pratique que d’entrer les adresses mail une par une (le seul moyen possible à ce stade). 

J’ai donc ajouté un bouton “Dépôt de fichier” relié à une fonction d’ouverture de fichier open_file qui renvoie le chemin du fichier sélectionné, qui entre lui-même en paramètre d’une fonction de lecture de fichier read_addresses(chemin) qui renvoie une liste d’adresses mail. Ces deux fonctions sont gérées par une fonction upload_file qui récupère cette liste pour la rajouter à la liste receivers

N’étant pas satisfait du bouton “Supprimer” qui obligeait à sélectionner une adresse mail avant de cliquer dessus, j’ai modifié le bouton de manière à ce qu’il agisse comme un interrupteur (deux états “normal” et “suppression”, l’état normal est par défaut, l’état suppression permet de supprimer une adresse mail en cliquant directement dessus dans la liste, on peut passer d’un état à l’autre simplement en cliquant sur le bouton “Supprimer”) 

J’en ai profité pour ajouter un bouton “Tout supprimer” qui supprime simplement toutes les adresses mail de la liste. 

Il ne me restait plus qu’à finaliser l’interface en ajoutant quelques détails (logo de l’entreprise, petit message indiquant l’état du processus (en cours d’exécution, OK, erreur) et des titres aux listes de fichiers et d’adresses pour faciliter la lecture des données) 

J’avais maintenant la version finale et aboutie de mon interface.

Il ne me restait plus qu’à attendre le retour de M. Lizot qui était absent durant cette semaine.

Compétences mobilisées pour la réalisation de cette mission

B1.2 : répondre aux incidents et aux demandes d’assistance et d’évolution
B1.5 : mettre à disposition des utilisateurs un service informatique
B2.2 : assurer la maintenance corrective ou évolutive d’une solution applicative

Mission 4 – semaine du 3 au 7 juillet

Évolution de script python (Rapport-AX)

Contexte 

Avec le retour de M. Lizot, j’ai pu obtenir plus d’éclaircissements quant à la finalité du script qu’il m’avait chargé de développer. Et il y avait quelques éléments à changer concernant l’interface.

En temps normal, tous les scripts VBS d’actualisation de fichier Excel doivent en réalité être exécutés par les scripts.bat de façon régulière suivant une planification précise.

Inutile de dire que l’interface permettant de les exécuter à la carte n’avait pas beaucoup d’utilité, d’autant plus que l’exécution de chaque script est plus ou moins espacée dans le temps et une telle interface permettait d’en lancer plusieurs en même temps, ce qui n’est pas idéal. 

De plus, il y avait trop de boutons sur l’interface. En fait, il y en avait autant que de fichiers Excel à actualiser mais finalement seules 10 tâches (parlons plutôt de tâche et non de fichier Excel, car l’actualisation de fichier Excel + envoi par mail est une tâche) nous intéressent, pour 13 scripts (une tâche exécute 4 scripts VBS). Il faudrait donc 10 boutons (un bouton par tâche)

Puisque les tâches seront planifiées, on ne doit plus pouvoir exécuter ces tâches avec l’interface. 

La vraie utilité de l’interface résiderait dans le fait de pouvoir modifier les listes d’adresses mail des destinataires du rapport de tâche (avec fichier Excel actualisé en pièce-jointe) ou du fichier de logs, et ce pour chaque tâche.

On pourrait donc modifier les listes des destinataires à tout moment grâce à l’interface tandis que les tâches s’exécuteraient automatiquement à des jours et heures différentes, définies dans le planning.

Réalisation

J’ai donc commencé à modifier l’interface.

Il faut fonctionner par tâche, les 17 boutons de fichiers Excel ont été remplacés par 10 boutons de tâches. Petite nouveauté : les boutons log_button et report_button correspondant respectivement à “Liste logs” et “Liste rapport”, permettant d’afficher la liste des destinataires du fichier de logs ou la liste des destinataires du rapport de tâche. 

Désormais, en cliquant sur un bouton de tâche, il serait sélectionné (couleur bleu foncé) et les boutons logs et rapport deviendraient cliquables (ils sont désactivés si aucun bouton de tâche n’est sélectionné). En cliquant sur l’un, on affiche la liste log_receivers; en cliquant sur l’autre, on affiche la liste report_receivers

Pour stocker toutes les données relatives à chaque tâche (fichier Excel, script VBS, fichier de logs, sujet de mail, liste logs et liste rapport), j’ai enfin décidé d’arrêter de tout mettre à l’intérieur même du code source en créant un fichier JSON nommé Dico_AX.json

La façon dont a évolué mon travail sur cette mission m’a mené à créer un deuxième fichier JSON par la suite plutôt que de tout faire avec un seul, mais cela m’aurait obligé à adapter le code en conséquence ce qui aurait pris un temps considérable et je n’aurais pas eu le temps de finir tout mon travail. 

Le fichier Dico_AX.json se présentait ainsi. Pour un script VBS, on fait correspondre le fichier Excel, le fichier de logs, le sujet de mail, la liste logs et la liste rapport. 

Dans l’interface, je n’associe plus chaque bouton à un nom de fichier Excel mais à un nom de script VBS. Cliquer sur un bouton appelle une fonction toggle_vbs_button qui permet la sélection du bouton (changement de couleur, activation des boutons logs et rapport et leur association à deux nouvelles fonctions, show_log_receivers et show_report_receivers), sa désélection manuelle (désactivation des boutons logs et rapport) ou automatique si on en sélectionne un autre. 

En cliquant sur le bouton logs ou rapport, on appelle respectivement les fonctions show_log_receivers ou show_report_receivers qui vérifient si l’état “list” (sélection de bouton de tâche) est activé, cherchent le bouton qui a cet état et affichent les listes d’adresses mail correspondantes au bouton sélectionné.  

Pour ce faire, elles appellent la fonction display_list qui vérifie l’état du bouton qui l’a appelée (“log” ou “report”) et appelle la fonction find_list.  

Cette fonction find_list prend le nom du script indiqué sur le bouton en paramètre, récupère les deux listes d’adresses mail correspondantes parmi tout ce que lui a envoyé la fonction read_json, (qui lit le fichier Dico_AX.json et envoie tout son contenu) et les renvoie à display_list

Enfin, display_list sélectionne la liste log_receivers ou report_receivers à afficher parmi ce que lui a renvoyé find_list

Il se passe beaucoup de choses en arrière-plan lorsqu’on clique sur un seul petit bouton. 

Les boutons “Ajouter”, “Dépôt fichier”, “Supprimer” et “Supprimer tout” ne changent pas. 

Le bouton “Valider”, ou plutôt la fonction on_valider_click, a été modifiée de façon à vérifier le bouton sélectionné, le bouton sur lequel on a cliqué (log ou rapport) et appelle la fonction write_json qui remplace la liste exacte dans Dico_AX.json par la liste receivers (variable essentielle qui stocke une liste d’adresses mails et qui accompagne beaucoup de fonctions dans l’interface) 

L’interface était terminée.

Il restait à adapter le script d’actualisation afin qu’il prenne les informations stockées dans le fichier Dico_AX.json, mais je voulais tout de même dissocier la fonction de lecture JSON et recherche de données de la fonction d’actualisation et envoi par mail. 

De cette manière, la planification des tâches serait plus simple. 

J’ai donc créé une dernière fonction pour le script python, slf_rapport_ax (nom du projet).  

Cette fonction lit un deuxième fichier Tasks_AX.json (explications sur la présence de ce deuxième fichier plus haut). 

Ce fichier stocke des noms de tâche (indiqués pour la planification) et associe à chaque tâche les scripts VBS qui doivent être exécutés. 

La fonction prend un nom de tâche en paramètre, cherche ce nom dans le fichier et récupère le ou les scripts associés dans une liste scripts. Elle lit ensuite le fichier Dico_AX.json, cherche le ou les noms de scripts VBS contenus dans scripts et pour chaque script, récupère les données associées (nom de fichier Excel etc.), stocke tout dans un tableau data qui prend une clé par script, avec toutes les données correspondantes à l’intérieur de chaque clé, et renvoie data. 

La fonction actualisation prend en paramètre ce tableau data et effectue la tâche spécifiée, comme elle l’a toujours fait. 

Lors d’un dernier passage en revue, M. Lizot m’a indiqué qu’afin de pouvoir planifier les tâches, il fallait pouvoir entrer ces tâches en argument sur ligne de commande

J’ai utilisé le module sys qui permet d’ajouter des arguments à un script puis j’ai créé une boucle dans le main qui exécute la fonction slf_rapport_ax avec chaque argument entré dans la commande. 

Le code était lourd (près de 750 lignes) à cause de l’interface. Comme celle-ci n’avait plus aucun lien avec le script d’actualisation, je l’ai déplacée dans un autre script InterfaceMail.py. (482 lignes) 

J’ai également renommé le script python d’actualisation en RapportAX.py. (277 lignes) 

Le premier script permet de lancer l’interface pour modifier les listes de destinataires. 

Le second script peut être exécuté en ligne de commande avec en argument le nom des tâches, dans l’objectif de mettre en place une planification par la suite. 

Compétences mobilisées pour la réalisation de cette mission

B1.2 : répondre aux incidents et aux demandes d’assistance et d’évolution
B1.5 : mettre à disposition des utilisateurs un service informatique
B2.2 : assurer la maintenance corrective ou évolutive d’une solution applicative

Fin de stage et mise en production

Mon travail était terminé, il restait à le tester en production. 

L’interface avait le mérite d’exister mais bien qu’elle soit fonctionnelle, M. Lizot a pointé le fait qu’elle n’était pas très intuitive pour un utilisateur lambda (trop de combinaisons de boutons, trop de manipulations à faire) 

Nous nous sommes connectés en RDP (bureau à distance) au poste de M. Lizot via MobaXterm pour avoir accès au serveur de données avec un compte administrateur et avons exécuté une tâche planifiée appelant le script RapportAX avec l’un des arguments. 

Après avoir réglé quelques soucis (notamment l’envoi de mail qui bouclait sur le nombre de destinataires de la liste, exemple : tout le monde aurait reçu 10 fois le même mail s’il y avait 10 personnes dans la liste) le script était opérationnel et utilisable pour les tâches planifiées. 

Ma partie du projet était terminée une demi-heure avant la fin du stage. 

Retour en haut