# Módulo Mejoras

El módulo `Mejoras` recoge ideas internas de evolución del producto y las guía
desde propuesta hasta cierre sin enseñar el alta, el detalle y las cuatro
columnas a la vez.

## Uso

- Abrir `Planificación > Mejoras`, `#mejoras`, el panel de módulos o el selector ERP.
- La entrada `Tablero` no muestra campos: enseña primero el trabajo existente.
- Pulsar una tarjeta abre `Idea`, donde viven descripción, autor, fecha,
  prioridad, imágenes/documentos y una sola copia de los movimientos de estado
  y `Borrar`.
- En la ficha, `Adjuntar` abre la biblioteca común limitada a Mejoras. Una
  imagen o documento recién subido se vincula al instante; también se puede
  reutilizar un recurso anterior del módulo con `Usar`.
- Cada adjunto conserva `Vista previa` cuando el formato es seguro, `Descargar`
  y `Quitar`. Quitar rompe solo el vínculo con la idea: el recurso permanece en
  la biblioteca para poder reutilizarlo. El selector no ofrece borrado
  permanente y la API rechaza eliminar un recurso mientras siga vinculado a
  una o más mejoras.
- Pulsar `Nueva idea` abre el alta en `Idea`; título, autor, prioridad y detalle
  ya no compiten con el tablero.
- El alta se conserva como borrador local mientras se vuelve al `Tablero`, se
  consulta otra ficha o se pulsa de nuevo `Nueva idea`. Al regresar se restaura
  completa y muestra `Borrador restaurado`.
- Marcar la prioridad de 1 a 5 y pulsar `Colgar idea`.
- Los movimientos nombran siempre el destino, por ejemplo `Mover a Valorando`
  o `Mover a En curso`; la etiqueta cambia al mismo tiempo que el estado.
- En PC se conservan las cuatro columnas y el arrastre entre estados.
- En Galaxy Tab A9+ e iPad Air se muestra una columna cada vez y se cambia con
  `Ideas / Valorando / En curso / Hecho`; la detección usa interacción táctil,
  no solo el ancho del viewport.
- Borrar pide confirmación y vuelve al tablero.

En tablets el tablero no necesita desplazamiento horizontal. Las tarjetas
ocupan todo el ancho útil, la descripción se limita en el tablero y se conserva
completa en la ficha. Una marca con contador indica qué tarjetas tienen
adjuntos; los archivos se revisan en la ficha para no recargar el kanban.

Los adjuntos son privados frente a accesos anónimos y visibles para todas las
cuentas que tengan acceso efectivo a `Mejoras`, incluido un perfil cliente
habilitado para ese módulo. No se deben usar para información que requiera un
ámbito más restringido. Cada idea admite hasta 20 adjuntos; el límite se
impone dentro de la transacción también ante altas simultáneas.

El borrador usa la clave versionada
`animalcharlie.improvements.draft.v1`. El controlador acepta
`draftStorage` y `draftStorageKey` para pruebas o adaptadores, y usa
`localStorage` únicamente dentro de operaciones protegidas: si el navegador lo
bloquea, el alta continúa funcionando sin lanzar errores. El contenido se
elimina en cuanto el `POST /api/improvements` termina correctamente, antes de
refrescar el tablero. Si falla la red, se mantienen formulario, prioridad,
modo de alta y borrador para poder reintentar.

## Estados

El tablero usa cuatro estados fijos:

- `new`: ideas recién propuestas.
- `review`: ideas que se están valorando.
- `doing`: mejoras en curso.
- `done`: mejoras terminadas o descartadas como cerradas.

## Controlador Frontend

La lógica visible vive en `module-improvements.js`, cargado antes de `app.js`.
El archivo expone `AnimalCharlieImprovementsModule.createController(...)` y
encapsula en una sola unidad el estado de ideas, la selección activa, el filtro
de estado táctil, los modos `detail / create`, prioridad, render del kanban,
creación, cambio de estado, confirmación de borrado, actualización manual y
drag-and-drop. También es dueño del borrador local y de las etiquetas dinámicas
de movimiento; estos estados no deben duplicarse en `app.js`.

