# Certificacion

El modulo `Certificacion` mantiene informes BEA/A2A2, plantillas, versiones, comentarios, adjuntos y exportaciones formales. La UI usa `#modulo-bea`; las rutas internas conservan el prefijo historico `/api/reports`.

## Carcasa Y Navegación

La cabecera común concentra el estado del expediente y una única acción principal, `Generar manual`, mientras está abierta la entrada; al pasar a `Documento` esa acción se retira y quedan las herramientas propias del manual. `Modo visita`, `Limpiar formulario` y la documentación permanecen disponibles dentro de `Más`, evitando duplicar controles en la cabecera global y en el formulario. La guía `Cómo funciona` ya no ocupa una franja exterior: queda plegada dentro del paso `Datos` y resume expediente, procedimiento, registros y emisión solo cuando el usuario la solicita.

El workspace usa `master-detail` con las vistas `Expediente` y `Documento`. Dentro de `Expediente`, `#certificationPreparationSteps` muestra una sola fase cada vez:

1. `Datos`: tipo de certificación, idioma/normativa plegados, compañía, técnico, histórico y fecha.
2. `Explotación`: ubicación, producción, tamaño, alojamiento y acceso a pasto o patio.
3. `Ajustes`: prioridades, datos técnicos, campos propios de A2A2 o buenas prácticas, imagen corporativa y `#calidad` como control técnico plegado.

Los botones `Anterior` y `Siguiente`, las pestañas y las teclas `Flecha izquierda`, `Flecha derecha`, `Inicio` y `Fin` cambian de fase sin borrar el formulario. Los pasos informan si están pendientes, completos u opcionales. Los bloques avanzados y el específico de A2A2 nacen cerrados; seleccionar un tipo de certificación solo decide qué bloque existe, no lo abre automáticamente.

Si `generateManual()` detecta un campo obligatorio ausente, `certificationStepForField()` abre primero la fase correspondiente y `revealCertificationField()` despliega sus ancestros antes de enfocar el control. `language` y `companyName` llevan a `Datos`; `region`, `productionType`, `herdSize`, `housingSystem` y `pastureAccess` llevan a `Explotación`; `a2CertifiedAnimals` lleva a `Ajustes` y abre A2A2. Al cambiar de tipo se limpian las validaciones personalizadas de los bloques que quedan inactivos, de modo que un aviso A2A2 oculto nunca impide generar Bienestar, Pastoreo o Buenas prácticas. Al generar o cargar un manual se abre `Documento` a ancho completo, y `Limpiar formulario` cierra todos los plegables y vuelve a `Datos`. `data-ac-focus-both="hidden"` evita una vista simultánea que reduciría el documento sin aportar una comparación útil. El botón histórico `#generateSideBtn` sigue retirado; cualquier acceso ERP o atajo ejecuta `#generateTopBtn` para reutilizar el mismo flujo.

## Uso operativo

1. Entrar en `Certificacion` desde la barra lateral o abrir `#modulo-bea`.
2. Completar `Datos` y avanzar a `Explotación`; los campos opcionales permanecen en `Ajustes`.
3. Abrir `Control técnico` solo cuando se necesite revisar el score y los avisos, y generar el manual desde el último paso o desde la cabecera.
4. Editar el documento sin perder las funciones de formato, versiones, IA, comentarios, adjuntos o exportación.
5. Guardar para crear version en `reports` y `versions`.
6. Usar estados `draft`, `review`, `approved`, `issued` o `archived` segun el ciclo de revision.
7. Compartir enlace de cliente, exportar PDF/DOCX o duplicar el informe cuando proceda.
8. En `Tecnico responsable` y en los responsables avanzados de A2A2/Buenas practicas, elegir una sugerencia de usuario global con `reports.write` cuando exista o escribir manualmente el nombre externo que deba aparecer en el informe.
9. Tras generar o cargar un informe, usar `Charlie en documento` para pedir una propuesta sobre la seleccion, la seccion o el informe completo; `Canvas informe` abre el lienzo con KPIs, grafica de secciones, tabla de estructura y extracto editable.

## Verificacion De Interfaz

