Aller au contenu principal

Import et export — guide technique

Ce guide décrit les centres uniquement legacy, pour les équipes d’ingénierie, d’intégration et de support. Le guide fonctionnel présente les écrans observés et le guide de configuration distingue plateforme et administration client. Le code local établit une implémentation, pas sa version déployée ni la réussite d’un traitement réel.

Architecture et périmètre​

Vérifié dans le code : les deux centres reposent sur Symfony, Twig/jQuery et Doctrine dans smartmobility-legacy. L’import prépare des lignes avant d’appliquer les changements métier. L’export de campagnes suit un autre chemin asynchrone qui génère des fichiers privés et envoie un lien par e-mail. Les rapports d’import appartiennent au bundle ImportCenter et sont distincts de l’export des campagnes.

Aucun centre équivalent n’a été établi dans les recherches nextgen frontend/backend et aihub. Cela n’exclut pas des imports/exports distincts ailleurs. Aucune migration, passerelle de routage ou dépendance IA n’est vérifiée pour ces centres.

Composants​

Chemins relatifs à smartmobility-legacy/. Dans les lignes ImportCenter, … signifie src/Company/ImportCenterBundle.

Source / symboleResponsabilité
config/routes.yamlPréfixes /company/import-center et /company/export-center.
…/Controller/DefaultController.php::indexActionAccès, historique par entreprise, types et campagnes du formulaire.
…/Controller/ImportController.phpChargement, prévisualisation, lancement, suppression, correction préparée et revalidation.
…/Controller/MatchController.php::indexAction/updateActionChamps par type, langues/référentiels autorisés, associations obligatoires et tâche de validation.
…/Adapters/AdapterFactory.php::getImporterSélection d’un des 12 adaptateurs et injection du service métier.
…/Adapters/AbstractAdapter.php::importFile/validateRowStockage du fichier, métadonnées, soumission de l’analyse et validation de DTO.
…/Services/Imports/Création/mise à jour métier propre à chaque famille.
…/Services/ImportCenterUploadService.phpProjection de l’historique et transitions Symfony.
…/Services/ExcelDataExportService.phpRapport des erreurs et des modifications importées.
src/Command/ImportCenter/ImportCenter{ParseFile,ValidateRows,ImportRows}Command.phpAnalyse, validation et import asynchrones.
src/Company/ExportCenterBundle/Controller/DefaultController.php::indexActionAutorisation d’entrée et tableaux des campagnes de l’entreprise.
src/Company/ExportCenterBundle/Controller/ExportController.phpLancement des générateurs et ZIP de fichiers autorisés.
src/Command/Export/ExportCenter1to1Command.php, ExportReviewsCommand.phpGénération des classeurs, médias privés, File et e-mail.

Les interactions sont dans Resources/views/js/ de chaque bundle. Une navigation récente ne transforme pas ces pages rendues côté serveur en écrans nextgen.

Flux d’import​

Transfert et analyse​

ImportController::ImportFileAction attend une requête AJAX multipart avec file, file-type, active-sheet, interview-choice si nécessaire et _csrf_token. Il vérifie le voter d’import, le jeton import_center_csrf_token, le type dans AdapterFactory::IMPORT_TYPES, l’entretien pour les réponses et MediaService::isValidFile(..., MediaReference::SHEET_TYPE).

L’adaptateur déplace le fichier dans la zone transitoire, crée ImportCenterUpload pour le setting du demandeur, place PARSING et soumet ImportCenterParseFileCommand::NAME via CommandTaskRepository::push. Le succès signifie « préparé », pas « import métier terminé ».

Le parseur appelle PhpSpreadsheet IOFactory::load. La feuille est numérotée à partir de 1 dans l’interface puis convertie à partir de 0. Un index invalide revient à la première feuille. Les en-têtes de la ligne 1 s’arrêtent au premier vide, les données commencent ligne 2 et s’arrêtent à la première ligne entièrement vide. Les dates formatées utilisent leur représentation formatée ; les autres cellules deviennent des chaînes nettoyées. Aucun contrat de lecture de classeur arbitrairement clairsemé n’en découle.

Matching et validation​

MatchController choisit champs et indicateurs obligatoires dans les DTO. Il récupère selon le type langues de l’entreprise, référentiels publics et champs Smart Editor visibles. Les champs de réponses d’entretien dépendent de l’entretien sélectionné. Le JSON stocké associe champ cible → lettre de colonne source :

{
"jobs.title": "A",
"jobs.code": "B"
}

