clinical_laboratory/lims_management/models/lims_result.py
Luis Ernesto Portillo Zaldivar a1b8f7b1de feat(#8): Task 1 y 2 completadas - Crear modelos lims.test y lims.result
- Modelo lims.test con todos los campos especificados
- Modelo lims.result con soporte para múltiples tipos de valor
- Secuencia automática para códigos de prueba
- Flujo de estados: draft -> in_process -> result_entered -> validated
- Validación de un solo tipo de valor por resultado
- Permisos de seguridad configurados
2025-07-15 00:36:58 -06:00

124 lines
3.6 KiB
Python

# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
import logging
_logger = logging.getLogger(__name__)
class LimsResult(models.Model):
_name = 'lims.result'
_description = 'Resultado de Prueba de Laboratorio'
_rec_name = 'display_name'
_order = 'test_id, sequence'
display_name = fields.Char(
string='Nombre',
compute='_compute_display_name',
store=True
)
test_id = fields.Many2one(
'lims.test',
string='Prueba',
required=True,
ondelete='cascade'
)
# Por ahora, estos campos básicos
parameter_name = fields.Char(
string='Parámetro',
required=True
)
sequence = fields.Integer(
string='Secuencia',
default=10
)
# TODO: Implementar parameter_id cuando exista lims.test.parameter
# parameter_id = fields.Many2one(
# 'lims.test.parameter',
# string='Parámetro'
# )
value_numeric = fields.Float(
string='Valor Numérico'
)
value_text = fields.Char(
string='Valor de Texto'
)
value_selection = fields.Selection(
[], # Por ahora vacío
string='Valor de Selección'
)
is_out_of_range = fields.Boolean(
string='Fuera de Rango',
compute='_compute_is_out_of_range',
store=True
)
notes = fields.Text(
string='Notas del Técnico'
)
# Campos para rangos normales (temporal)
normal_min = fields.Float(
string='Valor Normal Mínimo'
)
normal_max = fields.Float(
string='Valor Normal Máximo'
)
unit = fields.Char(
string='Unidad'
)
@api.depends('test_id', 'parameter_name')
def _compute_display_name(self):
"""Calcula el nombre a mostrar."""
for record in self:
if record.test_id and record.parameter_name:
record.display_name = f"{record.test_id.name} - {record.parameter_name}"
else:
record.display_name = record.parameter_name or _('Nuevo')
@api.depends('value_numeric', 'normal_min', 'normal_max')
def _compute_is_out_of_range(self):
"""Determina si el valor está fuera del rango normal."""
for record in self:
if record.value_numeric and (record.normal_min or record.normal_max):
if record.normal_min and record.value_numeric < record.normal_min:
record.is_out_of_range = True
elif record.normal_max and record.value_numeric > record.normal_max:
record.is_out_of_range = True
else:
record.is_out_of_range = False
else:
record.is_out_of_range = False
@api.constrains('value_numeric', 'value_text', 'value_selection')
def _check_single_value_type(self):
"""Asegura que solo un tipo de valor esté lleno."""
for record in self:
filled_values = 0
if record.value_numeric:
filled_values += 1
if record.value_text:
filled_values += 1
if record.value_selection:
filled_values += 1
if filled_values > 1:
raise ValidationError(
_('Solo se puede ingresar un tipo de valor (numérico, texto o selección) por resultado.')
)
if filled_values == 0:
raise ValidationError(
_('Debe ingresar al menos un valor para el resultado.')
)