`tools/verify_certification_ui.py` recorre PC, Galaxy Tab A9+ e iPad Air. Comprueba navegación exterior, los tres pasos, botones y teclado, tipo A2A2, plegables cerrados, control técnico, salto automático al campo inválido, generación, reset, ausencia de overflow e IDs duplicados.

Con `--screenshots`, el verificador reutiliza `run_interaction_capture()` y conserva `capture-manifest.json`; no llama a `page.screenshot()`. `Datos`, `Explotación`, `Ajustes`, `Control técnico` y el documento generado exigen cobertura completa de scroll. El PNG principal es el viewport inicial real y el resto de la secuencia conserva cada desplazamiento; una imagen aislada ya no se acepta como evidencia.

## Vista De Documento Y Charlie

Cuando existe un manual activo, `#beaModule` entra en modo documento y la navegación enfocada abre la región `Documento`, para que la entrada y el panel de calidad no reduzcan ni entierren el preview. Las exportaciones de texto, HTML e impresión/PDF aparecen en la cabecera del documento cuando ya existe una salida.

El bloque `#reportAiQuickInstructionInput` es el acceso rapido al mismo flujo seguro de `improve_report_text`: copia la instruccion al panel `IA del informe`, registra el log de instrucciones y no modifica el documento hasta que el usuario pulsa `Aplicar` o `Insertar debajo`. `#openReportCanvasBtn` no llama al backend: construye el canvas desde el documento cargado en navegador, con paginas, secciones, palabras, grafica de peso por seccion y tabla de estructura.

Certificación monta su informe con `AnimalCharlieDocumentEditor.mount(...)` y perfil `report`: la toolbar compacta conserva formato, historial, tablas, imágenes, saltos, zoom, vista previa y pantalla completa, mientras el pegado inicial se adapta a la maquetación del informe. La banda exterior conserva únicamente funciones propias del módulo: navegación por secciones, bloqueo de apartados críticos, versiones, estados, `improve_report_text`, Canvas, comentarios, adjuntos y exportaciones trazables.

El logo corporativo y los adjuntos existentes ofrecen `Desde biblioteca` mediante
`AnimalCharlieAssetLibrary.mountFileInput(...)`; el recurso seleccionado recorre
los mismos validadores, relaciones de expediente y rutas de guardado que una
selección local. Las imágenes insertadas en el documento siguen llegando por el
montaje común del editor.

El antiguo `pro-editor.js` y la segunda toolbar de formato se retiraron. Cualquier capacidad documental general se añade al motor compartido; Certificación solo configura sus plantillas de tabla, imagen y salto de página.

## Permisos globales

Las rutas backend ya no dependen solo del rol legacy. Mantienen compatibilidad con `admin`, `technician` y `reviewer`, pero aceptan usuarios delegados con permisos globales:

| Permiso | Alcance |
| --- | --- |
| `reports.read` | Listar informes, consultar detalle, leer comentarios, leer plantillas y exportar PDF/DOCX de informes guardados. |
| `reports.write` | Crear, editar, duplicar, compartir, archivar/borrar informes, guardar plantillas y crear o resolver comentarios. |
| `reports.review` | Leer informes, crear o resolver comentarios y aprobar/emitir informes aunque el rol no sea `reviewer`. |

Reglas concretas:

- Lectura: `reports.read`, `reports.write` o `reports.review`.
- Escritura de informes, plantillas, duplicados y enlaces cliente: `reports.write`.
- Comentarios: `reports.write` o `reports.review`.
- Borrado/archivo de informes: `reports.write` o roles legacy `admin`/`technician`.
- Estados `approved` e `issued`: rol legacy `admin`/`reviewer` o permiso explicito `reports.review`.

## API interna

Todas las rutas internas, incluida `/api/pdf`, requieren cabecera de autorización de sesión; la exportación server-side queda limitada a usuarios con lectura de informes.

Entrada principal de lectura: `GET /api/reports`.