`app.js` conserva únicamente dos adaptadores transversales:
`refreshImprovements()` para refrescos generales o acciones de Charlie y
`focusImprovementIdea(id)` para abrir un resultado de búsqueda. Sesión, API,
escape HTML, formato de fecha, foco `Tablero / Idea` y actualización de Inicio se inyectan al crear el
controlador; no deben volver a añadirse listeners de `#ideaForm` o `#ideaBoard`
al monolito.

`tools/verify_improvements_ui.py` comprueba los cuatro dispositivos, cero campos
en la carga inicial, una columna por estado en tablets, ficha exclusiva, alta
exclusiva, restauración y limpieza del borrador, destinos explícitos, fallo de
red sin pérdida y un CRUD temporal completo con movimiento y borrado. Si la copia está
vacía, crea una idea base temporal para verificar la apertura de ficha y la
elimina al terminar. Sus PNG se crean
mediante el capturador común y exigen cobertura completa y código fresco.

`tools/verify_improvements_controller.js` prueba el mismo contrato sin red ni
navegador: almacenamiento inyectado y bloqueado, restauración, error de POST,
limpieza después del éxito, actualización de los destinos al mover una idea y
el ciclo de vincular, previsualizar, descargar y quitar un adjunto.

La carga reutiliza `AnimalCharlieAssetLibrary.open(...)` con
`module=improvements`, `entityType=improvement_idea` y `moduleOnly=true`. La
apertura autenticada reutiliza `AnimalCharlieAttachmentPreview.open(...)`;
Mejoras no mantiene un cargador, modal ni allowlist paralelos. La relación de
negocio vive en `improvement_attachments`, mientras que el binario sigue siendo
un `shared_asset`. `tools/verify_improvements_attachments.py` comprueba en
datos temporales el aislamiento de módulo, el límite, las rutas autenticadas,
las cascadas y que quitar o borrar una idea no elimina el recurso común.

## API Interna

Las ideas se guardan en SQLite en la tabla `improvement_ideas`.

Endpoints:

- `GET /api/improvements`: lista ideas. Acepta `status` opcional.
- `POST /api/improvements`: crea o actualiza una idea si se pasa `id`.
- `PUT /api/improvements/{id}`: actualiza título, descripción, autor o estado.
- `DELETE /api/improvements/{id}`: borra la idea.
- `GET /api/improvements/{id}/attachments`: lista sus adjuntos.
- `POST /api/improvements/{id}/attachments`: vincula un `assetId` de Mejoras.
- `GET /api/improvements/{id}/attachments/{assetId}`: consulta sus metadatos
  seguros.
- `GET /api/improvements/{id}/attachments/{assetId}/preview`: abre una vista
  previa autenticada segura.
- `GET /api/improvements/{id}/attachments/{assetId}/download`: descarga el
  binario autenticado.
- `DELETE /api/improvements/{id}/attachments/{assetId}`: quita el vínculo sin
  borrar el recurso común.

Campos principales:

- `title`: obligatorio, máximo 140 caracteres.
- `description`: opcional, máximo 1200 caracteres.
- `author`: opcional, máximo 80 caracteres.
- `priority`: entero de `1` a `5`; si no se informa se guarda como `3`.
- `status`: `new`, `review`, `doing` o `done`.
- `attachments`: metadatos seguros, contador y rutas autenticadas; nunca rutas
  locales de almacenamiento.

Los endpoints usan la capa global de permisos: `GET /api/improvements` exige acceso efectivo al módulo `improvements` y las operaciones de escritura (`POST`, `PUT`, `DELETE`) exigen `improvements.write`. Los roles base `technician`, `reviewer`, `staff` y `client` lo incluyen para mantener el tablero como canal compartido de propuesta y seguimiento, mientras que usuarios personalizados pueden perderlo quitando el permiso. Cada cambio queda registrado en auditoría con `improvement_save`, `improvement_update` e `improvement_delete`.

## Consumo Por Otros Módulos

Otros módulos pueden enlazar a `#mejoras` usando `data-module-nav="improvements"` o `data-module-shortcut="improvements"`.

Para abrir una idea desde búsqueda global o desde Charlie, devuelve un resultado con `type: "mejora"`, `id`, `title` o `name`; el frontend abrirá el módulo y resaltará la tarjeta.
