Aller au contenu principal

Référentiel emplois et compétences — guide technique

Ce guide couvre le domaine du catalogue dans legacy, nextgen-back, nextgen-front et AIhub pour les équipes techniques et d'intégration. Les affirmations d'implémentation sont Vérifiées dans le code, sauf mention contraire. Les sources locales établissent des contrats et responsabilités, pas la topologie déployée. Consultez les guides fonctionnel et configuration pour les parcours illustrés et l'administration.

Architecture et frontières​

ComposantResponsabilité et points d'entrée vérifiés
Catalogue manager legacyContrôleurs Symfony, Twig et JavaScript dans src/Company/{Job,Skill,Referential}Bundle ; listes /company/job et /company/skill.
Exploration collaborateur legacysrc/Customer/InternalJobBundle/Controller/DefaultController.php::listingAction, SearchController::{homeAction,filterAction,suggestionsAction} et Services/SearchService.php ; navigation observée sur /plateforme/internal-job/.
Backend nextgenRoutes V1, validation DTO, dépôts limités à l'entreprise, listeners et consommateurs. config/routes.yaml monte les routes V1 sous /api/v1. V1 est ici l'espace de noms API, pas une désignation de l'interface legacy.
Frontend nextgensrc/router/private-routes.ts et une recherche ciblée des modules liés n'ont pas identifié d'éditeur dédié du référentiel. Des composants de compétences dans les entretiens ne démontrent pas une parité CRUD du catalogue.
AIhubImports explicites des données SmartMobility et normalisation ; aucun appel direct sauvegarde du catalogue → actualisation AIhub immédiate établi.

Flux de requêtes :

Catalogue manager -> contrôleur legacy + droits/entreprise
-> filtres Twig + script -> dépôt -> enregistrements
Exploration collaborateur -> SearchController InternalJob -> SearchService -> entreprise/langue/statut
Client API -> route /api/v1 -> permission -> DTO -> gestionnaire/dépôt -> persistance
Création JobSkill -> listener -> événement SkillAttachedToJob -> consommateur -> compétences individuelles manquantes
Import AIhub -> extraction -> normalisation/standardisation (intégration distincte)

Observé dans l'application : la navigation manager moderne ouvrait des routes legacy. Le guide fonctionnel documente cette observation, sans établir l'intégration nextgen déployée ni une base partagée.

Domaine et modèle de données​

Entité / relationSignification et source
JobDescriptions traduites, code, entreprise, état actif, statut et référentiel. Entité/dépôt legacy Main/ConfigBundle ; nextgen Infrastructure/Persistence/Entity/Job/Job.php.
SkillIntitulés/descriptions traduits, attentes de niveaux de maîtrise, code externe, groupe et référentiel. Nextgen Domain/V1/Skill/DTO/SkillDTO.php, mappé à Infrastructure/Persistence/Entity/Skill/Skill.php.
JobSkillCouple unique métier + compétence ; maîtrise attendue mappée à note. Domain/V1/JobSkill/DTO/JobSkillDTO.php.
SkillGroupClassification/type et rattachement au référentiel ; le formulaire legacy expose aussi poids, mesurable et position. Main/ConfigBundle/Form/Type/SkillGroupType.php.
ReferentialRéférentiel limité à l'entreprise, titre/langue et indicateurs principal/public. Le contrat nextgen s'appelle ReferentialDTO, la persistance Referentiel.
Compétence individuelleEnregistrement distinct ; l'évaluation n'est pas la maîtrise attendue du métier. Infrastructure/Service/User/UserSkillService.php.

Les deux dépôts utilisent des tables familières, dont job, skill, jobskill, referentiel et SkillGroup. Cela indique une filiation de domaine compatible, sans prouver un stockage déployé commun, une synchronisation bidirectionnelle ou une stratégie de migration. Le formulaire legacy traduit du référentiel et le DTO nextgen titre/langue sont des contrats différents.

