Skip to content

Commit

Permalink
Merge pull request #188 from Black-Dot-2024/develop
Browse files Browse the repository at this point in the history
Develop a main
  • Loading branch information
DiegoSandovalV authored May 31, 2024
2 parents fb0790b + 02e5b87 commit daf069e
Show file tree
Hide file tree
Showing 37 changed files with 1,614 additions and 569 deletions.
3 changes: 3 additions & 0 deletions talent360/evaluaciones/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
"views/reporte_nom_035_template.xml",
"views/reporte_generico_template.xml",
"views/evaluaciones_menus.xml",
"views/importar_preguntas_wizard_views.xml",
"views/evaluaciones_responder.xml",
"views/wizards_views.xml",
"models/xml/cron_jobs.xml",
"views/registrar_avance_wizard.xml",
"data/pregunta.csv",
"data/competencia.csv",
"data/opcion.csv",
Expand Down
10 changes: 10 additions & 0 deletions talent360/evaluaciones/controllers/evaluaciones.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ def reporte_controller(self, evaluacion, filtros=None):

parametros["filtros"] = filtros

tiene_respuestas = True

for pregunta in parametros["preguntas"]:
if not pregunta["respuestas"]:
tiene_respuestas = False
break

if not tiene_respuestas:
return request.render("evaluaciones.encuestas_reporte_no_respuestas", parametros)

if evaluacion.incluir_demograficos:
parametros.update(evaluacion.generar_datos_demograficos(filtros))
if evaluacion.tipo == "NOM_035":
Expand Down
2 changes: 2 additions & 0 deletions talent360/evaluaciones/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@
from . import pregunta_escala
from . import reporte_resumen
from . import usuario_externo
from . import niveles
from . import objetivo_avances
204 changes: 180 additions & 24 deletions talent360/evaluaciones/models/evaluacion.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from collections import defaultdict, Counter
from odoo import exceptions
from datetime import timedelta
from odoo.exceptions import ValidationError


class Evaluacion(models.Model):
Expand All @@ -28,11 +29,10 @@ class Evaluacion(models.Model):
_description = "Evaluacion de personal"
_rec_name = "nombre"
nombre = fields.Char(string="Título de la evaluación", required=True)

escalar_format = fields.Selection([
("numericas", "Numéricas"),
("textuales", "Textuales"),
("caritas", "Caritas"),
("caritas", "LIKERT"),
("estrellas", "Estrellas")
], string="Formato para las preguntas escalares", required=True, default="numericas")

Expand All @@ -44,7 +44,7 @@ class Evaluacion(models.Model):
("generico", "Genérico"),
],
required=True,
default="competencia",
default="generico",
)
descripcion = fields.Text(string="Descripción")
estado = fields.Selection(
Expand Down Expand Up @@ -89,6 +89,12 @@ class Evaluacion(models.Model):
string="Asignados Externos",
)

niveles = fields.One2many(
"niveles",
"evaluacion_id",
string="Niveles",
)

