Files
ihrm/project/cbv/timesheet.py

498 lines
16 KiB
Python

"""
CBV of time sheet page
"""
from typing import Any
from django import forms
from django.contrib import messages
from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import render
from django.urls import resolve, reverse
from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _
from employee.models import Employee
from horilla_views.cbv_methods import login_required
from horilla_views.generic.cbv.views import (
HorillaCardView,
HorillaDetailedView,
HorillaFormView,
HorillaListView,
HorillaNavView,
TemplateView,
)
from project.cbv.cbv_decorators import is_projectmanager_or_member_or_perms
from project.cbv.projects import DynamicProjectCreationFormView
from project.cbv.tasks import DynamicTaskCreateFormView
from project.filters import TimeSheetFilter
from project.forms import TimeSheetForm
from project.models import Project, Task, TimeSheet
@method_decorator(login_required, name="dispatch")
@method_decorator(
is_projectmanager_or_member_or_perms("project.view_timesheet"), name="dispatch"
)
class TimeSheetView(TemplateView):
"""
for time sheet page
"""
template_name = "cbv/timesheet/timesheet.html"
@method_decorator(login_required, name="dispatch")
@method_decorator(
is_projectmanager_or_member_or_perms("project.view_timesheet"), name="dispatch"
)
class TimeSheetNavView(HorillaNavView):
"""
Nav bar
"""
template_name = "cbv/timesheet/timesheet_nav.html"
def __init__(self, **kwargs: Any) -> None:
super().__init__(**kwargs)
self.search_url = reverse("time-sheet-list")
url = f"{reverse('personal-time-sheet-view',kwargs={'emp_id': self.request.user.employee_get.id})}"
self.actions = [
{
"action": _("Delete"),
"attrs": """
class="oh-dropdown__link--danger"
data-action ="delete"
onclick="deleteTimeSheet();"
style="cursor: pointer; color:red !important"
""",
},
]
self.view_types = [
{
"type": "list",
"icon": "list-outline",
"url": reverse("time-sheet-list"),
"attrs": """
title ='List'
""",
},
{
"type": "card",
"icon": "grid-outline",
"url": reverse("time-sheet-card"),
"attrs": """
title ='Card'
""",
},
{
"type": "graph",
"icon": "bar-chart",
"attrs": f"""
onclick="event.stopPropagation();
window.location.href='{url}'"
title ='Graph'
""",
},
]
self.create_attrs = f"""
onclick = "event.stopPropagation();"
data-toggle="oh-modal-toggle"
data-target="#genericModal"
hx-target="#genericModalBody"
hx-get="{reverse('create-time-sheet')}"
"""
group_by_fields = [
("employee_id", _("Employee")),
("project_id", _("Project")),
("date", _("Date")),
("status", _("Status")),
(
"employee_id__employee_work_info__reporting_manager_id",
_("Reporting Manager"),
),
("employee_id__employee_work_info__department_id", _("Department")),
("employee_id__employee_work_info__job_position_id", _("Job Position")),
("employee_id__employee_work_info__employee_type_id", _("Employement Type")),
("employee_id__employee_work_info__company_id", _("Company")),
]
nav_title = _("Time Sheet")
filter_instance = TimeSheetFilter()
filter_form_context_name = "form"
filter_body_template = "cbv/timesheet/filter.html"
search_swap_target = "#listContainer"
@method_decorator(login_required, name="dispatch")
@method_decorator(
is_projectmanager_or_member_or_perms("project.view_timesheet"), name="dispatch"
)
class TimeSheetList(HorillaListView):
"""
Time sheet list view
"""
def get_queryset(self):
queryset = super().get_queryset()
if not self.request.user.has_perm("project.view_timesheet"):
employee = self.request.user.employee_get
queryset = queryset.filter(
Q(task_id__task_managers=employee)
| Q(project_id__managers=employee)
| Q(employee_id=employee)
).distinct()
return queryset
def __init__(self, **kwargs: Any) -> None:
super().__init__(**kwargs)
self.search_url = reverse("time-sheet-list")
self.action_method = "actions"
model = TimeSheet
filter_class = TimeSheetFilter
columns = [
(_("Employee"), "employee_id", "employee_id__get_avatar"),
(_("Project"), "project_id"),
(_("Task"), "task_id"),
(_("Date"), "date"),
(_("Time Spent"), "time_spent"),
(_("Status"), "status_column"),
(_("Description"), "description"),
]
sortby_mapping = [
("Employee", "employee_id__employee_first_name", "employee_id__get_avatar"),
("Project", "project_id__title"),
("Task", "task_id__title"),
("Time Spent", "time_spent"),
("Date", "date"),
]
row_status_indications = [
(
"in-progress--dot",
_("In progress"),
"""
onclick="
$('#applyFilter').closest('form').find('[name=status]').val('in_Progress');
$('#applyFilter').click();
"
""",
),
(
"completed--dot",
_("Completed"),
"""
onclick="
$('#applyFilter').closest('form').find('[name=status]').val('completed');
$('#applyFilter').click();
"
""",
),
]
row_attrs = """
hx-get='{detail_view}?instance_ids={ordered_ids}'
hx-target="#genericModalBody"
data-target="#genericModal"
data-toggle="oh-modal-toggle"
"""
row_status_class = "status-{status}"
@method_decorator(login_required, name="dispatch")
@method_decorator(
is_projectmanager_or_member_or_perms("project.view_timesheet"), name="dispatch"
)
class TaskTimeSheet(TimeSheetList):
row_attrs = ""
row_status_indications = False
bulk_select_option = False
def __init__(self, **kwargs: Any) -> None:
super().__init__(**kwargs)
self.view_id = "task-timesheet-container"
task_id = resolve(self.request.path_info).kwargs.get("task_id")
self.request.task_id = task_id
employee_id = self.request.GET.get("employee_id")
if employee_id:
self.action_method = "actions"
def get_context_data(self, **kwargs: Any):
context = super().get_context_data(**kwargs)
task_id = self.kwargs.get("task_id")
task = Task.objects.get(id=task_id)
project = task.project
context["task_id"] = task_id
context["project"] = project
context["task"] = task
return context
template_name = "cbv/timesheet/task_timesheet.html"
def get_queryset(self):
queryset = HorillaListView.get_queryset(self)
task_id = self.kwargs.get("task_id")
task = Task.objects.filter(id=task_id).first()
queryset = TimeSheet.objects.filter(task_id=task_id)
queryset = queryset.filter(task_id=task_id)
employee_id = self.request.GET.get("employee_id")
if employee_id:
employee = Employee.objects.filter(id=employee_id).first()
if (
not employee in task.task_managers.all()
and not employee in task.project.managers.all()
and not employee.employee_user_id.is_superuser
):
queryset = queryset.filter(employee_id=employee_id)
return queryset
@method_decorator(login_required, name="dispatch")
@method_decorator(
is_projectmanager_or_member_or_perms("project.view_timesheet"), name="dispatch"
)
class TimeSheetFormView(HorillaFormView):
"""
form view for create project
"""
def __init__(self, **kwargs: Any) -> None:
super().__init__(**kwargs)
self.dynamic_create_fields = [
("task_id", DynamicTaskCreateFormView),
]
if self.request.user.has_perm("project.add_project"):
self.dynamic_create_fields.append(
("project_id", DynamicProjectCreationFormView)
)
form_class = TimeSheetForm
model = TimeSheet
new_display_title = _("Create Time Sheet")
# template_name = "cbv/timesheet/form.html"
def get_initial(self) -> dict:
initial = super().get_initial()
task_id = self.kwargs.get("task_id")
if task_id:
task = Task.objects.get(id=task_id)
project_id = task.project
initial["project_id"] = project_id.id
initial["task_id"] = task.id
return initial
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
task_id = self.kwargs.get("task_id")
user_employee_id = self.request.user.employee_get.id
project = None
if task_id:
task = Task.objects.get(id=task_id)
project = task.project
employee = Employee.objects.filter(id=user_employee_id)
if self.form.instance.pk:
task_id = self.form.instance.task_id.id
project = self.form.instance.project_id
tasks = Task.objects.filter(project=project)
employee = Employee.objects.filter(id=user_employee_id)
task = Task.objects.get(id=task_id)
self.form.fields["task_id"].queryset = tasks
self.form.fields["task_id"].choices = [
(item.id, item.title) for item in tasks
]
self.form.fields["task_id"].choices.append(
("dynamic_create", "Dynamic create")
)
task_id = self.request.GET.get("task_id")
self.form_class.verbose_name = _("Update Time Sheet")
# If the timesheet create from task or project
if project:
if self.request.user.is_superuser or self.request.user.has_perm(
"project.add_project"
):
members = (
project.managers.all()
| project.members.all()
| task.task_members.all()
| task.task_managers.all()
).distinct()
elif employee.first() in project.managers.all():
members = (
employee
| project.members.all()
| task.task_members.all()
| task.task_managers.all()
).distinct()
elif employee.first() in task.task_managers.all():
members = (employee | task.task_members.all()).distinct()
else:
members = employee
if task_id:
self.form.fields["project_id"].widget = forms.HiddenInput()
self.form.fields["task_id"].widget = forms.HiddenInput()
self.form.fields["employee_id"].queryset = members
# If the timesheet create directly
else:
employee = self.request.user.employee_get
if self.request.user.has_perm("project.add_timesheet"):
projects = Project.objects.all()
else:
projects = (
Project.objects.filter(managers=employee)
| Project.objects.filter(members=employee)
| Project.objects.filter(
id__in=Task.objects.filter(task_managers=employee).values_list(
"project", flat=True
)
)
| Project.objects.filter(
id__in=Task.objects.filter(task_members=employee).values_list(
"project", flat=True
)
)
).distinct()
self.form.fields["project_id"].queryset = projects
return context
def form_valid(self, form: TimeSheetForm) -> HttpResponse:
if form.is_valid():
if form.instance.pk:
message = _(f"{self.form.instance} Updated")
else:
message = _("New time sheet created")
form.save()
messages.success(self.request, _(message))
return self.HttpResponse()
return super().form_valid(form)
@method_decorator(login_required, name="dispatch")
@method_decorator(
is_projectmanager_or_member_or_perms("project.view_timesheet"), name="dispatch"
)
class TimeSheetCardView(HorillaCardView):
"""
For card view
"""
model = TimeSheet
filter_class = TimeSheetFilter
def get_queryset(self):
queryset = super().get_queryset()
if not self.request.user.has_perm("project.view_timesheet"):
employee = self.request.user.employee_get
queryset = queryset.filter(
Q(task_id__task_managers=employee)
| Q(project_id__managers=employee)
| Q(employee_id=employee)
).distinct()
return queryset
def __init__(self, **kwargs: Any) -> None:
super().__init__(**kwargs)
self.search_url = reverse("time-sheet-card")
self.actions = [
{
"action": "Edit",
"attrs": """
hx-get='{get_update_url}'
hx-target='#genericModalBody'
data-toggle="oh-modal-toggle"
data-target="#genericModal"
class="oh-dropdown__link"
""",
},
{
"action": "Delete",
"attrs": """
onclick="
event.stopPropagation()
deleteItem({get_delete_url});
"
class="oh-dropdown__link oh-dropdown__link--danger"
""",
},
]
details = {
"image_src": "employee_id__get_avatar",
"title": "{employee_id}",
"subtitle": " <b>{date}</b> <br>Project : <b>{project_id}</b> <br><b>{task_id}</b> | Time Spent : <b>{time_spent}</b>",
}
card_status_class = "status-{status}"
card_status_indications = [
(
"in-progress--dot",
_("In progress"),
"""
onclick="
$('#applyFilter').closest('form').find('[name=status]').val('in_Progress');
$('#applyFilter').click();
"
""",
),
(
"completed--dot",
_("Completed"),
"""
onclick="
$('#applyFilter').closest('form').find('[name=status]').val('completed');
$('#applyFilter').click();
"
""",
),
]
card_attrs = """
hx-get='{detail_view}?instance_ids={ordered_ids}'
hx-target="#genericModalBody"
data-target="#genericModal"
data-toggle="oh-modal-toggle"
"""
@method_decorator(login_required, name="dispatch")
@method_decorator(
is_projectmanager_or_member_or_perms("project.view_timesheet"), name="dispatch"
)
class TimeSheetDetailView(HorillaDetailedView):
"""
detail view of the page
"""
model = TimeSheet
title = _("Details")
header = {
"title": "employee_id",
"subtitle": "project_id",
"avatar": "employee_id__get_avatar",
}
body = [
(_("Task"), "task_id"),
(_("Date"), "date"),
(_("Time Spent"), "time_spent"),
(_("Status"), "status_column"),
(_("Description"), "description"),
]
action_method = "detail_actions"