Un référentiel contient métiers, compétences et groupes. findUnusedReferential du dépôt nextgen contrôle leurs liens. ReferentielListener::preDelete délègue à ReferentielManager::isDeletable et refuse une suppression non autorisée. preCreate rend principal le premier référentiel ; postCreateOrUpdate appelle unsetMainReferential pour un enregistrement principal. Les garanties transactionnelles/concurrentes de modifications simultanées du principal n'ont pas été étudiées.

Requêtes et recherche legacy​

L'entrée manager est src/Company/JobBundle/Controller/DefaultController.php::indexAction, qui rend Resources/views/Default/index.html.twig. web/assets_search/js/SearchCompanyJob.js::{getFilters,CallSearch} sérialise critères et pagination. La route de recherche est définie dans src/Main/ConfigBundle/Resources/config/routing/companyjob.yml ; Controller/CompanyJobController.php::searchAction contrôle l'usage Ajax authentifié et le jeton CSRF referential_token, puis sélectionne la requête manager/client selon le contexte.

src/Main/ConfigBundle/Repository/JobRepository.php::applyKeywordSearchConditions recherche les intitulés traduits dans la langue active et gère le masquage. Les indicateurs d'incohérence sont combinés par Expr\Andx. Les méthodes manager/client diffèrent. Ne pas transposer le prédicat de référentiel public de l'ancienne recherche client de ce dépôt à chaque parcours collaborateur.

Le parcours collaborateur observé utilise Customer/InternalJobBundle/Services/SearchService.php::{jobs,findFilteredCustomerJob}. Sa requête limite l'entreprise et les métiers actifs, joint la langue courante, applique la visibilité du statut lorsqu'elle est demandée et gère les métiers masqués : sans texte ils sont exclus ; un intitulé exact peut les inclure. Le masquage n'est pas une frontière d'autorisation. La proximité dépend du paramétrage et des données de matching ; valeurs et seuils courants non validés.

Customer/InternalJobBundle/Resources/views/Partials/scripts.search.html.twig::resetAll réinitialise champs avancés et proximité puis soumet, mais conserve le texte principal : sa ligne d'effacement est commentée. resetElement vide les entrées visibles du groupe puis soumet. Côté manager Compétences, web/assets_search/js/SearchActivities.js::clearSearch vide les contrôles sans relancer la recherche. Le guide fonctionnel distingue donc les remises à zéro.

Contrats API nextgen​

Définitions : src/Http/Api/Routing/V1/{job,skill,skill_group,referential,job_skill}.yaml. Tous les chemins ci-dessous ont le préfixe /api/v1. CRUD correspond à GET liste/détail, POST création, PUT/PATCH modification et DELETE, avec identifiants numériques dans les routes de détail.

CheminsPermissions par actionListe / suppression configurée
/job, /job/{id}read-job, create-job, update-job, delete-jobTri titre ASC ; filtres title/code equal, contain, start, end. Suppression logique.
/skill, /skill/{id}read-skill, create-skill, update-skill, delete-skillTri titre ASC ; filtres title/type/id. soft_deletable: false.
/skill-group, /skill-group/{id}read-skill-group, create-skill-group, update-skill-group, delete-skill-groupFiltres title/type/referential_id. Suppression logique.
/referential, /referential/{id}read-referential, create-referential, update-referential, delete-referentialTri titre ASC ; titre et égalité stricte public/main. Suppression physique configurée, sous contrôle du listener.
/job/{jobId}/skill, /job/{jobId}/skill/{skillId}read-job-skill, create-job-skill, update-job-skill, delete-job-skillTri required_level ASC ; identifiant de détail = compétence imbriquée sous le métier. DELETE retire la relation, en suppression physique configurée.

Noms et opérateurs proviennent des métadonnées de route. Encodage complet des filtres, en-têtes de pagination, authentification et totalité des groupes de sérialisation dépassent ce contrat fonctionnel ; utiliser la documentation API générée du déploiement plutôt qu'inventer une syntaxe.

