docs(#11): Plan detallado para implementación de informe de resultados en PDF

This commit is contained in:
Luis Ernesto Portillo Zaldivar 2025-07-16 14:16:41 -06:00
parent fca7a187d9
commit b9cd21b2c2

View File

@ -0,0 +1,294 @@
# 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