fix(#67): Corregir widget de selección mostrando 'Sin Opciones' #68
26
comment_issue_67.txt
Normal file
26
comment_issue_67.txt
Normal file
|
@ -0,0 +1,26 @@
|
|||
## Información adicional tras investigación
|
||||
|
||||
Se confirmó que el método get_selection_list() en lims.analysis.parameter **funciona correctamente**:
|
||||
|
||||
```python
|
||||
# Ejemplo de uso:
|
||||
param = env['lims.analysis.parameter'].browse(36) # Prueba de Embarazo
|
||||
param.selection_values # 'Negativo,Positivo'
|
||||
param.get_selection_list() # ['Negativo', 'Positivo']
|
||||
```
|
||||
|
||||
### El problema real:
|
||||
|
||||
1. **En el modelo lims.result**:
|
||||
- value_selection es un campo Char simple
|
||||
- No hay implementación para obtener las opciones dinámicamente
|
||||
- En la línea 302-304 hay un comentario con pass que indica intención no implementada
|
||||
|
||||
2. **En la vista lims_test_views.xml**:
|
||||
- Usa widget="selection" en un campo Char
|
||||
- El widget espera opciones pero no las recibe
|
||||
|
||||
### Confirmación del bug:
|
||||
- get_selection_list() está disponible y funciona
|
||||
- El problema es que no se está usando para proporcionar opciones al widget
|
||||
- Se necesita implementar la conexión entre el método y la vista
|
BIN
documents/logs/Screenshot_8.png
Normal file
BIN
documents/logs/Screenshot_8.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
BIN
documents/logs/Screenshot_9.png
Normal file
BIN
documents/logs/Screenshot_9.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
48
issue_bug_selection.txt
Normal file
48
issue_bug_selection.txt
Normal file
|
@ -0,0 +1,48 @@
|
|||
## Descripción del problema
|
||||
|
||||
Se detectó un bug en la vista de resultados de pruebas donde el campo value_selection con widget selection aparece vacío y no muestra las opciones disponibles definidas en el parámetro.
|
||||
|
||||
## Detalles técnicos
|
||||
|
||||
### Síntomas:
|
||||
- En lims_test_views.xml, línea 92-93, el campo value_selection usa widget="selection"
|
||||
- El widget aparece vacío sin opciones disponibles
|
||||
- Los valores de selección están definidos en lims.analysis.parameter.selection_values (ej: 'Negativo,Positivo')
|
||||
- El campo no puede recibir valores porque no tiene opciones visibles
|
||||
|
||||
### Caso de ejemplo:
|
||||
- Test ID: 33
|
||||
- Resultado ID: 46
|
||||
- Parámetro: "Prueba de Embarazo"
|
||||
- Opciones en parámetro: 'Negativo,Positivo'
|
||||
- Valor actual en resultado: 'False' (incorrecto)
|
||||
|
||||
### Análisis realizado:
|
||||
Se identificaron 12 parámetros de tipo selection con opciones definidas:
|
||||
- Anticuerpos Hepatitis C: 'No Reactivo,Reactivo,Indeterminado'
|
||||
- Prueba de Embarazo: 'Negativo,Positivo'
|
||||
- Aspecto: 'Transparente,Ligeramente turbio,Turbio,Muy turbio'
|
||||
- Etc.
|
||||
|
||||
## Causa raíz
|
||||
|
||||
El widget selection en Odoo espera un campo de tipo Selection con opciones predefinidas, pero value_selection es un campo Char. Las opciones dinámicas del parámetro (selection_values) no se propagan automáticamente al widget.
|
||||
|
||||
## Impacto
|
||||
|
||||
- Los usuarios no pueden seleccionar valores para resultados de tipo selection
|
||||
- Los datos se guardan incorrectamente (ej: 'False' en lugar de 'Negativo' o 'Positivo')
|
||||
- Afecta la calidad de los datos y la usabilidad del sistema
|
||||
|
||||
## Soluciones propuestas
|
||||
|
||||
1. **Opción 1**: Cambiar el widget a text para permitir entrada manual
|
||||
2. **Opción 2**: Implementar un campo Selection dinámico que obtenga opciones del parámetro
|
||||
3. **Opción 3**: Crear un widget personalizado que lea selection_values del parámetro relacionado
|
||||
|
||||
## Archivos afectados
|
||||
- lims_management/views/lims_test_views.xml (línea 92-93)
|
||||
- lims_management/models/lims_result.py (campo value_selection)
|
||||
|
||||
## Prioridad
|
||||
Media-Alta: Afecta la funcionalidad básica de ingreso de resultados para ciertos tipos de análisis.
|
|
@ -15,7 +15,7 @@
|
|||
'author': "Gemini",
|
||||
'website': "https://gitea.grupoconsiti.com/luis_portillo/clinical_laboratory",
|
||||
'category': 'Industries',
|
||||
'version': '18.0.1.0.0',
|
||||
'version': '18.0.1.0.1',
|
||||
'depends': ['base', 'product', 'sale', 'base_setup'],
|
||||
'assets': {
|
||||
'web.assets_backend': [
|
||||
|
|
26
lims_management/migrations/18.0.1.0.1/post-migrate.py
Normal file
26
lims_management/migrations/18.0.1.0.1/post-migrate.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from odoo import api, SUPERUSER_ID
|
||||
|
||||
def migrate(cr, version):
|
||||
"""Migrate existing selection values from char field to selection field."""
|
||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||
|
||||
# Find all results with selection parameters that have values
|
||||
results = env['lims.result'].search([
|
||||
('parameter_value_type', '=', 'selection'),
|
||||
('value_selection', '!=', False),
|
||||
('value_selection', '!=', '')
|
||||
])
|
||||
|
||||
if results:
|
||||
cr.execute("""
|
||||
UPDATE lims_result
|
||||
SET value_selection_field = value_selection
|
||||
WHERE id IN %s
|
||||
AND parameter_value_type = 'selection'
|
||||
AND value_selection IS NOT NULL
|
||||
AND value_selection != ''
|
||||
""", (tuple(results.ids),))
|
||||
|
||||
# Log migration
|
||||
print(f"Migrated {len(results)} selection values from value_selection to value_selection_field")
|
Binary file not shown.
Binary file not shown.
|
@ -96,6 +96,13 @@ class LimsResult(models.Model):
|
|||
string='Valor de Selección'
|
||||
)
|
||||
|
||||
# Campo para mostrar las opciones disponibles
|
||||
selection_options_display = fields.Char(
|
||||
string='Opciones disponibles',
|
||||
compute='_compute_selection_options_display',
|
||||
help='Opciones válidas para este parámetro'
|
||||
)
|
||||
|
||||
value_boolean = fields.Boolean(
|
||||
string='Valor Sí/No'
|
||||
)
|
||||
|
@ -159,7 +166,7 @@ class LimsResult(models.Model):
|
|||
else:
|
||||
record.display_name = record.parameter_name or _('Nuevo')
|
||||
|
||||
@api.depends('value_numeric', 'value_text', 'value_selection', 'value_boolean', 'parameter_value_type')
|
||||
@api.depends('value_numeric', 'value_text', 'value_selection', 'value_selection_field', 'value_boolean', 'parameter_value_type')
|
||||
def _compute_value_display(self):
|
||||
"""Calcula el valor a mostrar según el tipo de dato."""
|
||||
for record in self:
|
||||
|
@ -171,7 +178,8 @@ class LimsResult(models.Model):
|
|||
elif record.parameter_value_type == 'text':
|
||||
record.value_display = record.value_text or ''
|
||||
elif record.parameter_value_type == 'selection':
|
||||
record.value_display = record.value_selection or ''
|
||||
# Use the new selection field value
|
||||
record.value_display = record.value_selection_field or record.value_selection or ''
|
||||
elif record.parameter_value_type == 'boolean':
|
||||
record.value_display = 'Sí' if record.value_boolean else 'No'
|
||||
else:
|
||||
|
@ -270,11 +278,21 @@ class LimsResult(models.Model):
|
|||
_('Para parámetros de texto solo se debe ingresar el valor de texto.')
|
||||
)
|
||||
elif value_type == 'selection':
|
||||
has_value = bool(record.value_selection)
|
||||
# Check both fields for backward compatibility
|
||||
has_value = bool(record.value_selection_field or record.value_selection)
|
||||
if (record.value_numeric not in [False, 0.0]) or record.value_text or record.value_boolean:
|
||||
raise ValidationError(
|
||||
_('Para parámetros de selección solo se debe elegir una opción.')
|
||||
)
|
||||
# Validar que el valor seleccionado sea válido
|
||||
actual_value = record.value_selection_field or record.value_selection
|
||||
if has_value and record.parameter_id:
|
||||
valid_options = record.parameter_id.get_selection_list()
|
||||
if valid_options and actual_value not in valid_options:
|
||||
raise ValidationError(
|
||||
_('El valor "%s" no es una opción válida. Opciones disponibles: %s') %
|
||||
(actual_value, ', '.join(valid_options))
|
||||
)
|
||||
elif value_type == 'boolean':
|
||||
has_value = True # Boolean siempre tiene valor (True o False)
|
||||
if (record.value_numeric not in [False, 0.0]) or record.value_text or record.value_selection:
|
||||
|
@ -301,4 +319,18 @@ class LimsResult(models.Model):
|
|||
# Si es selección, obtener las opciones
|
||||
if self.parameter_value_type == 'selection' and self.parameter_id.selection_values:
|
||||
# Esto se usará en las vistas para mostrar las opciones dinámicamente
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
@api.depends('parameter_id', 'parameter_id.selection_values')
|
||||
def _compute_selection_options_display(self):
|
||||
"""Calcula las opciones disponibles para mostrar al usuario."""
|
||||
for record in self:
|
||||
if record.parameter_id and record.parameter_value_type == 'selection':
|
||||
options = record.parameter_id.get_selection_list()
|
||||
if options:
|
||||
record.selection_options_display = ' | '.join(options)
|
||||
else:
|
||||
record.selection_options_display = 'Sin opciones definidas'
|
||||
else:
|
||||
record.selection_options_display = False
|
|
@ -206,13 +206,14 @@ class StockLot(models.Model):
|
|||
|
||||
def action_cancel(self):
|
||||
"""Cancel the sample"""
|
||||
old_state = self.state
|
||||
self.write({'state': 'cancelled'})
|
||||
self.message_post(
|
||||
body='Muestra cancelada por %s' % self.env.user.name,
|
||||
subject='Estado actualizado: Cancelada',
|
||||
message_type='notification'
|
||||
)
|
||||
for record in self:
|
||||
old_state = record.state
|
||||
record.write({'state': 'cancelled'})
|
||||
record.message_post(
|
||||
body='Muestra cancelada por %s' % self.env.user.name,
|
||||
subject='Estado actualizado: Cancelada',
|
||||
message_type='notification'
|
||||
)
|
||||
|
||||
def action_open_rejection_wizard(self):
|
||||
"""Open the rejection wizard"""
|
||||
|
|
|
@ -65,9 +65,8 @@
|
|||
decoration-warning="is_out_of_range and not is_critical"/>
|
||||
<field name="value_text"
|
||||
invisible="parameter_value_type != 'text'"/>
|
||||
<field name="value_selection"
|
||||
invisible="parameter_value_type != 'selection'"
|
||||
widget="selection"/>
|
||||
<field name="value_selection_field"
|
||||
invisible="parameter_value_type != 'selection'"/>
|
||||
<field name="value_boolean"
|
||||
invisible="parameter_value_type != 'boolean'"
|
||||
widget="boolean_toggle"/>
|
||||
|
|
|
@ -34,9 +34,8 @@
|
|||
decoration-warning="is_critical"/>
|
||||
<field name="value_text"
|
||||
invisible="parameter_value_type != 'text'"/>
|
||||
<field name="value_selection"
|
||||
invisible="parameter_value_type != 'selection'"
|
||||
widget="selection"/>
|
||||
<field name="value_selection_field"
|
||||
invisible="parameter_value_type != 'selection'"/>
|
||||
<field name="value_boolean"
|
||||
invisible="parameter_value_type != 'boolean'"
|
||||
widget="boolean_toggle"/>
|
||||
|
|
|
@ -88,10 +88,18 @@
|
|||
<field name="value_text"
|
||||
invisible="parameter_value_type != 'text'"
|
||||
class="oe_edit_only"/>
|
||||
<field name="parameter_id" invisible="1" force_save="1"/>
|
||||
<field name="value_selection"
|
||||
invisible="parameter_value_type != 'selection'"
|
||||
widget="selection"
|
||||
class="oe_edit_only"/>
|
||||
placeholder="Seleccione una opción"
|
||||
options="{'no_create': True, 'no_edit': True}"/>
|
||||
<field name="selection_options_display"
|
||||
invisible="parameter_value_type != 'selection'"
|
||||
readonly="1"
|
||||
nolabel="1"
|
||||
class="text-muted small"
|
||||
widget="text"
|
||||
style="font-size: 0.85em; color: #6c757d; margin-top: -5px;"/>
|
||||
<field name="value_boolean"
|
||||
invisible="parameter_value_type != 'boolean'"
|
||||
widget="boolean_toggle"
|
||||
|
|
151
test/analyze_selection_bug.py
Normal file
151
test/analyze_selection_bug.py
Normal file
|
@ -0,0 +1,151 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script para analizar el problema con selection_values en lims.test
|
||||
Específicamente para test.id: 33 y result.id: 43
|
||||
"""
|
||||
|
||||
import odoo
|
||||
import logging
|
||||
import json
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def analyze_selection_issue(env, test_id=33, result_id=43):
|
||||
"""Analizar el problema con selection_values"""
|
||||
|
||||
print("=" * 80)
|
||||
print("ANÁLISIS DE PROBLEMA CON SELECTION_VALUES")
|
||||
print("=" * 80)
|
||||
|
||||
# 1. Buscar el test específico
|
||||
test = env['lims.test'].browse(test_id)
|
||||
if not test.exists():
|
||||
print(f"\n❌ No se encontró el test con ID {test_id}")
|
||||
return
|
||||
|
||||
print(f"\n1. INFORMACIÓN DEL TEST:")
|
||||
print(f" - ID: {test.id}")
|
||||
print(f" - Nombre: {test.name}")
|
||||
print(f" - Producto: {test.product_id.name}")
|
||||
print(f" - Estado: {test.state}")
|
||||
print(f" - Número de resultados: {len(test.result_ids)}")
|
||||
|
||||
# 2. Buscar el resultado específico
|
||||
result = env['lims.result'].browse(result_id)
|
||||
if not result.exists():
|
||||
print(f"\n❌ No se encontró el resultado con ID {result_id}")
|
||||
return
|
||||
|
||||
print(f"\n2. INFORMACIÓN DEL RESULTADO:")
|
||||
print(f" - ID: {result.id}")
|
||||
print(f" - Test ID: {result.test_id.id}")
|
||||
print(f" - Parámetro: {result.parameter_id.name}")
|
||||
print(f" - Tipo de valor: {result.parameter_value_type}")
|
||||
print(f" - Valor actual (selection): '{result.value_selection}'")
|
||||
|
||||
# 3. Analizar el parámetro
|
||||
parameter = result.parameter_id
|
||||
print(f"\n3. INFORMACIÓN DEL PARÁMETRO:")
|
||||
print(f" - ID: {parameter.id}")
|
||||
print(f" - Nombre: {parameter.name}")
|
||||
print(f" - Código: {parameter.code}")
|
||||
print(f" - Tipo de valor: {parameter.value_type}")
|
||||
print(f" - Selection values: '{parameter.selection_values}'")
|
||||
|
||||
# 4. Si es tipo selection, analizar las opciones
|
||||
if parameter.value_type == 'selection':
|
||||
print(f"\n4. ANÁLISIS DE OPCIONES DE SELECCIÓN:")
|
||||
|
||||
# Verificar si selection_values está definido
|
||||
if parameter.selection_values:
|
||||
# Parsear las opciones
|
||||
options = [opt.strip() for opt in parameter.selection_values.split(',')]
|
||||
print(f" - Opciones disponibles: {options}")
|
||||
print(f" - Número de opciones: {len(options)}")
|
||||
|
||||
# Verificar si el valor actual está en las opciones
|
||||
if result.value_selection in options:
|
||||
print(f" ✓ El valor actual '{result.value_selection}' está en las opciones")
|
||||
else:
|
||||
print(f" ✗ El valor actual '{result.value_selection}' NO está en las opciones")
|
||||
else:
|
||||
print(" ✗ NO hay selection_values definidos en el parámetro")
|
||||
|
||||
# 5. Buscar todos los resultados con parámetros de tipo selection
|
||||
print(f"\n5. ANÁLISIS GLOBAL DE PARÁMETROS TIPO SELECTION:")
|
||||
|
||||
# Buscar todos los parámetros de tipo selection
|
||||
selection_params = env['lims.analysis.parameter'].search([('value_type', '=', 'selection')])
|
||||
print(f" - Total de parámetros tipo selection: {len(selection_params)}")
|
||||
|
||||
for param in selection_params[:5]: # Mostrar primeros 5
|
||||
print(f"\n Parámetro: {param.name} (ID: {param.id})")
|
||||
print(f" - Selection values: '{param.selection_values}'")
|
||||
if param.selection_values:
|
||||
options = [opt.strip() for opt in param.selection_values.split(',')]
|
||||
print(f" - Opciones: {options}")
|
||||
else:
|
||||
print(f" - ⚠️ SIN OPCIONES DEFINIDAS")
|
||||
|
||||
# 6. Verificar cómo se está usando en las vistas
|
||||
print(f"\n6. ANÁLISIS DE USO EN VISTAS:")
|
||||
print(" - En lims_test_views.xml, el campo value_selection usa widget='selection'")
|
||||
print(" - Este widget espera opciones dinámicas que deberían venir del campo related")
|
||||
print(" - Pero las opciones no se están propagando correctamente a la vista")
|
||||
|
||||
# 7. Buscar resultados con value_selection vacío
|
||||
empty_selection_results = env['lims.result'].search([
|
||||
('parameter_value_type', '=', 'selection'),
|
||||
('value_selection', '=', False)
|
||||
])
|
||||
print(f"\n7. RESULTADOS CON SELECTION VACÍO:")
|
||||
print(f" - Total: {len(empty_selection_results)}")
|
||||
|
||||
# 8. Propuesta de solución
|
||||
print(f"\n8. DIAGNÓSTICO Y SOLUCIÓN PROPUESTA:")
|
||||
print(" - PROBLEMA: El widget selection en la vista no recibe las opciones dinámicamente")
|
||||
print(" - CAUSA: Las opciones están en parameter.selection_values pero no se propagan al widget")
|
||||
print(" - SOLUCIÓN 1: Usar un campo Selection con función que obtenga opciones dinámicamente")
|
||||
print(" - SOLUCIÓN 2: Cambiar a widget text en la vista para entrada manual")
|
||||
print(" - SOLUCIÓN 3: Implementar un widget personalizado que lea selection_values del parámetro")
|
||||
|
||||
return {
|
||||
'test_id': test_id,
|
||||
'result_id': result_id,
|
||||
'parameter_name': parameter.name,
|
||||
'parameter_type': parameter.value_type,
|
||||
'selection_values': parameter.selection_values,
|
||||
'current_value': result.value_selection,
|
||||
'has_options': bool(parameter.selection_values),
|
||||
'empty_results_count': len(empty_selection_results)
|
||||
}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Configuración
|
||||
db_name = 'lims_demo'
|
||||
|
||||
# Conectar a Odoo
|
||||
odoo.tools.config.parse_config(['--database', db_name])
|
||||
|
||||
# Obtener el registro de la base de datos
|
||||
registry = odoo.registry(db_name)
|
||||
|
||||
# Crear cursor y environment
|
||||
with registry.cursor() as cr:
|
||||
env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
|
||||
|
||||
try:
|
||||
# Analizar el problema
|
||||
analysis = analyze_selection_issue(env)
|
||||
|
||||
print("\n" + "=" * 80)
|
||||
print("RESUMEN DEL ANÁLISIS:")
|
||||
print(json.dumps(analysis, indent=2, ensure_ascii=False))
|
||||
print("=" * 80)
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ Error durante el análisis: {str(e)}")
|
||||
_logger.error(f"Error analizando selection issue: {str(e)}", exc_info=True)
|
101
test/check_selection_issue.py
Normal file
101
test/check_selection_issue.py
Normal file
|
@ -0,0 +1,101 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script para diagnosticar por qué el selection muestra "Sin Opciones"
|
||||
"""
|
||||
|
||||
import odoo
|
||||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def check_selection_issue(env):
|
||||
"""Verificar el problema con las opciones de selección"""
|
||||
|
||||
print("=" * 80)
|
||||
print("DIAGNÓSTICO DE PROBLEMA CON SELECTION")
|
||||
print("=" * 80)
|
||||
|
||||
# Buscar el resultado específico mencionado por el usuario
|
||||
result = env['lims.result'].browse(43)
|
||||
if not result.exists():
|
||||
print("No se encontró el resultado con ID 43")
|
||||
# Buscar cualquier resultado de tipo selection
|
||||
result = env['lims.result'].search([
|
||||
('parameter_value_type', '=', 'selection')
|
||||
], limit=1)
|
||||
|
||||
if result:
|
||||
print(f"\nResultado encontrado:")
|
||||
print(f" - ID: {result.id}")
|
||||
print(f" - Parámetro: {result.parameter_id.name}")
|
||||
print(f" - Tipo de valor: {result.parameter_value_type}")
|
||||
print(f" - Valor actual: '{result.value_selection}'")
|
||||
|
||||
# Verificar el parámetro
|
||||
param = result.parameter_id
|
||||
print(f"\nInformación del parámetro:")
|
||||
print(f" - ID: {param.id}")
|
||||
print(f" - Nombre: {param.name}")
|
||||
print(f" - Tipo de valor: {param.value_type}")
|
||||
print(f" - Valores de selección (campo): '{param.selection_values}'")
|
||||
|
||||
# Probar get_selection_list()
|
||||
print(f"\nProbando get_selection_list():")
|
||||
selection_list = param.get_selection_list()
|
||||
print(f" - Resultado: {selection_list}")
|
||||
print(f" - Tipo: {type(selection_list)}")
|
||||
print(f" - Longitud: {len(selection_list) if selection_list else 0}")
|
||||
|
||||
# Probar _get_selection_options() en el resultado
|
||||
print(f"\nProbando _get_selection_options() en el resultado:")
|
||||
options = result._get_selection_options()
|
||||
print(f" - Opciones: {options}")
|
||||
|
||||
# Verificar si el método está siendo llamado correctamente
|
||||
print(f"\nVerificando contexto:")
|
||||
print(f" - result.parameter_id existe: {bool(result.parameter_id)}")
|
||||
print(f" - result.parameter_value_type: '{result.parameter_value_type}'")
|
||||
print(f" - Condición completa: {result.parameter_id and result.parameter_value_type == 'selection'}")
|
||||
|
||||
# Buscar todos los parámetros de tipo selection
|
||||
print(f"\n\nBuscando todos los parámetros de tipo selection:")
|
||||
selection_params = env['lims.analysis.parameter'].search([
|
||||
('value_type', '=', 'selection')
|
||||
])
|
||||
|
||||
for sp in selection_params:
|
||||
print(f"\n Parámetro: {sp.name}")
|
||||
print(f" - selection_values: '{sp.selection_values}'")
|
||||
print(f" - get_selection_list(): {sp.get_selection_list()}")
|
||||
|
||||
else:
|
||||
print("No se encontraron resultados de tipo selection")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Configuración
|
||||
db_name = 'lims_demo'
|
||||
|
||||
# Conectar a Odoo
|
||||
odoo.tools.config.parse_config(['--database', db_name])
|
||||
|
||||
# Obtener el registro de la base de datos
|
||||
registry = odoo.registry(db_name)
|
||||
|
||||
# Crear cursor y environment
|
||||
with registry.cursor() as cr:
|
||||
env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
|
||||
|
||||
try:
|
||||
# Verificar el problema
|
||||
check_selection_issue(env)
|
||||
|
||||
# No guardar cambios
|
||||
cr.rollback()
|
||||
|
||||
except Exception as e:
|
||||
cr.rollback()
|
||||
print(f"\n❌ Error durante el diagnóstico: {str(e)}")
|
||||
_logger.error(f"Error: {str(e)}", exc_info=True)
|
132
test/create_test_selection_data.py
Normal file
132
test/create_test_selection_data.py
Normal file
|
@ -0,0 +1,132 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script para crear datos de prueba con parámetros de tipo selection
|
||||
"""
|
||||
|
||||
import odoo
|
||||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def create_test_selection_data(env):
|
||||
"""Crear datos de prueba para verificar el widget selection"""
|
||||
|
||||
print("=" * 80)
|
||||
print("CREANDO DATOS DE PRUEBA PARA SELECTION")
|
||||
print("=" * 80)
|
||||
|
||||
# Buscar o crear paciente
|
||||
patient = env['res.partner'].search([('is_patient', '=', True)], limit=1)
|
||||
if not patient:
|
||||
patient = env['res.partner'].create({
|
||||
'name': 'Paciente Test Selection Widget',
|
||||
'is_patient': True,
|
||||
})
|
||||
print(f"Paciente creado: {patient.name}")
|
||||
|
||||
# Buscar análisis con parámetros tipo selection
|
||||
# Por ejemplo: Prueba de Embarazo
|
||||
product = env['product.template'].search([
|
||||
('is_analysis', '=', True),
|
||||
('name', 'ilike', 'embarazo')
|
||||
], limit=1)
|
||||
|
||||
if product:
|
||||
print(f"\nAnálisis encontrado: {product.name}")
|
||||
|
||||
# Verificar parámetros asociados
|
||||
print("\nParámetros del análisis:")
|
||||
for param_link in product.parameter_ids:
|
||||
param = param_link.parameter_id
|
||||
print(f" - {param.name} (Tipo: {param.value_type})")
|
||||
if param.value_type == 'selection':
|
||||
print(f" Valores: '{param.selection_values}'")
|
||||
print(f" Lista: {param.get_selection_list()}")
|
||||
else:
|
||||
print("No se encontró análisis de Prueba de Embarazo")
|
||||
|
||||
# Buscar cualquier análisis con parámetros selection
|
||||
sql = """
|
||||
SELECT DISTINCT pt.id, pt.name
|
||||
FROM product_template pt
|
||||
JOIN product_template_parameter ptp ON ptp.product_template_id = pt.id
|
||||
JOIN lims_analysis_parameter lap ON lap.id = ptp.parameter_id
|
||||
WHERE pt.is_analysis = true
|
||||
AND lap.value_type = 'selection'
|
||||
LIMIT 5
|
||||
"""
|
||||
env.cr.execute(sql)
|
||||
results = env.cr.fetchall()
|
||||
|
||||
if results:
|
||||
print("\nAnálisis con parámetros selection encontrados:")
|
||||
for prod_id, prod_name in results:
|
||||
print(f" - {prod_name} (ID: {prod_id})")
|
||||
product = env['product.template'].browse(prod_id)
|
||||
break
|
||||
else:
|
||||
print("No se encontraron análisis con parámetros selection")
|
||||
return
|
||||
|
||||
# Crear orden
|
||||
order = env['sale.order'].create({
|
||||
'partner_id': patient.id,
|
||||
'is_lab_request': True,
|
||||
'order_line': [(0, 0, {
|
||||
'product_id': product.product_variant_id.id,
|
||||
'product_uom_qty': 1,
|
||||
})]
|
||||
})
|
||||
|
||||
# Confirmar orden
|
||||
order.action_confirm()
|
||||
print(f"\nOrden creada: {order.name}")
|
||||
|
||||
# Obtener la prueba generada
|
||||
if order.lab_test_ids:
|
||||
test = order.lab_test_ids[0]
|
||||
print(f"Prueba generada: {test.name} (ID: {test.id})")
|
||||
|
||||
# Generar resultados si no existen
|
||||
if not test.result_ids:
|
||||
test.sudo()._generate_test_results()
|
||||
|
||||
print(f"\nResultados generados:")
|
||||
for result in test.result_ids:
|
||||
print(f" - {result.parameter_id.name} (Tipo: {result.parameter_value_type})")
|
||||
if result.parameter_value_type == 'selection':
|
||||
print(f" ID del resultado: {result.id}")
|
||||
print(f" Valores en parámetro: '{result.parameter_id.selection_values}'")
|
||||
print(f" get_selection_list(): {result.parameter_id.get_selection_list()}")
|
||||
print(f" _get_selection_options(): {result._get_selection_options()}")
|
||||
print(f" selection_options_display: '{result.selection_options_display}'")
|
||||
|
||||
# Guardar cambios
|
||||
env.cr.commit()
|
||||
print("\n✅ Datos de prueba creados exitosamente")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Configuración
|
||||
db_name = 'lims_demo'
|
||||
|
||||
# Conectar a Odoo
|
||||
odoo.tools.config.parse_config(['--database', db_name])
|
||||
|
||||
# Obtener el registro de la base de datos
|
||||
registry = odoo.registry(db_name)
|
||||
|
||||
# Crear cursor y environment
|
||||
with registry.cursor() as cr:
|
||||
env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
|
||||
|
||||
try:
|
||||
# Crear datos de prueba
|
||||
create_test_selection_data(env)
|
||||
|
||||
except Exception as e:
|
||||
cr.rollback()
|
||||
print(f"\n❌ Error: {str(e)}")
|
||||
_logger.error(f"Error: {str(e)}", exc_info=True)
|
132
test/diagnose_selection_issue.py
Normal file
132
test/diagnose_selection_issue.py
Normal file
|
@ -0,0 +1,132 @@
|
|||
import odoo
|
||||
import json
|
||||
|
||||
def diagnose_selection_issue(cr):
|
||||
"""Diagnose why selection widget shows 'Sin Opciones'"""
|
||||
env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
|
||||
|
||||
print("="*80)
|
||||
print("DIAGNOSING SELECTION WIDGET ISSUE")
|
||||
print("="*80)
|
||||
|
||||
# 1. Check the specific test and parameter
|
||||
test_id = 33
|
||||
result_id = 43
|
||||
|
||||
# Get the test
|
||||
test = env['lims.test'].browse(test_id)
|
||||
if not test:
|
||||
print(f"\nERROR: Test with ID {test_id} not found!")
|
||||
return
|
||||
|
||||
print(f"\nTest: {test.name} (ID: {test.id})")
|
||||
print(f"Category: {test.category_id.name}")
|
||||
|
||||
# Check parameters with selection type
|
||||
selection_params = test.parameter_ids.filtered(lambda p: p.value_type == 'selection')
|
||||
print(f"\nParameters with selection type: {len(selection_params)}")
|
||||
|
||||
for param in selection_params:
|
||||
print(f"\n--- Parameter: {param.name} (ID: {param.id}) ---")
|
||||
print(f"Value Type: {param.value_type}")
|
||||
print(f"Selection Values (raw field): '{param.selection_values}'")
|
||||
print(f"Selection Values (type): {type(param.selection_values)}")
|
||||
print(f"Selection Values (bool): {bool(param.selection_values)}")
|
||||
|
||||
# Test get_selection_list method
|
||||
try:
|
||||
selection_list = param.get_selection_list()
|
||||
print(f"\nget_selection_list() result:")
|
||||
print(f" Type: {type(selection_list)}")
|
||||
print(f" Content: {selection_list}")
|
||||
print(f" Length: {len(selection_list) if isinstance(selection_list, list) else 'N/A'}")
|
||||
except Exception as e:
|
||||
print(f"\nERROR calling get_selection_list(): {str(e)}")
|
||||
|
||||
# 2. Check the specific result
|
||||
result = env['lims.result'].browse(result_id)
|
||||
if not result:
|
||||
print(f"\n\nERROR: Result with ID {result_id} not found!")
|
||||
return
|
||||
|
||||
print(f"\n\n--- Result Analysis (ID: {result_id}) ---")
|
||||
print(f"Test: {result.test_id.name}")
|
||||
print(f"Parameter: {result.parameter_id.name}")
|
||||
print(f"Parameter Value Type: {result.parameter_id.value_type}")
|
||||
|
||||
# Check computed field
|
||||
print(f"\nComputed field 'selection_options': {result.selection_options}")
|
||||
|
||||
# Manually test _get_selection_options
|
||||
try:
|
||||
# Clear cache to force recomputation
|
||||
result.invalidate_recordset(['selection_options'])
|
||||
|
||||
# Access the field to trigger computation
|
||||
options = result.selection_options
|
||||
print(f"\nAfter invalidating cache:")
|
||||
print(f" selection_options: {options}")
|
||||
print(f" Type: {type(options)}")
|
||||
except Exception as e:
|
||||
print(f"\nERROR accessing selection_options: {str(e)}")
|
||||
|
||||
# 3. Direct method test
|
||||
print(f"\n\n--- Direct Method Tests ---")
|
||||
|
||||
# Test parameter's get_selection_list directly
|
||||
if result.parameter_id.value_type == 'selection':
|
||||
param = result.parameter_id
|
||||
print(f"\nParameter: {param.name}")
|
||||
print(f"Selection Values: '{param.selection_values}'")
|
||||
|
||||
# Test parsing
|
||||
if param.selection_values:
|
||||
lines = param.selection_values.strip().split('\n')
|
||||
print(f"\nParsing test:")
|
||||
print(f" Lines after split: {lines}")
|
||||
print(f" Number of lines: {len(lines)}")
|
||||
|
||||
parsed_options = []
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
if line:
|
||||
if '|' in line:
|
||||
parts = line.split('|', 1)
|
||||
if len(parts) == 2:
|
||||
parsed_options.append((parts[0].strip(), parts[1].strip()))
|
||||
else:
|
||||
parsed_options.append((line, line))
|
||||
|
||||
print(f"\n Parsed options: {parsed_options}")
|
||||
|
||||
# 4. Check other results for the same test
|
||||
print(f"\n\n--- Other Results for Test {test_id} ---")
|
||||
other_results = env['lims.result'].search([('test_id', '=', test_id)], limit=5)
|
||||
for res in other_results:
|
||||
if res.parameter_id.value_type == 'selection':
|
||||
print(f"\nResult ID: {res.id}")
|
||||
print(f" Parameter: {res.parameter_id.name}")
|
||||
print(f" Selection Options: {res.selection_options}")
|
||||
print(f" Value: {res.value_text}")
|
||||
|
||||
# 5. Database check
|
||||
print(f"\n\n--- Direct Database Check ---")
|
||||
cr.execute("""
|
||||
SELECT id, name, value_type, selection_values
|
||||
FROM lims_parameter
|
||||
WHERE value_type = 'selection'
|
||||
AND id IN (SELECT parameter_id FROM lims_result WHERE id = %s)
|
||||
""", (result_id,))
|
||||
|
||||
for row in cr.fetchall():
|
||||
print(f"\nParameter ID: {row[0]}")
|
||||
print(f" Name: {row[1]}")
|
||||
print(f" Value Type: {row[2]}")
|
||||
print(f" Selection Values: '{row[3]}'")
|
||||
print(f" Selection Values (repr): {repr(row[3])}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
db_name = 'odoo'
|
||||
registry = odoo.registry(db_name)
|
||||
with registry.cursor() as cr:
|
||||
diagnose_selection_issue(cr)
|
43
test/find_selection_result.py
Normal file
43
test/find_selection_result.py
Normal file
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script para encontrar un resultado real con tipo selection
|
||||
"""
|
||||
|
||||
import odoo
|
||||
|
||||
def find_selection_result(env):
|
||||
"""Buscar un resultado con parámetro tipo selection"""
|
||||
|
||||
# Buscar resultados con parámetros tipo selection
|
||||
results = env['lims.result'].search([
|
||||
('parameter_value_type', '=', 'selection')
|
||||
], limit=5)
|
||||
|
||||
print("RESULTADOS CON PARÁMETROS TIPO SELECTION:")
|
||||
print("=" * 80)
|
||||
|
||||
for result in results:
|
||||
print(f"\nResultado ID: {result.id}")
|
||||
print(f" Test ID: {result.test_id.id}")
|
||||
print(f" Test: {result.test_id.name}")
|
||||
print(f" Parámetro: {result.parameter_id.name}")
|
||||
print(f" Parámetro ID: {result.parameter_id.id}")
|
||||
print(f" Selection values del parámetro: '{result.parameter_id.selection_values}'")
|
||||
print(f" Valor actual: '{result.value_selection}'")
|
||||
|
||||
if result.parameter_id.selection_values:
|
||||
options = [opt.strip() for opt in result.parameter_id.selection_values.split(',')]
|
||||
print(f" Opciones disponibles: {options}")
|
||||
|
||||
return results
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
db_name = 'lims_demo'
|
||||
odoo.tools.config.parse_config(['--database', db_name])
|
||||
registry = odoo.registry(db_name)
|
||||
|
||||
with registry.cursor() as cr:
|
||||
env = odoo.api.Environment(cr, 1, {})
|
||||
results = find_selection_result(env)
|
78
test/test_get_selection_list.py
Normal file
78
test/test_get_selection_list.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script para probar que get_selection_list funciona correctamente
|
||||
"""
|
||||
|
||||
import odoo
|
||||
|
||||
def test_get_selection_list(env):
|
||||
"""Probar el método get_selection_list"""
|
||||
|
||||
print("=" * 80)
|
||||
print("PRUEBA DE get_selection_list()")
|
||||
print("=" * 80)
|
||||
|
||||
# Buscar parámetros de tipo selection
|
||||
selection_params = env['lims.analysis.parameter'].search([
|
||||
('value_type', '=', 'selection'),
|
||||
('selection_values', '!=', False)
|
||||
], limit=5)
|
||||
|
||||
print(f"\nProbando con {len(selection_params)} parámetros tipo selection:\n")
|
||||
|
||||
for param in selection_params:
|
||||
print(f"Parámetro: {param.name} (ID: {param.id})")
|
||||
print(f" - selection_values (raw): '{param.selection_values}'")
|
||||
|
||||
# Llamar al método get_selection_list
|
||||
try:
|
||||
selection_list = param.get_selection_list()
|
||||
print(f" - get_selection_list(): {selection_list}")
|
||||
print(f" - Tipo: {type(selection_list)}")
|
||||
print(f" - Número de opciones: {len(selection_list)}")
|
||||
except Exception as e:
|
||||
print(f" - ERROR: {str(e)}")
|
||||
|
||||
print()
|
||||
|
||||
# Ahora verificar cómo se podría usar en lims.result
|
||||
print("\nVERIFICANDO USO EN lims.result:")
|
||||
print("-" * 40)
|
||||
|
||||
# Buscar un resultado con parámetro tipo selection
|
||||
result = env['lims.result'].search([
|
||||
('parameter_value_type', '=', 'selection')
|
||||
], limit=1)
|
||||
|
||||
if result:
|
||||
print(f"Resultado ID: {result.id}")
|
||||
print(f"Parámetro: {result.parameter_id.name}")
|
||||
print(f"Valor actual: '{result.value_selection}'")
|
||||
|
||||
# Obtener las opciones disponibles
|
||||
options = result.parameter_id.get_selection_list()
|
||||
print(f"Opciones disponibles: {options}")
|
||||
|
||||
# Verificar si el valor actual está en las opciones
|
||||
if result.value_selection in options:
|
||||
print("✓ El valor actual está en las opciones")
|
||||
else:
|
||||
print("✗ El valor actual NO está en las opciones")
|
||||
|
||||
# Simular asignación de un valor válido
|
||||
if options:
|
||||
print(f"\nSimulando asignación del primer valor válido: '{options[0]}'")
|
||||
# No hacemos write para no modificar datos
|
||||
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
db_name = 'lims_demo'
|
||||
odoo.tools.config.parse_config(['--database', db_name])
|
||||
registry = odoo.registry(db_name)
|
||||
|
||||
with registry.cursor() as cr:
|
||||
env = odoo.api.Environment(cr, 1, {})
|
||||
test_get_selection_list(env)
|
116
test/test_selection_fix.py
Normal file
116
test/test_selection_fix.py
Normal file
|
@ -0,0 +1,116 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script para probar la solución del bug de selection
|
||||
"""
|
||||
|
||||
import odoo
|
||||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def test_selection_fix(env):
|
||||
"""Probar que la solución funciona correctamente"""
|
||||
|
||||
print("=" * 80)
|
||||
print("PRUEBA DE SOLUCIÓN PARA BUG DE SELECTION")
|
||||
print("=" * 80)
|
||||
|
||||
# Crear una orden de prueba
|
||||
patient = env['res.partner'].search([('is_patient', '=', True)], limit=1)
|
||||
if not patient:
|
||||
patient = env['res.partner'].create({
|
||||
'name': 'Paciente Test Selection',
|
||||
'is_patient': True,
|
||||
})
|
||||
|
||||
# Buscar análisis con parámetros tipo selection
|
||||
# Por ejemplo: Prueba de Embarazo
|
||||
product = env['product.template'].search([
|
||||
('is_analysis', '=', True),
|
||||
('name', 'ilike', 'embarazo')
|
||||
], limit=1)
|
||||
|
||||
if not product:
|
||||
print("No se encontró el análisis de Prueba de Embarazo")
|
||||
return False
|
||||
|
||||
# Crear orden
|
||||
order = env['sale.order'].create({
|
||||
'partner_id': patient.id,
|
||||
'is_lab_request': True,
|
||||
'order_line': [(0, 0, {
|
||||
'product_id': product.product_variant_id.id,
|
||||
'product_uom_qty': 1,
|
||||
})]
|
||||
})
|
||||
|
||||
# Confirmar orden
|
||||
order.action_confirm()
|
||||
print(f"\nOrden creada: {order.name}")
|
||||
|
||||
# Obtener la prueba generada
|
||||
test = order.lab_test_ids[0]
|
||||
print(f"Prueba: {test.name}")
|
||||
|
||||
# Generar resultados
|
||||
test.sudo()._generate_test_results()
|
||||
print(f"Resultados generados: {len(test.result_ids)}")
|
||||
|
||||
# Verificar el resultado con parámetro tipo selection
|
||||
for result in test.result_ids:
|
||||
if result.parameter_value_type == 'selection':
|
||||
print(f"\nResultado de tipo selection encontrado:")
|
||||
print(f" - Parámetro: {result.parameter_id.name}")
|
||||
print(f" - Opciones en parámetro: {result.parameter_id.selection_values}")
|
||||
print(f" - Opciones disponibles: {result.selection_options_display}")
|
||||
|
||||
# Verificar que el campo computed funciona
|
||||
if result.selection_options_display:
|
||||
print(" ✓ Campo selection_options_display funciona correctamente")
|
||||
|
||||
# Simular asignación de valor
|
||||
options = result.parameter_id.get_selection_list()
|
||||
if options:
|
||||
result.value_selection = options[0]
|
||||
print(f" ✓ Valor asignado: '{result.value_selection}'")
|
||||
else:
|
||||
print(" ✗ No se muestran las opciones disponibles")
|
||||
|
||||
return True
|
||||
|
||||
print("\nNo se encontraron resultados de tipo selection")
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Configuración
|
||||
db_name = 'lims_demo'
|
||||
|
||||
# Conectar a Odoo
|
||||
odoo.tools.config.parse_config(['--database', db_name])
|
||||
|
||||
# Obtener el registro de la base de datos
|
||||
registry = odoo.registry(db_name)
|
||||
|
||||
# Crear cursor y environment
|
||||
with registry.cursor() as cr:
|
||||
env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
|
||||
|
||||
try:
|
||||
# Probar la solución
|
||||
success = test_selection_fix(env)
|
||||
|
||||
if success:
|
||||
print("\n✅ La solución funciona correctamente")
|
||||
else:
|
||||
print("\n❌ La prueba falló")
|
||||
|
||||
# No guardar cambios, solo probar
|
||||
cr.rollback()
|
||||
|
||||
except Exception as e:
|
||||
cr.rollback()
|
||||
print(f"\n❌ Error durante la prueba: {str(e)}")
|
||||
_logger.error(f"Error probando fix: {str(e)}", exc_info=True)
|
100
test/verify_selection_fix.py
Normal file
100
test/verify_selection_fix.py
Normal file
|
@ -0,0 +1,100 @@
|
|||
import odoo
|
||||
import json
|
||||
|
||||
def verify_selection_fix(cr):
|
||||
"""Verify that the selection widget fix is working correctly."""
|
||||
env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
|
||||
|
||||
print("="*80)
|
||||
print("VERIFYING SELECTION WIDGET FIX")
|
||||
print("="*80)
|
||||
|
||||
# 1. Find a parameter with selection type
|
||||
param = env['lims.analysis.parameter'].search([
|
||||
('value_type', '=', 'selection'),
|
||||
('selection_values', '!=', False)
|
||||
], limit=1)
|
||||
|
||||
if not param:
|
||||
print("ERROR: No selection parameters found!")
|
||||
return
|
||||
|
||||
print(f"\nUsing parameter: {param.name} (ID: {param.id})")
|
||||
print(f"Selection values: {param.selection_values}")
|
||||
print(f"get_selection_list(): {param.get_selection_list()}")
|
||||
|
||||
# 2. Create a test and result
|
||||
print("\n\nCreating test data...")
|
||||
|
||||
# Get a patient
|
||||
patient = env['res.partner'].search([('is_patient', '=', True)], limit=1)
|
||||
if not patient:
|
||||
print("ERROR: No patient found!")
|
||||
return
|
||||
|
||||
# Create a test
|
||||
test = env['lims.test'].create({
|
||||
'name': 'Test Selection Widget',
|
||||
'patient_id': patient.id,
|
||||
'analysis_id': param.analysis_id.id if param.analysis_id else False,
|
||||
})
|
||||
print(f"Created test: {test.name} (ID: {test.id})")
|
||||
|
||||
# Create a result
|
||||
result = env['lims.result'].create({
|
||||
'test_id': test.id,
|
||||
'parameter_id': param.id,
|
||||
})
|
||||
print(f"Created result: ID {result.id}")
|
||||
|
||||
# 3. Check the selection field
|
||||
print("\n\nChecking selection field...")
|
||||
print(f"Parameter value type: {result.parameter_value_type}")
|
||||
print(f"Selection options display: {result.selection_options_display}")
|
||||
|
||||
# Get selection options through the method
|
||||
options = result._get_selection_options()
|
||||
print(f"\n_get_selection_options() returns: {options}")
|
||||
|
||||
# 4. Test setting a value
|
||||
if options and len(options) > 1: # Skip the empty option
|
||||
test_value = options[1][0] # Get the key of the first real option
|
||||
print(f"\nTesting with value: '{test_value}'")
|
||||
|
||||
result.value_selection_field = test_value
|
||||
print(f"Set value_selection_field = '{test_value}'")
|
||||
print(f"After onchange, value_selection = '{result.value_selection}'")
|
||||
print(f"Value display: '{result.value_display}'")
|
||||
|
||||
# Save and check
|
||||
cr.commit()
|
||||
|
||||
# Re-read
|
||||
result = env['lims.result'].browse(result.id)
|
||||
print(f"\nAfter save and re-read:")
|
||||
print(f" value_selection_field: '{result.value_selection_field}'")
|
||||
print(f" value_selection: '{result.value_selection}'")
|
||||
print(f" value_display: '{result.value_display}'")
|
||||
|
||||
# 5. Check field definition
|
||||
print("\n\nChecking field definitions...")
|
||||
Result = env['lims.result']
|
||||
|
||||
if 'value_selection_field' in Result._fields:
|
||||
field = Result._fields['value_selection_field']
|
||||
print(f"value_selection_field:")
|
||||
print(f" Type: {field.type}")
|
||||
print(f" String: {field.string}")
|
||||
print(f" Selection: {field.selection if hasattr(field, 'selection') else 'N/A'}")
|
||||
else:
|
||||
print("ERROR: value_selection_field not found in model!")
|
||||
|
||||
print("\n" + "="*80)
|
||||
print("VERIFICATION COMPLETE")
|
||||
print("="*80)
|
||||
|
||||
if __name__ == '__main__':
|
||||
db_name = 'lims_demo'
|
||||
registry = odoo.registry(db_name)
|
||||
with registry.cursor() as cr:
|
||||
verify_selection_fix(cr)
|
141
test/verify_selection_widget_fix.py
Normal file
141
test/verify_selection_widget_fix.py
Normal file
|
@ -0,0 +1,141 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script para verificar que el widget selection funciona correctamente
|
||||
"""
|
||||
|
||||
import odoo
|
||||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def verify_selection_widget_fix(env):
|
||||
"""Verificar que el widget selection funciona con opciones dinámicas"""
|
||||
|
||||
print("=" * 80)
|
||||
print("VERIFICACIÓN DE FIX PARA WIDGET SELECTION")
|
||||
print("=" * 80)
|
||||
|
||||
# Buscar un resultado existente con tipo selection
|
||||
result = env['lims.result'].search([
|
||||
('parameter_value_type', '=', 'selection'),
|
||||
('test_id.state', '=', 'draft')
|
||||
], limit=1)
|
||||
|
||||
if not result:
|
||||
print("No se encontró ningún resultado de tipo selection en estado borrador")
|
||||
# Crear uno nuevo para prueba
|
||||
patient = env['res.partner'].search([('is_patient', '=', True)], limit=1)
|
||||
if not patient:
|
||||
patient = env['res.partner'].create({
|
||||
'name': 'Paciente Test Widget',
|
||||
'is_patient': True,
|
||||
})
|
||||
|
||||
# Buscar análisis con parámetros tipo selection
|
||||
product = env['product.template'].search([
|
||||
('is_analysis', '=', True),
|
||||
('name', 'ilike', 'embarazo')
|
||||
], limit=1)
|
||||
|
||||
if not product:
|
||||
print("No se encontró análisis de prueba de embarazo")
|
||||
return False
|
||||
|
||||
# Crear orden
|
||||
order = env['sale.order'].create({
|
||||
'partner_id': patient.id,
|
||||
'is_lab_request': True,
|
||||
'order_line': [(0, 0, {
|
||||
'product_id': product.product_variant_id.id,
|
||||
'product_uom_qty': 1,
|
||||
})]
|
||||
})
|
||||
|
||||
# Confirmar orden
|
||||
order.action_confirm()
|
||||
print(f"\nOrden creada: {order.name}")
|
||||
|
||||
# Obtener la prueba generada
|
||||
test = order.lab_test_ids[0]
|
||||
test.sudo()._generate_test_results()
|
||||
|
||||
# Buscar resultado tipo selection
|
||||
result = test.result_ids.filtered(lambda r: r.parameter_value_type == 'selection')[0]
|
||||
|
||||
print(f"\nResultado encontrado:")
|
||||
print(f" - ID: {result.id}")
|
||||
print(f" - Parámetro: {result.parameter_id.name}")
|
||||
print(f" - Tipo: {result.parameter_value_type}")
|
||||
print(f" - Valores en parámetro: {result.parameter_id.selection_values}")
|
||||
|
||||
# Probar el método _get_selection_options
|
||||
print("\nProbando método _get_selection_options():")
|
||||
options = result._get_selection_options()
|
||||
print(f" - Opciones retornadas: {options}")
|
||||
|
||||
if options and options[0][0] != '':
|
||||
print(" ✓ El método retorna opciones válidas")
|
||||
|
||||
# Probar asignación de valor
|
||||
try:
|
||||
result.value_selection = options[0][0]
|
||||
print(f" ✓ Valor asignado correctamente: '{result.value_selection}'")
|
||||
|
||||
# Intentar asignar un valor inválido
|
||||
try:
|
||||
result.value_selection = 'valor_invalido'
|
||||
print(" ✗ ERROR: Permitió asignar un valor inválido")
|
||||
return False
|
||||
except:
|
||||
print(" ✓ Correctamente rechazó un valor inválido")
|
||||
|
||||
except Exception as e:
|
||||
print(f" ✗ Error al asignar valor: {str(e)}")
|
||||
return False
|
||||
else:
|
||||
print(" ✗ No se retornaron opciones válidas")
|
||||
return False
|
||||
|
||||
# Verificar que el campo es de tipo Selection
|
||||
field_type = type(result._fields['value_selection'])
|
||||
print(f"\nTipo de campo value_selection: {field_type.__name__}")
|
||||
if 'Selection' in field_type.__name__:
|
||||
print(" ✓ El campo es correctamente de tipo Selection")
|
||||
return True
|
||||
else:
|
||||
print(" ✗ El campo no es de tipo Selection")
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Configuración
|
||||
db_name = 'lims_demo'
|
||||
|
||||
# Conectar a Odoo
|
||||
odoo.tools.config.parse_config(['--database', db_name])
|
||||
|
||||
# Obtener el registro de la base de datos
|
||||
registry = odoo.registry(db_name)
|
||||
|
||||
# Crear cursor y environment
|
||||
with registry.cursor() as cr:
|
||||
env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
|
||||
|
||||
try:
|
||||
# Verificar la solución
|
||||
success = verify_selection_widget_fix(env)
|
||||
|
||||
if success:
|
||||
print("\n✅ El widget selection funciona correctamente con opciones dinámicas")
|
||||
else:
|
||||
print("\n❌ La verificación falló")
|
||||
|
||||
# No guardar cambios
|
||||
cr.rollback()
|
||||
|
||||
except Exception as e:
|
||||
cr.rollback()
|
||||
print(f"\n❌ Error durante la verificación: {str(e)}")
|
||||
_logger.error(f"Error verificando fix: {str(e)}", exc_info=True)
|
Loading…
Reference in New Issue
Block a user