Validation DTO et exemple​

src/Domain/V1/Job/DTO/JobDTO.php impose des intitulés traduits avec contraintes de longueur, contrôle le code facultatif unique et déclare les sections descriptives traduites. SkillDTO.php valide les intitulés, le code externe facultatif unique, les identifiants groupe/référentiel de l'entreprise et les libellés des niveaux attendus 1–5. Le type hard/soft/other est en lecture seule, other par défaut dans le DTO ; ce n'est pas un champ libre d'affectation de groupe.

ReferentialDTO.php impose un titre non vide de 255 caractères maximum en écriture, une langue prise en charge à la création et des booléens main/public non nuls en validation d'écriture ; ces booléens appartiennent au groupe de sérialisation Detailed. Le listener impose ensuite le caractère principal du premier référentiel. Ces contraintes ne donnent pas les valeurs initiales des cases legacy.

JobSkillDTO.php vérifie l'existence du métier et de la compétence dans l'entreprise à la création et l'unicité du couple. requiredLevel est un entier nullable mappé à note ; le DTO n'impose pas une échelle universelle 1–4. Le scénario Behat inspecté utilise 10, 20 et 30 : ce sont des valeurs de test, pas une recommandation métier.

Exemple illustratif de rattachement, non exécuté ; identifiants fictifs à remplacer par des enregistrements autorisés, échelle à convenir pour l'intégration :

POST /api/v1/job/123/skill
Content-Type: application/json

{
"skill_id": 456,
"required_level": 3
}

tests/Behat/Features/V1/job_skill/crud.feature prévoit 201 en création, 400 avec This job already has this skill. en doublon, 200 en lecture/modification, 204 en suppression puis 404 en relecture. Le scénario Nested inclut la compétence liée ; Detailed ajoute les dates. Tests lus, non exécutés. Aucun secret, identifiant réel ou changement en production n'est nécessaire pour comprendre le contrat.

Autorisation et isolation par entreprise​

Legacy Company/JobBundle/Controller/DefaultController.php::grantOrDenyAccess contrôle les permissions du profil par ET par défaut ; le paramètre strict à false active OU. L'absence de profil contourne aussi ce contrôle du helper, point à examiner dans un audit. indexAction utilise referentiel_r ; les créations/éditions inspectées passent ['referentiel_c','job_c_d'] avec OU. Les routes de duplication diffèrent, dont job_duplicate : ne pas annoncer de règle universelle. Mise à jour des compétences et actions de statut ont leurs propres contrôles d'écriture référentiel. Les créations/éditions de compétence inspectées dans Company/SkillBundle/Controller/DefaultController.php contrôlent la lecture référentiel ; l'apparence de l'interface ne prouve pas un contrôle d'écriture plus fort.

Nextgen déclare les droits par route. Infrastructure/Persistence/Repository/Job/JobRepository.php::findJobs limite entreprise et état actif ; Skill/SkillRepository.php::findSkills et Referential/ReferentielRepository.php::findReferentials limitent l'entreprise. La requête générale de compétences n'est pas automatiquement un catalogue public collaborateur. EntityExist(... hasCompany: true) ajoute une validation de rattachement, sans remplacer l'autorisation de route.

Identifiants d'une autre entreprise, permissions absentes et visibilité doivent être testés séparément. Les scénarios Behat métier–compétence prévoient 403 sans permission et 400 pour les relations invalides : preuves du contrat de test, pas un test d'intrusion réel.

Événements et cycle de vie des compétences individuelles​

  1. Infrastructure/Persistence/Listener/Job/JobSkillListener.php::postCreate publie SkillAttachedToJob après création du lien.
  2. Command/Consumer/Job/SkillAttachedToJobConsumerCommand.php résout métier/compétence puis invoque UserSkillService::attachSkillFromJob.
  3. Command/Consumer/User/JobAssignedToUserConsumerCommand.php invoque UserSkillService::addSkillsToUser lors d'une affectation à un métier.
  4. Infrastructure/Service/User/UserSkillService.php ajoute les compétences manquantes, avec lots de 100 dans l'implémentation inspectée. Cela n'établit pas un remplacement des évaluations individuelles par la maîtrise attendue du métier.

