# Plan de Desarrollo - Issue #11: Informe Final de Resultados en PDF

## Resumen del Issue
Crear una plantilla de reporte QWeb compleja y profesional para el informe de resultados de laboratorio, con capacidad de resaltar valores fuera de rango, incluir datos del laboratorio y paciente, y guardarse automáticamente como adjunto.

## Análisis de Requerimientos

### Componentes del Reporte
1. **Encabezado**
   - Logo del laboratorio
   - Datos del laboratorio (nombre, dirección, teléfono)
   - Datos del paciente (nombre, ID, edad, sexo)
   - Número de orden y fecha

2. **Sección de Resultados**
   - Agrupación por tipo de análisis
   - Tabla con columnas: Parámetro | Resultado | Unidad | Valor de Referencia
   - Resaltado visual de valores fuera de rango (color/símbolo)
   - Indicación especial para valores críticos

3. **Sección de Comentarios**
   - Observaciones generales de la orden
   - Notas específicas por resultado si las hay

4. **Pie del Informe**
   - Datos del profesional validador (nombre, título, registro)
   - Fecha y hora de validación
   - Firma digital o espacio para firma

### Requisitos Técnicos
- Botón "Imprimir Informe de Resultados" solo activo cuando todas las pruebas estén en estado "validated"
- PDF generado se guarda automáticamente como adjunto en la orden
- Formato profesional y limpio

## Estructura de Archivos a Crear/Modificar

### 1. Reporte QWeb
```
lims_management/
├── reports/
│   ├── lab_results_report.xml         # Plantilla QWeb del reporte
│   └── lab_results_report_data.xml    # Definición del reporte y paper format
```

### 2. Modelos a Modificar
```
lims_management/
├── models/
│   └── sale_order.py                  # Agregar método para generar reporte
```

### 3. Vistas a Modificar
```
lims_management/
├── views/
│   └── sale_order_views.xml           # Agregar botón de impresión
```

### 4. Manifest
```
lims_management/
├── __manifest__.py                    # Agregar archivos de reportes
```

## Implementación Detallada

### Fase 1: Estructura Base del Reporte

#### 1.1 Definir Paper Format Personalizado
```xml
<!-- lab_results_report_data.xml -->
<record id="paperformat_lab_results" model="report.paperformat">
    <field name="name">Formato Resultados de Laboratorio</field>
    <field name="format">A4</field>
    <field name="orientation">Portrait</field>
    <field name="margin_top">40</field>
    <field name="margin_bottom">25</field>
    <field name="margin_left">10</field>
    <field name="margin_right">10</field>
    <field name="header_spacing">35</field>
</record>
```

#### 1.2 Definir Acción del Reporte
```xml
<record id="action_report_lab_results" model="ir.actions.report">
    <field name="name">Informe de Resultados</field>
    <field name="model">sale.order</field>
    <field name="report_type">qweb-pdf</field>
    <field name="report_name">lims_management.report_lab_results</field>
    <field name="report_file">lims_management.report_lab_results</field>
    <field name="paperformat_id" ref="paperformat_lab_results"/>
    <field name="attachment">'Resultados_Lab_' + object.name + '.pdf'</field>
    <field name="attachment_use">True</field>
</record>
```

### Fase 2: Plantilla QWeb del Reporte

#### 2.1 Estructura Principal
```xml
<!-- lab_results_report.xml -->
<template id="report_lab_results">
    <t t-call="web.html_container">
        <t t-foreach="docs" t-as="o">
            <t t-call="lims_management.report_lab_results_document"/>
        </t>
    </t>
</template>
```

#### 2.2 Documento Individual
```xml
<template id="report_lab_results_document">
    <div class="page">
        <!-- Encabezado -->
        <div class="header">
            <!-- Logo y datos del laboratorio -->
            <!-- Datos del paciente -->
        </div>
        
        <!-- Cuerpo con resultados -->
        <div class="body">
            <!-- Iterar por pruebas validadas -->
            <t t-foreach="o.lab_test_ids.filtered(lambda t: t.state == 'validated')" t-as="test">
                <!-- Tabla de resultados -->
            </t>
        </div>
        
        <!-- Pie con validación -->
        <div class="footer">
            <!-- Datos del validador -->
        </div>
    </div>
</template>
```

### Fase 3: Lógica del Modelo

#### 3.1 Método para Verificar Estado
```python
# En sale_order.py
@api.depends('lab_test_ids.state')
def _compute_can_print_results(self):
    for order in self:
        tests = order.lab_test_ids
        order.can_print_results = (
            tests and 
            all(test.state == 'validated' for test in tests)
        )

can_print_results = fields.Boolean(
    compute='_compute_can_print_results',
    string="Puede Imprimir Resultados"
)
```