Exemple illustratif, non suffisant pour une requête complète : le formulaire fournit aussi les choix langue/référentiel et les clés de colonnes. Deux associations vers la même cible se réduisent à une seule clé ; il ne s’agit pas d’une fusion de colonnes prise en charge. Utilisateurs exige contacts. Le contrôleur vérifie certaines associations obligatoires ; les DTO et recherches de références ajoutent les contraintes ligne par ligne.

Le matching applique une transition, place VALIDATING et soumet app:import-center:validate-rows. Validité et erreurs des lignes préparées sont séparées des écritures métier ; une prévisualisation validée peut contenir des lignes valides et invalides.

Correction et exécution​

changeImportRowColumnValue reçoit key, value, row, recherche le chargement du setting courant, exige l’état validé et une ligne invalide, résout la colonne associée puis enregistre la correction. Le client l’appelle à la sortie du champ. La revalidation soumet une nouvelle tâche et revient à l’état de validation.

ImportAction contrôle le chargement de l’entreprise et la transition, place IMPORTING et soumet app:import-center:import-rows avec les identifiants du chargement et du demandeur. ImportCenterImportRowsCommand::importRows prend les lignes valides par lots de 500, les adapte et revalide, appelle le service métier, enregistre les changements et marque les lignes importées. Il effectue flush/clear entre lots ; certains services font aussi un flush. Il n’existe pas de transaction atomique couvrant tout le fichier. Un échec peut laisser des changements persistés ; aucune garantie générale de rollback ou d’idempotence ne doit être déduite.

Types et identification​

Les valeurs des constantes ImportCenterUpload::IMPORT_TYPE_* sont : skills, jobs, jobsOffers, jobsSkills, users, userCompanyHierarchicalRelationships, companyEntityGroupUsers, formations, formationsSkills, userCampaigns, userSkills, interviewAnswers. Les libellés traduits sont distincts.

IdentificationRequête vérifiée
Utilisateursrc/Repository/UserRepository.php::getUsersByUserRowQuery : setting + e-mail, jusqu’à deux résultats pour détecter une ambiguïté.
Emploisrc/Main/ConfigBundle/Repository/JobRepository.php::getJobsByJobRowQuery : setting + référentiel + code.
Compétencesrc/Main/ConfigBundle/Repository/SkillRepository.php::getSkillsBySkillRowQuery : setting + référentiel + code.
TraductionServices Jobs/Skills : locale du chargement pour la traduction ; elle ne fait pas partie de l’identité métier de base.

UsersService, JobsService et SkillsService::persistImportCenterRowDto refusent les correspondances ambiguës. Les imports de relations ont des services distincts ; Emplois&Compétences ne doit pas être supposé créer les références absentes. Les champs facultatifs utilisateur incluent activation, rôle et envoi d’identifiants : les effets dépassent le texte du profil.

Routes et contrats représentatifs​

Contrats legacy pour navigateur, pas API publique d’intégration. Les exemples ne doivent pas être exécutés en production pour vérifier la documentation.

Méthode / cheminContrat
GET /company/import-center/Historique et formulaire.
POST /company/import-center/uploadMultipart AJAX, droit et CSRF ; JSON de succès status, fileUploaded, data.
GET / POST /company/import-center/match/{id}Afficher / soumettre les associations et lancer la validation.
GET /company/import-center/preview/{id}Chargement validé de l’entreprise, sinon redirection.
POST /company/import-center/import/{id}Mise en file ; {"message":"success"} si transition acceptée, erreur type 404 sinon.
DELETE /company/import-center/import/{id}Suppression du chargement après contrôles AJAX/voter ; pas de rollback métier.
POST /company/import-center/import/{id}/change-import-row-column-valueCorrection préparée ; {"success":true}.
POST /company/import-center/import/{id}/revalidate-import-rowsRevalidation ; {"success":true}.
GET /company/import-center/import/{id}/export/{exportType}invalid_rows exige l’état validé ; imported_rows l’état importé. Informations de fichier JSON via SpreadsheetService::downloadToNav.
GET /company/export-center/Tableaux des campagnes autorisées.
/company/export-center/export/exportsfilesClient en POST AJAX avec data[module] et data[campaigns][] ; la route YAML ne limite pas elle-même la méthode.
GET /company/export-center/export/download/Paramètre files, tableau JSON d’identifiants File ; ZIP des fichiers autorisés.

Exemple illustratif avec identifiants fictifs :

data[module]=1to1
data[campaigns][]=101
data[campaigns][]=102

Modules : 1to1 et PR. Les réponses des helpers utilisent respectivement message ou response ; certaines branches vides/non traitées de exportDocumentsAction renvoient un succès générique. Ni ce JSON ni la fenêtre affichée avant la requête ne prouvent la génération.