Les consommateurs interceptent Throwable, consignent le contexte critique via CatchEvent et renvoient un rejet. Relances du broker, files de rejet, planification et latence de production non vérifiées. Retirer une relation ne doit pas être supposé supprimer symétriquement les compétences individuelles ou annuler les évaluations. Une réponse API réussie ne confirme pas que tous les collaborateurs sont déjà actualisés.

Frontière AIhub et intégrations externes​

aihub/src/entity/job/imports/data_sources/import_jobs_sm.py::import_jobs_from_sm extrait les relations métier–compétence, descriptions, statuts et niveaux requis, avec sélection par défaut actif/statut visible dans l'import inspecté. create_job_description et create_skills_list normalisent le contenu ; src/entity/job/imports/import_jobs_process.py::standardize_job_batch appelle la standardisation asynchrone. L'ingestion de compétences suit une chaîne séparée : src/entity/skill/import_service.py::import_skills → process_all_skills.

Cela prouve une filiation d'import/standardisation, pas un rafraîchissement AIhub immédiat à chaque sauvegarde ni un bouton Lexi client. Sources en exécution, planification, modèles/fournisseurs activés, quotas et retour des résultats vers le catalogue non vérifiés. Ne pas exposer les détails de connexion dans les journaux ou la documentation.

Legacy JobBundle/Controller/DefaultController.php::jobgenerateAction concerne une intégration ATS/Teamtailor dans la source inspectée, pas un générateur IA général de fiches métiers. Export et PDF sont des chemins distincts ; aucun export, appel externe ou traitement IA exécuté.

Configuration, dépendances et extensions​

Le guide de configuration sépare responsable et génération. Les clés legacy conditionnent filtres direction/famille/évolutions/qualification/classification, codes automatiques, recommandations et format d'export. Les défauts effectifs de l'entreprise n'ont pas été récupérés. Les champs Job SmartEditor sont contextuels (bo/fo) ; ajouter un filtre impose de vérifier schéma, requête et traduction dans les routes concernées.

Nextgen dépend de son runtime Symfony/API, de Doctrine, du contexte entreprise/sécurité et des consommateurs pour la propagation. AIhub utilise ses propres extractions et standardisations. Des noms de tables communs ne prouvent pas une connectivité partagée. Pour étendre le domaine, suivre route → droit → validation/mapping DTO → dépôt isolé → listener/consommateur, puis les clients API/UI avant de changer identifiants ou échelles.

Erreurs, observabilité et confidentialité​

SymptômePoint d'investigation vérifié / limite
Catalogue manager plus largeRoutes/requêtes différentes, entreprise, traduction, actif, statut et masquage. Ne pas diagnostiquer depuis la seule case d'un référentiel.
Accès API refuséPermission exacte et entreprise courante ; contrat Behat 403.
Doublon ou relation invalideUnicité et existence dans l'entreprise du DTO ; 400 attendu avec informations de paramètres invalides.
Suppression de référentiel refuséeReferentielListener::preDelete, ReferentielManager::isDeletable, recherche de référentiel inutilisé ; erreur Cannot delete the referential.
Compétences individuelles absentes après ajoutPublication, consommation et journaux critiques/rejets ; aucun engagement synchrone.
Résultats vides dans une langueJointures de traduction et contenu réel de la langue ; cause observée non diagnostiquée.
Dérive d'identité à l'importCodes externes stables, correspondance des remplacements et évaluations séparées ; récupération automatique non établie.

