diff --git a/docs/superpowers/specs/2026-03-12-task-archiving-design.md b/docs/superpowers/specs/2026-03-12-task-archiving-design.md index c5aa1b0..013e8de 100644 --- a/docs/superpowers/specs/2026-03-12-task-archiving-design.md +++ b/docs/superpowers/specs/2026-03-12-task-archiving-design.md @@ -10,26 +10,44 @@ Permettre d'archiver des tickets individuels (quand leur statut est final) et de - Nouveau champ `isFinal: bool` (default `false`) - Mis à `true` sur le statut "Terminé" dans les fixtures -- Exposé en lecture via API Platform +- Exposé en lecture et écriture via API Platform (groupes de sérialisation `task_status:read`, `task_status:write`, et `task:read`) - Permet d'identifier dynamiquement quels statuts autorisent l'archivage ### Task — ajout `archived` - Nouveau champ `archived: bool` (default `false`) -- Filtre API Platform `archived` (exact) pour requêter `?archived=false` ou `?archived=true` +- Filtre API Platform `BooleanFilter` sur `archived` pour requêter `?archived=false` ou `?archived=true` - Le kanban charge les tickets avec `archived=false` - La page archives charge les tickets avec `archived=true` ### TaskGroup — ajout `archived` - Nouveau champ `archived: bool` (default `false`) -- Filtre API Platform `archived` (exact) +- Filtre API Platform `BooleanFilter` sur `archived` - Le kanban et le filtre groupe n'affichent que les groupes `archived=false` ### Migration Une migration Doctrine unique pour les 3 champs (`task_status.is_final`, `task.archived`, `task_group.archived`). +## Backend — logique métier + +### Archivage de groupe (bulk) + +L'archivage d'un groupe est une opération frontend multi-appels : +1. PATCH chaque ticket du groupe avec `{ archived: true }` +2. PATCH le groupe avec `{ archived: true }` + +Pas de endpoint custom côté backend — on réutilise les PATCH existants. + +### Permissions + +L'archivage suit le modèle de permissions existant : les opérations PATCH sur Task et TaskGroup requièrent `ROLE_ADMIN`. Pas de règle supplémentaire. + +### Pas de validation backend sur `isFinal` + +La règle "archiver seulement si statut final" est appliquée côté frontend (visibilité du bouton). Pas de State Processor dédié — cohérent avec le reste de l'app qui ne valide pas les transitions de statut côté serveur. + ## Frontend ### TaskDrawer — archivage et modale suppression @@ -37,6 +55,7 @@ Une migration Doctrine unique pour les 3 champs (`task_status.is_final`, `task.a **Bouton "Archiver"** : - Visible uniquement quand le ticket a un statut avec `isFinal: true` - PATCH `{ archived: true }` sur le ticket +- Si un timer est actif sur ce ticket, l'arrêter avant d'archiver - Ferme le drawer et rafraîchit la liste des tickets **Bouton "Désarchiver"** : @@ -65,24 +84,33 @@ Une migration Doctrine unique pour les 3 champs (`task_status.is_final`, `task.a **Toggle "Voir les groupes archivés"** : bascule pour afficher les groupes archivés. **Bouton "Archiver" sur un groupe** : -- Visible uniquement si **tous** les tickets du groupe ont un statut `isFinal: true` -- Archive le groupe (`archived: true`) + tous ses tickets d'un coup +- Visible uniquement si le groupe a au moins un ticket ET que **tous** ses tickets ont un statut `isFinal: true` (un ticket sans statut bloque l'archivage) +- Archive tous les tickets du groupe puis le groupe lui-même (appels PATCH séquentiels) - Rafraîchit la liste **Bouton "Désarchiver" sur un groupe archivé** : -- Désarchive le groupe + tous ses tickets +- Désarchive le groupe + tous ses tickets (écrase l'état individuel des tickets) - Rafraîchit la liste +### Admin — toggle `isFinal` sur les statuts + +- Ajout d'un checkbox/toggle "Statut final" dans l'AdminStatusTab (création et édition de statuts) +- Permet aux admins de configurer quels statuts sont considérés comme finaux + ### Kanban — filtrage - Le filtre groupe dans le dropdown n'affiche que les groupes `archived=false` - Les tickets `archived=true` sont exclus du kanban +### Time tracking + +- Les entrées de temps liées à des tickets archivés restent visibles dans les vues time-tracking (pas de changement) + ## DTOs ### TaskStatus -Ajout du champ `isFinal: boolean` dans le type `TaskStatus`. +Ajout du champ `isFinal: boolean` dans les types `TaskStatus` et `TaskStatusWrite`. ### Task @@ -100,9 +128,11 @@ Clés à ajouter dans `fr.json` : - `group.archive` / `group.unarchive` - `group.show_archived` / `group.hide_archived` - `project.tabs.archives` +- `status.is_final` ## Hors périmètre - Historique/date d'archivage (pourra être ajouté plus tard avec un champ `archivedAt`) - Archivage automatique (cron/scheduler) - Archivage en masse depuis la page archives +- Verrouillage des tickets archivés (modification de statut, etc.)