Données et cycle de vie​

Entité / sourceDonnées
src/Entity/ImportCenterUpload.phpSetting, auteur, nom/taille/type, dates, statut/workflow, en-têtes source/associés, locale, référentiel, entretien facultatif.
src/Entity/ImportCenterUploadRow.phpNuméro et données source, validité/erreurs, indicateur importé et changements ; relation au chargement supprimée en cascade.
src/Entity/ImportCenterReferences.phpRéférences additionnelles dont type de campagne ; cascade vers le chargement.
src/Entity/ImportCenterUploadStatus.phpRéférentiel distinct de statuts.
src/Entity/ImportCenterUploadLog.php, ImportCenterUploadUserAction.phpTraces de traitement et d’actions ; conservation non établie.
Entité legacy File et générateursFichiers privés et créateur pour téléchargement ultérieur.

Constantes : 1 PARSING, 2 PARSED, 3 VALIDATING, 4 VALIDATED, 5 IMPORTING, 6 IMPORTED, 7 PARSING_FAILED, 8 VALIDATING_FAILED, 9 IMPORT_FAILED. Statut et workflow sont distincts. ImportCenterUploadService délègue les transitions à la machine d’état Symfony ; les contrôleurs/commandes mettent explicitement à jour le statut.

ImportCenterUploadStatusRepository::ALLOW_DELETE_STATUSES détermine l’affichage de la corbeille aux états analysé, validé, importé ou en échec. deleteAction supprime l’entité chargement, pas les entités métier. Il ne répète pas lui-même la liste d’états de l’interface. Cela n’établit ni nettoyage garanti du fichier physique source ni annulation automatique.

Génération et livraison des exports​

ExportCenterBundle/Controller/DefaultController::indexAction limite l’affichage aux campagnes du setting courant et exige droits/activation ainsi que campagnes existantes pour les onglets. Le tableau jQuery combine recherche globale et filtres exacts multiples de questionnaire/statut : OU entre valeurs, ET entre colonnes. La sélection globale utilise rows({search:'applied'}) ; la demande collecte les cases cochées dans ce même périmètre, au-delà de la seule page visible.

ExportController::exportDocumentsAction distribue selon le module. export1to1 / exportPR lancent les commandes PHP export-center:export1to1 et exportCenter:exportreviews en arrière-plan avec le runtime configuré. Ce n’est pas la file de tâches d’import.

Les générateurs créent des XLSX dans le stockage privé, enregistrent File puis envoient un lien. Le libellé CSV du bouton diffère du format du writer inspecté. Les feuilles et réponses prises en charge dépendent du module et de sa structure de questionnaire ; aucun aller-retour sans perte vers un import n’est établi.

exportDownloadAction décode les identifiants File, résout chaque fichier et ne l’inclut que si le setting de son créateur correspond à celui du demandeur. Il lit les médias, crée une archive ZIP temporaire, renvoie une pièce jointe puis supprime le ZIP après envoi. Le contrôle est au niveau de l’entreprise du créateur, sans restriction au seul propriétaire démontrée. Le nettoyage du ZIP ne supprime pas les médias source.

Configuration, autorisations et confidentialité​

Vérifié dans le code : config/configuration/feature_module.yml déclare les bases import_center_access=false et export_center_menu_display=true dans Reporting avancé. default_permission.yml place import et Gestion des données à false pour les rôles standards listés. Surcharges tenant et évaluation des modules déterminent l’accès effectif.

ImportCenterVoter::canView/canImport combine module et permission du compte concerné. VIEW, IMPORT et DELETE partagent la même règle de base. La page d’export exige export_center et export_center_menu_display, puis les droits/activations propres aux onglets.

Les contrôles se vérifient route par route : le CSRF explicite du chargement ne prouve pas un contrôle identique sur chaque mutation. La plupart des recherches de chargement vérifiées incluent le setting ; la suppression cherche directement l’identifiant. Les helpers de lancement d’export ne répètent pas tous les contrôles de la page d’accueil dans le contrôleur inspecté. Des protections globales peuvent s’appliquer ; leur couverture complète est non vérifiée. Ces limites sont des points de revue d’ingénierie autorisée, pas des procédures client ni une preuve de vulnérabilité déployée.

Lignes préparées, rapports de changements et fichiers de campagnes peuvent contenir des données personnelles. Limiter les accès, éviter les payloads dans les notes de support et suivre la politique de conservation convenue. Aucune durée, expiration de lien, propriété individuelle stricte ni politique universelle de masquage n’a été établie.

