Tableau de bord RH — guide technique
Cette page décrit le tableau de bord historique manager/RH accessible par Analytique → Tableaux de bord : structure, agrégations, résolution de population, réponses partielles et dépendances de configuration. Elle s’adresse aux équipes d’implémentation et de support. Consultez le guide fonctionnel pour l’utilisation et le guide de configuration pour l’activation.
Sauf mention contraire, les affirmations sont vérifiées dans le code des dépôts locaux examinés. Les chemins sont relatifs au dépôt nommé et constituent des références techniques sans données de clients ni adresses de déploiement.
Architecture et responsabilités
| Composant | Responsabilité |
|---|---|
Company/ManagerDashboardBundle/Controller/DefaultController.php | Entrées page/onglets, état hiérarchie/session, requêtes d’éligibilité, graphiques et rendu Twig. |
Services/Helper.php | Contexte utilisateur/entreprise, fonctionnalités, repli d’accès historique, classification administrateur, libellés, échelle et palette. |
Chart/TeamProficiency.php | Calculs de maîtrise, écarts, motivation et répartition des emplois. |
Chart/SkillsMapCampaign.php | Statistiques des campagnes d’auto-déclaration/compétences. |
Controller/OneToOneController.php | Progression des entretiens dans le dernier périmètre résolu. |
Controller/PerimeterController.php | Liste des collaborateurs du dialogue de périmètre, recherchée et paginée côté serveur. |
Resources/views/Default, Tabs, Partials | Structure de page, contenu des onglets et tableaux détaillés. |
Resources/public/js/{dashboard,perimeter}.js | Chargement des onglets, filtres, initialisation, détails et téléchargements. |
La page charge jQuery/Bootstrap, Select2, DataTables et Highcharts avec ses modules d’export. Doctrine lit le modèle relationnel historique. Aucun appel à un service IA n’a été identifié dans ces agrégations.
Requêtes et rendu
indexActionrécupère leSchoolde l’utilisateur authentifié et construit les onglets activés et l’arbre organisationnel.- Twig expose les points d’entrée et le formulaire de périmètre. Le navigateur restaure si possible l’onglet depuis le fragment d’URL.
- Un changement d’onglet envoie les champs
.filtercochés par POST. jQuery fournit l’en-tête XMLHttpRequest attendu. - Le gestionnaire valide l’accès et un
level[]ourelation[]non vide, résout les identifiants de managers, conserve les marqueurs en session et calcule le périmètre. - Un périmètre vide renvoie un fragment d’état vide avec son attribut de périmètre. Sinon les agrégations activées sont exécutées.
- Le navigateur insère
html, actualiseattributes.perimeterSize, initialise graphiques et tableaux, puis permet les requêtes de détail.
Le message de requête longue apparaît après 15 secondes. Ce minuteur d’affichage ne constitue ni un délai d’expiration API ni une garantie de fraîcheur. Les requêtes d’onglet détruisent les graphiques existants avant le nouveau rendu.
Contrats HTTP
Les chemins utilisent le préfixe historique /company/dashboard-manager défini dans config/routes.yaml. Il s’agit de points d’entrée applicatifs authentifiés par session, pas d’une API publique de rapports JSON. Les exemples omettent hôtes, cookies et identifiants personnels.
| Méthode / suffixe | Gestionnaire / réponse |
|---|---|
GET / | indexAction ; page Twig complète. |
POST /team-activity | teamActivityAction ; HTML activité/complétion, graphiques et périmètre. |
POST /team-proficiency | teamProficiencyAction ; HTML/graphiques par emploi et détails pris en charge. |
POST /skill-analysis | skillAnalysisAction ; HTML/graphiques de compétences ou fragments de sélection. |
POST /skills-map-campaign | campaignAction ; panneaux de campagnes de compétences. |
POST /1to1 | oneToOneAction ; sélecteur de campagnes d’entretien éligibles. |
GET /1to1/progress/{id} | OneToOneController::progressAction ; progression d’entretien ; identifiant numérique. |
POST /perimeter | PerimeterController::indexAction ; réponse serveur DataTables à partir du périmètre en session. |
Requête illustrative, vérifiée dans le code, non rejouée sur le service :
POST /company/dashboard-manager/skill-analysis
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded
level%5B%5D=1
level[]=entire_company sélectionne l’arbre de l’entreprise ; les valeurs numériques choisissent les niveaux. relation[] contient les identifiants des relations hiérarchiques configurées lorsque l’option est activée. Les choix de l’interface et les autorisations serveur doivent être considérés séparément.
Structure habituelle d’une réponse d’onglet ; les valeurs sont explicatives, pas des données réelles :
{
"html": "<rendered tab markup>",
"highcharts": {},
"attributes": {"perimeterSize": "<rendered population label and count>"}
}
Toutes les branches ne renvoient pas toutes les clés. Un périmètre vide renvoie html et attributes ; un détail de compétence peut renvoyer html et tableId. Les branches prises en charge utilisent notamment skill, motivation, vw et jid. vw=top/flop sélectionne les classements par somme, vw=topMastered/flopMastered ceux par moyenne. Le filtre d’emploi dépend de dashboard_filter_by_job.
Le point d’entrée de périmètre consomme draw, start, length, search[value] et order[0] de DataTables. Il renvoie draw, recordsTotal, recordsFiltered et data ; les deux effectifs proviennent actuellement du même comptage. Il dépend d’un périmètre déjà établi en session et ne constitue pas une API autonome de recherche de collaborateurs.
Permissions et limites de population
indexAction accepte l’un des cinq commutateurs d’onglet ou Helper::isManagerDashboardActive(). Ce repli repose sur la permission historique, notamment le rôle manager_dashboard ou la condition de permissions vides du helper. Chaque onglet affiché exige néanmoins son commutateur. Les gestionnaires acceptent généralement leur commutateur ou le repli ; les générateurs de graphiques contrôlent aussi leurs éléments.
PerimeterController exige tous les commutateurs ou les alternatives permission/administrateur, contrairement au test « au moins un » de la page. Le détail d’entretien exige directement dashboard_team_1to1 et renvoie 404 pour un entretien inconnu. L’ouverture de la page ne prouve pas l’accès à tous les détails.
getManagerIds choisit l’arbre normal ou celui de l’entreprise. extractLevel inclut aussi le niveau 0 lorsque le niveau 1 est sélectionné. Pour les comptes subordonnés sans all_collaborators, applyVisibilityRules délègue à VisibilityFilter. Certaines requêtes réunissent les utilisateurs liés par relation et ceux de la hiérarchie.
Helper::isAdmin() est une classification de périmètre propre à ce tableau, fondée sur la hiérarchie School, la visibilité et all_managers_filter. Elle n’équivaut pas à l’administration des paramètres. Observé : Jim disposait du périmètre élargi alors que les paramètres lui étaient refusés.
FeatureSwitchVoter/BaseVoter délègue l’évaluation aux commutateurs/tokenizers de l’entreprise. FeatureSwitchService lit les valeurs persistées par Setting et accepte aussi l’accès par tokenizer. Les valeurs YAML servent à l’initialisation, sans repli automatique pour chaque valeur manquante à l’exécution.
Modèle et cycle de vie de l’état
| Données | Utilisation |
|---|---|
User, Customer, School, Setting | Identité activée, lien de profil, rattachement, contexte d’entreprise et échelle. |
Job, Jobskill | Emploi attribué et niveaux requis. |
Userskill | Maîtrise (note), motivation et origine éligible. |
| Traductions compétences/emplois | Libellés de la langue active, avec repli sur les titres sources dans les parcours examinés. |
CompanyHierarchicalRelationship | Types de relations optionnels et utilisateurs liés pour le périmètre. |
Interview, InterviewUser, états d’évaluation/signature | Éligibilité des campagnes et suivi des entretiens. |
Le tableau agrège des enregistrements existants sans cycle d’évaluation distinct. Aucun traitement d’agrégation en arrière-plan propre au tableau n’a été trouvé sur les parcours examinés. Les commandes d’installation créent le catalogue/la configuration, sans prouver un rafraîchissement planifié.
La session contient filters, perimeter (managerIds, hierarchicalUsers, total) et treeStructure. Le cache hiérarchique conserve arbre, profondeur, utilisateur et expiration time() + 600, avec des clés normale/entreprise distinctes. Le contrôleur remplace treeStructure lorsqu’il met une branche en cache ; les deux branches ne sont pas nécessairement conservées ensemble. Services/Memcache.php existe, mais ce parcours utilise explicitement la session.
Observé : le passage entre onglets conservait le périmètre d’entreprise ; quitter puis rouvrir la page rétablissait N - 1. Les marqueurs de session ne garantissent pas une préférence durable.
Calculs et éligibilité des données
Population et complétion
getPerimeterSize compte les collaborateurs activés distincts avec un Customer, rattachés aux identifiants organisationnels ou aux relations sélectionnés, en excluant l’utilisateur connecté. Il mémorise le résultat pour le dialogue de périmètre sans appliquer le filtre de connexion optionnel des compétences.
La complétion est recalculée par Profile::getActionCompletenessByUsers, pas depuis User.completeness. L’indicateur compte les profils complets à au moins 60 %, divisés par le périmètre, arrondis à une décimale. Helper construit les tranches à partir du nombre d’étapes du service de profil. Le libellé français « plus de 60 % » diffère donc du calcul à la borne.
Maîtrise et écarts à l’emploi
getJobOrUserSkills construit les correspondances emplois/compétences et collaborateurs/compétences. La requête collaborateur exige Userskill.source IS NULL ; les deux peuvent exiger logincounter > 0. Elle peut filtrer l’emploi par jid et intégrer les utilisateurs liés par relation.
TeamProficiency::jobMasteryRatio calcule, pour les compétences présentes dans les deux ensembles :
pourcentage = 100 × somme(min(niveau collaborateur, niveau requis))
/ somme(niveau requis)
Le résultat vaut zéro si la somme requise est nulle. Les compétences requises absentes de l’ensemble collaborateur ne figurent pas au dénominateur. Un résultat de 100 % sur les correspondances ne prouve donc pas la couverture complète de l’emploi. L’implémentation examinée est plus restreinte que le texte explicatif de la page.
Les écarts individuels parcourent les compétences requises et calculent niveau collaborateur − niveau requis ; une compétence absente contribue 0 − niveau requis. La moyenne est divisée par le nombre de compétences requises. Une moyenne négative indique un manque. Les agrégations par emploi ont leur propre implémentation : ne supposez pas des dénominateurs identiques pour tous les panneaux.
Analyse des compétences
getSkillMotivationAndMastery lit les comptes activés hors utilisateur connecté, les compétences de source nulle et éventuellement l’éligibilité de connexion. Il ignore un enregistrement dont maîtrise calculée et motivation sont toutes deux nulles. Il conserve séparément maîtrise brute et plafonnée à l’emploi, puis produit totaux/moyennes. Les détails n’utilisent pas tous la même valeur brute ou plafonnée.
Le graphique utilise maîtrise en X, motivation en Y et nombre de collaborateurs pour la taille. La réponse inclut aussi des points de référence de taille nulle de 0 à 5 ; leurs références d’accessibilité ne sont pas des mesures réelles. Les classements trient séparément par total ou moyenne. dashboard_graph_unmastered_skills figure dans l’initialisation, mais son appel TeamProficiency est commenté.
Observé : un périmètre de 62 alimentait la complétion, mais pas les tableaux emplois/compétences. Les filtres de connexion, les sources et les données manquantes sont des pistes issues du code ; la cause réelle dans PS Testing reste non vérifiée.
Suivi des campagnes
getActiveCampaings sélectionne les entretiens publiés et démarrés, accessibles aux écoles/participants éligibles. La classification administrateur et interview_all changent la branche de requête. Le regroupement inclut les campagnes en cours et terminées, pas uniquement les campagnes actives.
OneToOneController récupère le dernier périmètre de session, y limite les participants activés et construit les indicateurs de préparation, entretien et signature. Les absents sont séparés. Les indicateurs peuvent se recouper ; ils ne s’additionnent pas automatiquement comme des étapes exclusives. SkillsMapCampaign concerne les campagnes de déclaration de compétences, pas les entretiens.
Exports, erreurs et observabilité
Dashboard.exportAsCsv lit les lignes DataTables avec {filter: 'applied'}, retire le balisage et les points-virgules internes, puis écrit une marque UTF-8 et du contenu séparé par points-virgules dans un Blob navigateur. Le nom vient du texte du panneau. L’export porte sur le tableau chargé et filtré, sans nouvelle requête sur tous les collaborateurs. L’export graphique utilise les modules Highcharts distincts.
| Résultat | Implémentation / diagnostic |
|---|---|
| Requête d’onglet/détail/périmètre hors XHR | HTTP 400 Bad Request. Reproduire avec le parcours navigateur réel. |
| Aucun niveau ni relation | HTTP 400 avec message traduit sur les filtres. |
| Fonctionnalité/accès refusé | Les onglets renvoient 403 ; les contrôleurs page/détail peuvent lever une exception d’accès. |
| Entretien inconnu | Détail de progression : 404. |
| Périmètre vide valide | JSON avec fragment vide et effectif ; pas nécessairement une erreur HTTP. |
| Périmètre alimenté, graphique vide | Jointures, filtre de connexion, sources, évaluations et exigences. |
| Hiérarchie modifiée encore ancienne | Expiration de l’arbre en session et branche choisie avant d’incriminer l’agrégation. |
Utilisez les journaux applicatifs, statuts réseau, onglet et filtres pour le diagnostic. Aucune métrique dédiée, corrélation, politique de reprise automatique ou tâche de surveillance n’a été établie. Excluez noms, coordonnées et données brutes d’export des diagnostics partagés.
Interfaces, refonte et dépendances
Observé : la navigation actuelle hébergeait la route historique. Vérifié dans le code : la logique appartient à smartmobility-legacy ; les recherches ciblées dans smartmobility-nextgen-front/src et smartmobility-nextgen-back/src n’ont pas établi d’équivalent RH. Les composants de tableau People Review couvrent un autre parcours et ne prouvent pas un remplacement.
aihub/src/templates/config_file.json n’a pas identifié d’intégration et les requêtes tracées n’appellent pas AIHub. Aucune dépendance de scoring/matching IA n’est établie pour ces graphiques. Ce contrôle ciblé n’exclut pas l’affichage de données IA ailleurs dans le produit.
Dépendances : session Symfony historique authentifiée, Doctrine/base, rattachement utilisateur/entreprise valide, traductions et bibliothèques chargées par Twig. La hiérarchie exige la continuité de session ; les détails de périmètre et d’entretien dépendent d’une résolution préalable. La topologie et les versions de bibliothèques de production n’ont pas été vérifiées en direct.
Sécurité, confidentialité et extensions
Les tableaux individuels, liens de profil et exports contiennent des données personnelles. Maintenez autorisation, contexte d’entreprise et périmètre côté serveur ; masquer un onglet ne prouve pas la protection des points d’entrée. Contrôlez les populations autorisées et exclues lors d’une modification. Les exemples ne doivent exposer ni session, ni données réelles, ni identifiants secrets.
Pour une extension, suivez route → gestionnaire → population/éligibilité → générateur graphique → Twig → initialisation navigateur. Ajoutez catalogue, défauts et contrôles aux couches concernées. Distinguez permission d’onglet, activation graphique, visibilité hiérarchique et accès au détail. Explicitez calcul et export pour éviter des dénominateurs incompatibles entre panneaux proches. Cette mise à jour documentaire ne change aucune implémentation.
Sources et limites
- Observé dans l’application : 23 octobre 2026, Chrome, PS Testing 2026 avec Jim Carter : quatre onglets, périmètres vide et entreprise, complétion alimentée, emplois/compétences et sélecteur d’entretien vides, paramètres refusés. Aucun changement de compte, de données ou de configuration.
- Vérifié dans le code :
config/routes.yaml,config/configuration/{feature_module,default_permission}.yml;src/Company/ManagerDashboardBundle/{Controller,Chart,Services,Resources/views,Resources/public/js};src/Security/{FeatureSwitchVoter.php,Voter/BaseVoter.php};src/Service/Configuration/FeatureSwitchService.php; éditeursrc/Company/AccountBundle/Resources/views/Setting/module.html.twigdu dépôt historique. - Vérifié dans le code — coexistence ciblée : front nextgen
src/router/src/modules, back nextgensrc/configet AIHubsrc/templates/config_file.json. Aucun dépôt applicatif modifié. - Déduit : ordre de diagnostic et conseils d’extension issus du parcours examiné, sans constituer une surveillance déployée.
- Non vérifié : concordance du déploiement avec les sources locales, topologie de production, détails/campagnes alimentés, contenu des téléchargements, couverture des autorisations de tous les comptes et cause des données de compétences vides.
Sources du guide fonctionnel
Ces références soutiennent le guide fonctionnel. Les sources locales ne prouvent ni la révision déployée ni les fonctions optionnelles actives. Les observations applicatives restent distinctes du code et des documents.
- Observé : 23 octobre 2026, Chrome, PS Testing 2026, Jim Carter, espace manager ; quatre onglets, filtres N - 1/entreprise, complétion alimentée, emplois/compétences vides, sélecteur d’entretien vide et configuration refusée. Six captures de fenêtre complète soutiennent les trois guides ; menu ouvert et onglet actif identifient les contrôles.
- Vérifié dans le code : contrôleurs de
smartmobility-legacy/src/Company/ManagerDashboardBundle/,Chart/TeamProficiency.php,Services/Helper.php, modèles etResources/public/js/dashboard.js; valeurs initialesconfig/configuration/feature_module.yml. Voir la cartographie des sources ci-dessus. - Déduit : utiliser ces résultats pour préparer des échanges de développement est une recommandation, pas une décision automatique de la plateforme.
- Non vérifié : cause des compétences vides, détails alimentés, téléchargements, activation privilégiée, statistiques de campagne et accès des autres comptes. Seuls des filtres de vue ont été appliqués ; aucun enregistrement ni paramètre modifié.
Dernière mise à jour : 3 novembre 2026