Catalogue de formation — guide technique
Référence d’ingénierie pour découverte, administration et catalogue consommé par les entretiens. Le catalogue autonome observé est legacy ; nextgen expose des API et une modale d’entretien. Voir fonctionnel pour les observations et configuration pour les responsabilités. Le code ne prouve ni la version déployée ni un résultat d’exécution.
Architecture et composants
Vérifié dans le code : contrôleurs/modèles legacy et entité nextgen Infrastructure/Persistence/Entity/Training/Formation.php mappent la table nommée formation, comme Formation.orm.yml legacy. Compatibilité des mappings ne prouve pas un même serveur de base déployé. Le switch legacy new_formation_view choisit un modèle Twig plus récent, pas une API nextgen.
| Dépôt / source | Responsabilité |
|---|---|
legacy src/Company/FormationBundle/Controller/InterneController.php | Liste/détail RH, création/modification, liens de compétences, export et sessions/demandes connexes. |
legacy src/Customer/FormationBundle/Controller/{Interne,Search,Favorites,Requests}Controller.php | Accueil/détail salarié, recherche, favoris, demandes. |
legacy src/Main/ConfigBundle/Controller/FormationController.php | Recherche JSON administrative et résultats salarié rendus. |
legacy src/Repository/FormationRepository.php::createFilteredFormations | Périmètre entreprise et prédicats communs. |
legacy src/Customer/FormationBundle/Services/{AccessGroupService,FormationService}.php | Groupes/historique configurés et suggestions de motivation. |
legacy src/Main/ConfigBundle/Form/Type/FormationType.php | Champs et options du formulaire. |
legacy web/assets_search/js/SearchFormations.js | Critères/requêtes RH, pagination de 12 cartes. |
legacy src/Customer/FormationBundle/Resources/views/Modern/ | Filtres, cartes, sections, détail et interactions salarié. |
nextgen-front …/Development/components/DevelopmentTrainingCatalogModal.vue | Catalogue dans l’entretien : tous/suggestions/sélection, critères et sélection de demandes. |
nextgen-front …/Development/api/trainingCatalogFilters.api.ts | Chargement des définitions/options de filtres visibles salarié. |
nextgen-back src/Http/Api/Routing/V1/training.yaml | Contrats CRUD et catalogue de l’évalué. |
nextgen-back src/Infrastructure/Persistence/Repository/Training/FormationRepository.php | Périmètre entreprise/salarié, historique, durée et champs personnalisés. |
Le préfixe frontend …/Development est src/modules/ModuleConfig/Campaigns/modules/Reviews/modules/FormRender/components/renderers/Development.
Flux legacy
Recherche RH
Company/FormationBundle/InterneController::indexAction contrôle le masquage du module, charge les compétences/organismes/catégories/états de l’entreprise et prépare Smart Editor en contexte bo. SearchFormations.js envoie criterias, limit=12, offset à formation_search. Main/ConfigBundle/FormationController::searchAction exige AJAX et utilisateur connecté, résout l’entreprise, délègue à createFilteredFormations puis applique les critères personnalisés.
Les critères comprennent search, organisme, status, tags, category, typef, duration et swpFields sérialisé. Le client RH inspecté n’envoie pas le champ locale qu’il calcule ; le serveur applique sa gestion des langues d’entreprise. Ne pas lui attribuer le sélecteur salarié.
Les groupes indépendants se combinent avec ET. Recherche partielle LIKE dans nom, description, résumé et code ; organisme par nom partiel ; catégorie/état/type par valeur exacte. Les compétences sélectionnées correspondent à une relation items ou directe avec OU, sans exiger toutes les compétences choisies.
La projection JSON fournit identifiant/titre, résumé, compétences, organisme/catégorie, appréciations et durée formatée. clearSearch conserve une dépendance à un slider ; l’affichage d’un bouton ne prouve pas une remise à zéro universellement fonctionnelle.
Recherche et suggestions salarié
Customer/FormationBundle/InterneController::metiersAction rend sections ou détail. SearchController::indexAction prépare la recherche avec options d’entreprise et Smart Editor fo. Le formulaire vise /plateforme/formation/search ; les résultats sont traités par formation_fo_search, associé à Main/ConfigBundle/FormationController::searchFormationFO.
Ce traitement reçoit critères, page, params Smart Editor et jobParams. Il demande les cours publiés de l’entreprise, applique langue sélectionnée/par défaut, exclut les identifiants d’historique, fusionne filtres d’audience et champs explicites puis ajoute durée/suggestions. Il trie par nom et pagine selon LIST_MAX_ITEMS_PER_PAGE. Population et tri ne sont pas supposés identiques au client RH.
onlyUserSuggestions utilise les niveaux attendus des emplois actuels/cibles. Dans InterneController::_getUserCareerSkillsFormations, l’absence de plan ou d’emploi cible renvoie des données de suggestions vides ; la méthode compare ensuite les niveaux attendus de l’emploi cible aux niveaux salarié et aux résultats associés des cours. Pour une compétence évaluée : niveau attendu emploi au moins égal au salarié et résultat acquis du cours au moins égal au salarié. Une compétence requise absente du salarié peut correspondre aux cours liés. retrieveSkillsNoteFromJob conserve le niveau requis maximal entre plusieurs emplois cibles. Le détail du parcours suit l’état individuel des actions UserPlanAction.completed et affiche un message lorsque toutes les actions listées sont terminées ; le mapping examiné de UserPlan ne comporte pas d’état d’achèvement global du projet. Modern/_formation.section.html.twig affiche l’état vide carrière lorsque la section ne contient aucun résultat ; le générateur utilise plans, emplois cibles et correspondances éligibles entre compétences et formations, pas les états d’achèvement des actions. Dans ce parcours legacy, le texte d’absence ne prouve donc pas à lui seul qu’un plan est inachevé. Le comportement exact de l’espace déployé reste à confirmer.
La motivation utilise FormationService::createSuggestionByUserSkillMotivationQuery et UserskillRepository::findSkillsByMotivationLevel, seuil par défaut >=3, puis niveau acquis moins niveau salarié >=0. En recherche combinée, emploi/carrière et motivation sont réunis avec OU avant les autres critères. Le script applicable rend exclusifs les interrupteurs emploi et carrière.
Ces règles décrivent ce chemin de recherche, pas tous les carrousels, LinkedIn ou résultats IA nextgen. La documentation de 2023 alterne « plus de 3 » et « >=3 » ; le dépôt inspecté confirme >=3 ici.
Choix de compétences et critères effectifs
SearchController::indexAction charge FormationRepository::getAllFormationsSkills(settingId, user.locale). La requête exige une association à une formation publiée de l’entreprise et une traduction skill_translation.locale dans la langue du salarié. Le filtre de langue du cours est distinct : choisir des cours français ne change pas la langue utilisée pour construire cette liste.
Modern/_formation.box.html.twig et _formation_sections_paginated.html.twig::populateFormations limitent les cartes à trois compétences et conditionnent leurs liens à formation_hide_home_filters. Le lien transmet tags=<skillId>, mais getFilters envoie les options sélectionnées dans #tags plutôt que l’identifiant de l’URL directement. Si l’option est absente, le lien ne garantit donc pas un filtre effectif.
Observé dans l’application : une page ouverte par lien de compétence ne proposait aucune option non vide dans Compétences et affichait des résultats plus larges. Ce cas ne signifie pas que tous les liens échouent. Vérifiez associations publiées et traductions dans la langue du salarié avant de considérer les résultats comme filtrés par compétence.
Navigation et actions enregistrées
Modern/_formation.box.html.twig choisit route interne ou URL externe selon always_display_course_detailed_view. Le résultat salarié observé était externe ; le résultat RH ouvrait la fiche interne. Le contrôleur de détail salarié examine la demande existante et adapte l’action selon état actif/en attente/terminé/refusé.
FavoritesController::manageAction reçoit du JSON formation et operation (add ou retrait), met à jour la relation du salarié, enregistre et émet FormationAddFavoriteEvent / FormationRemoveFavoriteEvent. Réponse {"status":true|false}. J’aime/Je n’aime pas est une autre action avec effets de présentation/popularité distincts. Le favori ne vaut ni inscription ni achèvement.
La fiche interne salarié et la destination du titre d’une carte sont distinctes. Observé dans l’application : le lien interne d’une formation publiée affichait Formation, Compétences et Infos utiles alors que son titre de catalogue pointait vers un prestataire. Dans le modèle de fiche, le statut compare userSkill.note >= skill.note. Un libellé acquis reflète cette comparaison des niveaux enregistrés plutôt qu’un achèvement du cours.
metiersAction déduit la disponibilité de demande de son état existant. Modern/view_formation.html.twig affiche Accéder à la formation lorsqu’une URL externe existe ; le bouton alternatif de demande exige allowrequest == 1, tous les niveaux prérequis et bo_formation_request. Une réponse salarié en attente présente acceptation/refus ; une demande active empêche une nouvelle demande. Ces conditions de rendu sont définies dans le code ; envoi et approbation restent hors du parcours observé en lecture seule.
Création et suivi d’une demande catalogue
Vérifié dans le code : Customer/FormationBundle/Controller/InterneController::addAction, Main/ConfigBundle/Services/FormationRequest/FormationRequestService.php, Modern/view_formation.html.twig, RequestsController::listAction et Modern/requests_new.html.twig.
| Contrat | Comportement |
|---|---|
POST /plateforme/formation/add | Route AJAX legacy ; le client de la fiche transmet le champ de formulaire formation. Le contrôleur résout un cours de l’entreprise du salarié et son enregistrement Customer. |
| État initial | FormationRequestService::with exige un état de demande de l’entreprise avec is_active=true et default_value=true. Son absence produit une erreur avant création. Il est distinct de l’état de publication du cours. |
| Création | createRequest fixe salarié, cours, état, titre et date, persiste et effectue un flush, puis appelle la création d’historique. |
| Notification et événement | sendNotificationEmail appelle MailerHandler avec TRAINING_REQUEST et le User du manager comme contexte, puis vient FormationPostulateEvent. Destinataires et livraison dépendent de la configuration de notification. |
| Réponse | Succès : {"response":1}. Une exception interceptée émet PostCatchEvent et renvoie HTTP 400 avec {"response":"error"}. |
La persistance précède la notification. Une erreur après le flush peut donc coexister avec une demande enregistrée ; consultez demandes et historique avant de réessayer. Le client désactive Envoyer et traite le callback de succès, sans callback d’erreur défini dans ce flux. L’état d’un bouton ou d’une fenêtre ne suffit pas à établir le résultat final.
request_formation_form est utilisé dans Company/ProspectBundle/Resources/views/Includes/development.html.twig, autour d’un bouton de fiche collaborateur qui porte aussi un style masqué. Il est distinct du contrôle bo_formation_request de la fiche autonome récente. module_formation_catalogue_fo_demande masque l’entrée Mes demandes dans Modern/_top.page.options.html.twig ; RequestsController::listAction ne répète pas ce flag de navigation. hide_formation_demands est décrit par l’écran d’administration, mais son consommateur de rendu n’a pas été localisé dans les sources inspectées.
La page récente classe les entrées ainsi :
- Coming : états éligibles avec une session dont la fin est future, ou demandes admissibles sans session ; ce dernier cas peut inclure un état terminé.
- Completed : session terminée dans le temps, hors abandon/refus salarié et refus manager/RH. La comparaison de date n’exige pas
isFinished. - Refused : flags de refus/abandon salarié ou de refus manager/RH.
_request_new.box.html.twig peut ouvrir le prestataire depuis l’image alors que le titre texte ouvre la fiche interne. Classement, notification, présence et acquisition de compétences restent distincts.
Observé dans l’application : Training Management sépare Management Platform et Employee Platform ; la page salarié présente Coming, Completed et Refused avec leurs messages d’absence. Ces observations étayent la navigation et la structure, sans établir création, livraison de notification ou approbation dans l’application déployée.
Affectation à une session et confirmation de présence
Vérifié dans le code : Company/FormationBundle/Resources/views/Interne/requests.html.twig affiche l’affectation uniquement si des demandes existent, si show_formation_session est actif et si la permission effective de l’entreprise est vide ou contient delete_create_edit_give_sessions. Les commandes de création/modification/suppression utilisent ce droit dans les modèles de liste et de détail des sessions. Le fichier de permissions par défaut l’accorde à hrbp ; il vaut false pour admin_rh et manager. La configuration réelle du tenant peut remplacer ces valeurs.
Dans Company/FormationBundle/Controller/InterneController::checkPresenceAction, l’action formateur/RH retrouve les demandes associées aux utilisateurs sélectionnés et à une session, fixe validationTrainer, persiste les demandes et envoie un courriel de confirmation à chaque utilisateur sélectionné. Le message contient des liens Oui/Non. Dans Customer/FormationBundle/Controller/InterneController::checkPresenceAction, la route salarié vérifie que la demande appartient à l’utilisateur courant, enregistre isParticipated selon la réponse et date participationDate une seule fois ; une réponse ultérieure renvoie un avertissement sans écraser la première. Il s’agit d’un flux de notification et de mutation des données, pas d’une étape en lecture seule.
La catégorie salarié Completed est calculée selon la date de fin de session et les états d’exclusion ; elle n’exige ni réponse de présence ni isFinished. Réponse de présence, classement de la demande, achèvement auprès du prestataire externe et acquisition de compétences sont des états distincts.
Modèle et administration
Legacy src/Main/ConfigBundle/Resources/config/doctrine/Formation.orm.yml mappe contenu, langue, URL, durée/unité/type/devise/lieu facultatifs, organisme/catégorie/état, compétences et contenu associé. Les compétences avec niveaux utilisent Formationskill ; la recherche conserve aussi des liens directs. Smart Editor dispose d’entités de valeurs Formation. Demandes, états de demande, sessions, historique et favoris sont séparés.
FormationType exige nom, langue et état. Organisme devient obligatoire avec formation_show_organisme_field. Choix liés à l’entreprise ; l’entité legacy commence en fr indépendamment de l’interface. Prix/diplôme/alternance/débouchés dépendent des activations et modèles.
Le contrôleur du détail admin appelle CompanyEntityItemManager::getAllFormationData($formation, true) pour l’onglet Infos utiles. L’argument true limite la liste aux champs Formation visibles ; le gestionnaire inclut les champs configurés même si aucune valeur n’est enregistrée sur la fiche. Le modèle affiche alors Non défini ; les champs Url/Url_i18n affichent un lien qui s’ouvre dans un nouvel onglet. Ces règles de rendu ne prouvent pas qu’un champ particulier du tenant est renseigné.
InterneController::newAction traite le formulaire, fixe l’entreprise, lit le résumé séparément, valide/charge les médias et persiste cours/documents/valeurs. editAction contrôle en plus modify_training. L’ouverture de la route legacy d’édition a un effet d’écriture : avant d’afficher le formulaire, elle retire du résumé les wrappers <span class="no-translate"> et les espaces initiaux, puis persiste et flush la fiche même lors d’un GET. Le formulaire d’édition n’est donc pas une route d’inspection en lecture seule. Son action de suppression enlève la fiche, ses demandes, favoris, compétences/associations, fichiers, valeurs de champs d’entreprise, sessions/fichiers de session et appréciations ; cette route ne prévoit pas de récupération. Création, compétences, documents et ajout de compétences après achèvement ne constituent pas une transaction globale garantie. Les adaptateurs Formations/Formations&Compétences sont documentés dans Import Center.
Priorité flux/saisie manuelle, rollback des demandes et conservation ne sont pas établis. La source faisant autorité relève du contrat d’intégration.
Le champ who (Pour qui) est un TextareaType descriptif dans FormationType. Les restrictions de découverte proviennent des champs d’entreprise User/Formation associés aux groupes d’accès, plutôt que de ce texte.
Groupes d’accès et historique
Legacy AccessGroupService emploie training_visibilty (orthographe réelle) et training_attendance. Il résout les champs User/Formation et les noms de groupes, puis produit or_null pour admettre les cours sans restriction ainsi que les groupes autorisés. Champs/valeurs utilisateur absents peuvent conduire à aucune restriction. L’historique fournit les formations exclues à partir de valeurs flaggées portant l’identifiant salarié.
Nextgen TrainingAccessGroupProvider::provideScope résout aussi champs/options/noms ; FormationRepository::applyEmployeeScope applique groupes et historique. Un périmètre résolu sans option correspondante n’admet que les cours sans restriction ; aucun périmètre utilisable peut laisser le filtre absent. findTrainingsForUserReview résout l’évalué via TrainingCatalogRevieweeProvider, renvoie 1=0 s’il manque et applique son périmètre plutôt que celui du réviseur.
Observé dans l’application : une formation non publiée restait accessible par son lien interne salarié. Vérifié dans le code : la branche numérique de Customer/FormationBundle/InterneController::metiersAction résout la fiche et vérifie l’entreprise, mais n’applique pas dans cette branche les prédicats de publication, groupes et historique du catalogue. L’autorisation globale des routes reste distincte. L’exclusion du catalogue ne garantit donc pas le refus d’un lien direct.
La requête nextgen générique établit entreprise/groupes/historique, sans preuve de reproduction de toutes les conditions legacy de publication/langue. Vérifier les filtres du consommateur. Ces prédicats de découverte ne prouvent pas toute l’autorisation des routes.
API nextgen et consommateur entretien
config/routes.yaml monte les routes V1 sur /api/v1. training.yaml définit :
| Méthode / route | Permission et comportement |
|---|---|
GET /api/v1/training | read-training, findTrainings, nom ascendant par défaut. |
GET /api/v1/training/{id} | read-training, entreprise/utilisateur courant. |
POST /api/v1/training | create-training, validation DTO de création. |
PUT/PATCH /api/v1/training/{id} | update-training, validation et recherche ciblée. |
DELETE /api/v1/training/{id} | delete-training, route déclarée soft_deletable: false. |
GET /api/v1/user-review/{userReviewId}/training | read-training, catalogue de l’évalué. |
GET /api/v1/user-review/{userReviewId}/training/{id} | Même périmètre, une fiche. |
Exemple illustratif de lecture :
GET /api/v1/training?filters[name][contain]=Excel&filters[duration][gte]=4&filters[duration][lte]=16&sorting[name]=asc
Filtres : opérateurs texte nom/langue/type, comparaisons numériques de durée et champs Smart Editor dynamiques. ET entre champs personnalisés ; valeurs d’option multiples séparables par | selon le type. Un opérateur incompatible avec le type est ignoré dans le contrat déclaré : envoyer un paramètre ne prouve pas son application.
Domain/V1/Training/DTO/TrainingDTO.php exige nom en écriture et langue/code en création, avec unicité langue+code via le dépôt limité à l’entreprise. Nom/code limités à 255, HTML de description à 50 000. Durée/unité/type/lieu sont en lecture seule dans le DTO détaillé. Formulaire legacy et API n’ont pas un schéma identique.
La modale d’entretien utilise /api/v1/user-review/{id}/training et récupère les critères via /api/v1/custom-field/training-filter puis /custom-field/{fieldId}/option. trainingCatalogFilters.api.ts lit une première page de 50 champs et 100 options par champ, masque les notifications d’erreur et renvoie des choix vides en cas d’échec. Un filtre absent peut refléter erreur ou limite de récupération.
development.utils.ts::TRAINING_DURATION_FILTERS définit Court <4h, Moyen 4–16h inclus, Long >16h. Onglets tous/suggestions/sélection et événement de sauvegarde appartiennent au formulaire de développement ; leur disponibilité déployée reste distincte du catalogue autonome observé.
Différences de durée
| Chemin | Interprétation vérifiée |
|---|---|
| Dépôt RH legacy | <=3 heures ; <=48 heures ou <=2 jours ; >=48 heures/>=2 jours ou unité mois pour la plage longue. |
Salarié legacy setDuration | Comparaisons inclusives et conversion 24 heures/jour pour les plages concernées ; petites plages limitées à l’unité heure. Des bornes mutables peuvent persister entre cases sélectionnées. |
Nextgen DurationType::hours / applyDurationFilter | Heure=1, jour=7, mois=147. Comparaison normalisée en heures ; durée absente/vide exclue si filtre numérique appliqué. |
Conserver les unités et tester le consommateur réel ; ne pas uniformiser silencieusement la définition d’un jour.
IA et intégrations
Nextgen src/Infrastructure/Persistence/Service/Development/TrainingSuggestionProvider.php appelle matching/explication AIHub, exclut historique et demandes existantes, met en cache et recontrôle les identifiants retournés selon les cours demandables pour l’évalué. L’appelant attend une liste plate d’identifiants et transforme un échec de transport en exception de suggestion. Le contrat de l’appelant ne définit pas le classement ni la disponibilité du service déployé.
AIHub src/matching/training/service.py expose search_accessible_training_ids et get_user_training_rationale, capacité distincte de la recherche déterministe legacy. La chaîne HTTP/authentification/ranking complète n’a pas été retracée ici ; attente de l’appelant n’établit pas le contrat déployé du serveur. Legacy src/Service/MessageBroker/Formatter/FormationFormatter.php produit des messages identité formation/entreprise ; ce seul formatter ne prouve ni livraison ni délai de rafraîchissement.
LMS externe, LinkedIn et learning hub dépendent de la configuration. Ouvrir un titre ne fournit pas de retour d’achèvement : confirmez le contrat d’intégration pour l’historique et les compétences.
Permissions, échecs et observabilité
Les droits legacy de masquage/modification diffèrent du CRUD nextgen. Le détail salarié vérifie l’entreprise d’une fiche rattachée ; tous les chemins favoris/session/mutation ne répètent pas localement ces mêmes contrôles. Configuration de sécurité globale non auditée exhaustivement. Menu et formulaire ne prouvent pas une politique générale d’autorisation/CSRF.
| Symptôme | Contrôle |
|---|---|
| Aucun résultat salarié | Publication/langue, critères, groupes/historique et données emploi/carrière/profil. |
| Comptages RH/salarié différents | Prédicats de publication, langue et audience distincts. |
| Critères d’entretien absents | Contexte, erreurs, premières pages et options. |
| Durées inattendues | Seuils/conversion par génération et bornes legacy multisélection. |
| Carte sans détail interne | URL et switch de détail systématique. |
| Enregistrement refusé | Contraintes formulaire/DTO, choix état/organisme, médias. |
| Favori en échec | Réponse status:false après exception ; ne pas déduire du seul cœur. |
| Suggestions indisponibles | Exception/cache/périmètre nextgen versus prérequis legacy. |
Le détail émet FormationOpenEvent, les favoris leurs événements dédiés. Demandes/sessions peuvent notifier et ajouter des compétences à l’achèvement. Monitoring, relances, fraîcheur de flux et remontée d’achèvement LMS non vérifiés.
Dépendances : Symfony/Doctrine, configuration/Smart Editor, jQuery/Select2/Switchery legacy, Vue/Mk4Http et permissions nextgen, médias et services externes lorsqu’activés. Étendre ensemble formulaire/DTO, mapping, filtre, modèle/modale et validations pertinentes ; ajouter un libellé ne crée pas un champ intergénération complet.
Sources et limites
| Preuve | Périmètre |
|---|---|
| Vérifié dans le code | Formulaires, contrôleurs et dépôt de recherche legacy, cartes, associations de compétences, groupes d’accès et favoris ; catalogue d’entretien nextgen, API et dépôt limité au salarié. Les chemins et symboles figurent dans les sections précédentes. |
| Observé dans l’application | Catalogues administrateur et salarié distincts, contenu enregistré et niveaux de compétences acquises, découverte d’une formation publiée, liens de compétences, recherche/réinitialisation, favoris et navigation externe. Les guides fonctionnel et de configuration présentent les captures réelles. |
| Contexte documentaire | Playbook Training Matching, configurations, règles de suggestion et cas d’usage. Ces pages décrivent l’intention ; les contrats du code et l’application déployée déterminent le comportement effectif. |
| Non vérifié dans l’application déployée | Effets et retrait d’un prérequis enregistré, accès des autres groupes salariés et de toutes les variantes de route, demandes/approbations/achèvement, appréciations, exports, complétion LMS externe et catalogue d’entretien nextgen. |
Le code local n’établit ni la révision déployée, ni la topologie de la base, ni la fraîcheur des intégrations, ni toutes les autorisations. Les observations de référence datent d’octobre 2026.
Sources du guide fonctionnel
Les distinctions suivantes étayent le guide fonctionnel :
| Comportement produit | Preuve et périmètre |
|---|---|
| La langue du contenu est indépendante de celle de l’interface. | Observé dans l’application et Vérifié dans le code dans FormationType et les valeurs initiales de l’entité. |
| Une carte salarié peut présenter un sous-ensemble des compétences du cours. | Vérifié dans le code : Modern/_formation.box.html.twig limite l’affichage à trois compétences. Observé dans l’application : la carte de management présente trois libellés, tandis que son onglet administrateur Compétences contient huit résultats. |
| Un lien de compétence ouvre la recherche selon les choix disponibles. | Vérifié dans le code : le lien porte un identifiant, mais la recherche lit les options Compétences sélectionnées. Observé dans l’application : une liste vide a produit des résultats plus larges. Le lien seul ne garantit pas le filtrage. |
| Les associations décrivent prérequis ou résultats attendus. | Vérifié dans le code : view_formation.html.twig sépare les relations required et acquired et utilise une fenêtre de modification des lignes sélectionnées ; InterneController::addFormationSkillAction enregistre le type et le niveau. Pour acquired, cette action peut appeler assignSkillToUsersOfFormation pour les utilisateurs associés à la fiche ; le service d’import conserve un niveau existant non nul. L’action de retrait supprime uniquement le lien cours-compétence. Les niveaux acquis enregistrés ont été Observés dans l’application. Cela n’établit ni l’acquisition par un salarié ni l’impact utilisateur déployé. |
| Publication et configuration d’accès influent sur la découverte. | Observé dans l’application : une formation non publiée visible en administration était absente de la recherche salarié, tandis qu’une formation publiée était visible. Vérifié dans le code : publication, langue, groupes et historique sont appliqués dans le flux de recherche legacy concerné. Le même salarié pouvait ouvrir une formation non publiée par lien direct. Les filtres de découverte ne définissent pas l’autorisation d’accès direct. |
| Favoris, appréciations et demandes sont distincts. | Vérifié dans le code : actions et relations distinctes ; ajout/retrait des favoris Observés dans l’application. |
| Le titre peut ouvrir une destination externe. | Observé dans l’application et Vérifié dans le code de navigation des cartes et fiches. Disponibilité du prestataire et achèvement relèvent du contrat d’intégration externe. |
Dernière mise à jour : 3 novembre 2026