diff --git a/planes/plan_issue_11_informe_resultados_pdf.md b/documents/plans/plan_issue_11_informe_resultados_pdf.md
similarity index 100%
rename from planes/plan_issue_11_informe_resultados_pdf.md
rename to documents/plans/plan_issue_11_informe_resultados_pdf.md
diff --git a/issue_body.txt b/issue_body.txt
deleted file mode 100644
index 7cf6864..0000000
--- a/issue_body.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-## Descripción
-
-Actualmente, cuando se cancela una orden de laboratorio, las muestras asociadas permanecen activas y no se descartan automáticamente. Esto puede causar confusión ya que quedan muestras "huérfanas" en el sistema que ya no tienen una orden válida.
-
-## Comportamiento esperado
-
-Cuando se cancela una orden de laboratorio:
-1. Todas las muestras generadas asociadas a esa orden deben cambiar automáticamente su estado a "cancelled"
-2. Si hay pruebas (lims.test) asociadas a esas muestras, también deben cancelarse
-3. Se debe registrar en el chatter de la muestra que fue cancelada debido a la cancelación de la orden
-
-## Criterios de aceptación
-
-- [ ] Al cancelar una orden de laboratorio, todas sus muestras asociadas se marcan como canceladas
-- [ ] Las pruebas asociadas a las muestras también se cancelan
-- [ ] Se registra un mensaje en el chatter de cada muestra indicando la razón de cancelación
-- [ ] Si una muestra ya estaba cancelada o completada, no se modifica
-- [ ] La acción es reversible: si se vuelve a poner la orden en borrador, las muestras NO deben reactivarse automáticamente
-
-## Notas técnicas
-
-- El método a modificar es `action_cancel()` en el modelo `sale.order`
-- Verificar el campo `generated_sample_ids` para obtener las muestras asociadas
-- Solo cancelar muestras que estén en estados: 'pending_collection', 'collected', 'in_analysis'
\ No newline at end of file
diff --git a/issue_content.txt b/issue_content.txt
deleted file mode 100644
index 59ced20..0000000
--- a/issue_content.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-**Contexto:**
-Para poder implementar la automatización de generación de muestras (Issue #32), es necesario establecer una relación entre los productos tipo análisis y los tipos de muestra que requieren.
-
-**Problema Actual:**
-- Los productos tipo test (is_analysis=True) no tienen campo que indique qué tipo de muestra requieren
-- Los productos tipo muestra (is_sample_type=True) no están relacionados con los tests
-- El modelo stock.lot tiene container_type como Selection hardcodeado, no como relación
-
-**Tareas Requeridas:**
-
-1. **Modificar product.template:**
- - Agregar campo Many2one 'required_sample_type_id' que relacione análisis con tipo de muestra
- - Domain: [('is_sample_type', '=', True)]
-
-2. **Actualizar stock.lot:**
- - Opción A: Cambiar container_type de Selection a Many2one hacia product.template
- - Opción B: Agregar nuevo campo sample_type_product_id
- - Mantener compatibilidad con datos existentes
-
-3. **Actualizar vistas:**
- - Agregar campo en formulario de productos cuando is_analysis=True
- - Mostrar tipo de muestra requerida en vistas de análisis
-
-4. **Migración de datos:**
- - Mapear valores actuales de container_type a productos tipo muestra
- - Actualizar registros existentes
-
-5. **Actualizar demo data:**
- - Asignar tipos de muestra correctos a cada análisis
- - Ejemplo: Hemograma → Tubo EDTA, Glucosa → Tubo Suero
-
-**Beneficios:**
-- Permitirá automatizar la generación de muestras al confirmar órdenes
-- Evitará errores al saber exactamente qué contenedor usar para cada test
-- Facilitará la agrupación de análisis que usan el mismo tipo de muestra
-
-**Dependencia:**
-Este issue es prerequisito para poder implementar el Issue #32
\ No newline at end of file
diff --git a/lims_management/data/lims_sequence.xml b/lims_management/data/lims_sequence.xml
index 8179dbc..88df11a 100644
--- a/lims_management/data/lims_sequence.xml
+++ b/lims_management/data/lims_sequence.xml
@@ -11,5 +11,14 @@
+
+
+ Secuencia de Muestras de Laboratorio
+ stock.lot.serial
+ M-%(year)s%(month)s%(day)s-
+ 6
+
+
+
\ No newline at end of file
diff --git a/lims_management/demo/z_lims_demo.xml b/lims_management/demo/z_lims_demo.xml
index 3559a36..6159f77 100644
--- a/lims_management/demo/z_lims_demo.xml
+++ b/lims_management/demo/z_lims_demo.xml
@@ -10,8 +10,9 @@
Carga Inicial
1985-05-15
female
- +1-202-555-0174
+ +503 7234-5678
ana.torres@example.com
+ 03245678-9
@@ -21,8 +22,9 @@
Carga Inicial
1992-11-20
male
- +1-202-555-0192
+ +503 7892-3456
carlos.ruiz@example.com
+ 04567890-1
@@ -32,8 +34,9 @@
Carga Inicial
1978-03-10
female
- +1-202-555-0201
+ +503 7345-6789
maria.gonzalez@example.com
+ 01234567-8
@@ -41,7 +44,7 @@
Dr. Luis Herrera
L-98765
- +1-202-555-0145
+ +503 2234-5678
luis.herrera@hospital.com
@@ -49,14 +52,14 @@
Dra. Sofia Vargas
L-54321
- +1-202-555-0133
+ +503 2345-6789
sofia.vargas@clinic.com
Laura Mendoza
- +1-202-555-0188
+ +503 7456-7890
laura.mendoza@example.com
@@ -70,5 +73,562 @@
+
+
+ Sofía Jiménez
+
+ P-S45F04
+ Carga Inicial
+
+ female
+ +503 7567-8901
+
+
+
+ Diego Morales
+
+ P-D78M05
+ Carga Inicial
+
+ male
+ +503 7678-9012
+
+
+
+ Valentina Castro
+
+ P-V23F06
+ Carga Inicial
+
+ female
+ +503 7789-0123
+
+
+
+
+ Santiago Pérez
+
+ P-S90M07
+ Carga Inicial
+
+ male
+ +503 7890-1234
+
+
+
+ Isabella Rodríguez
+
+ P-I34F08
+ Carga Inicial
+
+ female
+ +503 7901-2345
+
+
+
+
+ Camila Fernández
+
+ P-C67F09
+ Carga Inicial
+ 1995-07-22
+ female
+
+ +503 7012-3456
+ camila.fernandez@example.com
+ 05678901-2
+
+
+
+ Alejandro Gutiérrez
+
+ P-A12M10
+ Carga Inicial
+ 1990-02-14
+ male
+ +503 7123-4567
+ alejandro.gutierrez@example.com
+ 06789012-3
+
+
+
+ Lucía Mendoza
+
+ P-L89F11
+ Carga Inicial
+ 1992-09-30
+ female
+
+ +503 7234-5678
+ 07890123-4
+
+
+
+ Miguel Ángel Silva
+
+ P-M45M12
+ Carga Inicial
+ 1988-11-05
+ male
+ +503 7345-6789
+ 08901234-5
+
+
+
+ Natalia Vargas
+
+ P-N78F13
+ Carga Inicial
+ 1996-04-18
+ female
+ +503 7456-7890
+ 09012345-6
+
+
+
+
+ Roberto Martínez
+
+ P-R23M14
+ Carga Inicial
+ 1975-06-12
+ male
+ +503 7567-8901
+ 00123456-7
+
+
+
+ Patricia López
+
+ P-P56F15
+ Carga Inicial
+ 1972-12-25
+ female
+ +503 7678-9012
+ 01234567-8
+
+
+
+ Fernando Díaz
+
+ P-F90M16
+ Carga Inicial
+ 1980-03-08
+ male
+ +503 7789-0123
+ 02345678-9
+
+
+
+ Andrea Herrera
+
+ P-A34F17
+ Carga Inicial
+ 1978-08-17
+ female
+
+ +503 7890-1234
+ 03456789-0
+
+
+
+
+ José Luis Ramírez
+
+ P-J67M18
+ Carga Inicial
+ 1965-01-20
+ male
+ +503 7901-2345
+ 04567890-1
+
+
+
+ Carmen Sánchez
+
+ P-C12F19
+ Carga Inicial
+ 1958-10-15
+ female
+ +503 7012-3456
+ 05678901-2
+
+
+
+ Ricardo Flores
+
+ P-R89M20
+ Carga Inicial
+ 1960-05-28
+ male
+ +503 7123-4567
+ 06789012-3
+
+
+
+
+ Esperanza Romero
+
+ P-E45F21
+ Carga Inicial
+ 1945-12-03
+ female
+ +503 7234-5678
+ 07890123-4
+
+
+
+ Francisco Aguilar
+
+ P-F78M22
+ Carga Inicial
+ 1943-07-19
+ male
+ +503 7345-6789
+ 08901234-5
+
+
+
+
+ Daniela Cortés
+
+ P-D23F23
+ Carga Inicial
+ 1998-02-11
+ female
+ +503 7456-7890
+ 09012345-6
+
+
+
+ Gabriel Moreno
+
+ P-G56M24
+ Carga Inicial
+
+ male
+ +503 7567-8901
+
+
+
+ Valeria Ruiz
+
+ P-V90F25
+ Carga Inicial
+ 1987-09-24
+ female
+
+ +503 7678-9012
+ 00123456-7
+
+
+
+ Eduardo Navarro
+
+ P-E34M26
+ Carga Inicial
+ 1970-11-30
+ male
+ +503 7789-0123
+ 01234568-8
+
+
+
+ Mariana Delgado
+
+ P-M67F27
+ Carga Inicial
+ 1999-06-07
+ female
+ +503 7890-1234
+ 02345679-9
+
+
+
+ Andrés Jiménez
+
+ P-A12M28
+ Carga Inicial
+ 1955-08-21
+ male
+ +503 7901-2345
+ 03456780-0
+
+
+
+ Paola Méndez
+
+ P-P89F29
+ Carga Inicial
+ 1991-03-16
+ female
+
+ +503 7012-3456
+ 04567891-1
+
+
+
+ Sebastián Vega
+
+ P-S45M30
+ Carga Inicial
+
+ male
+ +503 7123-4567
+
+
+
+ Claudia Paredes
+
+ P-C78F31
+ Carga Inicial
+ 1982-10-09
+ female
+ +503 7234-5678
+ 05678902-2
+
+
+
+ Raúl Castro
+
+ P-R23M32
+ Carga Inicial
+ 1948-04-27
+ male
+ +503 7345-6789
+ 06789013-3
+
+
+
+ Adriana Guerrero
+
+ P-A56F33
+ Carga Inicial
+ 1994-12-13
+ female
+
+ +503 7456-7890
+ 07890124-4
+
+
+
+ Javier Molina
+
+ P-J90M34
+ Carga Inicial
+
+ male
+ +503 7567-8901
+
+
+
+ Rosa María Ochoa
+
+ P-R34F35
+ Carga Inicial
+ 1962-01-05
+ female
+ +503 7678-9012
+ 08901235-5
+
+
+
+ Manuel Reyes
+
+ P-M67M36
+ Carga Inicial
+ 1976-07-31
+ male
+ +503 7789-0123
+ 09012346-6
+
+
+
+ Teresa Campos
+
+ P-T12F37
+ Carga Inicial
+ 1940-09-18
+ female
+ +503 7890-1234
+ 00123457-7
+
+
+
+ Pablo Espinoza
+
+ P-P89M38
+ Carga Inicial
+ 1989-05-03
+ male
+ +503 7901-2345
+ 01234569-8
+
+
+
+ Mónica Villanueva
+
+ P-M45F39
+ Carga Inicial
+ 1985-11-26
+ female
+
+ +503 7012-3456
+ 02345670-9
+
+
+
+ Diego Alejandro Luna
+
+ P-D78M40
+ Carga Inicial
+
+ male
+ +503 7123-4567
+
+
+
+ Beatriz Salazar
+
+ P-B23F41
+ Carga Inicial
+ 1968-02-14
+ female
+ +503 7234-5678
+ 03456781-0
+
+
+
+ Héctor Valdés
+
+ P-H56M42
+ Carga Inicial
+ 1973-06-29
+ male
+ +503 7345-6789
+ 04567892-1
+
+
+
+ Silvia Peña
+
+ P-S90F43
+ Carga Inicial
+ 1997-08-11
+ female
+ +503 7456-7890
+ 05678903-2
+
+
+
+ Arturo Domínguez
+
+ P-A34M44
+ Carga Inicial
+ 1951-12-07
+ male
+ +503 7567-8901
+ 06789014-3
+
+
+
+ Gloria Ríos
+
+ P-G67F45
+ Carga Inicial
+ 1983-04-22
+ female
+
+ +503 7678-9012
+ 07890125-4
+
+
+
+ Emilio Núñez
+
+ P-E12M46
+ Carga Inicial
+
+ male
+ +503 7789-0123
+
+
+
+ Laura Patricia Ibarra
+
+ P-L89F47
+ Carga Inicial
+ 1979-10-16
+ female
+ +503 7890-1234
+ 08901236-5
+
+
+
+ Óscar Medina
+
+ P-O45M48
+ Carga Inicial
+ 1966-03-25
+ male
+ +503 7901-2345
+ 09012347-6
+
+
+
+ Verónica Soto
+
+ P-V78F49
+ Carga Inicial
+ 1993-07-08
+ female
+
+ +503 7012-3456
+ 00123458-7
+
+
+
+ Rubén Contreras
+
+ P-R23M50
+ Carga Inicial
+ 1937-11-14
+ male
+ +503 7123-4567
+ 01234560-8
+
+
+
+ Alejandra Fuentes
+
+ P-A56F51
+ Carga Inicial
+
+ female
+ +503 7234-5678
+
+
+
+ Nicolás Ramos
+
+ P-N90M52
+ Carga Inicial
+ 1986-01-19
+ male
+ +503 7345-6789
+ 02345671-9
+
+
+
+ Fernanda Acosta
+
+ P-F34F53
+ Carga Inicial
+ 2000-05-12
+ female
+ +503 7456-7890
+ 03456782-0
+
+
\ No newline at end of file
diff --git a/pr_body_10.txt b/pr_body_10.txt
deleted file mode 100644
index d8673a2..0000000
--- a/pr_body_10.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-## Descripción
-Implementación del sistema de etiquetas con código de barras para las muestras de laboratorio.
-
-## Cambios realizados
-
-### Funcionalidad principal
-- Creado reporte QWeb para imprimir etiquetas de muestras (100x50mm)
-- Implementado botón 'Imprimir Etiquetas' en órdenes de laboratorio
-- Las etiquetas incluyen:
- - Información del paciente
- - Código de muestra y orden
- - Tipo de contenedor
- - Fecha de recolección
- - Código de barras Code128
- - Lista de análisis a realizar
-
-### Correcciones técnicas
-- **Código de barras**: Corregido problema de visualización usando widget nativo de Odoo 18
-- **Caracteres especiales**: Solucionado problema de codificación UTF-8 con referencias numéricas
-- **Layout**: Ajustado diseño para mostrar múltiples etiquetas por página sin solapamiento
-- **Espaciado**: Optimizado el tamaño y posición del código de barras
-
-## Testing
-- Probado con órdenes que tienen múltiples muestras
-- Verificado que los códigos de barras se generen y visualicen correctamente
-- Confirmado que los caracteres en español (tildes, ñ) se muestren bien
-- Validado que no hay solapamiento entre etiquetas
-
-## Capturas
-- Los códigos de barras ahora se visualizan correctamente
-- Las etiquetas respetan el formato 100x50mm
-- Múltiples etiquetas por página sin problemas de diseño
diff --git a/pr_body_54.txt b/pr_body_54.txt
deleted file mode 100644
index f942676..0000000
--- a/pr_body_54.txt
+++ /dev/null
@@ -1,74 +0,0 @@
-## Descripción
-
-Implementación de la funcionalidad para cancelar automáticamente muestras y pruebas cuando se cancela una orden de laboratorio, evitando que queden elementos "huérfanos" en el sistema.
-
-## 🎯 Objetivo
-
-Resolver el issue #54: Las muestras y pruebas asociadas a una orden de laboratorio deben cancelarse automáticamente cuando se cancela la orden.
-
-## 🔧 Cambios implementados
-
-### 1. Modelo `stock.lot` (Muestras)
-- Agregado nuevo estado `'cancelled'` a la selección de estados
-- Implementado método `action_cancel()` para cambiar el estado a cancelado
-
-### 2. Modelo `sale.order` (Órdenes)
-- Override del método `action_cancel()` que:
- - Llama primero al método padre para mantener el comportamiento estándar
- - Si es una orden de laboratorio (`is_lab_request = True`):
- - Cancela muestras en estados: `pending_collection`, `collected`, `received`, `in_process`
- - Cancela pruebas asociadas que no estén en estado `validated` o `cancelled`
- - Registra mensajes en el chatter de cada elemento cancelado
- - Muestra un resumen en la orden con la cantidad de elementos cancelados
-
-### 3. Tests unitarios
-- Creado `test_order_cancel_cascade.py` con 6 tests que verifican:
- - ✅ Cancelación correcta de muestras
- - ✅ Cancelación correcta de pruebas
- - ✅ No cancelación de muestras en estados finales (analyzed, stored, disposed)
- - ✅ No cancelación de pruebas validadas
- - ✅ Generación de mensajes en chatter
- - ✅ Órdenes normales (no laboratorio) no afectadas
-
-## 🧪 Pruebas realizadas
-
-### Test manual exitoso:
-```
-📦 Muestras generadas:
- - 0000012: Contenedor de Heces (Estado: pending_collection)
-
-🔬 Pruebas generadas:
- - LAB-2025-00014: Coprocultivo (Estado: draft)
-
-❌ Cancelando la orden de laboratorio...
-
-📦 Estado final de las muestras:
- - 0000012: cancelled ✓
-
-🔬 Estado final de las pruebas:
- - LAB-2025-00014: cancelled ✓
-
-✅ Mensajes de cancelación registrados en todos los elementos
-```
-
-## 📋 Checklist
-
-- [x] Código implementado y probado
-- [x] Tests unitarios creados
-- [x] Pruebas manuales exitosas
-- [x] Mensajes en chatter funcionando
-- [x] Sin errores o warnings
-- [x] Documentación en código
-
-## 🔍 Cómo probar
-
-1. Crear una orden de laboratorio con análisis
-2. Confirmar la orden (se generan muestras y pruebas)
-3. Opcionalmente iniciar proceso en alguna prueba
-4. Cancelar la orden
-5. Verificar que:
- - Las muestras cambiaron a estado "Cancelada"
- - Las pruebas cambiaron a estado "Cancelado"
- - Hay mensajes en el chatter explicando la cancelación
-
-Resuelve #54
\ No newline at end of file
diff --git a/pr_body_9.txt b/pr_body_9.txt
deleted file mode 100644
index fa45958..0000000
--- a/pr_body_9.txt
+++ /dev/null
@@ -1,48 +0,0 @@
-## Implementación del flujo de validación y seguridad
-
-### Cambios realizados
-
-#### 1. Ajuste de permisos base (ir.model.access.csv)
-- Recepcionista: Solo lectura en lims.test y lims.result
-- Técnico: Lectura/escritura pero sin crear/eliminar
-- Administrador: Permisos completos
-
-#### 2. Reglas de registro implementadas (lims_security.xml)
-- Recepcionistas no pueden editar pruebas
-- Técnicos solo pueden editar pruebas no validadas
-- Administradores tienen acceso completo
-
-#### 3. Validación de permisos en transiciones (lims_test.py)
-- `action_start_process()`: Solo técnicos y administradores
-- `action_enter_results()`: Solo técnicos y administradores
-- `action_validate()`: Solo administradores
-- `action_cancel()`: Técnicos (excepto validadas) y administradores
-- `action_draft()`: Solo administradores
-
-#### 4. Trazabilidad mejorada
-- stock.lot ahora hereda de mail.thread
-- Todos los cambios de estado se registran en el chatter
-- Mensajes más descriptivos con contexto
-
-#### 5. Validaciones adicionales
-- Control de transiciones de estado válidas
-- Verificación del estado de la muestra
-- Validación de resultados críticos fuera de rango
-- No se puede crear pruebas en estado != draft sin ser admin
-
-#### 6. Vistas actualizadas
-- Botones visibles solo para roles apropiados
-- Campos de resultados editables solo por técnicos/admin
-
-#### 7. Usuarios demo para pruebas
-- Usuario: `recepcionista` / Contraseña: `demo`
-- Usuario: `tecnico` / Contraseña: `demo`
-- Usuario: `administrador` / Contraseña: `demo`
-
-### Pruebas realizadas
-- Verificación de permisos por rol
-- Validación de transiciones de estado
-- Trazabilidad en chatter
-- Restricciones visuales en formularios
-
-Closes #9
\ No newline at end of file
diff --git a/test/create_lab_requests.py b/test/create_lab_requests.py
index 226bc25..741e650 100644
--- a/test/create_lab_requests.py
+++ b/test/create_lab_requests.py
@@ -1,5 +1,198 @@
import odoo
import json
+import random
+from datetime import datetime
+
+# Diccionario de notas médicas para parámetros críticos
+CRITICAL_NOTES = {
+ 'glucosa': {
+ 'high': 'Valor elevado de glucosa. Posible prediabetes o diabetes. Se recomienda repetir la prueba en ayunas y consultar con endocrinología.',
+ 'low': 'Hipoglucemia detectada. Riesgo de síntomas neuroglucogénicos. Evaluar causas: medicamentos, insuficiencia hepática o endocrinopatías.'
+ },
+ 'hemoglobina': {
+ 'high': 'Policitemia. Evaluar posibles causas: deshidratación, tabaquismo, cardiopatía o policitemia vera.',
+ 'low': 'Anemia severa. Investigar origen: deficiencia de hierro, pérdida sanguínea, hemólisis o enfermedad crónica.'
+ },
+ 'hematocrito': {
+ 'high': 'Hemoconcentración. Correlacionar con hemoglobina. Descartar deshidratación o policitemia.',
+ 'low': 'Valor compatible con anemia. Evaluar junto con hemoglobina e índices eritrocitarios.'
+ },
+ 'leucocitos': {
+ 'high': 'Leucocitosis marcada. Descartar proceso infeccioso, inflamatorio o hematológico.',
+ 'low': 'Leucopenia severa. Riesgo de infecciones. Evaluar causas: viral, medicamentosa o hematológica.'
+ },
+ 'plaquetas': {
+ 'high': 'Trombocitosis. Riesgo trombótico. Descartar causa primaria vs reactiva.',
+ 'low': 'Trombocitopenia severa. Riesgo de sangrado. Evaluar PTI, hiperesplenismo o supresión medular.'
+ },
+ 'neutrofilos': {
+ 'high': 'Neutrofilia. Sugiere infección bacteriana o proceso inflamatorio agudo.',
+ 'low': 'Neutropenia. Alto riesgo de infección bacteriana. Evaluar urgentemente.'
+ },
+ 'linfocitos': {
+ 'high': 'Linfocitosis. Considerar infección viral o proceso linfoproliferativo.',
+ 'low': 'Linfopenia. Evaluar inmunodeficiencia o efecto de corticoides.'
+ },
+ 'colesterol total': {
+ 'high': 'Hipercolesterolemia. Riesgo cardiovascular elevado. Iniciar medidas dietéticas y evaluar tratamiento con estatinas.',
+ 'low': 'Hipocolesterolemia. Evaluar malnutrición, hipertiroidismo o enfermedad hepática.'
+ },
+ 'trigliceridos': {
+ 'high': 'Hipertrigliceridemia severa. Riesgo de pancreatitis aguda. Considerar tratamiento farmacológico urgente.',
+ 'low': 'Valor bajo, generalmente sin significado patológico.'
+ },
+ 'hdl': {
+ 'high': 'HDL elevado, factor protector cardiovascular.',
+ 'low': 'HDL bajo. Factor de riesgo cardiovascular. Recomendar ejercicio y cambios en estilo de vida.'
+ },
+ 'ldl': {
+ 'high': 'LDL elevado. Alto riesgo aterogénico. Evaluar inicio de estatinas según riesgo global.',
+ 'low': 'LDL bajo, generalmente favorable.'
+ },
+ 'glucosa en sangre': {
+ 'high': 'Hiperglucemia. Si en ayunas >126 mg/dL sugiere diabetes. Confirmar con segunda muestra.',
+ 'low': 'Hipoglucemia. Evaluar síntomas y causas. Riesgo neurológico si <50 mg/dL.'
+ }
+}
+
+def get_critical_note(param_name, value, normal_min=None, normal_max=None):
+ """Obtiene la nota apropiada para un resultado crítico"""
+ param_lower = param_name.lower()
+
+ # Buscar el parámetro en el diccionario
+ for key in CRITICAL_NOTES:
+ if key in param_lower:
+ if normal_max and value > normal_max:
+ return CRITICAL_NOTES[key].get('high', f'Valor crítico alto para {param_name}. Requiere evaluación médica inmediata.')
+ elif normal_min and value < normal_min:
+ return CRITICAL_NOTES[key].get('low', f'Valor crítico bajo para {param_name}. Requiere evaluación médica inmediata.')
+
+ # Nota genérica si no se encuentra el parámetro
+ if normal_max and value > normal_max:
+ return f'Valor significativamente elevado. Rango normal: {normal_min}-{normal_max}. Se recomienda evaluación médica.'
+ elif normal_min and value < normal_min:
+ return f'Valor significativamente bajo. Rango normal: {normal_min}-{normal_max}. Se recomienda evaluación médica.'
+
+ return 'Valor fuera de rango normal. Requiere interpretación clínica.'
+
+def process_order_tests(env, order):
+ """Process all tests for a given order: regenerate results, fill values, and validate"""
+ print(f"\nProcessing tests for order {order.name}...")
+
+ # First, update sample states to allow processing
+ samples = order.generated_sample_ids.sudo()
+ for sample in samples:
+ if sample.state == 'pending_collection':
+ sample.action_collect()
+ print(f" - Sample {sample.name} collected")
+ if sample.state == 'collected':
+ sample.action_receive()
+ print(f" - Sample {sample.name} received")
+ if sample.state == 'received':
+ sample.action_start_analysis()
+ print(f" - Sample {sample.name} analysis started")
+
+ # Find all tests associated with this order
+ tests = env['lims.test'].search([('sale_order_id', '=', order.id)])
+ print(f"Found {len(tests)} tests for order {order.name}")
+
+ # Ensure we have the right permissions by using sudo()
+ tests = tests.sudo()
+
+ for test in tests:
+ try:
+ print(f"\nProcessing test {test.name} - {test.product_id.name}")
+
+ # First, mark the test as in_process if it's in draft state
+ if test.state == 'draft':
+ test.write({'state': 'in_process'})
+
+ # Manually create results if they don't exist
+ if not test.result_ids:
+ # Get analysis parameters from product template
+ product_tmpl = test.product_id.product_tmpl_id
+ for param_link in product_tmpl.parameter_ids:
+ param = param_link.parameter_id
+ result = env['lims.result'].create({
+ 'test_id': test.id,
+ 'parameter_id': param.id,
+ })
+ # Immediately set a value to avoid validation errors
+ if param.value_type == 'numeric':
+ # Generar valor que a veces esté fuera de rango
+ if random.random() < 0.3: # 30% de valores críticos
+ # Obtener rangos normales del parámetro
+ normal_min = param_link.normal_min if hasattr(param_link, 'normal_min') and param_link.normal_min else 10
+ normal_max = param_link.normal_max if hasattr(param_link, 'normal_max') and param_link.normal_max else 100
+
+ # Decidir si será alto o bajo
+ if random.random() < 0.5:
+ # Valor alto
+ value = round(random.uniform(normal_max * 1.2, normal_max * 1.5), 2)
+ else:
+ # Valor bajo
+ value = round(random.uniform(normal_min * 0.5, normal_min * 0.8), 2)
+ result.value_numeric = value
+ else:
+ result.value_numeric = 50.0
+ elif param.value_type == 'text':
+ result.value_text = "Normal"
+ elif param.value_type == 'boolean':
+ result.value_boolean = False
+ elif param.value_type == 'selection' and param.selection_options:
+ options = param.selection_options.split(',')
+ result.value_selection = options[0].strip()
+ print(f" - Created {len(product_tmpl.parameter_ids)} result fields")
+
+ # Evaluar resultados críticos y agregar notas
+ for result in test.result_ids:
+ # Leer el registro para actualizar campos computados
+ result.read(['is_critical'])
+
+ # Si el resultado es crítico, agregar nota
+ if result.is_critical and result.parameter_id.value_type == 'numeric':
+ value = result.value_numeric
+ param_name = result.parameter_id.name
+
+ # Obtener rangos del rango aplicable si existe
+ normal_min = normal_max = None
+ if result.applicable_range_id:
+ normal_min = result.applicable_range_id.normal_min
+ normal_max = result.applicable_range_id.normal_max
+
+ # Obtener la nota apropiada
+ note = get_critical_note(param_name, value, normal_min, normal_max)
+ result.write({'notes': note})
+ print(f" - Agregada nota crítica para {param_name}: valor {value}")
+
+ print(f" - Results ready with values and critical notes")
+
+ # Update test state directly to bypass permission checks
+ if test.state == 'in_process':
+ # Mark as results entered
+ test.write({
+ 'state': 'result_entered'
+ })
+ print(f" - Results entered")
+
+ # Then validate the test
+ if test.state == 'result_entered':
+ test.write({
+ 'state': 'validated',
+ 'validator_id': env.user.id,
+ 'validation_date': datetime.now()
+ })
+ print(f" - Test validated successfully")
+
+ except Exception as e:
+ print(f" - Error processing test {test.name}: {str(e)}")
+ import traceback
+ traceback.print_exc()
+ print(f" - Test state: {test.state}")
+ print(f" - Product template: {test.product_id.product_tmpl_id.name}")
+ print(f" - Parameters: {len(test.product_id.product_tmpl_id.parameter_ids)}")
+
+ print(f"\nCompleted processing tests for order {order.name}")
def create_lab_requests(cr):
env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
@@ -48,6 +241,9 @@ def create_lab_requests(cr):
# Confirm the order to test automatic sample generation
order1.action_confirm()
print(f"Confirmed Lab Order 1. Generated samples: {len(order1.generated_sample_ids)}")
+
+ # Process tests for order1
+ process_order_tests(env, order1)
# Create Lab Request 2 - Different sample types
if patient2 and glucosa and urocultivo:
@@ -65,6 +261,9 @@ def create_lab_requests(cr):
order2.action_confirm()
print(f"Confirmed Lab Order 2. Generated samples: {len(order2.generated_sample_ids)}")
+ # Process tests for order2
+ process_order_tests(env, order2)
+
except Exception as e:
print(f"Error creating lab requests: {str(e)}")
import traceback