fecha_inicio = fields.Date(string="Fecha de inicio", required=True)
fecha_final = fields.Date(string="Fecha de finalización", required=True)
mensaje_bienvenida = fields.Text(
Expand Down Expand Up @@ -156,13 +162,22 @@ def copiar_preguntas_de_template(self):

if not self:

ultimo_id = self.env["evaluacion"].search([], order="id desc", limit=1)

new_evaluation = self.env["evaluacion"].create(
{
"nombre": "",
"nombre": str(ultimo_id.id + 1) + " Evaluación Clima",
"descripcion": "La evaluación Clima es una herramienta de medición de clima organizacional, cuyo objetivo es conocer la percepción que tienen las personas que laboran en los centros de trabajo, sobre aquellos aspectos sociales que conforman su entorno laboral y que facilitan o dificultan su desempeño.",
"tipo": "CLIMA",
"fecha_inicio": fields.Date.today(),
"fecha_final": fields.Date.today(),
"niveles": [
(0, 0, {"descripcion_nivel": "Muy malo", "techo": 20, "color": "#ff4747"}),
(0, 0, {"descripcion_nivel": "Malo", "techo": 40, "color": "#ffa446"}),
(0, 0, {"descripcion_nivel": "Regular", "techo": 60, "color": "#ebae14"}),
(0, 0, {"descripcion_nivel": "Bueno", "techo": 80, "color": "#5aaf2b"}),
(0, 0, {"descripcion_nivel": "Muy bueno", "techo": 100, "color": "#2894a7"}),
],
}
)
self = new_evaluation
Expand Down Expand Up @@ -194,9 +209,12 @@ def copiar_preguntas_de_template_nom035(self):
"""

if not self:

ultimo_id = self.env["evaluacion"].search([], order="id desc", limit=1)

new_evaluation = self.env["evaluacion"].create(
{
"nombre": "",
"nombre": str(ultimo_id.id + 1) + " Evaluación NOM 035",
"descripcion": "La NOM 035 tiene como objetivo establecer los elementos para identificar, analizar y prevenir los factores de riesgo psicosocial, así como para promover un entorno organizacional favorable en los centros de trabajo.",
"tipo": "NOM_035",
"fecha_inicio": fields.Date.today(),
Expand Down Expand Up @@ -633,9 +651,7 @@ def generar_datos_reporte_clima_action(self, filtros=None):
else "Sin departamento"
)
elif respuesta.usuario_externo_id:
usuario_externo = self.env["usuario.externo"].browse(
respuesta.usuario_externo_id
)
usuario_externo = respuesta.usuario_externo_id
nombre_departamento = (
usuario_externo.direccion
if usuario_externo.direccion
Expand Down Expand Up @@ -724,9 +740,7 @@ def validar_filtro(self, filtros, respuesta=None, datos_demograficos=None):
respuesta.usuario_id
)
elif respuesta.usuario_externo_id:
usuario_externo = self.env["usuario.externo"].browse(
respuesta.usuario_externo_id
)
usuario_externo = respuesta.usuario_externo_id
datos_demograficos = self.obtener_datos_demograficos_externos(
usuario_externo
)
Expand Down Expand Up @@ -987,16 +1001,10 @@ def asignar_color_clima(self, valor):
:return: El color asignado al valor.
"""
if self.techo_verde <= valor <= self.techo_azul:
return "#2894a7" # Azul clarito
elif self.techo_amarillo <= valor <= self.techo_verde:
return "#5aaf2b" # Verde
elif self.techo_naranja <= valor <= self.techo_amarillo:
return "#ebae14" # Amarillo
elif self.techo_rojo <= valor <= self.techo_naranja:
return "#ffa446" # Naranja
else:
return "#ff4747" # Rojo

for nivel in self.niveles:
if valor <= nivel.techo:
return nivel.color

def obtener_dato(self, dato):
"""
Expand Down Expand Up @@ -1162,7 +1170,6 @@ def write(self, vals):
]
)

print(f"Respuestas: {respuestas}")
respuestas.unlink()

if "usuario_externo_ids" in vals:
Expand All @@ -1174,13 +1181,18 @@ def write(self, vals):
if usuarios_eliminados:
respuestas = self.env["respuesta"].search(
[
("usuario_externo_id", "in", usuarios_eliminados),
("usuario_externo_id.id", "in", usuarios_eliminados),
("evaluacion_id.id", "=", self.id),
]
)
print(f"Respuestas: {respuestas}")
respuestas.unlink()

for record in self:
if record.tipo == "generico" and len(record.pregunta_ids) < 1:
raise exceptions.ValidationError(_("La evaluación debe tener al menos una pregunta."))
if record.tipo == "generico" and len(record.usuario_ids) < 1:
raise exceptions.ValidationError(_("La evaluación debe tener al menos una persona asignada."))

return resultado

def action_asignar_usuarios_externos(self):
Expand All @@ -1196,6 +1208,117 @@ def action_asignar_usuarios_externos(self):
"view_mode": "form",
"target": "new",
}

@api.constrains("niveles")
def checar_techo(self):
"""
Verifica que los valores de la ponderación sean válidos.
Validación 1: Verifica que el valor de la ponderación no sea menor o igual a 0.
Validación 2: Verifica que no haya valores duplicados en la ponderación para la misma evaluación.
Validación 3: Verifica que no haya más de 10 techos.
Validación 4: Verifica que los valores de la ponderación estén en orden ascendente.
Validación 5: Verifica que el valor de las ponderaciones no sean mayores a 100 y que el último sea 100.
"""
for nivel in self.niveles:
if nivel.techo <= 0:
raise ValidationError(
"El valor de la ponderación no debe ser menor o igual a 0."
)

techos = self.niveles.filtered(lambda n: n.id != nivel.id).mapped("techo")
if nivel.techo in techos:
raise ValidationError(
"No puede haber valores duplicados en la ponderación."
)

todos_techos = self.niveles.mapped("techo")
if len(todos_techos) > 10:
raise ValidationError(
"No puede haber más de 10 valores de ponderación."
)

if todos_techos != sorted(todos_techos):
raise ValidationError(
"Los valores de la ponderación deben estar en orden ascendente."
)

if todos_techos[-1] > 100:
raise ValidationError(
"El valor de la ponderación no puede ser mayor a 100."
)
if todos_techos[-1] != 100:
raise ValidationError("El último valor de la ponderación debe ser 100.")


def actualizar_estados_eval(self):
"""
Actualiza el estado de las evaluaciones según la fecha actual.
- Si la fecha actual está dentro del rango de fechas de inicio y finalización,
se cambia el estado a 'publicado' (Abierta).
- De lo contrario, pasa a 'finalizado' (Cerrada).
:return: None
"""

hoy = fields.Date.today()
hora = fields.Datetime.now().strftime("%H:%M:%S")

# asignar 11:59pm como hora de cierre de evaluaciones
hora_cierre = "23:59:55"

# Asignar la hora de apertura de las evaluaciones 12:01am
hora_apertura = "00:00:55"

evaluaciones = self.search([])

# Actualizar el estado de las evaluaciones según la fecha y hora actual
for evaluacion in evaluaciones:
if evaluacion.fecha_inicio <= hoy <= evaluacion.fecha_final:
if hoy == evaluacion.fecha_inicio and hora < hora_apertura:
evaluacion.estado = "borrador"
elif hoy == evaluacion.fecha_final and hora > hora_cierre:
evaluacion.estado = "finalizado"
else:
evaluacion.estado = "publicado"
elif evaluacion.fecha_final < hoy:
evaluacion.estado = "finalizado"
elif evaluacion.fecha_inicio > hoy:
evaluacion.estado = "borrador"

def evaluacion_general_action_form(self):
"""
Ejecuta la acción de redireccionar a la evaluación general y devuelve un diccionario
Este método utiliza los parámetros necesarios para redireccionar a la evaluación general
:return: Un diccionario que contiene todos los parámetros necesarios para redireccionar la
a una vista de la evaluación general.
"""

ultimo_id = self.env["evaluacion"].search([], order="id desc", limit=1)

nueva_evaluacion = self.env["evaluacion"].create(
{
"nombre": str(ultimo_id.id + 1) + " Evaluación Genérica",
"tipo": "generico",
"fecha_inicio": fields.Date.today(),
"fecha_final": fields.Date.today(),
}
)
self = nueva_evaluacion

return {
"type": "ir.actions.act_window",
"name": "General",
"res_model": "evaluacion",
"view_mode": "form",
"view_id": self.env.ref("evaluaciones.evaluacion_general_view_form").id,
"target": "current",
"res_id": self.id,
}

def get_escalar_format(self):
"""
Expand All @@ -1204,3 +1327,36 @@ def get_escalar_format(self):
:return: El formato escalar seleccionado para la evaluación.
"""
return self.escalar_format

def generar_reporte(self):
"""
Devuelve las fechas de inicio y final que el usuario acordo al realizar la evaluación.
:return: Las fechas de inicio y final.
"""
return {

"type": "ir.actions.report",
"report_name": "evaluaciones.reporte_template",
"context": {
"evaluacion_id": self.id,
"fecha_inicio": self.fecha_inicio,
"fecha_final": self.fecha_final,
}
}

def action_importar_preguntas_clima(self):
"""
Abre la ventana para importar preguntas de clima laboral.
:return: Una acción para abrir la ventana de importación de preguntas
"""
return {
"name": "Importar preguntas de clima laboral",
"type": "ir.actions.act_window",
"res_model": "importar.preguntas.wizard",
"view_mode": "form",
"target": "new",
}


30 changes: 28 additions & 2 deletions talent360/evaluaciones/models/evaluacion_clima.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,11 @@ def _checar_techos(self):

for techo in techos:
if techo[1] <= 0:
raise ValidationError(_((f"El nivel {techo[0]} debe ser mayor a 0")))
raise ValidationError(
_((f"El nivel {techo[0]} debe ser mayor a 0")))
elif techo[1] > 100:
raise ValidationError((f"El nivel {techo[0]} no puede ser mayor a 100"))
raise ValidationError(
(f"El nivel {techo[0]} no puede ser mayor a 100"))

for i in range(len(techos) - 1):
for j in range(i + 1, len(techos)):
Expand All @@ -114,3 +116,27 @@ def _checar_techos(self):
raise ValidationError(
_((f"Los niveles de techo no pueden ser iguales"))
)

@api.constrains(
"descripcion_rojo", "descripcion_naranja", "descripcion_amarillo", "descripcion_verde", "descripcion_azul"
)
def _checar_descripciones(self):
"""
Se valida que las descripciones no estén vacías.
"""
descripciones = [
("rojo", self.descripcion_rojo),
("naranja", self.descripcion_naranja),
("amarillo", self.descripcion_amarillo),
("verde", self.descripcion_verde),
("azul", self.descripcion_azul),
]

for descripcion in descripciones:
if not descripcion[1]:
raise ValidationError(
_((f"La descripción del nivel {descripcion[0]} no puede estar vacía")))

elif len(descripcion[1]) > 50:
raise ValidationError(
_((f"La descripción del nivel {descripcion[0]} no puede tener más de 50 caracteres")))
Loading

0 comments on commit daf069e

Please sign in to comment.