#### 3.2 Método para Generar y Adjuntar PDF
```python
def action_print_lab_results(self):
    """Genera el informe de resultados y lo adjunta"""
    self.ensure_one()
    
    # Verificar que todas las pruebas estén validadas
    if not self.can_print_results:
        raise ValidationError("No se puede imprimir: hay pruebas sin validar")
    
    # Generar el reporte
    return self.env.ref('lims_management.action_report_lab_results').report_action(self)
```

### Fase 4: Botón en la Vista

```xml
<!-- En sale_order_views.xml -->
<xpath expr="//header" position="inside">
    <button name="action_print_lab_results" 
            string="Imprimir Informe de Resultados" 
            type="object" 
            class="btn-primary"
            invisible="not can_print_results or not is_lab_request"/>
</xpath>
```

### Fase 5: Estilos CSS para el Reporte

#### 5.1 Estilos para Resaltado
```xml
<style>
    .result-out-of-range {
        color: #d9534f;
        font-weight: bold;
    }
    
    .result-critical {
        background-color: #f2dede;
        color: #a94442;
        font-weight: bold;
    }
    
    .result-normal {
        color: #5cb85c;
    }
</style>
```

#### 5.2 Aplicación Condicional
```xml
<td t-attf-class="#{result.is_critical and 'result-critical' or result.is_out_of_range and 'result-out-of-range' or 'result-normal'}">
    <t t-esc="result.value_display"/>
</td>
```

### Fase 6: Datos Demo para Pruebas

Crear script Python que:
1. Genere órdenes con múltiples análisis
2. Ingrese resultados variados (normales, fuera de rango, críticos)
3. Valide las pruebas
4. Permita probar la generación del PDF

## Consideraciones Especiales

### 1. Manejo de Caracteres Especiales
- Usar entidades HTML para tildes y ñ en el reporte
- Ejemplo: `&#205;` para Í, `&#241;` para ñ

### 2. Códigos de Barras
- Usar widget nativo de Odoo 18: `t-options="{'widget': 'barcode', 'type': 'Code128'}"`
- NO usar rutas deprecated como `/report/barcode/`

### 3. Agrupación de Resultados
- Agrupar por tipo de análisis para mejor legibilidad
- Mantener orden por secuencia definida en parámetros

### 4. Seguridad
- Solo usuarios con permisos de lectura en órdenes pueden generar el reporte
- El PDF se adjunta con permisos heredados de la orden

## Secuencia de Implementación

1. **Crear estructura base de reportes**
   - Crear carpeta reports/
   - Definir paper format y acción

2. **Implementar plantilla QWeb básica**
   - Estructura HTML con secciones
   - Iterar sobre pruebas y resultados

3. **Agregar lógica en modelo**
   - Campo computado can_print_results
   - Método action_print_lab_results

4. **Integrar botón en vista**
   - Agregar botón con visibilidad condicional

5. **Implementar estilos y resaltado**
   - CSS para valores fuera de rango
   - Clases condicionales en plantilla

6. **Configurar adjunto automático**
   - Configurar attachment en ir.actions.report
   - Verificar guardado en ir.attachment

7. **Crear datos demo y probar**
   - Script para generar casos de prueba
   - Validar formato y contenido del PDF

## Validación y Pruebas

### Casos de Prueba
1. **Orden sin pruebas validadas**: Botón invisible
2. **Orden parcialmente validada**: Botón invisible
3. **Orden completamente validada**: Botón visible, genera PDF
4. **Valores normales**: Sin resaltado
5. **Valores fuera de rango**: Resaltado en color
6. **Valores críticos**: Resaltado especial
7. **PDF adjunto**: Verificar que se guarda en la orden

### Criterios de Aceptación
- [ ] Reporte muestra todos los datos requeridos
- [ ] Valores fuera de rango se resaltan correctamente
- [ ] Botón solo visible cuando todas las pruebas están validadas
- [ ] PDF se genera con formato profesional
- [ ] PDF se adjunta automáticamente a la orden
- [ ] Datos del validador aparecen correctamente
- [ ] Comentarios y observaciones se muestran si existen

## Notas Técnicas

- Usar Odoo 18 syntax para invisibility: `invisible="not can_print_results"`
- Verificar compatibilidad con wkhtmltopdf para renderizado PDF
- Considerar tamaño del archivo para órdenes con muchos análisis
- El attachment_use=True garantiza que no se regenere si ya existe