diff --git a/dashboard_analysis.md b/dashboard_analysis.md new file mode 100644 index 0000000..54479fd --- /dev/null +++ b/dashboard_analysis.md @@ -0,0 +1,78 @@ +# Análisis de Dashboards para LIMS - Issue #71 + +## Dashboards Implementables sin Módulos Adicionales ni Cambios Estructurales + +### 1. ✅ Dashboard de Estado de Órdenes +**Factibilidad**: Alta +- Usar vistas graph y pivot nativas de Odoo +- Datos disponibles: sale.order con is_lab_request=True +- Métricas: órdenes por estado, por fecha, por paciente + +### 2. ✅ Dashboard de Productividad de Técnicos +**Factibilidad**: Alta +- Datos disponibles: lims.test (technician_id, state, create_date, validation_date) +- Métricas: pruebas procesadas por técnico, tiempos promedio, estados + +### 3. ✅ Dashboard de Muestras +**Factibilidad**: Alta +- Datos disponibles: stock.lot con is_lab_sample=True +- Métricas: muestras por estado, rechazos, re-muestreos + +### 4. ✅ Dashboard de Parámetros Fuera de Rango +**Factibilidad**: Alta +- Datos disponibles: lims.result (is_out_of_range, is_critical) +- Métricas: resultados críticos, fuera de rango por parámetro + +### 5. ✅ Dashboard de Análisis Más Solicitados +**Factibilidad**: Alta +- Datos disponibles: sale.order.line con productos is_analysis=True +- Métricas: top análisis, tendencias por período + +### 6. ⚠️ Dashboard de Tiempos de Respuesta +**Factibilidad**: Media +- Requiere campos calculados (no almacenados actualmente) +- Necesitaría agregar campos store=True para métricas de tiempo + +### 7. ❌ Dashboard de Facturación +**Factibilidad**: Baja +- Requiere módulo account (facturación) +- No está en las dependencias actuales + +### 8. ❌ Dashboard de Inventario de Reactivos +**Factibilidad**: Baja +- Requiere configuración adicional de stock +- No hay modelo específico para reactivos + +## Implementación Técnica + +### Herramientas Disponibles en Odoo 18: +1. **Vistas Graph**: Gráficos de barras, líneas, pie +2. **Vistas Pivot**: Tablas dinámicas +3. **Vistas Cohort**: Análisis de cohortes +4. **Filtros y Agrupaciones**: Para segmentar datos +5. **Acciones de Servidor**: Para cálculos complejos + +### Estructura Propuesta: +```xml + + +``` + +## Recomendación + +Sugiero comenzar con los 5 dashboards marcados con ✅ ya que: +1. Utilizan datos existentes +2. No requieren cambios en modelos +3. Usan herramientas nativas de Odoo +4. Proveen valor inmediato al administrador + +Orden de implementación sugerido: +1. Dashboard de Estado de Órdenes (más básico) +2. Dashboard de Productividad de Técnicos +3. Dashboard de Muestras +4. Dashboard de Parámetros Fuera de Rango +5. Dashboard de Análisis Más Solicitados \ No newline at end of file diff --git a/lims_management/__manifest__.py b/lims_management/__manifest__.py index 16f9d1f..d188b78 100644 --- a/lims_management/__manifest__.py +++ b/lims_management/__manifest__.py @@ -45,6 +45,7 @@ 'views/analysis_parameter_views.xml', 'views/product_template_parameter_config_views.xml', 'views/parameter_dashboard_views.xml', + 'views/dashboard_views.xml', 'views/menus.xml', 'views/lims_config_views.xml', 'report/sample_label_report.xml', diff --git a/lims_management/models/__pycache__/partner.cpython-312.pyc b/lims_management/models/__pycache__/partner.cpython-312.pyc index 0b833d5..3134b6c 100644 Binary files a/lims_management/models/__pycache__/partner.cpython-312.pyc and b/lims_management/models/__pycache__/partner.cpython-312.pyc differ diff --git a/lims_management/models/lims_test.py b/lims_management/models/lims_test.py index 3a9f3c9..98f9699 100644 --- a/lims_management/models/lims_test.py +++ b/lims_management/models/lims_test.py @@ -116,6 +116,21 @@ class LimsTest(models.Model): default=lambda self: self.env.company ) + # Campos para dashboards demográficos + patient_gender = fields.Selection( + related='patient_id.gender', + string='Género del Paciente', + store=True, + readonly=True + ) + + patient_age_range = fields.Selection( + related='patient_id.age_range', + string='Rango de Edad', + store=True, + readonly=True + ) + @api.depends('company_id') def _compute_require_validation(self): """Calcula si la prueba requiere validación basado en configuración.""" diff --git a/lims_management/models/partner.py b/lims_management/models/partner.py index b2f567d..0c85b92 100644 --- a/lims_management/models/partner.py +++ b/lims_management/models/partner.py @@ -29,6 +29,17 @@ class ResPartner(models.Model): 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)" @@ -54,6 +65,34 @@ class ResPartner(models.Model): 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""" diff --git a/lims_management/views/dashboard_views.xml b/lims_management/views/dashboard_views.xml new file mode 100644 index 0000000..a204bc3 --- /dev/null +++ b/lims_management/views/dashboard_views.xml @@ -0,0 +1,321 @@ + + + + + + + sale.order.lab.dashboard.graph + sale.order + + + + + + + + + + sale.order.lab.dashboard.pivot + sale.order + + + + + + + + + + + Estado de Órdenes + sale.order + graph,pivot,tree,form + [('is_lab_request', '=', True)] + {'search_default_group_by_state': 1} + +