Limiter les journaux au contexte technique nécessaire ; profils, motivations et évaluations sont des données personnelles distinctes. Les indicateurs de présentation public/masqué ne remplacent pas l'autorisation. Aucun compte de test, secret, chaîne de connexion ou identifiant d'infrastructure n'est nécessaire dans les pages client.

Preuves, tests et limites​

  • Vérifié dans le code : chemins et symboles cités, revue des quatre dépôts locaux le 15 octobre 2026. Aucune version de déploiement ni base commune déduite.
  • Tests lus, non exécutés : nextgen tests/Behat/Features/V1/{job,skill,skill_group,referential,job_skill}/crud.feature et contraintes pertinentes. Aucune source applicative modifiée, aucune mutation API, aucun import, worker ou appel externe exécuté.
  • Documenté dans Confluence : playbook Jobs & Skills Framework, v8, 8 août 2023 ; guide d'import Lexi, v4, 28 mai 2026. Ils établissent l'intention métier/import, pas les endpoints déployés ni les échelles de l'API. Le guide de configuration signale les divergences des anciennes consignes Référentiels/Groupes.
  • L'entrée KBCT 2136702980 était inaccessible. Les entrées PS 2104033292 (Delivery Philosophy & Project Methodology, v7, 30 décembre 2025) et 2104983553 (Onboarding/learning and partner certification, v9, 18 février 2026) apportent un contexte méthodologique, pas une preuve d'implémentation.
  • Non vérifié : parité de l'éditeur nextgen, routage en exécution entre générations, stockage/synchronisation communs, exhaustivité réelle des droits, sérialisation complète des filtres, relances consommateurs, latence, calendrier AIhub et restauration après migration destructive.

Sources du guide fonctionnel​

Ces références d’implémentation et de produit étayent le guide fonctionnel. Le code local n’établit pas la révision ou les options déployées. Les observations dans l’application restent distinctes du code et des sources documentaires.

  • Observé dans l'application : smartmobility.io, 15 octobre 2026 ; session de test déjà authentifiée, espaces manager et personnel confirmés ; captures FR et EN séparées. Les en-têtes personnels et le navigateur ont été exclus des images. Une fiche métier brouillon synthétique et une relation métier-compétence ont été enregistrées dans le tenant de test, avec maîtrise attendue et importance réglées à 3. L’espace collaborateur Career planner s’est ouvert sans afficher de fiche ; visibilité et détail collaborateur ne sont donc pas confirmés. Deux compétences synthétiques ont été importées dans le catalogue avec la langue française par défaut de l’entreprise. Aucune évaluation individuelle n’a été modifiée.
  • Vérifié dans le code : legacy src/Company/JobBundle/Controller/DefaultController.php, modèle de liste métiers, web/assets_search/js/SearchCompanyJob.js, SearchActivities.js ; src/Customer/InternalJobBundle/Controller/{DefaultController,SearchController}.php, Services/SearchService.php et Resources/views/Partials/scripts.search.html.twig. Le guide technique détaille les API nextgen et la recherche limitée dans le front.
  • Documenté dans Confluence : Creating a job description, v3, 10 novembre 2022, pour le contenu, les compétences rattachées et l'intention de publication ; Importer un référentiel Lexi dans SmartMobility, v4, 28 mai 2026, pour la distinction entre exigences du référentiel et évaluations et la correspondance des remplacements. Ces procédures n'ont pas été exécutées.
  • Non vérifié : validations après sauvegarde, exports/imports, transfert/suppression de compétences, détail collaborateur, actions personnelles, traduction automatique, éditeur nextgen dédié et équivalence avec les déploiements. Les captures manquantes ne sont pas remplacées par celles d'une autre langue ou génération. L'entrée KBCT 2136702980 était inaccessible ; des pages pertinentes accessibles ont été utilisées. Les deux entrées PS fournies portent sur la méthodologie et l'onboarding, sans établir les règles de l'interface du référentiel.

Dernière mise à jour : 3 novembre 2026