
- Dashboard de Estado de Órdenes: Vista gráfica y pivot de órdenes por estado - Dashboard de Productividad de Técnicos: Análisis de pruebas por técnico - Dashboard de Muestras: Estado y distribución de muestras por tipo - Dashboard de Parámetros Fuera de Rango: Identificación de resultados críticos - Dashboard de Análisis Más Solicitados: Top de análisis por período - Dashboard de Distribución Demográfica: Tests por género y rango de edad - Agregar campos computed age_range, patient_gender y patient_age_range - Configurar menú de Dashboards solo para administradores 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
131 lines
4.8 KiB
Python
131 lines
4.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
from odoo import models, fields, api
|
|
from odoo.exceptions import ValidationError
|
|
from datetime import date
|
|
from dateutil.relativedelta import relativedelta
|
|
|
|
class ResPartner(models.Model):
|
|
_inherit = 'res.partner'
|
|
|
|
is_patient = fields.Boolean(string="Es Paciente")
|
|
patient_identifier = fields.Char(string="Identificador de Paciente", copy=False)
|
|
origin = fields.Char(
|
|
string="Origen",
|
|
default='Manual',
|
|
help="Este campo indica el origen del registro del paciente (ej. Manual, Carga Inicial)."
|
|
)
|
|
birthdate_date = fields.Date(string="Fecha de Nacimiento")
|
|
gender = fields.Selection([
|
|
('male', 'Masculino'),
|
|
('female', 'Femenino'),
|
|
('other', 'Otro')
|
|
], string="Género")
|
|
|
|
# Nuevos campos para el cálculo de rangos
|
|
age = fields.Integer(
|
|
string="Edad",
|
|
compute='_compute_age',
|
|
store=False,
|
|
help="Edad calculada en años basada en la fecha de nacimiento"
|
|
)
|
|
|
|
age_range = fields.Selection([
|
|
('0-10', '0-10 años'),
|
|
('11-20', '11-20 años'),
|
|
('21-30', '21-30 años'),
|
|
('31-40', '31-40 años'),
|
|
('41-50', '41-50 años'),
|
|
('51-60', '51-60 años'),
|
|
('61-70', '61-70 años'),
|
|
('71+', 'Más de 70 años')
|
|
], string="Rango de Edad", compute='_compute_age_range', store=True)
|
|
|
|
is_pregnant = fields.Boolean(
|
|
string="Embarazada",
|
|
help="Marcar si la paciente está embarazada (solo aplica para género femenino)"
|
|
)
|
|
|
|
is_doctor = fields.Boolean(string="Es Médico")
|
|
doctor_license = fields.Char(string="Licencia Médica", copy=False)
|
|
|
|
_sql_constraints = [
|
|
('patient_identifier_unique', 'unique(patient_identifier)', 'El identificador del paciente debe ser único.'),
|
|
('doctor_license_unique', 'unique(doctor_license)', 'La licencia médica debe ser única.')
|
|
]
|
|
|
|
@api.depends('birthdate_date')
|
|
def _compute_age(self):
|
|
"""Calcula la edad en años basada en la fecha de nacimiento"""
|
|
today = date.today()
|
|
for partner in self:
|
|
if partner.birthdate_date:
|
|
# Calcular diferencia usando relativedelta para precisión
|
|
delta = relativedelta(today, partner.birthdate_date)
|
|
partner.age = delta.years
|
|
else:
|
|
partner.age = 0
|
|
|
|
@api.depends('birthdate_date')
|
|
def _compute_age_range(self):
|
|
"""Calcula el rango de edad basado en la edad"""
|
|
for partner in self:
|
|
if partner.birthdate_date:
|
|
today = date.today()
|
|
delta = relativedelta(today, partner.birthdate_date)
|
|
age = delta.years
|
|
|
|
if age <= 10:
|
|
partner.age_range = '0-10'
|
|
elif age <= 20:
|
|
partner.age_range = '11-20'
|
|
elif age <= 30:
|
|
partner.age_range = '21-30'
|
|
elif age <= 40:
|
|
partner.age_range = '31-40'
|
|
elif age <= 50:
|
|
partner.age_range = '41-50'
|
|
elif age <= 60:
|
|
partner.age_range = '51-60'
|
|
elif age <= 70:
|
|
partner.age_range = '61-70'
|
|
else:
|
|
partner.age_range = '71+'
|
|
else:
|
|
partner.age_range = False
|
|
|
|
@api.constrains('is_pregnant', 'gender')
|
|
def _check_pregnant_gender(self):
|
|
"""Valida que solo pacientes de género femenino puedan estar embarazadas"""
|
|
for partner in self:
|
|
if partner.is_pregnant and partner.gender != 'female':
|
|
raise ValidationError('Solo las pacientes de género femenino pueden estar marcadas como embarazadas.')
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals_list):
|
|
for vals in vals_list:
|
|
if vals.get('is_patient') and not vals.get('patient_identifier'):
|
|
vals['patient_identifier'] = self.env['ir.sequence'].next_by_code('res.partner.patient_identifier')
|
|
return super(ResPartner, self).create(vals_list)
|
|
|
|
def get_age_at_date(self, target_date=None):
|
|
"""
|
|
Calcula la edad del paciente en una fecha específica.
|
|
|
|
:param target_date: Fecha en la que calcular la edad. Si es None, usa la fecha actual.
|
|
:return: Edad en años
|
|
"""
|
|
self.ensure_one()
|
|
if not self.birthdate_date:
|
|
return 0
|
|
|
|
if not target_date:
|
|
target_date = date.today()
|
|
elif isinstance(target_date, str):
|
|
target_date = fields.Date.from_string(target_date)
|
|
|
|
if target_date < self.birthdate_date:
|
|
return 0
|
|
|
|
delta = relativedelta(target_date, self.birthdate_date)
|
|
return delta.years
|