+ No hay órdenes de laboratorio registradas +

+

+ Este dashboard muestra el estado actual de todas las órdenes de laboratorio. +

+
+
+ + + + + + lims.test.technician.productivity.graph + lims.test + + + + + + + + + + + lims.test.technician.productivity.pivot + lims.test + + + + + + + + + + + Productividad de Técnicos + lims.test + graph,pivot,tree,form + {'search_default_group_by_technician': 1, 'search_default_this_month': 1} + +

+ No hay pruebas registradas +

+

+ Este dashboard muestra la productividad de cada técnico del laboratorio. +

+
+
+ + + + + + stock.lot.sample.status.graph + stock.lot + + + + + + + + + + stock.lot.sample.type.pivot + stock.lot + + + + + + + + + + + Dashboard de Muestras + stock.lot + graph,pivot,tree,form + [('is_lab_sample', '=', True)] + {'search_default_group_by_state': 1} + +

+ No hay muestras registradas +

+

+ Este dashboard muestra el estado de todas las muestras del laboratorio. +

+
+
+ + + + + + lims.result.out.of.range.graph + lims.result + + + + + + + + + + + lims.result.critical.pivot + lims.result + + + + + + + + + + + + Parámetros Fuera de Rango + lims.result + graph,pivot,tree,form + [('test_id.state', '=', 'validated')] + {'search_default_out_of_range': 1} + +

+ No hay resultados fuera de rango +

+

+ Este dashboard muestra los parámetros que están fuera de los rangos normales. +

+
+
+ + + + + + sale.order.line.top.analysis.graph + sale.order.line + + + + + + + + + + + sale.order.line.analysis.period.pivot + sale.order.line + + + + + + + + + + + + Análisis Más Solicitados + sale.order.line + graph,pivot,tree + [('order_id.is_lab_request', '=', True), ('product_id.is_analysis', '=', True)] + {'search_default_group_by_product': 1} + +

+ No hay análisis registrados +

+

+ Este dashboard muestra los análisis más solicitados en el laboratorio. +

+
+
+ + + + + + lims.test.gender.distribution.graph + lims.test + + + + + + + + + + lims.test.demographics.pivot + lims.test + + + + + + + + + + + Distribución Demográfica de Tests + lims.test + graph,pivot,tree + [('state', '=', 'validated')] + {'search_default_this_year': 1} + +

+ No hay tests validados +

+

+ Este dashboard muestra la distribución de tests por características demográficas de los pacientes. +

+
+
+ + + + + + lims.test.dashboard.search + lims.test + + + + + + + + + + + + + + + + + + + + + + + + + + + lims.result.dashboard.search + lims.result + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/lims_management/views/menus.xml b/lims_management/views/menus.xml index c8bd994..a726237 100644 --- a/lims_management/views/menus.xml +++ b/lims_management/views/menus.xml @@ -155,6 +155,51 @@ action="action_lims_result" sequence="30"/> + + + + + + + + + + + + + + + +