Files
fn_registry/dev/issues/0092-kanban-done-archive.md
T

74 lines
3.1 KiB
Markdown

---
id: "0092"
title: "kanban: archivo automatico para cards en columnas Done con +30 dias"
status: pendiente
type: feature
domain:
- kanban
scope: multi-app
priority: media
depends: []
blocks: []
related: []
created: 2026-05-17
updated: 2026-05-17
tags: []
---
## Problema
Las columnas Done acumulan decenas de cards completadas que ya no participan en el trabajo activo. Lastran el board, gastan render (incluso con el split memoizado por perf) y obligan a scroll horizontal hasta el infinito sin aportar valor diario.
## Solucion
Archive `archived_at` por card (independiente de papelera `deleted_at`). Card archivada sale del board pero sigue en BD. Cajon "Hecho (archivo)" en el sidebar bajo Papelera con boton para sacar una card de vuelta a su columna Done.
### Migration
`apps/kanban/backend/migrations/012_card_archived.sql`:
```sql
ALTER TABLE cards ADD COLUMN archived_at TEXT;
```
`NULL` = card activa. ISO timestamp = card archivada.
### Backend
- `Card.ArchivedAt *string` json `archived_at`.
- `ListCardsWithTime` filtra `archived_at IS NULL`.
- `ArchiveCard(id)`, `UnarchiveCard(id)`, `ListArchivedCards()`.
- `AutoArchiveDoneOlderThan(d)`: UPDATE cards SET archived_at=now WHERE archived_at IS NULL AND deleted_at IS NULL AND column_id IN (SELECT id FROM columns WHERE is_done=1) AND id IN (SELECT card_id FROM card_column_history WHERE exited_at IS NULL AND entered_at < cutoff).
- `maybeAutoArchive(db)` con throttle `archiveSweepEvery = 30m` y `archiveAfter = 30d`. Disparado lazy desde `handleGetBoard`.
- Rutas:
- `GET /api/archive`
- `POST /api/cards/{id}/archive`
- `POST /api/cards/{id}/unarchive`
### Frontend
- Tipo `Card.archived_at: string | null`.
- `api.listArchive()` / `api.archiveCard(id)` / `api.unarchiveCard(id)`.
- `App` state `archive`, `archiveOpen`, `reloadArchive`, `handleArchiveCard`, `handleUnarchiveCard`. `reloadArchive` se llama tras login + tras archivar/desarchivar.
- UI: cajon "Hecho (archivo)" bajo "Papelera" en el sidebar. Toggle similar (`Badge` con conteo, `IconChevronRight/Down`). Solo boton "Restaurar" (`IconArrowBackUp`). No hay "purgar permanentemente" desde el archivo — solo borrado via card normal en su columna.
- `KanbanCard`: nuevo `Menu.Item` "Archivar" (`IconArchive` teal) condicionado a `isDone && onArchive` antes del divisor + Borrar.
### Tests
- Playwright `e2e/archive.spec.ts`: archivar manual via menu de card en columna done, asserta desaparece del board, abre cajon "Hecho", des-archiva, asserta vuelve al board.
- Auto-archive 30d sin test e2e (timing real no es practico). Cubierto por audit manual del flag `archiveAfter` y la query SQL.
## Criterios de aceptacion
- [ ] Cards con +30 dias en columna Done se auto-archivan tras la primera lectura del board (max 30m).
- [ ] Cajon "Hecho (archivo)" visible bajo Papelera. Muestra conteo.
- [ ] Boton "Restaurar" devuelve la card a su columna sin reset de historial.
- [ ] Menu de card en columna Done muestra "Archivar" para archivado manual.
- [ ] Cards archivadas NO aparecen en `/api/board`.
- [ ] E2E `archive.spec.ts` pasa.
## Rama / commits
- Rama: `issue/0092-kanban-done-archive`
- Merge `--no-ff` a master.