Appearance
BDD-159 — Organiser les Sources Heriade publiées en dossiers
1. User Story
En tant qu'utilisateur, je veux pouvoir organiser mes Sources Heriade publiées dans des dossiers nommés (ex. RH, Finance), afin de retrouver facilement les sources disponibles lors de la configuration d'un workflow.
2. Critères d'acceptance
| # | Critère | Statut |
|---|---|---|
| 1 | Lors de la publication d'une Source Heriade (bloc Destination), un champ "Dossier" optionnel est affiché sous le champ "Nom de la source" | ✅ |
| 2 | L'utilisateur peut saisir un nom de dossier existant ou en créer un nouveau | ✅ |
| 3 | Le champ "Dossier" propose en autocomplétion les dossiers déjà existants pour l'entreprise | ✅ |
| 4 | Si aucun dossier n'est renseigné, la source est publiée sans dossier | ✅ |
| 5 | Dans le sélecteur de Source Heriade (bloc Source), les sources sont affichées groupées par dossier ; les sources sans dossier apparaissent dans un groupe "Sans dossier" | ✅ |
| 6 | Les dossiers sont scoped par entreprise : un utilisateur ne voit que les dossiers de son entreprise | ✅ |
| 7 | La valeur du dossier est conservée entre les versions d'une même source (v1, v2, v3...) | ✅ |
3. Décision de conception : un champ dédié, pas le modèle folders
Le modèle Prisma folders existant sert au dépôt de fichiers clients : structure hiérarchique (parent_id/children), un seul dossier racine actif par entreprise (contrainte d'unicité partielle), created_by obligatoire. Le réutiliser pour organiser des Sources Heriade aurait :
- cassé la contrainte "1 dossier racine par entreprise" (les dossiers "RH", "Finance", etc. seraient tous des racines) ;
- mélangé deux concepts métier distincts (espace de fichiers déposés vs étiquette d'organisation d'une source).
Choix retenu : un champ texte simple et optionnel heriade_folder sur sources, sans hiérarchie ni entité dédiée. Le libellé utilisateur reste "Dossier" mais le nom technique est différent pour éviter toute confusion avec folders / folderName (déjà utilisé par les sources de type DOCUMENT).
4. Périmètre fonctionnel
Base de données
| Fichier | Rôle |
|---|---|
sql/tool_24_add_heriade_folder_to_sources.sql | Ajoute sources.heriade_folder (VARCHAR(255), nullable) + index (enterprise_id, heriade_folder) |
back/prisma/schema.prisma | Modèle sources : champ heriade_folder String? |
Backend
| Fichier | Rôle |
|---|---|
back/src/api/workflows/staging/workflow-heriade-publish.service.ts | publishFromStaging() accepte heriadeFolder ; persisté à la création et lors d'un overwrite |
back/src/api/workflows/staging/workflow-destination-run.service.ts | DestinationConfig.heriadeFolder lu depuis la configuration du nœud et transmis au service de publication |
back/src/api/sources/sources.controller.ts | Nouvel endpoint GET /sources/workflow-published/folders (autocomplétion, scope entreprise) |
back/src/api/sources/sources.service.ts | listWorkflowPublishedFolders() : dossiers distincts, triés, scopés par entreprise |
back/src/api/sources/dto/workflow-published-folders.dto.ts | WorkflowPublishedFoldersResponseDto |
back/src/api/sources/dto/source.dto.ts | SourceResponseDto.heriadeFolder |
back/src/api/sources/source.presenter.ts | Expose heriadeFolder dans la réponse GET /sources |
Frontend
| Fichier | Rôle |
|---|---|
front/src/components/workflows/WorkflowDestinationPanel.vue | Champ "Dossier" (q-select autocomplétion + saisie libre) affiché sous "Nom de la source Heriade" |
front/src/pages/admin/workflows/workflow-destination.engine.js | heriadeFolder ajouté à la configuration normalisée (réinitialisé si outputType !== 'publish_heriade') |
front/src/composables/useWorkflowPublishedFolders.js | Appel GET /sources/workflow-published/folders |
front/src/components/workflows/WorkflowHeriadeSourcePanel.vue | Sélecteur de Source Heriade groupé par dossier |
front/src/pages/admin/workflows/workflow-heriade-source-grouping.engine.js | Logique pure de regroupement/tri/filtre (groupHeriadeSourcesByFolder, buildGroupedHeriadeSourceOptions) |
5. Comportement de persistance entre versions (critère 7)
Le dossier est stocké dans la configuration du nœud Destination (workflow_nodes.configuration.heriadeFolder), au même titre que publishSourceName. Tant que l'utilisateur ne modifie pas le champ, chaque nouvelle exécution du workflow republie avec la même valeur de dossier — aucune logique serveur d'héritage supplémentaire n'est nécessaire (le serveur reçoit et persiste simplement la valeur courante à chaque publication, y compris lors de la création d'une nouvelle version v2, v3...).
6. Format de configuration JSONB (bloc Destination)
json
{
"type": "destination",
"outputType": "publish_heriade",
"publishSourceName": "Résultat RH 2026",
"heriadeFolder": "RH",
"lastResult": null
}7. Tests
Backend
| Fichier | Couverture |
|---|---|
back/src/api/workflows/staging/workflow-heriade-publish.service.spec.ts | Persistance du dossier (création, overwrite), valeur vide → null, absence de dossier → null |
back/src/api/sources/sources.service.spec.ts | listWorkflowPublishedFolders : dédoublonnage, tri alphabétique, scope entreprise |
back/test/e2e/sources-controller.e2e-spec.ts | GET /sources/workflow-published/folders : 401 sans jeton, 403 rôle client externe, 200 scopé entreprise |
Frontend
| Fichier | Couverture |
|---|---|
front/src/__tests__/pages/admin/workflows/workflow-destination.engine.spec.js | heriadeFolder réinitialisé hors publish_heriade, trim, valeur par défaut null |
front/src/__tests__/composables/useWorkflowPublishedFolders.spec.js | Appel API, réponse mal formée, résilience en cas d'erreur |
front/src/__tests__/pages/admin/workflows/workflow-heriade-source-grouping.engine.spec.js | Regroupement, tri, groupe "Sans dossier", filtre par nom |
8. Hors périmètre
- Renommage ou fusion de dossiers existants (pas de gestion dédiée des dossiers, uniquement une étiquette texte par source).
- Application du champ Dossier aux sources
DOCUMENT/API_FORM(limité aux sourcesWORKFLOW_PUBLISHED).