Échecs et observabilité​

CasContrôle
Chargement refuséAJAX, voter, CSRF, type, entretien, MediaService, MIME/taille navigateur. Le serveur conserve un TODO de validation supplémentaire.
Analyse bloquée/en échecConsommation de tâches, présence du fichier, format/feuille/en-têtes, PARSING_FAILED.
Validation en échecDTO, mapping, références, VALIDATING_FAILED.
Import partielIMPORT_FAILED, isImported et changes, persistance métier et lots ; rapprochement avant relance.
Code retour trompeurLes handlers d’échec des commandes d’import mettent à jour l’état et émettent PostCatchEvent mais les méthodes execute inspectées renvoient SUCCESS. Examiner états/événements, pas uniquement le code retour.
Export accepté sans e-mailProcessus de fond, File, médias et envoi ; fenêtre optimiste sans suivi d’achèvement.
ZIP sans fichier utilisableExistence, setting du créateur et lecture média ; réponse d’erreur si aucun chemin accepté.

Le logger d’import trace notamment UPLOAD, MATCH, IMPORT et DELETE. Les commandes émettent des événements d’erreur contextualisés. Tableaux de monitoring, latence, relances, délais processus et alertes déployées non inspectés.

Extensions et dépendances d’exécution​

Un nouveau type demande constantes/listes, adaptateur conforme, DTO et contraintes, service métier, options de matching, compatibilité prévisualisation/rapports et contrôles d’entreprise. AdapterFactory construit dynamiquement le nom de classe et injecte le service ; un libellé supplémentaire ne suffit pas. Définir explicitement doublons et effets sur les accès.

Un changement d’export doit aligner module, commande, writer, File et livraison. Dépendances : Symfony/Doctrine, consommation des tâches d’import, PhpSpreadsheet, stockage transitoire/privé accessible, exécution PHP en arrière-plan, ZIP et mail. Aucun service IA externe n’a été retracé pour ces centres.

Sources et limites​

  • Vérifié dans le code, 16 octobre 2026 : sources/symboles des tableaux, requêtes d’identification, ImportCenterUploadStatusRepository, scripts des deux bundles, ExportCenter1to1Command::import, ExportReviewsCommand::saveAndSendFile et fichiers de configuration cités. Chemins précis utilisés sans inventer de liens distants.
  • Observé dans l’application : éléments complémentaires du guide fonctionnel, dont navigation et limites de traduction. Aucune capture intégrée au guide technique.
  • Documenté dans Confluence : PS Users, Jobs, Skills, Job&Skills, v2 du 29 avril 2025 : traitement préparé/asynchrone et correction. Anciennes formulations première feuille/identité incohérentes ; parseur et requêtes actuels fondent ce guide.
  • KBCT fourni : 404. Pages PS méthodologie (v7 du 30 décembre 2025) et onboarding (v9 du 18 février 2026) lues sans contrat d’implémentation des centres.
  • Non vérifié : version déployée, exécution réelle, livraison, autorisation globale de toutes les routes, comportement de chaque importeur pour valeurs vides/mises à jour, conservation/relances et centre nextgen. Aucun dépôt applicatif, paramètre ou donnée modifié.

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, 16 octobre 2026, centres en français/anglais, historique, types, feuille initiale, campagne conditionnelle et sélection réversible. Navigation salarié inspectée séparément en anglais. Aucun chargement, envoi de matching, correction, import, suppression ou export exécuté.
  • Vérifié dans le code : legacy src/Company/ImportCenterBundle/, src/Command/ImportCenter/, src/Company/ExportCenterBundle/ et générateurs de src/Command/Export/. Voir la carte des sources techniques.
  • Documenté dans Confluence : PS Users, Jobs, Skills, Job&Skills, version 2, mises à jour le 29 avril 2025. Navigation Gestion des données ancienne, descriptions de première feuille et d’identification parfois incohérentes ; les écrans actuels et les requêtes vérifiées fondent ce guide.
  • Non vérifié : captures de matching, prévisualisation/correction et échecs ; contenu des fichiers réellement générés, délais, toutes les règles spécifiques aux types et version déployée. Les dossiers existants contenant des données de tenant n’ont pas été ouverts pour publication. Aucun centre nextgen équivalent documenté.
  • La référence KBCT:2136702980 a renvoyé 404. Les deux pages PS de méthodologie/onboarding fournies ont été lues mais ne définissent pas les centres.

Combinaisons des filtres et comportement du tableau vérifiés dans le code : Company/ImportCenterBundle/Resources/views/js/index.js.twig.

Dernière mise à jour : 3 novembre 2026