# -*- coding: utf-8 -*- from odoo import models, fields, api from odoo.exceptions import ValidationError class LimsAnalysisParameter(models.Model): _name = 'lims.analysis.parameter' _description = 'Catálogo de Parámetros de Laboratorio' _order = 'name' _rec_name = 'name' name = fields.Char( string='Nombre', required=True, help='Nombre descriptivo del parámetro (ej: Hemoglobina)' ) code = fields.Char( string='Código', required=True, help='Código único del parámetro (ej: HGB)' ) value_type = fields.Selection([ ('numeric', 'Numérico'), ('text', 'Texto'), ('boolean', 'Sí/No'), ('selection', 'Selección') ], string='Tipo de Valor', required=True, default='numeric', help='Tipo de dato que acepta este parámetro' ) unit = fields.Char( string='Unidad de Medida', help='Unidad de medida del parámetro (ej: g/dL, mg/dL, %)' ) selection_values = fields.Text( string='Valores de Selección', help='Para tipo "Selección", ingrese los valores posibles separados por comas' ) description = fields.Text( string='Descripción', help='Descripción detallada del parámetro y su significado clínico' ) active = fields.Boolean( string='Activo', default=True, help='Si está desmarcado, el parámetro no estará disponible para nuevas configuraciones' ) category_id = fields.Many2one( 'product.category', string='Categoría', domain="[('parent_id.name', '=', 'Análisis de Laboratorio')]", help='Categoría del parámetro para agrupar en reportes' ) # Relaciones template_parameter_ids = fields.One2many( 'product.template.parameter', 'parameter_id', string='Análisis que usan este parámetro' ) range_ids = fields.One2many( 'lims.parameter.range', 'parameter_id', string='Rangos de Referencia' ) # Campos computados analysis_count = fields.Integer( string='Cantidad de Análisis', compute='_compute_analysis_count', store=True ) @api.depends('template_parameter_ids') def _compute_analysis_count(self): for record in self: record.analysis_count = len(record.template_parameter_ids) @api.constrains('code') def _check_code_unique(self): for record in self: if self.search_count([ ('code', '=', record.code), ('id', '!=', record.id) ]) > 0: raise ValidationError(f'El código "{record.code}" ya existe. Los códigos deben ser únicos.') @api.constrains('value_type', 'selection_values') def _check_selection_values(self): for record in self: if record.value_type == 'selection' and not record.selection_values: raise ValidationError('Debe especificar los valores de selección para parámetros de tipo "Selección".') @api.constrains('value_type', 'unit') def _check_numeric_unit(self): for record in self: if record.value_type == 'numeric' and not record.unit: raise ValidationError('Los parámetros numéricos deben tener una unidad de medida.') def get_selection_list(self): """Devuelve la lista de valores de selección como una lista de Python""" self.ensure_one() if self.value_type == 'selection' and self.selection_values: return [val.strip() for val in self.selection_values.split(',') if val.strip()] return [] @api.model def create(self, vals): # Convertir código a mayúsculas if 'code' in vals: vals['code'] = vals['code'].upper() return super(LimsAnalysisParameter, self).create(vals) def write(self, vals): # Convertir código a mayúsculas if 'code' in vals: vals['code'] = vals['code'].upper() return super(LimsAnalysisParameter, self).write(vals) def name_get(self): result = [] for record in self: name = f"[{record.code}] {record.name}" if record.unit: name += f" ({record.unit})" result.append((record.id, name)) return result @api.model def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): args = args or [] if name: args = ['|', ('code', operator, name), ('name', operator, name)] + args return self._search(args, limit=limit, access_rights_uid=name_get_uid)