feat: etat de l'art
This commit is contained in:
parent
2891b84867
commit
2b9072d733
@ -25,3 +25,5 @@
|
|||||||
- Analyse de résultats
|
- Analyse de résultats
|
||||||
- Au delà de la migration
|
- Au delà de la migration
|
||||||
- Conclusion
|
- Conclusion
|
||||||
|
|
||||||
|
[Correction grammaticale à partir d'une API](https://blog.stephane-robert.info/post/langagetool-visual-studio-code/)
|
BIN
assets/fonts/montserrat/Montserrat-Black.ttf
Normal file
BIN
assets/fonts/montserrat/Montserrat-Black.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/montserrat/Montserrat-BlackItalic.ttf
Normal file
BIN
assets/fonts/montserrat/Montserrat-BlackItalic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/montserrat/Montserrat-Bold.ttf
Normal file
BIN
assets/fonts/montserrat/Montserrat-Bold.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/montserrat/Montserrat-BoldItalic.ttf
Normal file
BIN
assets/fonts/montserrat/Montserrat-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/montserrat/Montserrat-ExtraBold.ttf
Normal file
BIN
assets/fonts/montserrat/Montserrat-ExtraBold.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/montserrat/Montserrat-ExtraBoldItalic.ttf
Normal file
BIN
assets/fonts/montserrat/Montserrat-ExtraBoldItalic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/montserrat/Montserrat-ExtraLight.ttf
Normal file
BIN
assets/fonts/montserrat/Montserrat-ExtraLight.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/montserrat/Montserrat-ExtraLightItalic.ttf
Normal file
BIN
assets/fonts/montserrat/Montserrat-ExtraLightItalic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/montserrat/Montserrat-Italic.ttf
Normal file
BIN
assets/fonts/montserrat/Montserrat-Italic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/montserrat/Montserrat-Light.ttf
Normal file
BIN
assets/fonts/montserrat/Montserrat-Light.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/montserrat/Montserrat-LightItalic.ttf
Normal file
BIN
assets/fonts/montserrat/Montserrat-LightItalic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/montserrat/Montserrat-Medium.ttf
Normal file
BIN
assets/fonts/montserrat/Montserrat-Medium.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/montserrat/Montserrat-MediumItalic.ttf
Normal file
BIN
assets/fonts/montserrat/Montserrat-MediumItalic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/montserrat/Montserrat-Regular.ttf
Normal file
BIN
assets/fonts/montserrat/Montserrat-Regular.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/montserrat/Montserrat-SemiBold.ttf
Normal file
BIN
assets/fonts/montserrat/Montserrat-SemiBold.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/montserrat/Montserrat-SemiBoldItalic.ttf
Normal file
BIN
assets/fonts/montserrat/Montserrat-SemiBoldItalic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/montserrat/Montserrat-Thin.ttf
Normal file
BIN
assets/fonts/montserrat/Montserrat-Thin.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/montserrat/Montserrat-ThinItalic.ttf
Normal file
BIN
assets/fonts/montserrat/Montserrat-ThinItalic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/times-new-roman/times-new-roman-bold-italic.ttf
Normal file
BIN
assets/fonts/times-new-roman/times-new-roman-bold-italic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/times-new-roman/times-new-roman-bold.ttf
Normal file
BIN
assets/fonts/times-new-roman/times-new-roman-bold.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/times-new-roman/times-new-roman-italic.ttf
Normal file
BIN
assets/fonts/times-new-roman/times-new-roman-italic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/times-new-roman/times-new-roman.ttf
Normal file
BIN
assets/fonts/times-new-roman/times-new-roman.ttf
Normal file
Binary file not shown.
BIN
assets/images/logo-serfa.jpg
Normal file
BIN
assets/images/logo-serfa.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 151 KiB |
BIN
assets/images/logo-uha.png
Normal file
BIN
assets/images/logo-uha.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
BIN
assets/images/logo-uha40.png
Normal file
BIN
assets/images/logo-uha40.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
Binary file not shown.
@ -1,3 +1,5 @@
|
|||||||
|
#import "../template.typ": *
|
||||||
|
|
||||||
#pagebreak(weak: true)
|
#pagebreak(weak: true)
|
||||||
= Etat de l'art
|
= Etat de l'art
|
||||||
|
|
||||||
@ -73,13 +75,35 @@ PostgreSQL est un SGBDR@SGBDR_def open source très populaire, grâce à sa fiab
|
|||||||
== Une étape trop couteuse ?
|
== Une étape trop couteuse ?
|
||||||
|
|
||||||
Effectuer une migration de base de données n'est pas une tâche anodine. Cela demande du travail en amont, il faut analyser les différents scénarios possibles, estimer un budget pour une telle tâche, réaliser de potentiels développements, s'assurer de la fiabilités avant de mettre tout ça en pratique et enfin la réalisation de l'étape cruciale sur les environnements sensibles.
|
Effectuer une migration de base de données n'est pas une tâche anodine. Cela demande du travail en amont, il faut analyser les différents scénarios possibles, estimer un budget pour une telle tâche, réaliser de potentiels développements, s'assurer de la fiabilités avant de mettre tout ça en pratique et enfin la réalisation de l'étape cruciale sur les environnements sensibles.
|
||||||
|
Pour faire une migration de base de données il existes de nombreuses solutions, certaines plus couteuse, d'autre plus fiables, encore d'autres des plus spécialisées, ... Il faut donc dans un premier temps trouvers différents outils pour comparer les avantages et leur faiblesses.\
|
||||||
|
|
||||||
=== Les technologies utilisées
|
=== Les outils
|
||||||
|
|
||||||
Pour faire une migration de base de données il existes de nombreuses solutions, certaines plus couteuse, d'autre plus fiables, encore d'autres des plus spécialisées, ... Il faut donc dans un premier temps trouvers différents outils pour comparer les avantages et leur faiblesses.
|
On peut dans un premier temps penser à effectuer cette migration grâce à des outils spécialisés qui se chargent de faire la migration automatiquement et de s'assurer de la pérennité entre les données de l'ancienne base et les données insérée dans la nouvelle.\
|
||||||
|
En prenant pour exemple l'outil Oracle Data Dump fournit par l'entreprise Oracle, ce logiciel permet de sauvegarder et restaurer des données et des métadonnées pour les bases Oracle.\
|
||||||
|
Il est rapide et fiable, on peut ainsi lui fournir un fichier #ref-glossary(term: "Dump")[dump] de la base source et l'outil va se charger, grâce à ce fichier, d'intégrer les données dans la base cible.\
|
||||||
|
Microsoft propose sa solution alternative SSMA pour importer les types de bases Access, DB2, MySQL, Oracle, SAP ASE vers leurs différents SGBDR@SGBDR_def propriétaires (à savoir les suites SQL Server).\
|
||||||
|
Sur le même principe les outils MySQL workbench, AWS Database Migration Service (DMS) et PgAdmin permettent de réaliser le même type de migration vers leurs systèmes propriétaires à savoir respectivement MySQL, AWS et PostgreSQL.
|
||||||
|
|
||||||
|
Les principaux désavantages de ce genre de solutions sont:
|
||||||
|
- L'import des données reste assez stricte et ne permet pas de flexibilité, si les données ne sont pas compatiblé, il faut passer du temps à travailler le modèle de données pour essayer de palier aux incompatibilités.
|
||||||
|
- Ils peuvent également rendre les migrations onnéreuses avec certaines solutions qui coutent jusqu'à plusieures centaines d'euros pour les entreprises.
|
||||||
|
- Les logiciels proposés peuvent parfois être complexes et demander un certain temps d'adaptation avant de réellement pouvoir effectuer la tâche de migration.
|
||||||
|
|
||||||
|
=== Les types de migrations
|
||||||
|
|
||||||
|
Il est possible, comme vu précédement, d'effectuer une migration *à partir d'outils automatiques*. L'avantage est de déléguer la majorité de la complexité à une application qui va se charger d'effectuer la tâche cruciale, de réduire les risques d'erreurs pour de grosses applications mais peut être couteuses, insuffisement flexible si le besoin se présente et necessite une expertise pour la configuration des outils.
|
||||||
|
|
||||||
|
Une alternative à prendre en compte est la migration *manuelle*. Cette solution est interessante pour les petites bases de données sans trop de complexité. Le but est d'exporter un fichier #ref-glossary(term: "Dump")[dump] de la base source et de l'importer dans la base cible si possible, ou d'exporter les données sous un autre format pour l'importer simplement. Les couts de cette techniques sont faibles voir nuls et permet une flexibilité lors de la migration.
|
||||||
|
|
||||||
|
Pour palier au problème de prix, une autre solution envisageable est l'export d'un fichier de backup importé par la suite sur la nouvelle base. De la sorte, pas de cout supplémentaire, pas de temps dépensé pour effectuer la migration en elle même et cette méthode rentre dans le cas des bonnes pratiques de posséder un backup régulier d'une base de données pour s'assurer de ne pas perdre les données en cas de problème.\
|
||||||
|
Un problème majeur de cette solution est qu'elle ne pas de garantir que les données soient compatibles, ne permet pas de résoudre les erreurs si il y'en à, il n'y à aucune garantie de succèes.
|
||||||
|
|
||||||
|
Une solutions possible intermédiaire permettant de mitiger problèmes de coûts et problèmes de pérennité, serait de développer en interne de l'entreprise une application de migration de base de données. Même si les coûts ne sont pas moindre, la solution s'adapte au besoin précis à l'instant de la migration, il permet de gérer l'intégralité des actions réalisées et permet également de gérer les cas spéciaux si il y'en a.\
|
||||||
|
En prenant pour exemple une ancienne version de PostgreSQL qui ne supportait pas les identifiants uniques universels (GUID) et il est maintenant question de faire une migration vers une version qui supporte ce type de données. En dévveloppant un logiciel de migration on peut par exemple
|
||||||
|
|
||||||
=== Les ressources disponibles
|
=== Les ressources disponibles
|
||||||
|
|
||||||
=== La philosophie de l'entreprise
|
=== La philosophie de l'entreprise
|
||||||
|
|
||||||
== Conclusion
|
== La solution parfaite
|
||||||
|
3
main.typ
3
main.typ
@ -14,7 +14,8 @@
|
|||||||
"sample": ("sample")
|
"sample": ("sample")
|
||||||
),
|
),
|
||||||
glossary: (
|
glossary: (
|
||||||
"sample": ("sample")
|
"Sample": [Sample.],
|
||||||
|
"Dump": [Un fichier "dump" est un fichier de sauvegarde qui contient une copie de toutes les données et métadonnées d'une base de données à un instant T.],
|
||||||
),
|
),
|
||||||
hayagriva-bibliography: "bibliographie.yml",
|
hayagriva-bibliography: "bibliographie.yml",
|
||||||
thanks: [
|
thanks: [
|
||||||
|
Binary file not shown.
35
olds/n-hbist-back/bibliographie.yml
Normal file
35
olds/n-hbist-back/bibliographie.yml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
bienvenue-groupe-uem:
|
||||||
|
type: book
|
||||||
|
title: Bienvenue dans le groupe UEM
|
||||||
|
date: 2022-02
|
||||||
|
organization: Groupe UEM
|
||||||
|
affiliated:
|
||||||
|
- role: Conception
|
||||||
|
names: Phixso Communication
|
||||||
|
note: Livret d'accueil des apprentis, intérimaires et stagiaires
|
||||||
|
|
||||||
|
decouvrir-groupe-uem:
|
||||||
|
type: web
|
||||||
|
title: Découvrir le Groupe UEM
|
||||||
|
date: 2023
|
||||||
|
organization: Groupe UEM
|
||||||
|
url: https://www.uem-metz.fr/nous-decouvrir/
|
||||||
|
|
||||||
|
organigramme-groupe-uem:
|
||||||
|
type: report
|
||||||
|
title: Organigramme du Groupe UEM
|
||||||
|
date: 2022
|
||||||
|
organization: Groupe UEM
|
||||||
|
|
||||||
|
clients-efluid:
|
||||||
|
type: web
|
||||||
|
title: Nos clients
|
||||||
|
date: 2023
|
||||||
|
organization: Efluid SAS
|
||||||
|
url: https://www.efluid.com/corporate/nos-clients/
|
||||||
|
|
||||||
|
chiffres-efluid:
|
||||||
|
type: report
|
||||||
|
title: L'essentiel des chiffres Efluid 2020
|
||||||
|
date: 2020
|
||||||
|
organization: Groupe UEM
|
737
olds/n-hbist-back/main.typ
Normal file
737
olds/n-hbist-back/main.typ
Normal file
@ -0,0 +1,737 @@
|
|||||||
|
#import "template.typ": *
|
||||||
|
#show: rapport.with(
|
||||||
|
title: "Pilotage projet",
|
||||||
|
color: rgb(10, 19, 89),
|
||||||
|
company: (
|
||||||
|
name: "Efluid SAS",
|
||||||
|
logo: "images/premiere-page/logo-efluid.png",
|
||||||
|
tutor: "M. Benjamin POCHAT"
|
||||||
|
),
|
||||||
|
degree: "Licence professionnelle développeur informatique",
|
||||||
|
promotion: (title: "UHA 4.0.3", year: 2022),
|
||||||
|
acronyms: (
|
||||||
|
"STI2D": ("Sciences et Technologies de l'Industrie et du Développement Durable"),
|
||||||
|
"SIN": ("Systèmes d'Information et Numérique"),
|
||||||
|
"POO": ("Programmation Orientée Objet"),
|
||||||
|
"JWT": ("Json Web Tokens"),
|
||||||
|
"CRM": ("Customer Relationship Management"),
|
||||||
|
"POC": ("Proof Of Concept"),
|
||||||
|
"SQL": ("Structured Query Language"),
|
||||||
|
"JSON": ("Javascript Object Notation"),
|
||||||
|
"IEG": ("Industries Électriques et Gazières"),
|
||||||
|
"CSV": ("Comma-separated values"),
|
||||||
|
"ORM": ("Object Relational Mapper"),
|
||||||
|
"AWS": ("Amazon Web Services"),
|
||||||
|
"UEM": ("Usine d'Électricité de Metz"),
|
||||||
|
"ELD": ("Entreprise Locale de Distribution d'électricité"),
|
||||||
|
"ERP": ("Enterprise Resource Planning"),
|
||||||
|
"STEG": ("Société Tunisienne de l'Électricité et du Gaz"),
|
||||||
|
"ES": ("Électricité de Strasbourg"),
|
||||||
|
"EDF SEI": ("EDF Systèmes Énergétiques Insulaires"),
|
||||||
|
"AMM": ("Advanced Meter Management"),
|
||||||
|
"JSP": ("Java Server Pages"),
|
||||||
|
"W3C": ("World Wide Web Consortium"),
|
||||||
|
"URL": ("Uniform Resource Locator"),
|
||||||
|
"DRY": ("Don't Repeat Yourself")
|
||||||
|
),
|
||||||
|
glossary: (
|
||||||
|
"POO": [la "POO" (#display-def("POO")) est un paradigme de programmation informatique qui consiste à utiliser des "objets", qui représentent des choses réelles ou imaginaires et qui ont des caractéristiques.],
|
||||||
|
"Méthode Agile": [la méthode Agile est une méthodologie de gestion de projet qui consiste à diviser le projet en plusieurs étapes de conception.],
|
||||||
|
"JWT": [les "JWT" (#display-def("JWT"))" sont des "jetons" du standard éponyme, qui permettent d'échanger de façon sécurisée des informations entre plusieurs couches, par exemple client - serveur.],
|
||||||
|
"CRM": [un "CRM" (#display-def("CRM")) ou "gestion de la relation client" est un ensemble d'outils permettant d'améliorer les relations commerciales entre l'entreprise et ses clients.],
|
||||||
|
"Plugin": [un "plugin" est un module d'extension qui permet d'ajouter un ensemble de fonctionnalités à un logiciel.],
|
||||||
|
"POC": [un "POC" (#display-def("POC")) est une conception qui permet de démontrer qu'un projet est réalisable.],
|
||||||
|
"Back-end": ["Back-end" est la couche fonctionnelle d'une application, que l'utilisateur ne voit pas. Elle se situe généralement au niveau du serveur.],
|
||||||
|
"Front-end": ["Front-end" est la couche visible par l'utilisateur d'une application. Elle permet à l'utilisateur d'intéragir facilement avec l'application.],
|
||||||
|
"Bibliothèque de développement": [une "bibliothèque de développement est un ensemble de codes prêts à l'emploi qui permettent de gagner en temps et en efficacité pour un développement.],
|
||||||
|
"Notification push": [Une "notification push" est une alerte sur appareil mobile, similaire à un SMS, mais qui n'est envoyé qu'aux utilisateurs ayant installé l'application et qui ont autorisé les notifications.],
|
||||||
|
"SQL": [le "SQL" (#display-def("SQL")) est un langage informatique utilisé pour manipuler les données d'une base de données relationnelle (comme par exemple MySQL et PostgreSQL).],
|
||||||
|
"JSON": [le "JSON" (#display-def("JSON")) est un format de données flexible dérivé de la notation des objets JavaScript, et utilisé pour représenter et transmettre des données.],
|
||||||
|
"Service web": [les services web permettent à la couche serveur (back-end) de transmettre des données demandées. Dans le cas d'une application, la couche client (front-end) demande des informations à un service web, qui les lui renvoie aussitôt.],
|
||||||
|
"CSV": [le "CSV" (#display-def("CSV")) est un format texte ouvert sans spécification formelle représentant des données tabulaires, délimitées par des virgules ou des points virgules pour le format français.],
|
||||||
|
"ORM": [un "ORM" (#display-def("ORM")) est un processus de codes utilisé pour associer automatiquement la valeur d'un objet avec sa valeur en base de données, permettant de faciliter le processus d'enregistrement et de récupération de données en base de données.],
|
||||||
|
"ERP": ["ERP" (#display-def("ERP")), ou "progiciel de gestion intégré", est une solution informatique permettant à une entreprise de piloter facilement des processus liés à son activité.],
|
||||||
|
"URL": [l' "URL" (#display-def("URL")), plus connue sous le nom d' "adresse web", permet de localiser une ressource disponible sur internet.],
|
||||||
|
"Pop-up": [une fenêtre dite "pop-up" s'affiche en superposition de la fenêtre principale, ce qui permet de mettre son contenu en avant.]
|
||||||
|
),
|
||||||
|
hayagriva-bibliography: "bibliographie.yml",
|
||||||
|
thanks: [
|
||||||
|
Je remercie tout d'abord mon tuteur d'alternance, *M. Benjamin POCHAT*, pour m'avoir accueilli au sein de l'équipe Suivefluid, et pour son investissement dans le bon déroulement de mon alternance.
|
||||||
|
|
||||||
|
Je remercie également chaleureusement mon collègue *M. Jordan REPOVY*, qui s'est beaucoup investi dans mon alternance. Son aide m'a été très précieuse, et j'ai apprécié sa grande sympathie et ses conseils avisés.
|
||||||
|
|
||||||
|
Je n'oublie pas mes autres collègues de bureau, *M. Jean-Marc VAUTHIER*, *Mme. Nathalie MORICEAU*, *Mme. Juliette HOFFMANN*, *M. Benoit LÉOUTRE*, *M. Nicolas REITZ* et *M. Cyrille BRONDOLIN*. Leur gentillesse et leur bonne humeur m'ont permis de travailler dans de très bonnes conditions et de me sentir intégré dès le départ.
|
||||||
|
|
||||||
|
Je remercie l'équipe encadrante d'UHA 4.0, *M. Florent BOURGEOIS*, *Mme. Audrey BRUNSBERGER*, *M. Pierre SCHULLER*, *M. Daniel DA FONSECA*, *M. Florent SANLAVILLE* et *M. Mounir ELBAZ* pour leur implication dans mon cursus scolaire ces 3 dernières années; leurs conseils, leur aide précieuse et leur bonne humeur m'ont permis de mener au mieux mon projet professionnel.
|
||||||
|
|
||||||
|
Enfin, je remercie mes parents pour leur soutien et leur aide durant ma scolarité qui m'ont permis de toujours rester motivé et d'avancer.
|
||||||
|
],
|
||||||
|
introduction: [
|
||||||
|
Étudiant de la formation UHA 4.0 depuis 3 ans, j'ai eu l'opportunité de travailler lors de ma 2ème et de ma 3ème année de formation dans l'entreprise Efluid SAS, éditeur de logiciels destinés aux #acr("IEG") et aux industries de l'eau.\
|
||||||
|
J'ai intégré l'équipe Suivefluid, en charge du développement et de la maintenance du logiciel éponyme. Suivefluid est un logiciel interne conçu pour répondre aux besoins de chaque métier de l'entreprise.
|
||||||
|
|
||||||
|
Avec le temps et l'évolution des besoins métiers, Suivefluid est devenu complexe et volumineux, ce qui occasionne aujourd'hui des difficultés d'utilisation pour les utilisateurs. Certains processus sont fastidieux et entraînent une perte de temps et d'efficacité. Mon projet d'alternance, sujet de ce mémoire, propose une solution qui permettra de simplifier grandement l'une de ces tâches chronophages.
|
||||||
|
|
||||||
|
Dans ce mémoire, je présenterai mes 3 années de formation à UHA 4.0 et je détaillerai mon environnement de travail dans l'entreprise Efluid SAS.\
|
||||||
|
J'aborderai ensuite le cahier des charges du sujet d'alternance en exposant les problématiques rencontrées par les utilisateurs et les différentes solutions envisagées.\
|
||||||
|
Je détaillerai les différentes étapes de conception du projet, et les problématiques auxquelles j'ai été confronté, pour aboutir aux solutions pour y remédier.\
|
||||||
|
Enfin, je concluerai ce mémoire par le résultat de la mise en production du sujet et les retours des utilisateurs.
|
||||||
|
],
|
||||||
|
conclusion: [
|
||||||
|
Après une dernière phase de tests, "Pilotage projet" a pu être mis en production dans la nuit du 4 mai 2023. Sa conception ayant débuté mi-décembre 2022, le développement aura duré au total 4 mois pour s'achever fin avril 2023. Les délais ont été respectés et le projet a été livré dans les temps.
|
||||||
|
|
||||||
|
Depuis sa mise en production, le nouvel écran "Pilotage projet" n'a remonté aucune anomalie. Fonctionnalité très attendue des utilisateurs, elle est aujourd'hui utilisée très régulièrement et permet de faire économiser beaucoup de temps aux utilisateurs, très satisfaits de son fonctionnement.\
|
||||||
|
Ils disposent désormais d'une solution sécurisée et intuitive pour modifier et consulter un grand nombre d'événements Suivefluid simultanément, sans impacter les autres utilisateurs de l'application.
|
||||||
|
|
||||||
|
Aucune évolution de la fonctionnalité n'est prévue à ce jour. Cependant, il n'est pas exclu d'intégrer à l'avenir de nouvelles demandes ultérieures des utilisateurs (comme l'ajout d'un champ modifiable, ou l'ajout d'une action de modification...).
|
||||||
|
|
||||||
|
Grâce à cette année d'alternance, j'ai pu consolider mes connaissances sur le framework "FullJS", sur la technologie des composants web ainsi que dans le language Java.\
|
||||||
|
Durant toute ma formation, j'avais acquis des connaissances sur les tests automatisés, et j'ai pu cette année les renforcer en les appliquant à des cas réels : l'entreprise impose aujourd'hui la couverture complète du code par des tests automatisés.\
|
||||||
|
Mon expérience chez Efluid SAS m'a également fait découvrir de nombreux outils dont je n'avais pas connaissance, tel que l'outil "Gerrit" utilisé pour les revues de code de l'entreprise. J'ai d'ailleurs pu prendre part aux différentes revues de code de l'équipe, qui m'a permis d'apporter mes propres impressions.
|
||||||
|
|
||||||
|
Je suis heureux d'avoir passé ces 3 années de formation à UHA 4.0 car elles ont été très concluantes et elles m'ont apportées de nombreuses connaissances techniques et méthodologiques, en développement informatique comme en gestion de projet.\
|
||||||
|
Grâce à la méthodologie de travail proposée par la formation, j'ai pu m'intégrer facilement aux équipes et mener à bien les projets qui m'ont été confiés.
|
||||||
|
],
|
||||||
|
abstract: [
|
||||||
|
Passionné par le développement informatique, j'ai intégré la formation UHA 4.0 après le baccalauréat.
|
||||||
|
|
||||||
|
Dispensée à l'école et en entreprise, cette formation m'a offert l'opportunité d'effectuer un stage dans une agence web, puis d'intégrer la société Efluid SAS, éditeur de logiciels destinés aux #display-def("IEG") (IEG) et aux industries de l'eau, pour un stage suivi d'un contrat d'alternance.
|
||||||
|
|
||||||
|
J'ai travaillé dans l'équipe Suivefluid, logiciel interne pour tous les métiers de l'entreprise. Avec le temps et l'évolution des besoins métiers, Suivefluid est devenu complexe et volumineux et présente aujourd'hui certaines tâches chronophages pour les utilisateurs.
|
||||||
|
|
||||||
|
Mon sujet d’alternance a eu pour objectif d'élaborer une solution pour simplifier l'une de ces tâches. La fonctionnalité a été déployée et répond parfaitement aux problématiques des utilisateurs.
|
||||||
|
],
|
||||||
|
keywords: (
|
||||||
|
"Pilotage projet",
|
||||||
|
"IEG",
|
||||||
|
"Suivefluid",
|
||||||
|
"Efluid SAS",
|
||||||
|
"Java",
|
||||||
|
"JavaScript",
|
||||||
|
"Développement informatique",
|
||||||
|
"Composants web",
|
||||||
|
"Services web"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
= Contextualisation
|
||||||
|
Dans cette première partie, je commencerai par vous présenter ce qui m'a fait découvrir le métier de développeur, puis j'aborderai mon parcours scolaire jusqu'à mon entrée dans la formation d'UHA 4.0.
|
||||||
|
|
||||||
|
Je présenterai ensuite la formation UHA 4.0 et j'expliquerai pourquoi je l'ai choisie plutôt qu'une autre.
|
||||||
|
|
||||||
|
Je détaillerai également mes 3 années de formation à UHA 4.0 ainsi que mes expériences professionnelles et personnelles acquises grâce à la formation.
|
||||||
|
|
||||||
|
Enfin, je terminerai par une présentation de l'entreprise et de la filière dans laquelle j'effectue mon alternance.
|
||||||
|
|
||||||
|
== Choix d'orientation
|
||||||
|
Je me suis découvert une passion pour l'informatique dès l'âge de 11 ans, lorsque j'ai reçu mon premier ordinateur. Jouant aux jeux vidéos, j'ai rapidement souhaité y ajouter ma touche personnelle en les modifiant; c'est à ce moment que j'ai découvert le développement informatique.
|
||||||
|
|
||||||
|
Le développement est immédiatement devenu mon passe-temps favori.\
|
||||||
|
Lors de mon stage de 3ème au collège j'ai eu l'occasion, durant 1 semaine, de découvrir le métier de développeur informatique dans une agence web au Luxembourg. Ce stage m'a convaincu que c'était le métier que je voulais faire.
|
||||||
|
|
||||||
|
J'ai donc décidé de suivre la filière du baccalauréat technologique "Sciences et Technologies de l'Industrie et du Développement Durable (STI2D)" avec l'option "#acr("SIN")" qui me permettrait de poursuivre des études dans le domaine du développement informatique.
|
||||||
|
|
||||||
|
Durant mon année de première, j'ai eu l'occasion de découvrir UHA 4.0 en allant sur place rencontrer le directeur, les encadrants et les étudiants. J'ai tout de suite su que c'était cette formation que je souhaitais intégrer. Elle m'avait convaincu par sa méthodologie de travail.
|
||||||
|
|
||||||
|
Ayant obtenu mon baccalauréat, j'ai pu intégrer cette formation en septembre 2020.
|
||||||
|
|
||||||
|
== La formation UHA 4.0
|
||||||
|
La formation UHA 4.0, délivrée par l'Université de Haute-Alsace, forme des passionnés du développement informatique.\
|
||||||
|
Pendant 3 ans, les étudiants y découvrent tout d'abord les bases de la programmation par le biais des applications web, puis des concepts plus avancés comme la #ref-glossary(term: "POO", acr("POO")) qui est au cœur des applications les plus complexes.
|
||||||
|
|
||||||
|
Cette formation se démarque des autres car elle propose une approche unique dite "par projets" : les étudiants sont amenés à travailler en groupe de 4 à 6 sur des projets réels apportés par des entreprises et en suivant la #ref-glossary(term: "Méthode Agile")[méthode Agile] de gestion de projet "SCRUM". Cela permet aux étudiants d'être formés en travaillant dans des conditions similaires à celles d'une entreprise, tout en ayant un contact permanent avec le client final.\
|
||||||
|
Les étudiants sont également formés pour devenir chefs de projets (ou "Scrum masters"), c'est-à-dire qu'ils vont apprendre à diriger une équipe de développeurs et à réagir face à toutes sortes de situations et d'imprévus.
|
||||||
|
|
||||||
|
En plus de leurs propres recherches personnelles (ressources en ligne, aide par d'autres étudiants et encadrants, ressources mises à disposition par l'école...), les étudiants découvrent de nouveaux concepts grâce à des topos donnés par les encadrants. Ces concepts théoriques sont mis en pratique par l'étudiant lors du "fil rouge" : une période de 2 mois durant laquelle l'étudiant travaillera sur un projet individuel, qu'il fera évoluer chaque semaine en intégrant ces nouveaux concepts.
|
||||||
|
|
||||||
|
== Mon parcours à UHA 4.0
|
||||||
|
#[
|
||||||
|
#let formation-step(body) = [ *--- #body* \ ]
|
||||||
|
|
||||||
|
=== 1ère année de formation
|
||||||
|
Ma première année de formation à UHA 4.0 a eu pour objectif de me former aux technologies web.
|
||||||
|
|
||||||
|
Lors de cette première année, j'ai eu l'occasion de travailler sur 2 projets internes à l'école, Badgeuse et Admission, et de réaliser un stage en entreprise de 5 mois.
|
||||||
|
|
||||||
|
#formation-step[Badgeuse]
|
||||||
|
Le projet "Badgeuse" est un projet interne créé et maintenu depuis 2018 par les étudiants et les encadrants d'UHA 4.0 pendant les phases de projets. \
|
||||||
|
L'objectif du projet est d'apporter un ensemble d'outils pratiques aux encadrants et aux étudiants : il permet aux étudiants de pointer pour déclarer leur présence dans l'école, de constater en temps réel les absences et présences, de consulter et de postuler à des projets proposés pour les phases de projets... L'équipe pédagogique peut également utiliser l'application pour suivre le temps de présence des étudiants, diffuser des annonces, répartir les étudiants dans les projets et suivre leur activité journalière. \
|
||||||
|
Le projet ayant été développé avec les technologies Angular pour la partie client, NodeJS pour la partie serveur et MariaDB pour la base de données, j'ai pu approfondir mes connaissances dans ces technologies. \
|
||||||
|
J'ai été nommé chef de projet pour la première fois. Ma contribution a été la refactorisation complète du code du serveur, en collaboration avec un autre étudiant d'UHA 4.0, *Octave Blandet*. De plus, je me suis occupé d'une grande partie de la refonte des profils utilisateurs sur l'application, afin d'apporter une bien meilleure expérience utilisateur. J'ai également corrigé de nombreuses anomalies signalées.
|
||||||
|
|
||||||
|
#formation-step[Admission]
|
||||||
|
Mon second projet de première année se nomme "Admission".\
|
||||||
|
Également initié par l'UHA 4.0, c'est un outil destiné à l'équipe pédagogique d'UHA 4.0 afin de répondre à la problématique d'admission des nouveaux étudiants au sein de l'école : aujourd'hui, les candidatures d'admission à l'école se font par le biais de formulaires Google. Dès que la candidature est retenue, les candidats reçoivent par email une invitation à un entretien d'admission avec l'école. Ensuite, les candidats retenus doivent fournir des documents administratifs par email à l'école. Ce processus d'admission est aujourd'hui fastidieux pour l'équipe pédagogique. C'est pourquoi la mise en place de la plateforme Admission a été décidée, afin de permettre aux candidats de déposer et de consulter l'état de leur candidatures directement sur la plateforme, et également de pouvoir déposer les différents documents administratifs nécessaires à leur inscription. Pour l'équipe pédagogique, ce sera un gain de temps considérable car l'ensemble du processus pourra se faire à partir d'un même outil.\
|
||||||
|
Cette application est construite avec les technologies Angular pour la partie client, NestJS pour la partie serveur et MariaDB pour la base de données.\
|
||||||
|
Dans ce projet, ma tâche principale a été de mettre en place un système d'authentification complet et sécurisé, basé sur la technologie des #ref-glossary(term: "JWT", acr("JWT")). De plus, j'ai également contribué à l'ajout de plusieurs fonctionnalités importantes dans l'application telle que la possibilité de créer des configurations de candidats par année, pour pouvoir les retrouver ultérieurement.
|
||||||
|
|
||||||
|
#formation-step[Stage chez Conselio]
|
||||||
|
Après la période de 6 mois à l'école, j'ai effectué un stage de 5 mois dans l'entreprise Conselio, située au Luxembourg. \
|
||||||
|
Conselio est une entreprise spécialisée dans le développement de logiciels web et dans la création de sites internet. Elle commercialise également un #ref-glossary(term: "CRM", acr("CRM")) du nom de "eKo", conçu pour faciliter la gestion commerciale. \
|
||||||
|
Mon projet de stage, réalisé en totale autonomie, a porté sur la création et le développement d'un #ref-glossary(term: "Plugin")[plugin] WordPress destiné aux clients de Conselio qui disposent du #ref-glossary(term: "CRM", acr("CRM")) eKo et d'un site internet WordPress de vente d'articles. Le but de ce glossary(term: "Plugin")[plugin] est de permettre une synchronisation complète et autonome entre le site internet du client et eKo. Ainsi, les produits vendus par le client et renseignés sur eKo ont pu automatiquement être mis à jour sur le site internet du client. Également, les achats sur le site internet ont pu générer des commandes sur eKo pour avoir accès à des statistiques de vente.\
|
||||||
|
J'ai su réaliser ce projet dans les temps en respectant le cahier des charges.
|
||||||
|
Il a été commercialisé chez un client, suite à une démonstration concluante faite chez ce dernier. L'entreprise qui m'a accueillie a été très satisfaite.
|
||||||
|
|
||||||
|
=== 2ème année de formation <2e-annee-formation>
|
||||||
|
Ma seconde année de formation à l'école a eu pour objectif de me former à la programmation d'applications plus complexes, notamment grâce à la #ref-glossary(term: "POO", acr("POO")). À cette occasion j'ai travaillé sur 2 nouveaux projets : Steamer et Alertes.
|
||||||
|
|
||||||
|
#formation-step[Steamer]
|
||||||
|
"Steamer" est une application mobile que nous avons créée à la demande de l'entreprise "Mithra Productions", et qui a pour but de faciliter les rencontres entre passionnés de jeux-vidéos : lorsqu'un joueur de jeux-vidéos souhaite jouer en mode "multijoueurs" mais que ses partenaires de jeu habituels ne sont pas disponibles, l'application Steamer lui permettra de trouver d'autres partenaires pour jouer avec lui.\
|
||||||
|
Steamer se présente comme une application mobile de type "#ref-glossary(term: "POC", acr("POC"))" inspirée des applications de rencontre (par exemple Tinder).\
|
||||||
|
Le cahier des charges fourni par le client nous imposait de faciliter l'inscription des joueurs, de leur proposer des profils de partenaires en fonction de leurs préférences, et de leur donner accès à un tchat.
|
||||||
|
Pour réaliser ce projet, mes 4 collègues et moi avons choisi d'utiliser les technologies GraphQL, Cloudflare Workers, NestJS et MongoDB pour la partie #ref-glossary(term: "Back-end")[back-end], et Flutter pour la partie #ref-glossary(term: "Front-end")[front-end]. \
|
||||||
|
J'ai quant à moi principalement contribué au développement des différents services web nécessaires au fonctionnement de l'application, et mis en place l'algorithme permettant la mise en relation des utilisateurs compatibles. \
|
||||||
|
Nous avons réussi à livrer le projet dans les temps, en respectant les 3 fonctionnalités imposées par le cahier des charges.
|
||||||
|
|
||||||
|
#formation-step[Alertes]
|
||||||
|
Le projet "Alertes" nous a été confié par un ancien étudiant d'UHA 4.0, *M. Luc Ratelli*, et s'adresse à des informaticiens.\
|
||||||
|
L'objectif d’Alertes est de surveiller diverses sources de données et d'alerter l'utilisateur par mail ou par "#ref-glossary(term: "Notification push")[notification push]" lorsqu'une condition, configurée par l'utilisateur avec une syntaxe similaire au #ref-glossary(term: "SQL", acr("SQL")), est remplie. Les sources de données peuvent être des bases de données #ref-glossary(term: "SQL", acr("SQL")) (par exemple PostgreSQL ou MySQL) ou des réponses #ref-glossary(term: "JSON", acr("JSON")), provenant d'appels automatiques à un #ref-glossary(term: "Service web")[service web].\
|
||||||
|
Par exemple, Alertes pourrait prévenir un commerçant du stock faible d'un article lorsque la valeur du champ "stock" de cet article en base de données passe sous un seuil établi.\
|
||||||
|
Pour le développement de ce projet, les technologies suivantes nous ont été imposées par le client : Angular pour la partie client, Spring pour la partie serveur et PostgreSQL pour la persistance des données de l'application. \
|
||||||
|
Mon rôle a été de mettre en place les connecteurs intelligents entre l'application Alertes et les différentes sources de données sujettes aux notifications. J'ai également créé un #ref-glossary(term: "Service web")[service web] permettant l'introspection des sources de données : il permet d'afficher graphiquement à l'utilisateur un schéma de la structure d'une source de données. \
|
||||||
|
Ce projet a été très enrichissant pour notre équipe, car il a impliqué un grand travail de recherche et de nombreuses contraintes techniques auxquelles il a fallu faire face. Notre client a été très satisfait du travail réalisé.
|
||||||
|
|
||||||
|
#formation-step[Stage chez Efluid SAS]
|
||||||
|
Après ces 2 projets réalisés à l'école, j'ai effectué un stage de 6 mois dans l'entreprise Efluid SAS, à Metz. \
|
||||||
|
Efluid SAS est un éditeur de logiciels destinés aux #acr("IEG"). \
|
||||||
|
J'ai été affecté à l'équipe Suivefluid, une équipe de 4 développeurs travaillant sur le logiciel du même nom. Suivefluid est un logiciel interne conçu pour répondre aux besoins des différents métiers au sein de l'entreprise.\
|
||||||
|
L'entreprise disposant de nombreux clients, lorsqu'une fonctionnalité doit être développée pour un logiciel commercialisé à des clients, elle doit être déclinée en un événement dédié par client. Ceci permet de l'adapter au mieux en fonction du client cible. En conséquence, il peut arriver de devoir créer jusqu'à plusieurs centaines d'événements manuellement dans Suivefluid.\
|
||||||
|
Cette problématique avait été solutionnée par l'équipe de Suivefluid, en mettant en place en place un fichier Excel pré-rempli et qui permettait de générer une requête d'insertion #ref-glossary(term: "SQL", acr("SQL")) des événements à créer. Ces événements étaient saisis dans le fichier sous forme de lignes duplicables et adaptables au cas par cas. Chaque fichier d'injection d'évenements saisi était alors envoyé à l'équipe Suivefluid qui devait récupérer la requête #ref-glossary(term: "SQL", acr("SQL")) pour l'exécuter directement sur la base de données de Suivefluid. Cependant cette approche présentait un inconvénient majeur : elle ne permettait pas de vérifier la conformité des événements, soumis à de nombreuses contraintes de validation. L'équipe Suivefluid devait donc vérifier manuellement chaque ligne du fichier, occasionnant une perte de temps considérable.\
|
||||||
|
C'est pourquoi l'objectif de mon stage a été de palier à ces inconvénients. Pour cela, j'ai mis en place un système de création en masse d'événements que nous avons appelé "Système d'injection d'événements en masse".\
|
||||||
|
Pour fonctionner, le système reçoit un fichier "#ref-glossary(term: "CSV", acr("CSV"))" similaire aux fichiers Excel jusqu'alors utilisés, à la différence qu'il est désormais exploitable par Suivefluid qui pourra valider précisément la conformité de chaque événement à créer. Après injection, un rapport est généré et porte les informations des événements générés ou les éventuelles erreurs survenues.\
|
||||||
|
De plus, les chefs de projet peuvent désormais utiliser le système d'injection en masse pour créer eux-mêmes les événements sans passer par l'équipe Suivefluid, car toutes les étapes du processus sont sécurisées.\
|
||||||
|
Donnant satisfaction, il a été décidé de le déployer. Depuis sa mise en place, il a permis de faire gagner de nombreux jours de travail à l'équipe et de ne plus avoir d'impossiblité d'affichage d'événements car ceux-ci sont désormais tous conformes.
|
||||||
|
|
||||||
|
=== 3ème année de formation
|
||||||
|
La troisième année à UHA 4.0 a pour but de clôturer le parcours de formation des étudiants, en leur permettant de pouvoir obtenir la licence professionnelle "développeur informatique" au terme de l'année. \
|
||||||
|
Lors de cette dernière année, les étudiants ont pour objectif de mettre en application leurs connaissances acquises durant toute la durée de la formation. De plus, ils vont également pouvoir découvrir des concepts avancés de la programmation : mise en place de tests automatisés, outils d'analyse statique de code, concepts qualité, les #ref-glossary(term: "ORM", acr("ORM"))...
|
||||||
|
|
||||||
|
En ce qui me concerne, j'ai effectué cette dernière année de licence professionnelle en alternance dans l'entreprise *Efluid SAS*, qui m'a proposée cette alternance suite au succès de mon stage de l'année précédente. J'ai alterné les périodes de présence à l'école avec ma présence en entreprise.
|
||||||
|
|
||||||
|
Les projets sur lesquels j'ai travaillé à l'école pour ma troisième année ont été Envie et COP AMACO.
|
||||||
|
|
||||||
|
#formation-step[Envie]
|
||||||
|
Envie est une société basée en Alsace qui commercialise des pièces détachées pour les appareils d'électroménager.\
|
||||||
|
Pour faciliter la gestion du stock de ses pièces détachées dans ses entrepôts, Envie a demandé à UHA 4.0 de concevoir son nouveau système de gestion logistique. L'objectif était d'obtenir un nouveau système permettant de gérer facilement l’entrée et la sortie de stock des pièces détachées des entrepôts de l'entreprise.\
|
||||||
|
J'ai été affecté à ce projet avec 2 autres étudiants de 3ème année et 3 autres étudiants de 1ère année.\
|
||||||
|
Le client souhaitait disposer d'une application web destinée au paramétrage et à la consultation de ses diverses pièces détachées en stock, et d'une application mobile pour pouvoir gérer facilement l'entrée et la sortie de stock de ces pièces détâchées.\
|
||||||
|
Pour ce projet, ma contribution s'est majoritairement concentrée sur le #ref-glossary(term: "Back-end")[back-end] (développé avec NestJS) et l'application mobile : je me suis occupé de mettre en place des services web nécessaires au fonctionnement du système, et j'ai également eu la responsabilité de la création de l'application mobile avec la mise en place des fonctionnalités d'entrée et de sortie de stock dans celle-ci.\
|
||||||
|
Étant donné que le client voulait pouvoir utiliser l'application sur tout type d'appareils mobiles, mon choix technologique s'est porté sur Flutter : ce framework permet de développer des applications fonctionnant nativement sur tout type d'appareils avec une même base de code.\
|
||||||
|
J'ai également travaillé sur certaines fonctionnalités de l'interface web du système. Cela m'a permis de découvrir le framework NextJS choisi initialement par l'équipe.
|
||||||
|
Le projet a été réalisé avec succès, les demandes du client ont pu être respectées. Par la suite, il a été poursuivi par d'autres étudiants lors d'autres itérations de projets.
|
||||||
|
|
||||||
|
#formation-step[COP AMACO]
|
||||||
|
COP AMACO est le dernier projet sur lequel j'ai pu travailler à l'école.\
|
||||||
|
COP AMACO est une entreprise strasbourgeoise spécialisée dans l'équipement des points de vente commerciaux. Elle commercialise notamment l'écosystème "Atmos". Atmos permet le contrôle et la gestion d'un ensemble d'appareils connectés dans le magasin (par exemple les caisses), la diffusion de bandes sonores dans plusieurs rayons du magasin à des moments précis de la journée...\
|
||||||
|
Pour ce projet, notre tâche a consisté à mettre en place une nouvelle pièce de l'écosystème Atmos : la gestion d'écrans connectés dans le magasin.\
|
||||||
|
À cette occasion, j'ai été une nouvelle fois nommé "Scrum Master" pour diriger 4 étudiants de première année.\
|
||||||
|
L'objectif demandé était de permettre la diffusion de vidéos sur les écrans présents dans les points de vente en des lieux et à des fréquences choisies.\
|
||||||
|
Les technologies utilisées pour le projet ont été imposées par le client : Angular pour la partie client, NestJS pour la partie serveur et #acr("AWS") pour les solutions cloud.\
|
||||||
|
Ma contribution au sein de ce projet s'est portée sur la mise en place des différents services web nécessaires au fonctionnement du système, la mise en place de l'envoi des vidéos, la génération d'une miniature pour la vidéo envoyée et la lecture en streaming des vidéos.\
|
||||||
|
Les demandes du client ont pu être réalisées dans les temps.
|
||||||
|
|
||||||
|
#formation-step[Alternance chez Efluid SAS]
|
||||||
|
Après avoir effectué un stage de 2ème année très enrichissant chez Efluid SAS, j’ai choisi de poursuivre ma dernière année de formation en alternance au sein de cette entreprise. Dans la suite de ce mémoire, je présenterai d’abord mon entreprise et l’équipe au sein de laquelle j'ai travaillé. Puis je présenterai mon sujet d’alternance, les différentes étapes de sa réalisation et le résultat final obtenu.
|
||||||
|
]
|
||||||
|
|
||||||
|
== Entreprise d'accueil
|
||||||
|
=== Groupe UEM
|
||||||
|
L'#acr("UEM") a été créée en 1901. En 1925, elle est devenue la Régie Municipale de la Ville de Metz. @bienvenue-groupe-uem \
|
||||||
|
Lorsque le marché de l'électricité et du gaz a été nationalisé en France en 1946, #acr("UEM") a tout de même conservé son statut de Régie Municipale de Metz. Elle est la première #acr("ELD") indépendante du pays. @decouvrir-groupe-uem \
|
||||||
|
À ce jour, #acr("UEM") fournit 1/5#super("ème") du département de la Moselle en électricité, dont 140 communes et plus de 162 000 clients. @bienvenue-groupe-uem
|
||||||
|
|
||||||
|
En 2008, pour s'adapter à la nouvelle organisation du système électrique européen et français, #acr("UEM") a séparé ses différentes activités en 4 filiales : @decouvrir-groupe-uem
|
||||||
|
- Réséda, gestionnaire de réseaux de distribution électrique.
|
||||||
|
- Énergem, filiale de commercialisation d'offres électriques et gazières sur toute la France.
|
||||||
|
- Énergreen Production, producteur d'énergies renouvelables à partir de parcs éoliens et photovoltaïques.
|
||||||
|
- Efluid, éditeur informatique leader dans les systèmes d'informations de l'énergie et éditeur du logiciel de gestion du même nom, leader dans le secteur de l'énergie.
|
||||||
|
|
||||||
|
La @figure-groupe-uem présente l'organigramme du groupe UEM.
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
caption: [Organigramme du groupe UEM. @organigramme-groupe-uem],
|
||||||
|
image("images/contenu/organigramme-uem.png"),
|
||||||
|
) <figure-groupe-uem>
|
||||||
|
|
||||||
|
=== Efluid SAS
|
||||||
|
C'est au sein de la filiale d'#acr("UEM") "Efluid SAS" que j'ai réalisé mon alternance.\
|
||||||
|
Efluid est une société éditrice de logiciels destinés aux #acr("IEG") et aux industries de l'eau. Fondée en 2013 par le groupe UEM suite à la signature historique du contrat avec son principal client Enedis, Efluid est rapidement devenue leader dans le domaine des systèmes d'information de l'énergie.
|
||||||
|
À l'origine, Efluid était un progiciel front et back-office de gestion intégré (en anglais "#ref-glossary(term: "ERP", acr("ERP"))") créé en 2002 par #acr("UEM"). Il a été conçu principalement pour la gestion commerciale des clients ainsi que pour la gestion de l'activité technique et financière nécessaire à la fourniture et la distribution d'énergie. @bienvenue-groupe-uem
|
||||||
|
|
||||||
|
Au fil des années, le logiciel Efluid s'est développé et sa commercialisation a été étendue en 2010 hors métropole (en Martinique, Guyane, Guadeloupe, à La Réunion et en Corse).\
|
||||||
|
Aujourd'hui, l'entreprise compte plus de 40 clients majeurs, parmi lesquels figurent Enedis (client majeur et historique détenant 30% des parts d'Efluid SAS), la #acr("STEG"), la société #acr("ES"), #acr("EDF SEI"), Vialis, Eau Publique du Grand Lyon (distribution de l'eau dans l'agglomération lyonnaise) ou encore la Régie de L'Eau Bordeaux Métropole. @clients-efluid
|
||||||
|
|
||||||
|
Très flexible, le logiciel est capable de répondre à un grand nombre de besoins pour l'électricité, le gaz, l'eau, l'assainissement, l'éclairage public... Ce qui lui a permis de remporter l'appel d'offres de la #acr("STEG") en 2022, un contrat clé pour l'entreprise.
|
||||||
|
|
||||||
|
Quelques données clés d’Efluid en 2020 sont présentées dans la @figure-chiffres-efluid-2020.
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
caption: [L'essentiel des chiffres d'Efluid en 2020. @chiffres-efluid],
|
||||||
|
image("images/contenu/chiffres-efluid.png")
|
||||||
|
) <figure-chiffres-efluid-2020>
|
||||||
|
|
||||||
|
L'entreprise propose également une suite logicielle portant sur divers domaines, en plus de son progiciel historique. Par exemple, le logiciel "eot" permet la relève et la re-programmation de compteurs programmables à distance dits "#acr("AMM")", comme par exemple le compteur Linky. Efluid SAS propose également "mapefluid", un module de cartographie d'un réseau de distribution qui sera mis en application sur les bornes de recharge pour véhicules électriques et l'éclairage public; ainsi que l'application mobile "mobefluid" utilisée pour la planification et le suivi des interventions des agents sur le terrain.
|
||||||
|
|
||||||
|
Aujourd'hui, l'entreprise compte au total 8 services :
|
||||||
|
- Service Technologies.
|
||||||
|
- Service Développement Comptage & Réseaux (dont je fais partie).
|
||||||
|
- Service Développement #ref-glossary(term: "CRM")[CRM] & Facturation.
|
||||||
|
- Service Ginko.
|
||||||
|
- Service Expertise Fonctionnelle #ref-glossary(term: "CRM")[CRM] & Facturation.
|
||||||
|
- Service Expertise Fonctionnelle Comptage & Réseaux.
|
||||||
|
- Service Coordination & Clients.
|
||||||
|
- Service Prestations & Projets.
|
||||||
|
|
||||||
|
=== Suivefluid <suivefluid>
|
||||||
|
Durant toute la période de mon stage de l'année précédente ainsi que toute la période de mon alternance, j'ai été affecté à l'équipe Suivefluid, une équipe de 5 développeurs, dont moi-même, qui maintient à temps-plein le logiciel du même nom. \
|
||||||
|
La méthode de travail de notre équipe suit le modèle du "Cycle en V". Ainsi, j'ai participé aux réunions hebdomadaires chaque mardi avec l'équipe, ce qui permettait de faire le point sur les différentes tâches réalisées et les éventuelles nouvelles anomalies ou demandes de fonctionnalités des utilisateurs.
|
||||||
|
|
||||||
|
Suivefluid est un logiciel interne créé en 2007 par Efluid dans le but de répondre aux différentes tâches récurrentes apportées par l'ensemble des métiers de l'entreprise. Le logiciel est aujourd'hui un véritable écosystème acteur du bon fonctionnement de l'entreprise et est présent dans le quotidien de chaque employé.
|
||||||
|
|
||||||
|
Comme évoqué précédemment dans le @2e-annee-formation, Suivefluid est aujourd'hui au coeur du fonctionnement de l'entreprise et couvre de nombreux domaines, dont par exemple :
|
||||||
|
- Les événements (fonctionnalités de ticketing pour tous les métiers de l'entreprise).
|
||||||
|
- Gestion des environnements de déploiement des applications (développement, tests, copie de production, production...).
|
||||||
|
- Gestion de l'activité des employés (saisie du temps passé sur les événements de la journée).
|
||||||
|
- Annuaire d'entreprise.
|
||||||
|
- Gestion des versions des différents logiciels (date échéante d'une version en préparation avec des événements de développement associés, possibilité de consulter la version d'une application déployée chez un client précis...).
|
||||||
|
- Etc.
|
||||||
|
|
||||||
|
Afin d'optimiser la conception de ses logiciels, des équipes d'Efluid développent activement deux frameworks utilisés dans la totalité des applications de l'entreprise dont Suivefluid :
|
||||||
|
+ Le framework "historique", developpé à l'origine par un prestataire, est écrit dans le langage Java. Il est conçu pour les couches #ref-glossary(term: "Back-end")[back-end] (serveur) et #ref-glossary(term: "Front-end")[front-end] (client) des applications. Ce framework repose sur la technologie des #acr("JSP") et des services REST, et est utilisé aujourd'hui par la totalité des applications de l'entreprise.
|
||||||
|
+ Le framework "FullJS", développé initialement par Efluid SAS et écrit dans le language JavaScript, a été créé pour être en adéquation avec les nouvelles technologies et les contraintes imposées par celles-ci. Ce framework, conçu uniquement pour la couche #ref-glossary(term: "Front-end")[front-end], repose sur la #ref-glossary(term: "Bibliothèque de développement")[bibliothèque de développement] "lit-html", elle-même basée sur la nouvelle technologie des composants web en cours de normalisation par le "#acr("W3C")", organisme international régulateur des standards techniques liés au web. Il apporte un ensemble de composants graphiques utilisés afin de réduire le temps de développement des fonctionnalités tout en garantissant une cohérence graphique pour l'ensemble des applications développées par l'entreprise.
|
||||||
|
|
||||||
|
Suivefluid est conçu avec ces 2 frameworks mais la majeure partie de l'application repose sur le framework historique, alors qu'une partie plus minoritaire et plus récente de l'application côté #ref-glossary(term: "Front-end")[front-end] est développée avec le framework FullJS. Désormais, la volonté est de développer dès que possible les nouvelles fonctionnalités #ref-glossary(term: "Front-end")[front-end] de Suivefluid avec le framework FullJS.
|
||||||
|
|
||||||
|
#pagebreak(weak: true)
|
||||||
|
= Cahier des charges
|
||||||
|
Dans cette partie, je commencerai par expliquer le fonctionnement des événements Suivefluid et en particulier ceux de type "prestation client", car ils sont au cœur de mon sujet d'alternance.\
|
||||||
|
Je présenterai ensuite les problématiques rencontrées par les utilisateurs de l'application, puis j'exposerai la solution proposée aux utilisateurs qui fait l'objet de mon sujet d'alternance.
|
||||||
|
|
||||||
|
== Mise en contexte de l'existant
|
||||||
|
=== Les événements Suivefluid
|
||||||
|
Comme évoqué plus tôt dans le @suivefluid, Suivefluid est aujourd'hui un véritable écosystème conçu pour répondre à tous les métiers de l'entreprise. Il permet les interconnecter entre-eux et de centraliser tous les besoins en un seul et même endroit.
|
||||||
|
|
||||||
|
Dans le but de simplifier la planification et la consultation des tâches à effectuer pour chaque acteur de l'entreprise (employé, prestataire ou équipe), Suivefluid dispose de fonctionnalités de ticketing. Lorsqu'une action conséquente (nécessitant plusieurs heures de travail) doit être entreprise, un ticket (appelé un "événement" dans Suivefluid), doit être créé dans Suivefluid.
|
||||||
|
|
||||||
|
Ces événements peuvent être consultés dans le temps, et il en existe aujourd'hui une quarantaine de types, parmi lesquels figurent :
|
||||||
|
- Des événements de développement.
|
||||||
|
- Des événements d'anomalies.
|
||||||
|
- Des événements de paramétrage.
|
||||||
|
- Des événements de prestation client.
|
||||||
|
- Des événements de support client.
|
||||||
|
- Etc.
|
||||||
|
|
||||||
|
Ainsi, les événements contiennent de nombreuses informations pertinentes pour les différents métiers de l’entreprise. Cela rend la page de consultation des événements chargée d'une multitude d'informations, qui ne sont pas toutes utiles pour chaque utilisateur. Par exemple, le prix facturé à un client n’intéresse pas le développeur, mais plutôt le chef de projet. Cette situation résulte de la complexité technique de Suivefluid qui a dû évoluer avec le temps, et qui ne permet pas d’adapter l’affichage selon les métiers.
|
||||||
|
|
||||||
|
=== Prestations clients
|
||||||
|
Lorsqu'une entreprise cliente commande une prestation à Efluid, un événement de type "prestation client" est créé par un chef de projet.\
|
||||||
|
En fonction de la prestation, il arrive qu'Efluid propose également cette prestation à d'autres clients qui pourraient être intéressés.
|
||||||
|
Dans ce cas, un nouvel événement "prestation client" est alors créé pour chaque client et copie les informations de l'événement initial. Ce nouvel événement devient alors consultable par les clients qui peuvent vérifier l'avancée de leur propre prestation.
|
||||||
|
|
||||||
|
Pour pouvoir grouper les événements ensemble et les identifier facilement, un lien de parenté est automatiquement créé entre les événements client et l'événement de prestation d'origine : l’événement de prestation pour chaque client devient enfant de l’événement de prestation d’origine, et l’événement de prestation d’origine devient parent de chaque événement de prestation pour un client.
|
||||||
|
|
||||||
|
Chaque événement enfant peut également lui-même être divisé en plusieurs événements enfants suivant les besoins ou demandes du client, et ainsi de suite.
|
||||||
|
|
||||||
|
La @figure-evenements-prestations-parente illustre les événements de prestation et leur différents liens de parenté.
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
caption: "Événements de prestation client avec liens de parenté.",
|
||||||
|
image("images/contenu/evenements-prestations-parentes.png")
|
||||||
|
) <figure-evenements-prestations-parente>
|
||||||
|
|
||||||
|
Les chefs de projet peuvent donc avoir un nombre considérable d'événements à traiter pour une seule demande de prestation client.
|
||||||
|
|
||||||
|
=== Modification d'une prestation client <modification-prestation-client>
|
||||||
|
Les événements de prestation client sont parfois soumis à des modifications, qui peuvent faire suite à une demande du client ou à une demande en interne. \
|
||||||
|
Comme évoqué lors du point précédent, les événements de prestation client (parents) sont très souvent découpés en plusieurs événements enfants, qui correspondent à chaque client.\
|
||||||
|
Lorsqu'un chef de projet apporte une modification à un événement de prestation client, il doit répercuter manuellement la modification sur l'ensemble des événements enfants de la prestation, car les données des événements enfants de la prestation n'ont pas de lien direct avec les données de la prestation parent (les données sont simplement copiées à la création des sous-événements).\
|
||||||
|
Par exemple, dès lors qu'une prestation est ouverte, les chefs de projet identifient le coût total de celle-ci. Le chef de projet devra alors indiquer le budget client (tarif facturé au client) sur l’événement parent de la prestation, ainsi que sur les événements enfants de la prestation.
|
||||||
|
|
||||||
|
La @figure-modification-prestations-parentees illustre les modifications à apporter sur un événement parent, ayant un événement enfant, ce dernier ayant lui-même un enfant.
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
caption: "Modification manuelle d'un événement de prestation client.",
|
||||||
|
image("images/contenu/modification-prestations-parentees.png")
|
||||||
|
) <figure-modification-prestations-parentees>
|
||||||
|
|
||||||
|
=== Modifier un événement sur Suivefluid <modifier-evenement-suivefluid>
|
||||||
|
Pour modifier un événement sur Suivefluid, il est nécessaire de passer par plusieurs étapes. Reprenons l'exemple de l'ajout d'un budget client sur un événement :
|
||||||
|
|
||||||
|
1. Tout d'abord, il est nécessaire d'accéder à la page de consultation de l'événement sujet à la modification. Pour cela, il faut se rendre sur la page de recherche événement Suivefluid, accessible à partir du menu supérieur. L'événement à modifier est ensuite localisable grâce aux fonctionnalités de filtre de la page de recherche; il peut être consulté en cliquant sur sa référence (voir @figure-recherche-evenement-consultation).
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
caption: "Recherche d'un événement sur Suivefluid.",
|
||||||
|
image("images/contenu/recherche-evenement-consultation.png")
|
||||||
|
) <figure-recherche-evenement-consultation>
|
||||||
|
|
||||||
|
2. Une fois sur la page de consultation de l'événement, il faut se rendre dans l'onglet "analyse financière", qui est l'onglet dédié au suivi des coûts et qui regroupe les informations des budgets clients (voir @figure-consultation-evenement-suivefluid).
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
caption: "Page de consultation d'un événement",
|
||||||
|
image("images/contenu/ogeneralite.png")
|
||||||
|
) <figure-consultation-evenement-suivefluid>
|
||||||
|
|
||||||
|
3. Pour pouvoir modifier des données dans une page de consultation, il est nécessaire de passer en mode "modification", grâce au bouton en bas de la page (voir @figure-consultation-evenement-analyse-financiere).
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
caption: "Onglet d'analyse financière en consultation d'événement.",
|
||||||
|
image("images/contenu/oanafinanciere.png")
|
||||||
|
) <figure-consultation-evenement-analyse-financiere>
|
||||||
|
|
||||||
|
4. Ensuite, pour pouvoir ajouter le nouveau budget client, l'utilisateur doit cliquer sur le libellé "créer" (voir @figure-consultation-evenement-analyse-financiere-modification).
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
caption: "Onglet d'analyse financière en modification.",
|
||||||
|
image("images/contenu/oanafinancieremodification.png")
|
||||||
|
) <figure-consultation-evenement-analyse-financiere-modification>
|
||||||
|
|
||||||
|
5. Il s'affichera alors une nouvelle page avec un formulaire, qu'il faudra compléter avec les informations du nouveau budget client à créer. Pour valider la création du budget client, l'utilisateur devra cliquer sur le bouton "enregistrer" (@figure-formulaire-creation-budget-client).
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
caption: "Formulaire de création d'un budget client.",
|
||||||
|
image("images/contenu/creationbudget.png")
|
||||||
|
) <figure-formulaire-creation-budget-client>
|
||||||
|
|
||||||
|
6. L'enregistrement du nouveau budget client nous fait revenir sur la page de consultation de l'événement, qu'il faudra à son tour enregistrer pour pouvoir valider les modifications (@figure-enregistrement-evenement).
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
caption: "Enregistrement des modifications sur la page de consultation de l'événement.",
|
||||||
|
image("images/contenu/enregistrement_evenement.png")
|
||||||
|
) <figure-enregistrement-evenement>
|
||||||
|
|
||||||
|
Pas moins de 6 actions auront été nécessaires à l'utilisateur pour pouvoir modifier une information d'un seul événement, qui pourtant se trouvait dans un onglet accessible en un clic. Sachant que pour atteindre certaines informations il faut cliquer dans plusieurs sous-onglets successivement, l'utilisateur peut avoir à effectuer bien plus d'étapes encore avant de finaliser la modification de l'événement.
|
||||||
|
|
||||||
|
== Problématiques rencontrées
|
||||||
|
=== Modification fastidieuse des événements
|
||||||
|
Aujourd'hui, il arrive très souvent que les événements enfants d'une "prestation client" se comptent par plusieurs dizaines. Comme exposé dans le @modification-prestation-client, les chefs de projet sont contraints de modifier manuellement chaque événement avec les mêmes informations sur Suivefluid. Sachant que le nombre d'étapes à réaliser pour modifier un seul événement est important (6 étapes dans l'exemple du @modifier-evenement-suivefluid), c'est une tâche très fastidieuse qui demande de nombreuses heures de travail pour les chefs de projet.
|
||||||
|
|
||||||
|
=== Aucune vue d'ensemble des modifications
|
||||||
|
Devoir modifier manuellement chaque événement empêche d'avoir une vue d'ensemble sur la modification de tous les événements de la prestation. Les événements devant être modifiés en les affichant les uns après les autres, le chef de projet ne peut jamais être certain qu'il a bien appliqué la modification sur tous les événements enfants sans faute ni oubli.
|
||||||
|
|
||||||
|
== Proposition d'une solution
|
||||||
|
La première solution envisagée était de modifier totalement la page de consultation des événements, en allégeant la quantité de données affichées aux utilisateurs pour simplifier le processus de modification, et en limitant le nombre d'actions faites par l'utilisateur pour modifier une donnée.\
|
||||||
|
Cependant, les événements étant utilisés par tous les métiers de l'entreprise, modifier la page entraînerait des inconvénients pour les autres métiers de l'entreprise.\
|
||||||
|
De plus, cette solution ne répondrait pas à la problématique de pouvoir modifier plusieurs événements à la fois, car les chefs de projets seraient toujours contraints de devoir modifier individuellement chaque événement de la prestation client.
|
||||||
|
|
||||||
|
Une autre solution a donc été recherchée pour répondre à ces contraintes.
|
||||||
|
De cette réflexion sont apparues 2 possibilités :
|
||||||
|
+ Soit adapter la page existante de consultation des événements de Suivefluid en rajoutant une fonctionnalité de modification en masse des événements "prestation client", c'est-à-dire une fonctionnalité permettant de modifier un grand nombre d'événements simultanément.
|
||||||
|
+ Soit développer un nouvel écran, dédié au pilotage d'un événement parent "prestation client" et de ses événements enfants, rattachés à travers une vue hiérarchique et qui pourrait permettre :
|
||||||
|
- La consultation d'une grande quantité d'événements, représentés sous forme de "cartes", solution visuelle permettant l'affichage des informations de chaque événement dans un encadré.
|
||||||
|
- La visualisation des seules informations utiles aux chefs de projets.
|
||||||
|
- La possibilité d'appliquer les actions de modifications les plus courantes pour les chefs de projet sur un ensemble d'événements de prestation, permettant un gain de temps significatif.
|
||||||
|
|
||||||
|
Après réflexion, notre choix s'est porté sur la deuxième solution, qui aura l'avantage de ne pas impacter les autres métiers et d'être conçue spécifiquement pour répondre aux besoins des chefs de projet.\
|
||||||
|
De plus, elle pourra être développée avec le framework "FullJS" sur la partie plus récente de Suivefluid.\
|
||||||
|
La conception de ce nouvel écran m'a été confiée comme sujet d'alternance.
|
||||||
|
|
||||||
|
#pagebreak(weak: true)
|
||||||
|
= Réalisation de l'écran "Pilotage projet"
|
||||||
|
Dans cette dernière partie, j'aborderai les différentes étapes de conception de la solution retenue, en commençant par le prototypage de la solution juqu'aux dernières étapes avant sa mise en production.\
|
||||||
|
J'aborderai également les différentes problématiques que j'ai pu rencontrer et comment j'ai pu y remédier.
|
||||||
|
|
||||||
|
== Prototypage de la solution <prototypage-solution>
|
||||||
|
Il m'a été demandé tout d'abord d'élaborer un premier prototype, qui sera soumis aux avis des utilisateurs finaux pour avoir la garantie de répondre au mieux à leurs besoins.
|
||||||
|
|
||||||
|
Ayant une bonne connaissance du framework "FullJS" de l'entreprise grâce à mon dernier stage, j'ai pris l'initiative de concevoir le prototype de la solution directement en code dans l'application plutôt que dans un logiciel de prototypage. Cette approche m'a apporté plusieurs avantages :
|
||||||
|
- Les outils pour pouvoir utiliser les composants du framework dans des logiciels tiers de prototypage n'étant aujourd'hui pas autorisés dans l'entreprise, j'ai directement pu utiliser les composants du framework pour être au plus proche du rendu final.
|
||||||
|
- J'ai pu utiliser le prototype comme base de développement de la solution, ce qui a permis de gagner du temps sur la conception de la solution et pour d'éventuels changements.
|
||||||
|
|
||||||
|
En tenant compte des différentes problématiques rencontrées et des différentes fonctionnalités demandées pour la solution, j'ai pu concevoir un premier prototype (@figure-prototype-v1-pilotageprojet).
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
caption: [Premier prototype de "Pilotage projet".],
|
||||||
|
image("images/contenu/prototype_v1_pilotageprojet.png")
|
||||||
|
) <figure-prototype-v1-pilotageprojet>
|
||||||
|
|
||||||
|
Ce premier prototype reprend les demandes initialement formulées :
|
||||||
|
- La consultation dans une vue hiérarchique d'un événement de prestation parent, représenté en évidence par une carte dans la partie supérieure du prototype, avec ses différents sous-événements enfants représentés sous forme de cartes plus réduites dans la partie inférieure du prototype.
|
||||||
|
- La consultation des données des événements utiles aux chefs de projets, représentées par les champs gris des cartes événements.
|
||||||
|
- La possibilité de pouvoir appliquer différentes actions de modification, en cliquant sur les libellés bleus situés à droite de la prestation parente.
|
||||||
|
|
||||||
|
Ce prototype a été présenté aux utilisateurs lors d'une réunion. Ceux-ci ont souhaité apporter quelques modifications par rapports à leurs besoins initiaux :
|
||||||
|
- Se détacher de la notion d'événements de prestation et de hiérarchie, pour pouvoir piloter un ensemble d'événements qui seront sélectionnés au préalable à partir d'une recherche sur Suivefluid.
|
||||||
|
- Pouvoir retirer certains événements de la vue pilotage.
|
||||||
|
- Des modifications sur le visuel de l'écran.
|
||||||
|
|
||||||
|
À la suite de ces demandes, un second prototype (@annexe-prototype-v2-pilotageprojet) a été présenté aux utilisateurs. Cette présentation ayant été concluante, il a été convenu que le développement de la solution pourra être continué sans nécessité d'une nouvelle réunion avec les utilisateurs. Les utilisateurs ont également pu communiquer la liste des champs à afficher sur les cartes des événements et la liste des différentes actions de modification à ajouter. En effet, les différents champs visibles sur le prototype étaient jusqu'alors fictifs et non représentatifs des besoins des chefs de projet.
|
||||||
|
|
||||||
|
#appendix[
|
||||||
|
= Second prototype de "Pilotage projet" <annexe-prototype-v2-pilotageprojet>
|
||||||
|
#figure(
|
||||||
|
caption: [Second prototype de "Pilotage projet".],
|
||||||
|
image("images/contenu/prototype_v2_pilotageprojet.png")
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
== Planification du travail sur Suivefluid
|
||||||
|
La prochaine étape a été de planifier l'ensemble des actions nécessaires à la réalisation du sujet, sous la forme d'un événement saisi dans Suivefluid. Cet événement a ensuite pu être découpé en plusieurs sous-événements, qui représentent les différentes tâches de conception de la fonctionnalité.
|
||||||
|
|
||||||
|
La planification peut être résumée en 4 grandes étapes :
|
||||||
|
+ Intégrer le #ref-glossary(term: "Service web")[service web] de récupération des événements Suivefluid sur l'écran.
|
||||||
|
+ Mettre en place l'export des événements vers "Pilotage projet" à partir de Suivefluid "historique".
|
||||||
|
+ Rajouter un #ref-glossary(term: "Service web")[service web] sur Suivefluid permettant d'appliquer des modifications à un ensemble d'événements.
|
||||||
|
+ Mettre en place les différentes actions de modification sur l'écran.
|
||||||
|
|
||||||
|
La planification des différentes étapes nécessaires à la réalisation du sujet apporte plusieurs avantages :
|
||||||
|
- Cela permet de ne rien oublier lors du développement de la fonctionnalité.
|
||||||
|
- Cela permet d'évaluer le temps nécessaire à la réalisation complète de la fonctionnalité, en estimant le temps qui sera passé sur chaque découpage de l'événement.
|
||||||
|
- Enfin, les différents événements créés pour chaque étape pourront être consultés dans le futur pour avoir davantage d'informations sur l'idée de conception initiale de l'étape.
|
||||||
|
|
||||||
|
Durant tout le long de la conception de la solution, j'ai été amené à mettre à jour la planification pour y inclure de nouvelles demandes formulées mais également pour prendre en compte les remarques émises par les utilisateurs finaux.
|
||||||
|
|
||||||
|
== Intégration du #ref-glossary(term: "Service web")[service web] de récupération des événements Suivefluid
|
||||||
|
L'écran "Pilotage projet" a pour objectif d'afficher des événements demandés au préalable par les chefs de projet.\
|
||||||
|
Pour pouvoir afficher les événements, l'écran devra faire une requête au serveur pour récupérer les données des événements à afficher. Pour pouvoir identifier les différentes requêtes et répondre précisément à chaque demande, le serveur se base sur des "services web", qui peuvent être vus comme des intermédiaires entre la demande de l'écran et la réponse du serveur. Il existe des services web pour chaque requête.\
|
||||||
|
Dans notre cas, "Pilotage projet" devra effectuer une requête vers un #ref-glossary(term: "Service web")[service web] conçu spécifiquement pour récupérer les données des événements persistées dans une base de données "Oracle".
|
||||||
|
|
||||||
|
=== Identification des événements à afficher <identifiants-evenements>
|
||||||
|
Comme évoqué dans le @prototypage-solution, les chefs de projet veulent pouvoir afficher simultanément un ensemble d'événements qu'ils auront choisis à l'avance sur la page de recherche d'événements Suivefluid. Ainsi, l'écran devra fournir un ensemble "d'identifiants d'événements" dans la requête au #ref-glossary(term: "Service web")[service web], pour ne récupérer que les données des événements à afficher.\
|
||||||
|
|
||||||
|
Pour simplifier le passage des identifiants des événements sélectionnés par les utilisateurs sur la page de recherche des événements vers le nouvel écran, il a été décidé de passer par des paramètres "query" dans l'#ref-glossary(term: "URL", acr("URL")) de pilotage projet. Les paramètres "query" correspondent à la partie qui suit le "`?`" dans le lien ci-dessous, en exemple :\
|
||||||
|
`https://suivefluid.lan/#pilotageprojet?evts=0,1,2,3,4,5,6`\
|
||||||
|
Passer par l'#ref-glossary(term: "URL", acr("URL")) apportera aux chefs de projet l'avantage de pouvoir partager facilement une "préconfiguration" de pilotage avec un ensemble de données en partageant simplement l'#ref-glossary(term: "URL", acr("URL")) de la page.
|
||||||
|
|
||||||
|
=== Mise en place du #ref-glossary(term: "Service web")[service web]
|
||||||
|
Pour simplifier le développement de la solution, j'avais tout d'abord décidé d'utiliser un #ref-glossary(term: "Service web")[service web] déjà mis en place dans l'application et qui permettait de récupérer un ensemble d'événements à partir de leur identifiant.
|
||||||
|
|
||||||
|
Ce #ref-glossary(term: "Service web")[service web] étant utilisé par de nombreuses fonctionnalités et ne disposant pas de la totalité des données nécessaires pour "Pilotage projet", j'ai dû y apporter quelques modifications afin de pouvoir récupérer les données dont j'avais besoin.
|
||||||
|
|
||||||
|
Cependant, j'ai rapidement remarqué plusieurs problèmes non-négligeables suite à l'utilisation de ce service :
|
||||||
|
- Tout d'abord, le service renvoie une très grande quantité d'informations dont je n'ai pas besoin. C'est problématique car la quantité d'événements qui sera pilotée par les utilisateurs multipliée par la taille des données retournées par événement consommera inutilement une grande quantité de ressources et dégradera fortement les performances de fonctionnement. Un exemple de quantité considérable de données #ref-glossary(term: "JSON", acr("JSON")) renvoyées par le service pour un seul événement peut être consulté dans l'@annexe-donnees-json-evenement.
|
||||||
|
#appendix[
|
||||||
|
#pagebreak(weak: true)
|
||||||
|
= Exemple de données retournées par le #ref-glossary(term: "Service web")[service web] pour un seul événement <annexe-donnees-json-evenement>
|
||||||
|
#figure(
|
||||||
|
caption: [Exemple de données #ref-glossary(term: "JSON", acr("JSON")) renvoyées pour un seul événement (hauteur de l'image volontairement raccourcie au premier quart de sa taille réelle).],
|
||||||
|
image("images/contenu/exemple_json_evenement.png", width: 35%, height: 82%)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
- De plus, certaines données étaient imbriquées les unes dans les autres de manière redondante, ce qui engendrait une dépendance circulaire. Une dépendance circulaire se produit quand deux données se renvoient mutuellement l’une à l’autre sans fin. Dans mon cas, il était alors impossible de récupérer correctement les données des différents événements à afficher.\
|
||||||
|
Une solution possible pour régler le problème de dépendance circulaire aurait été d'enlever les données qui imbriquaient mes objets. Cependant, cela aurait pu occasionner un fort risque de régression pour les autres fonctionnalités utilisant ce service.
|
||||||
|
|
||||||
|
Face à ces 2 problèmes, j'ai finalement choisi de créer un nouveau #ref-glossary(term: "Service web")[service web] adapté à "Pilotage projet". Cette solution réduit considérablement la quantité de données en ne renvoyant que celles utilisées dans "Pilotage projet" et empêche les dépendances circulaires car les données renvoyées sont bien plus simples et ne se réfèrent plus entre-elles.
|
||||||
|
|
||||||
|
Pour créer ce nouveau service, j’ai tout de même pu réutiliser des parties du code de l'autre #ref-glossary(term: "Service web")[service web]. Elles m'ont permis de récupérer les événements dans la base de données. Le développement de mon nouveau service s'est surtout axé sur la mise en place d'une "représentation allégée" de les événements pour transmettre uniquement les données dont j'ai besoin dans "Pilotage projet", et la mise en place d'un nouveau "Mapper" qui permettra d'appliquer cette nouvelle représentation aux événements récupérés en base de données.\
|
||||||
|
Un diagramme illustrant le fonctionnement de ce nouveau service peut être consulté dans l'@annexe-diagramme-get-pilotageprojet.
|
||||||
|
|
||||||
|
#appendix[
|
||||||
|
= Diagramme du fonctionnement du #ref-glossary(term: "Service web")[service web] de récupération des événements pour "Pilotage projet". <annexe-diagramme-get-pilotageprojet>
|
||||||
|
#figure(
|
||||||
|
caption: [Diagramme de séquence simplifié du fonctionnement du #ref-glossary(term: "Service web")[service web] de récupération des événements pour "Pilotage projet".],
|
||||||
|
image("images/contenu/diagramme_get_pilotageprojet.svg")
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
Pour terminer, j'ai connecté mon nouveau #ref-glossary(term: "Service web")[service web] à l'écran "Pilotage projet". Désormais, dès qu'un utilisateur arrive sur la page, l'écran récupère les identifiants des événements passés en paramètres "query" comme expliqué dans le @identifiants-evenements et déclenche une requête avec les identifiants vers le #ref-glossary(term: "Service web")[service web]. Dans le cas où tous les événements existent, ils sont directement affichés. Sinon, une erreur est affichée invitant l'utilisateur à corriger sa demande.
|
||||||
|
|
||||||
|
== Export des événements à partir de Suivefluid "historique"
|
||||||
|
Les utilisateurs souhaitaient pouvoir exporter facilement des événements sur l'écran "Pilotage projet" à partir de Suivefluid "historique". Leur demande était motivée par 2 fonctionnalités présentes sur Suivefluid "historique" :
|
||||||
|
- La page de recherche des événements de Suivefluid "historique" permet, grâce à grande quantité de filtres, de trouver facilement les événements recherchés (voir @annexe-recherche-evenements). Il serait donc pratique de pouvoir facilement exporter sur "Pilotage projet" les événements déjà filtrés par Suivefluid "historique".
|
||||||
|
- Il en est de même concernant les résultats des requêtes "Requêteur", des requêtes de recherche d'événements déjà configurées et directement exécutées (voir @annexe-resultat-requeteur). Comme pour la page de recherche des événements, les chefs de projets pourraient utiliser les événements issus des résultats de requêtes "Requêteur" dans "Pilotage projet".
|
||||||
|
|
||||||
|
#appendix[
|
||||||
|
#pagebreak(weak: true)
|
||||||
|
= Page de recherche des événements avec résultats. <annexe-recherche-evenements>
|
||||||
|
#figure(
|
||||||
|
caption: "Page de recherche des événements avec résultats.",
|
||||||
|
image("images/contenu/recherche-evenements.png")
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
#appendix[
|
||||||
|
#pagebreak(weak: true)
|
||||||
|
= Résultat d'une requête "Requêteur" événements. <annexe-resultat-requeteur>
|
||||||
|
#figure(
|
||||||
|
caption: [Résultat de recherche d'une requête "Requêteur" événements.],
|
||||||
|
image("images/contenu/resultat-requeteur.png")
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
Pour rendre l'export simple d'utilisation, j'ai créé une #acr("JSP"), équivalent d'un composant web, dédié à l'export des événements et qui peut être intégré sur n'importe quelle autre page #acr("JSP").\
|
||||||
|
Cette #acr("JSP") ajoute un bouton avec le texte "exporter vers pilotage projet" et a été placé dans les 2 pages des fonctionnalités évoqués précédemment (voir @annexe-bouton-export-pilotageprojet).\
|
||||||
|
Lorsque l'utilisateur clique sur le bouton, une nouvelle fenêtre "Pilotage projet" s'ouvre avec les événements affichés.
|
||||||
|
|
||||||
|
#appendix[
|
||||||
|
#pagebreak(weak: false)
|
||||||
|
= Bouton d'export pilotage projet <annexe-bouton-export-pilotageprojet>
|
||||||
|
#figure(
|
||||||
|
caption: [Bouton "exporter vers pilotage projet" en bas de page de la recherche d'événements.],
|
||||||
|
image("images/contenu/recherche-evenements-pilotageprojet.png")
|
||||||
|
)
|
||||||
|
#figure(
|
||||||
|
caption: [Bouton "exporter vers pilotage projet" en bas de page du résultat d'une requête "Requêteur".],
|
||||||
|
image("images/contenu/resultat-requeteur-pilotageprojet.png")
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
== Migration des "cartes" en "tableau"
|
||||||
|
Pour permettre une visualisation plus facile des événements avec leurs données associées, nous avions décidé de faire apparaître les événements sous forme de cartes dans "Pilotage projet". Approuvée par les utilisateurs, la proposition avait été intégrée dès la première maquette présentée en @figure-prototype-v1-pilotageprojet.
|
||||||
|
|
||||||
|
Cependant, lors de la conception de la solution, une réunion entre les utilisateurs et l'équipe Suivefluid a eu lieu pour modifier l’agencement de l'écran "Pilotage projet". L'affichage en "cartes" n'était plus jugé judicieux; nous avions décidé d'utiliser les cartes car elles existaient déjà dans une autre partie de l'application, et elles semblaient bien adaptées pour notre cas. Cependant, à mesure que le développement avançait, nous nous sommes rendus compte qu'il était difficile d'afficher une quantité bien plus conséquente de cartes sur l'écran que celle utilisée dans nos tests.
|
||||||
|
|
||||||
|
Pour éviter ces désagréments, il a été suggéré de passer d'une présentation des événements sous forme de "cartes" en une présentation sous forme d'un tableau. Cette solution apporte de nombreux avantages :
|
||||||
|
- Possibilité de consulter une très grande quantité d'événements simultanément, sans être contraint de faire défiler la liste d'événements.
|
||||||
|
- Possibilité d'utiliser un composant "Tableau" fourni par le framework FullJS, qui apportera un grand nombre de fonctionnalités.
|
||||||
|
- Le composant "Tableau" permet de choisir les colonnes à afficher ou à masquer. Ainsi, on pourra enrichir les événements avec davantage de données de consultation (masquées par défaut), que les utilisateurs pourront afficher selon leurs besoins en cochant/décochant la colonne correspondante. Avec les "cartes", il aurait fallu limiter les données affichées pour optimiser l’espace.
|
||||||
|
|
||||||
|
Suite à la réunion, le changement d'affichage des événements a été approuvé et la suggestion a été retenue.\
|
||||||
|
Il m'a donc fallu migrer les "cartes" en "tableau", et j'ai dû adapter certaines parties du composant "Tableau" pour pouvoir répondre à des besoins qui n'étaient pas couverts par le composant du framework "FullJS". Le résultat de la migration est illustré par la @figure-tableau-pilotage-projet.
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
caption: [Interface "Pilotage projet" avec la nouvelle disposition par "tableau"],
|
||||||
|
image("images/contenu/tableau-pilotage-projet.png")
|
||||||
|
) <figure-tableau-pilotage-projet>
|
||||||
|
|
||||||
|
== #ref-glossary(term: "Service web")[Service web] de modification des événements
|
||||||
|
La prochaine étape a été de mettre en place un #ref-glossary(term: "Service web")[service web] de type "PATCH" pour la modification des événements. Afin de respecter l'échéance de mise en production de la fonctionnalité, c'est mon collègue M. Jordan REPOVY qui a développé ce service pour me permettre de me consacrer aux autres tâches.
|
||||||
|
|
||||||
|
Pour pouvoir appliquer des modifications à un ensemble d'événements, ce #ref-glossary(term: "Service web")[service web] doit recevoir les identifiants des événements avec les modifications associées en corps de requête. Ainsi, dans l'exemple ci-dessous, les modifications à appliquer sont le changement de statut en "livré" et l'ajout d'un commentaire, et elles s'appliquent aux événements portant les identifiants "000111", "000112" et "000113" :
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
000111: {
|
||||||
|
commentaire: {
|
||||||
|
texte: "Ceci est un commentaire",
|
||||||
|
visibleClient: true,
|
||||||
|
},
|
||||||
|
statut: "LIVRE"
|
||||||
|
},
|
||||||
|
000112: {
|
||||||
|
commentaire: {
|
||||||
|
texte: "Ceci est un commentaire",
|
||||||
|
visibleClient: true,
|
||||||
|
},
|
||||||
|
statut: "LIVRE"
|
||||||
|
},
|
||||||
|
000113: {
|
||||||
|
commentaire: {
|
||||||
|
texte: "Ceci est un commentaire",
|
||||||
|
visibleClient: true,
|
||||||
|
},
|
||||||
|
statut: "LIVRE"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
L'avantage de renseigner les modifications par événement est qu'il est possible d'appliquer une modification différente pour un événement précis, sans impacter les autres.
|
||||||
|
|
||||||
|
== Création des actions de modification
|
||||||
|
L'étape suivante a été de créer les "actions de modification".\
|
||||||
|
Pour le projet, j'ai appelé "action de modification" une modification qui peut s'appliquer sur un ou plusieurs événements.
|
||||||
|
|
||||||
|
Lors de la dernière réunion, les utilisateurs avaient demandé la possibilité de pouvoir appliquer les actions de modification suivantes sur les autres données des événements :
|
||||||
|
- Modifier le type de livrable
|
||||||
|
- Modifier le statut
|
||||||
|
- Modifier l'analyste
|
||||||
|
- Modifier le développeur
|
||||||
|
- Modifier le recetteur
|
||||||
|
- Modifier le mode de financement (en rapport avec les budgets clients)
|
||||||
|
|
||||||
|
Les utilisateurs souhaitaient également que le processus pour appliquer une action de modification soit le suivant :
|
||||||
|
+ Premièrement, l'utilisateur sélectionne les événements sur lesquels il souhaite appliquer l'action de modification.
|
||||||
|
+ Ensuite, l'utilisateur sélectionne l'action de modification qu'il souhaite appliquer.
|
||||||
|
+ Un formulaire doit alors s'ouvrir, dans lequel l'utilisateur saisira les données de l'action à appliquer.
|
||||||
|
+ L'utilisateur validera alors l'action par un bouton "enregistrer" ou l'annulera avec un bouton "annuler".
|
||||||
|
|
||||||
|
=== Première action de modification
|
||||||
|
La première action de modification que j'ai décidé de développer a été l'action d'ajout de commentaire.\
|
||||||
|
Pour la réaliser, j'ai développé un nouveau composant qui s'ouvre sous la forme d'une fenêtre "#ref-glossary(term: "Pop-up")[pop-up]" (@figure-actionmodification-ajoutcommentaire).
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
caption: [Composant #ref-glossary(term: "Pop-up")[pop-up] de l'action d'ajout de commentaire.],
|
||||||
|
image("images/contenu/actionmodification_ajoutcommentaire.png")
|
||||||
|
) <figure-actionmodification-ajoutcommentaire>
|
||||||
|
|
||||||
|
Le composant s'ouvre dès que des événements sont sélectionnés. L'utilisateur peut ensuite valider ou annuler l'action :
|
||||||
|
- Dans le cas où l'utilisateur valide l'action avec le bouton "enregistrer", le composant appelle le #ref-glossary(term: "Service web")[service web] de modification des événements. Deux cas peuvent se produire :
|
||||||
|
- Si tous les événements sont modifiés avec succès, le composant crée une copie des événements modifiés et leur applique la modification. Les événements sont ensuites transmis à la page "Pilotage projet", qui remplace chaque événement modifié pour les actualiser dans le tableau et affiche un message de succès de la modification à l'utilisateur.
|
||||||
|
- Si par-contre une erreur se produit, un message d'erreur est affiché à l'utilisateur l'invitant à modifier sa demande.
|
||||||
|
- Dans le cas où l'utilisateur annule la modification, le composant #ref-glossary(term: "Pop-up")[pop-up] se ferme sans modification des événements.
|
||||||
|
|
||||||
|
=== Mise en commun du code des actions de modification
|
||||||
|
Pour créer les autres actions de modification, j'ai déterminé le comportement commun à toutes les actions de modification. L'objectif était de mutualiser le code des actions pour les maintenir plus facilement et éviter la répétition de code (principe #acr("DRY")). De plus, l'entreprise impose une couverture de tests du code à 100%, ce qui signifie qu'il aurait fallu répéter une même vérification de bon comportement pour chaque action.
|
||||||
|
|
||||||
|
Le comportement commun peut être découpé en 2 parties :
|
||||||
|
+ Le comportement commun des composants d'action de modification.
|
||||||
|
+ Le comportement commun du fonctionnement des actions de modification.
|
||||||
|
|
||||||
|
J'ai tout d'abord identifié le comportement commun des composants :
|
||||||
|
- Chaque composant aura un bouton "valider" et "annuler".
|
||||||
|
- Lorsque le bouton "valider" est cliqué, le composant renverra les événements modifiés à la page "Pilotage projet".
|
||||||
|
- Dans le cas où le bouton "annuler" est cliqué, le composant se fermera.
|
||||||
|
- Lorsqu'un champ n'est pas correctement renseigné, un message d'erreur avec le nom du champ doit s'afficher.
|
||||||
|
|
||||||
|
Ensuite, j'ai dû identifier le comportement commun du fonctionnement de chaque "action de modification" :
|
||||||
|
- Chaque action doit créer une "représentation des modifications" qui contiendra les différentes informations saisies par l'utilisateur dans le formulaire.
|
||||||
|
- Chaque action doit ensuite appeler le #ref-glossary(term: "Service web")[service web] de modification des événements et lui transmettre les événements à modifier avec la "représentation des modifications".
|
||||||
|
- Dans le cas où les modifications ont été appliquées, un message de succès avec le nombre d'événements modifiés sera affiché à l'utilisateur.
|
||||||
|
- Si la modification doit être appliquée aux événements dans le tableau (par exemple une information affichée aux utilisateurs), l'action devra appliquer la modification aux événements, qui seront ensuite transmis à la page "Pilotage projet".
|
||||||
|
|
||||||
|
Afin de mutualiser le comportement des composants, j’ai créé un autre composant qui fera office de base pour chaque "action de modification". Ce composant gère le comportement partagé des composants des "actions de modification", comme l’affichage et le comportement commun des boutons "valider" et "annuler".
|
||||||
|
|
||||||
|
Pour la logique de fonctionnement commune des "actions de modification", j’ai créé une classe JavaScript hautement flexible pour mutualiser la base du code de fonctionnement. Cette classe permettra de définir un comportement commun à toutes les "actions de modification" qui l'utiliseront, tout en leur donnant la possibilité de redéfinir au besoin chaque comportement. Cette mutualisation permettra de maintenir une seule base de code commune aux "actions de modification". La @figure-diagramme-actionmodification illustre cette nouvelle "classe" créée avec un exemple d'implémentation pour 2 "actions de modifications".
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
caption: [Diagramme de la classe "ActionModifications" avec 2 exemples d'implémentation.],
|
||||||
|
image("images/contenu/diagramme_classe_actionmodification.svg")
|
||||||
|
) <figure-diagramme-actionmodification>
|
||||||
|
|
||||||
|
Le composant commun et la classe commune de fonctionnement des "actions de modification" fonctionnent ensemble, tout en étant pilotés par une même base de code. Cela signifie que s'il est nécessaire d'apporter une modification du code d'un fonctionnement commun pour toutes les "actions de modification", le changement pourra être fait dans une même base de code commune plutôt que devoir être appliqué individuellement dans le code de chaque "action de modification".
|
||||||
|
|
||||||
|
J'ai par la suite développé l'ensemble des actions de modification demandées initialement par les utilisateurs, mais également les nouvelles modifications émises dans leurs retours.\
|
||||||
|
Désormais, les utilisateurs peuvent appliquer facilement une "action de modification" en la choisissant à partir d'un menu déroulant sur le tableau (@annexe-liste-actions-modifications).
|
||||||
|
|
||||||
|
#appendix[
|
||||||
|
= Actions de modification disponibles <annexe-liste-actions-modifications>
|
||||||
|
#figure(
|
||||||
|
caption: "Actions de modification disponibles à ce jour dans le menu déroulant de modification.",
|
||||||
|
image("images/contenu/liste-actions-modifications.png")
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
Une fois cette étape achevée, la fonctionnalité a été déployée en phase de "recette" pour pouvoir être testée. Les utilisateurs ont été invités à tester en conditions réelles la fonctionnalité pendant plusieurs semaines, afin de leur laisser la possibilité d'émettre quelques dernières demandes avant que la fonctionnalité ne soit mise en production.
|
||||||
|
|
||||||
|
== Modifications unitaires
|
||||||
|
Suite à la phase de tests, les utilisateurs nous ont demandé d'avoir la possibilité de modifier unitairement des données des événements directement dans le tableau. En effet, la fonctionnalité "Pilotage projet" permet d'afficher plusieurs événements dans un même tableau et donc d'avoir une "vue d'ensemble" sur plusieurs événements à modifier, plutôt que de les modifier unitairement sur Suivefluid "historique".\
|
||||||
|
Il a été demandé que les champs suivants soient modifiables unitairement :
|
||||||
|
- Statut
|
||||||
|
- Version
|
||||||
|
- Budgets clients
|
||||||
|
|
||||||
|
=== Mode d'affichage
|
||||||
|
Pour ne pas impacter la consultation des événements lorsqu'on ne veut pas les modifier, il a été décidé que "Pilotage projet" devrait pouvoir être affiché en 2 modes distincts :
|
||||||
|
+ En *mode consultation*, les champs des événements ne seront pas modifiables et il sera possible de sélectionner des événements pour les retirer du pilotage et leur appliquer une action de modification.
|
||||||
|
+ En *mode modification*, les champs des événements pourront être modifiables et il ne sera pas possible de sélectionner des événements. Les actions à appliquer sur les événements ne seront pas affichées, car elles ne sont pas compatibles avec un fonctionnement "unitaire".
|
||||||
|
|
||||||
|
Pour cela, j'ai commencé par rajouter un bouton "modifier", qui permettra à l'utilisateur de passer en *mode modification*. En effet, l'utilisateur sera par défaut en *mode consultation*.
|
||||||
|
J'ai ensuite rajouté les boutons "enregistrer" et "annuler", qui sont affichés à la place du bouton "modifier" lorsque le *mode modification* est actif. Le mode de modification est conditionné dans la page par un attribut dit "booléen" (vrai ou faux). Si la valeur de l'attribut est "vrai", le mode actif est "modification", sinon le mode actif est "consultation".
|
||||||
|
|
||||||
|
J'ai ensuite dû adapter l'affichage de "Pilotage projet" pour qu'il diffère entre le *mode modification* et le *mode consultation*. Pour cette fonctionnalité, j'ai pu utiliser directement l'outillage fourni par le framework "FullJS". En effet, le framework fournit un moyen très facile d'activer la modification dans les tableaux, de désactiver la sélection des événements, d'activer certaines actions tableau (comme par exemple les actions de modification ou même l'action "retirer du pilotage"). Ces fonctionnalités sont également conditionnées par l'attribut du *mode modification* évoqué dans le paragraphe précédent.
|
||||||
|
|
||||||
|
Comme pour les actions de modifications en masse, j'ai pu utiliser la classe commune de fonctionnement des "actions de modification", qui était suffisamment flexible pour pouvoir implémenter la récupération, l'envoi et l'actualisation des données des événements modifiées unitairement dans le tableau.
|
||||||
|
|
||||||
|
La @figure-pilotage-projet-consultation illustre "Pilotage projet" en *mode consultation*, et la @figure-pilotage-projet-modification l'illustre en *mode modification*.
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
caption: ["Pilotage projet" en *mode consultation*.],
|
||||||
|
image("images/contenu/pilotage-projet-consultation.png")
|
||||||
|
) <figure-pilotage-projet-consultation>
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
caption: ["Pilotage projet" en *mode modification*.],
|
||||||
|
image("images/contenu/pilotage-projet-modification.png")
|
||||||
|
) <figure-pilotage-projet-modification>
|
||||||
|
|
||||||
|
=== Champ déroulant "intelligent"
|
||||||
|
Lors du développement des modifications unitaires, je me suis rendu compte que le composant de champ déroulant fourni par le framework "FullJS" se contente d'afficher un ensemble d'éléments et ne permet pas de récupérer des éléments "paresseusement" (ou suggérés automatiquement en fonction de la recherche utilisateur). Dans le cas du champ des versions (@figure-pilotage-projet-modification), Suivefluid renvoi plusieurs milliers de versions qui rend techniquement impossible l'affichage d'une telle quantité d'éléments dans un même composant.
|
||||||
|
|
||||||
|
Pour contourner ce problème, j'ai dû développer un nouveau composant intelligent qui fonctionne comme "surcouche" du composant de champ déroulant fourni par le framework "FullJS".
|
||||||
|
|
||||||
|
Le fonctionnement de ce nouveau composant est le suivant :
|
||||||
|
+ Lorsque l'utilisateur clique sur le champ, un ensemble de 15 éléments est suggéré par défaut à l'utilisateur.
|
||||||
|
+ Lorsque l'utilisateur saisit un caractère, le composant patiente *150 millisecondes* sans saisie de l'utilisateur avant d'envoyer une requête à Suivefluid pour récupérer les éléments en fonction de la saisie. Cette moyenne de temps d'attente permet d'éviter de surcharger Suivefluid de requêtes si l'utilisateur n'a pas terminé d'écrire.
|
||||||
|
+ Lors de chaque saisie par l'utilisateur, un maximum de 15 éléments sont récupérés et affichés par le composant. Si moins de 15 éléments sont renvoyés par Suivefluid, le résultat est mis en "cache" (en mémoire) et les éléments sont directement filtrés par le composant pour éviter d'éventuelles requêtes inutiles vers Suivefluid.
|
||||||
|
|
||||||
|
J'ai rendu ce composant le plus flexible possible sur des champs autres que celui des "versions". Au vu de son efficacité, il a d'ailleurs été intégré par la suite sur d'autres pages de Suivefluid dans le but d'améliorer leurs performances.
|
||||||
|
|
||||||
|
Cette étape terminée, "Pilotage projet" a pu entrer dans sa dernière phase de tests.
|
249
olds/n-hbist-back/template.typ
Normal file
249
olds/n-hbist-back/template.typ
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
#import "@preview/acrostiche:0.2.0": *
|
||||||
|
|
||||||
|
#let appendixes = state("appendixes", ())
|
||||||
|
#let section = state("section", none)
|
||||||
|
#let glossary-terms = state("glossary", ( : ))
|
||||||
|
|
||||||
|
#let rapport(
|
||||||
|
title: "",
|
||||||
|
author: "Hibst Nathan",
|
||||||
|
color: red,
|
||||||
|
company: (),
|
||||||
|
degree: "",
|
||||||
|
promotion: (),
|
||||||
|
acronyms: (),
|
||||||
|
glossary: ( : ),
|
||||||
|
hayagriva-bibliography: none,
|
||||||
|
thanks: lorem(150),
|
||||||
|
introduction: lorem(350),
|
||||||
|
conclusion: lorem(350),
|
||||||
|
abstract: lorem(100),
|
||||||
|
keywords: ("Min 7", "Max 15"),
|
||||||
|
body,
|
||||||
|
) = {
|
||||||
|
// Global settings.
|
||||||
|
set document(author: author, title: title)
|
||||||
|
set page(
|
||||||
|
background: [
|
||||||
|
#place(top, rect(fill: color, width: 100%, height: 5mm))
|
||||||
|
#place(bottom, rect(fill: color, width: 100%, height: 10mm))
|
||||||
|
]
|
||||||
|
)
|
||||||
|
set text(hyphenate: false, lang: "fr", weight: "regular")
|
||||||
|
|
||||||
|
set heading(outlined: false)
|
||||||
|
show heading: h => {
|
||||||
|
set text(color, font: "Montserrat", weight: "medium", style: "italic")
|
||||||
|
set text(21pt) if h.level == 1
|
||||||
|
set text(17pt) if (h.level == 2)
|
||||||
|
set pad(left: 1cm) if h.level > 1
|
||||||
|
set pad(bottom: 5mm)
|
||||||
|
set pad(bottom: 3mm) if h.level == 3
|
||||||
|
pad(h)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Title page.
|
||||||
|
{
|
||||||
|
set page(margin: (left: 15mm, right: 15mm, top: 15mm, bottom: 25mm))
|
||||||
|
set text(15pt, font: "Montserrat")
|
||||||
|
block(
|
||||||
|
height: 75pt,
|
||||||
|
grid(
|
||||||
|
columns: 3,
|
||||||
|
column-gutter: 45pt,
|
||||||
|
rows: auto,
|
||||||
|
align(horizon, image("assets/images/logo-uha.png")),
|
||||||
|
align(horizon, image("assets/images/logo-uha40.png")),
|
||||||
|
align(horizon, image("assets/images/logo-serfa.jpg"))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
v(3fr)
|
||||||
|
|
||||||
|
[
|
||||||
|
#text(30pt, color)[Mémoire de fin d'études] \
|
||||||
|
|
||||||
|
#text(40pt, weight: "bold", smallcaps(title))
|
||||||
|
]
|
||||||
|
|
||||||
|
v(3fr)
|
||||||
|
|
||||||
|
[
|
||||||
|
#text(18pt, weight: "bold", author) \
|
||||||
|
\
|
||||||
|
#degree \
|
||||||
|
#promotion.title - Promotion #promotion.year / #(promotion.year + 1) \
|
||||||
|
\
|
||||||
|
#text(black)[Alternance réalisée chez] #upper[*#company.name*]
|
||||||
|
]
|
||||||
|
|
||||||
|
v(2fr)
|
||||||
|
|
||||||
|
let stageActor(designation: "", tutor) = block[
|
||||||
|
#text(rgb(111, 111, 111), designation) \
|
||||||
|
#tutor
|
||||||
|
]
|
||||||
|
|
||||||
|
grid(
|
||||||
|
columns: 2,
|
||||||
|
[
|
||||||
|
#stageActor(designation: "Tuteur professionnel", company.tutor)
|
||||||
|
#stageActor(designation: "Tuteur pédagogique")[M. Mounir ELBAZ]
|
||||||
|
],
|
||||||
|
align(horizon + right, image(company.logo, width: 65%))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
pagebreak()
|
||||||
|
|
||||||
|
// Used to get custom page header.
|
||||||
|
let pageheader(content: "") = {
|
||||||
|
set text(10pt)
|
||||||
|
grid(
|
||||||
|
columns: 2,
|
||||||
|
gutter: 1fr,
|
||||||
|
title,
|
||||||
|
content
|
||||||
|
)
|
||||||
|
v(3mm)
|
||||||
|
place(bottom, rect(fill: color, width: 100%, height: 0.05mm))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Document-body settings.
|
||||||
|
show par: set block(spacing: 1.45em)
|
||||||
|
set page(
|
||||||
|
header: pageheader(),
|
||||||
|
footer: author,
|
||||||
|
margin: (left: 30mm, right: 30mm, top: 30mm, bottom: 30mm)
|
||||||
|
)
|
||||||
|
set text(font: "Times New Roman", size: 12pt)
|
||||||
|
set par(justify: true)
|
||||||
|
init-acronyms(acronyms)
|
||||||
|
counter(page).update(1)
|
||||||
|
|
||||||
|
// Defining, how marked glossary entries in the document appear
|
||||||
|
show figure.where(kind: "jkrb_glossary"): it => [#link(<Glossaire>)[#it.body]]
|
||||||
|
|
||||||
|
// Thanks page.
|
||||||
|
[
|
||||||
|
= Remerciements
|
||||||
|
#thanks
|
||||||
|
]
|
||||||
|
pagebreak()
|
||||||
|
|
||||||
|
|
||||||
|
// Summary.
|
||||||
|
outline(title: "Sommaire", depth: 2, indent: auto)
|
||||||
|
pagebreak()
|
||||||
|
|
||||||
|
{
|
||||||
|
set heading(outlined: true)
|
||||||
|
set page(footer: grid(
|
||||||
|
columns: 2,
|
||||||
|
gutter: 1fr,
|
||||||
|
author,
|
||||||
|
counter(page).display()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Introduction page.
|
||||||
|
[
|
||||||
|
= Introduction
|
||||||
|
#introduction
|
||||||
|
]
|
||||||
|
pagebreak()
|
||||||
|
|
||||||
|
// Content.
|
||||||
|
{
|
||||||
|
set heading(numbering: "1.1.")
|
||||||
|
set page(header: locate(loc => {
|
||||||
|
let sectiontitle = section.at(loc)
|
||||||
|
if (sectiontitle == none) {
|
||||||
|
sectiontitle = query(
|
||||||
|
heading.where(level: 1, outlined: true).after(loc),
|
||||||
|
loc
|
||||||
|
).first().body
|
||||||
|
}
|
||||||
|
pageheader(content: sectiontitle)
|
||||||
|
}))
|
||||||
|
show pagebreak: pb => {
|
||||||
|
section.update(none)
|
||||||
|
pb
|
||||||
|
}
|
||||||
|
show heading.where(level: 1): h => {
|
||||||
|
h
|
||||||
|
section.update(h.body)
|
||||||
|
}
|
||||||
|
|
||||||
|
body
|
||||||
|
}
|
||||||
|
pagebreak()
|
||||||
|
|
||||||
|
// Conclusion.
|
||||||
|
[
|
||||||
|
= Conclusion
|
||||||
|
#conclusion
|
||||||
|
]
|
||||||
|
pagebreak()
|
||||||
|
|
||||||
|
// Glossary.
|
||||||
|
[
|
||||||
|
#set page(header: pageheader(content: "Glossaire"))
|
||||||
|
= Glossaire
|
||||||
|
#for term in glossary.keys().sorted() {
|
||||||
|
locate(loc => glossary-terms.update(it => {
|
||||||
|
it.insert(term, loc)
|
||||||
|
return it
|
||||||
|
}))
|
||||||
|
[ - *#term* : #glossary.at(term) \ ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
pagebreak()
|
||||||
|
|
||||||
|
// Acronyms page.
|
||||||
|
[
|
||||||
|
= Liste des abréviations
|
||||||
|
#acros.display(acronyms => {
|
||||||
|
for acr in acronyms.keys().sorted() [
|
||||||
|
- *#acr* : #acronyms.at(acr) \
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
pagebreak()
|
||||||
|
|
||||||
|
// Bibliography.
|
||||||
|
bibliography(hayagriva-bibliography, title: "Bibliographie et webographie", style: "chicago-notes")
|
||||||
|
pagebreak()
|
||||||
|
|
||||||
|
// Table of contents.
|
||||||
|
outline(indent: auto)
|
||||||
|
pagebreak()
|
||||||
|
|
||||||
|
// Appendixes page.
|
||||||
|
[
|
||||||
|
#set page(header: pageheader(content: "Annexes"))
|
||||||
|
= Annexes
|
||||||
|
#counter(heading).update(0)
|
||||||
|
#set heading(numbering: "I.", outlined: false, supplement: "Annexe")
|
||||||
|
#locate(loc => {
|
||||||
|
for body in appendixes.final(loc) {
|
||||||
|
body
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last page.
|
||||||
|
[
|
||||||
|
= Résumé
|
||||||
|
#abstract
|
||||||
|
|
||||||
|
= Mots-clés
|
||||||
|
#for word in keywords.sorted() [
|
||||||
|
- #word
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#let appendix(body) = appendixes.update(it => it + (body,))
|
||||||
|
|
||||||
|
#let ref-glossary(term: "", body) = locate(loc => link(glossary-terms.final(loc).at(term), body))
|
@ -52,9 +52,9 @@
|
|||||||
columns: 3,
|
columns: 3,
|
||||||
column-gutter: 45pt,
|
column-gutter: 45pt,
|
||||||
rows: auto,
|
rows: auto,
|
||||||
align(horizon, image("images/premiere-page/logo-uha.png")),
|
align(horizon, image("./assets/images/logo-uha.png")),
|
||||||
align(horizon, image("images/premiere-page/logo-uha40.png")),
|
align(horizon, image("./assets/images/logo-uha40.png")),
|
||||||
align(horizon, image("images/premiere-page/logo-serfa.jpg"))
|
align(horizon, image("./assets/images/logo-serfa.jpg"))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user