| Ruta | Metodo | Permiso | Descripcion |
| --- | --- | --- | --- |
| `/api/reports` | `GET` | `reports.read`/`reports.write`/`reports.review` | Lista informes guardados. |
| `/api/reports` | `POST` | `reports.write` | Crea o actualiza informe y version. |
| `/api/reports/{id}` | `GET` | `reports.read`/`reports.write`/`reports.review` | Devuelve informe completo con versiones, adjuntos y recetas enlazadas. |
| `/api/reports/{id}` | `DELETE` | `reports.write` | Borra informe y datos asociados. |
| `/api/reports/{id}/status` | `POST` | `reports.write` o `reports.review` | Cambia estado y audita `report_status_{estado}`. |
| `/api/reports/{id}/share` | `POST` | `reports.write` | Genera enlace de cliente. |
| `/api/reports/{id}/duplicate` | `POST` | `reports.write` | Duplica informe como borrador. |
| `/api/reports/{id}/pdf` | `POST` | lectura de informes | Exporta PDF de informe guardado. |
| `/api/reports/{id}/docx` | `POST` | lectura de informes | Exporta DOCX de informe guardado. |
| `/api/reports/{id}/attachments` | `GET` | lectura de informes | Lista adjuntos del informe. |
| `/api/reports/{id}/attachments` | `POST` | `reports.write` | Sube adjunto al informe. |
| `/api/reports/{id}/attachment/{attachmentId}` | `GET` | lectura de informes | Descarga adjunto autenticado. |
| `/api/comments` | `GET` | lectura de informes | Lista comentarios por `reportId`. |
| `/api/comments` | `POST` | `reports.write` o `reports.review` | Crea comentario interno o de revision. |
| `/api/comments/{id}` | `PUT`/`DELETE` | `reports.write` o `reports.review` | Resuelve, reabre o borra comentario. |
| `/api/templates` | `GET` | lectura de informes | Lista plantillas guardadas. |
| `/api/templates` | `POST` | `reports.write` | Crea o actualiza plantilla. |
| `/api/templates/{id}` | `DELETE` | `reports.write` | Borra plantilla. |
| `/api/module-user-access?module=bea&permission=reports.write&status=active` | `GET` | acceso efectivo a Certificacion | Devuelve `options[]` de usuarios operativos para el `datalist` compartido de responsables de informe, incluyendo `links.history` y `userHistoryUrl`. |

## Datos de responsables de informe

El formulario guarda responsables en el payload del informe: `data.technicianName`, `data.a2ProgramOwner`, `data.a2QualityRepresentative`, `data.gpQualityResponsible`, `data.gpVeterinaryResponsible` y `data.gpMilkingResponsible`. Esos campos siguen siendo texto libre porque se usan en firmas, manuales generados y expedientes historicos donde puede aparecer un tecnico externo, un colegiado, un turno o una persona no dada de alta como usuario.

La UI solo usa `GET /api/module-user-access?module=bea&permission=reports.write&status=active` para precargar sugerencias de usuarios internos con permiso real de escritura en informes. No persiste `username` ni cambia el esquema de `reports`: si un modulo necesita seleccionar responsables de Certificacion debe consumir el mismo endpoint y guardar el texto o identificador que ya espera su propio contrato. Al cargar un informe, los valores actuales del payload tambien se añaden como opciones locales para no ocultar historicos o responsables externos.

Cuando uno de esos campos coincide con una opcion global que trae `links.history` o `userHistoryUrl`, los botones `Histórico técnico`, `Histórico responsable`, `Histórico representante`, `Histórico calidad`, `Histórico veterinario` e `Histórico ordeño` abren `Usuarios > Auditoria` con `GET /api/users/{username}/history?module=bea`. Los botones permanecen desactivados para texto libre, colegiados externos o expedientes historicos sin usuario global.

## Consumo por otros modulos

Los modulos que enlacen informes, como Calendario, Acciones, Medicamentos, Clientes o Charlie, deben consultar permisos efectivos de `GET /api/permissions` y no duplicar roles propios. Si solo necesitan mostrar el informe, basta comprobar lectura (`reports.read`, `reports.write` o `reports.review`). Si van a modificar estados finales, deben exigir `reports.review` o delegar en `/api/reports/{id}/status`.

La auditoria queda normalizada con eventos `report_create`, `report_update`, `report_delete`, `report_share`, `report_status_*`, `comment_*`, `template_*`, `pdf_export` y `docx_export`, por lo que los historiales de usuario pueden filtrar el modulo `bea` sin reglas locales.
