I have a table called Task. It captures task, task score and the employee it is assigned to. I want to calculate the performance of the employee using his total task scores for the week (duration should be dynamic. preferably input field) and the total scores allocated. I am thinking of aggregating the actual scores then dividing buy total score then multiply by 100 to get the percentage. My major challenge is where to perform this calculation. Should I create a model called performance and use a function? Or if can anyone show me how to go about this?
Here is the model;
class Task(models.Model):
title = model.CharField(max_length=200)
scores = models.IntegerField(null=True, blank=True)
def __str__(self):
return self.name
Here is the formula I want to use. Performance(%) = actual score / total score * 100. Total score should be input field.
UPDATE Here are the relevant models. I am using User model as Employee.
**USER OR EMPLOYEE MODEL**
class User(AbstractUser):
ROLE_CHOICES = (
("STAFF", "Staff"),
("HOD", "Hod"),
("CEO", "Ceo"),
)
GENDER_CHOICES = (
("Male", "Male"),
("Female", "Female")
)
CONFIRMATION_CHOICES = (
("YES", "yes"),
("NO", "no")
)
UNDERTAKING_CHOICES = (
("YES", "yes"),
("NOT YET", "Not yet")
)
GENDER_CHOICES = (
("Male", "Male"),
("Female", "Female")
)
EMPLOYEE_TYPE_CHOICES = (
("Permanent", "Permanent"),
("Contract", "Contract")
)
first_name = models.CharField(max_length=100, blank=True)
last_name = models.CharField(max_length=100, blank=True)
middle_name = models.CharField(max_length=100, null=True, blank=True)
email = models.EmailField(null=True)
avatar = models.ImageField(upload_to='images/avatar', null=True, blank=True)
department = models.ForeignKey(Department, related_name='userdept', on_delete=models.CASCADE, null=True)
role = models.ForeignKey(Role, related_name='userrol', on_delete=models.CASCADE, null=True, blank=True)
user_role = models.CharField(max_length=100, choices=ROLE_CHOICES, null=True)
avatar = models.ImageField(upload_to="avatars", null=True, blank=True)
is_hod = models.BooleanField(default=False)
is_ceo = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
gender = models.CharField(max_length=100, choices=GENDER_CHOICES, null=True, blank=True)
cell_phone = models.CharField(max_length=20, blank=True, null=True)
employee_id = models.CharField(max_length=200, null=True, blank=True)
supervisor = models.CharField(max_length=200, null=True, blank=True)
work_email = models.EmailField(null=True, blank=True)
work_phone = models.CharField(max_length=20, blank=True)
start_date = models.CharField(max_length=20, blank=True)
salary = models.CharField(max_length=20, blank=True, null=True)
work_location = models.CharField(max_length=20, null=True, blank=True)
probation_length = models.CharField(max_length=20, null=True, blank=True)
pay_slip_type = models.CharField(max_length=20, null=True, blank=True)
can_terminate = models.CharField(max_length=20, null=True, blank=True)
dob = models.CharField(max_length=20, null=True, blank=True)
employee_type = models.CharField(max_length=20, choices=EMPLOYEE_TYPE_CHOICES, null=True, blank=True)
comfirmed = models.CharField(max_length=3, choices=CONFIRMATION_CHOICES, null=True)
undertaking = models.CharField(max_length=8, choices=UNDERTAKING_CHOICES, null=True)
leave_days = models.IntegerField(null=True, blank=True)
line_manager = models.CharField(max_length=20, null=True, blank=True)
last_promotion_date = models.CharField(max_length=20, null=True, blank=True)
def __str__(self):
return self.first_name+' '+self.last_name
**TASK MODEL**
from django.db import models
from departments.models import Department
from akps.models import Akp
from users.models import User
from goals.models import OrganisationGoal, OrganisationSubGoal, DepartmentGoal
from django.template.loader import render_to_string
from django.core.mail import send_mail
from django.core.mail import EmailMultiAlternatives
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.utils.text import slugify
# from django.template.loader import render_to_string
from django.core.mail import send_mail
from django.core.mail import EmailMultiAlternatives
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.utils.text import slugify
from django.core.exceptions import ValidationError
class Task(models.Model):
STATUS_CHOICES = (
("COMPLETED", "completed"),
("FAILED", "failed"),
)
department = models.ForeignKey(Department, related_name='soussdepartmentt', on_delete=models.CASCADE, null=True)
akp = models.ForeignKey(Akp, related_name='sousakpp', on_delete=models.CASCADE, null=True)
organisationgoal = models.ForeignKey(OrganisationGoal, on_delete=models.CASCADE, null=True)
organisationsubgoal = models.ForeignKey(OrganisationSubGoal, on_delete=models.CASCADE, null=True, blank=True)
departmentgoal = models.ForeignKey(DepartmentGoal, on_delete=models.CASCADE, related_name='departgoal', null=True, blank=True)
name = models.CharField(max_length=300, null=True)
description = models.TextField(max_length=1000, null=True)
assignedby = models.ForeignKey(User, on_delete=models.CASCADE, related_name='taskassignb', null=True, blank=True)
assignedto = models.ForeignKey(User, on_delete=models.CASCADE, related_name='taskassignt', null=True, blank=True)
user = models.ForeignKey(User, related_name='usertas', on_delete=models.CASCADE, null=True)
scores = models.IntegerField(null=True, blank=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, null=True, blank=True)
email = models.EmailField(null=True)
due_date = models.DateField(null=True)
created_at = models.DateTimeField(auto_now_add=True, null=True)
updated_at = models.DateTimeField(auto_now=True, null=True)
def __str__(self):
return self.name
def clean(self):
other_tasks = Task.objects.exclude(pk=self.pk) \
.filter(departmentgoal=self.departmentgoal)
if other_tasks.count() > 0:
contributed = (
other_tasks.values("departmentgoal")
.annotate(total=models.Sum("scores"))
.values_list("total", flat=True)[0]
)
else:
contributed = 0
if self.scores and self.scores + contributed > self.departmentgoal.scores:
raise ValidationError({"scores": "Score is too much"})
Here is a scenario;
user A has completed 8 out of 10 weekly task. He scored a total of 18 point. NOTE: Weekly scores can not exceed 20 points.
The process above is repeated every week. Lets say the second week, he scored 20 points.
After either 1 month, 4 months, 6 months or 1 year, I want to calculate his performance and display on his dashboard. The maths is actual score / total score * 100. I believe this can be achieve with the user and task model but i dont know how to implement this.
USER AND DASHBOARD VIEW
from tasks.models import Task
from users.models import User
from goals.models import DepartmentGoal, OrganisationGoal
from django.utils import timezone
from datetime import timedelta
def dashboard(request):
completed_tasks = Task.objects.filter(status="COMPLETED", assignedto=request.user).count()
failed_tasks = Task.objects.filter(status="FAILED", assignedto=request.user).count()
debt_complt_goal = DepartmentGoal.objects.filter(status="COMPLETED", department=request.user.department).count()
debt_failed_goal = DepartmentGoal.objects.filter(status="FAILED", department=request.user.department).count()
complt_org_goals = OrganisationGoal.objects.filter(status="COMPLETED").count()
failed_org_goals = OrganisationGoal.objects.filter(status="FAILED").count()
return render (request, 'home.html', {
'completed_tasks':completed_tasks,
'failed_tasks':failed_tasks,
'debt_complt_goal':debt_complt_goal,
'debt_failed_goal':debt_failed_goal,
'complt_org_goals':complt_org_goals,
'failed_org_goals':failed_org_goals,
})
from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
from .models import Profile, User
from .forms import ProfileForm, CreateUserForm, UserSetPasswordForm
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages
def list_users_view(request):
department = request.user.department
dept_users = User.objects.filter(department=department)
users = User.objects.all()
context = {
'users':users,
'dept_users':dept_users
}
return render(request, 'users/list-users.html', context)
Here is the criteria that I interpreted:
assignedto
field.Solution
Add a custom method on your User
model to calculate the performance. The method will ask for a start
and end
date arguments to calculate the performance between a time range.
from django.db.models import Sum, Q
class User(AbstractUser):
...
def performance(self, start, end):
actual = Sum("scores", filter=Q(status="completed"))
q = self.taskassignt.filter(
due_date__gte=start,
due_date__lt=end # `end` is excluded from the range
).annotate(actual=actual, total=Sum("scores"))
return (q[0].actual / q[0].total) * 100
Note the time range implementation excludes end
from the range since it uses the lt
(less than) operator.
Usage of the method is:
from django.utils import timezone
from datetime import timedelta
# user is a `User` instance
user.performance(timezone.now() + timedelta(days=-7), timezone.now())