Skip to content
This repository has been archived by the owner on May 13, 2024. It is now read-only.

Commit

Permalink
chore(views): added type annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
c0rydoras committed Apr 29, 2024
1 parent a0579d3 commit 76f3a32
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 44 deletions.
25 changes: 14 additions & 11 deletions timed/employment/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"""Viewsets for the employment app."""

from __future__ import annotations

import datetime
from typing import TYPE_CHECKING

from django.contrib.auth import get_user_model
from django.db.models import CharField, DateField, IntegerField, Q, Value
Expand Down Expand Up @@ -28,6 +31,9 @@
from timed.projects.models import CustomerAssignee, Task
from timed.tracking.models import Absence, Report

if TYPE_CHECKING:
from django.db.models import QuerySet


class UserViewSet(ModelViewSet):
"""Expose user actions.
Expand Down Expand Up @@ -57,7 +63,7 @@ class UserViewSet(ModelViewSet):
"last_name",
)

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.User]:
user = self.request.user
queryset = get_user_model().objects.prefetch_related(
"employments", "supervisees", "supervisors"
Expand Down Expand Up @@ -114,7 +120,7 @@ def transfer(self, _request, pk=None): # noqa: ARG002
It will skip any credits if a credit already exists on the first
of the new year.
"""
user = self.get_object()
user: models.User = self.get_object()

year = datetime.date.today().year
start_year = datetime.date(year, 1, 1)
Expand Down Expand Up @@ -325,7 +331,7 @@ class EmploymentViewSet(ModelViewSet):
),
)

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.Employment]:
"""Get queryset of employments.
Following rules apply:
Expand All @@ -350,7 +356,7 @@ class LocationViewSet(ReadOnlyModelViewSet):
serializer_class = serializers.LocationSerializer
ordering = ("name",)

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.Location]:
"""Don't show locations to customers."""
user = self.request.user

Expand All @@ -368,13 +374,10 @@ class PublicHolidayViewSet(ReadOnlyModelViewSet):
filterset_class = filters.PublicHolidayFilterSet
ordering = ("date",)

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.PublicHoliday]:
"""Prefetch the related data.
Don't show public holidays to customers.
:return: The public holidays
:rtype: QuerySet
"""
user = self.request.user

Expand All @@ -393,7 +396,7 @@ class AbsenceTypeViewSet(ReadOnlyModelViewSet):
filterset_class = filters.AbsenceTypeFilterSet
ordering = ("name",)

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.AbsenceType]:
"""Don't show absence types to customers."""
user = self.request.user

Expand All @@ -418,7 +421,7 @@ class AbsenceCreditViewSet(ModelViewSet):
),
)

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.AbsenceCredit]:
"""Get queryset of absence credits.
Following rules apply:
Expand Down Expand Up @@ -450,7 +453,7 @@ class OvertimeCreditViewSet(ModelViewSet):
),
)

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.OvertimeCredit]:
"""Get queryset of overtime credits.
Following rules apply:
Expand Down
28 changes: 16 additions & 12 deletions timed/projects/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
"""Viewsets for the projects app."""

from __future__ import annotations

from typing import TYPE_CHECKING

from django.db.models import Q
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet

Expand All @@ -15,6 +19,9 @@
)
from timed.projects import filters, models, serializers

if TYPE_CHECKING:
from django.db.models import QuerySet


class CustomerViewSet(ReadOnlyModelViewSet):
"""Customer view set."""
Expand All @@ -23,13 +30,10 @@ class CustomerViewSet(ReadOnlyModelViewSet):
filterset_class = filters.CustomerFilterSet
ordering = ("name",)

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.Customer]:
"""Prefetch related data.
If an employee is external, get only assigned customers.
:return: The customers
:rtype: QuerySet
"""
user = self.request.user
queryset = models.Customer.objects.prefetch_related("projects")
Expand Down Expand Up @@ -63,7 +67,7 @@ class BillingTypeViewSet(ReadOnlyModelViewSet):
),
)

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.BillingType] | None:
"""Get billing types depending on the user's role.
Internal employees should see all billing types.
Expand Down Expand Up @@ -108,7 +112,7 @@ class CostCenterViewSet(ReadOnlyModelViewSet):
),
)

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.CostCenter]:
return models.CostCenter.objects.all()


Expand Down Expand Up @@ -136,7 +140,7 @@ class ProjectViewSet(ModelViewSet):
),
)

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.Project]:
"""Get only assigned projects, if an employee is external."""
user = self.request.user
queryset = (
Expand Down Expand Up @@ -180,7 +184,7 @@ class TaskViewSet(ModelViewSet):
),
)

def filter_queryset(self, queryset):
def filter_queryset(self, queryset: QuerySet[models.Task]) -> QuerySet[models.Task]:
"""Specific filter queryset options."""
# my most frequent filter uses LIMIT so default ordering
# needs to be disabled to avoid exception
Expand All @@ -190,7 +194,7 @@ def filter_queryset(self, queryset):

return super().filter_queryset(queryset)

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.Task]:
"""Get only assigned tasks, if an employee is external."""
user = self.request.user
queryset = super().get_queryset().select_related("project", "cost_center")
Expand Down Expand Up @@ -218,7 +222,7 @@ class TaskAsssigneeViewSet(ReadOnlyModelViewSet):
serializer_class = serializers.TaskAssigneeSerializer
filterset_class = filters.TaskAssigneeFilterSet

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.TaskAssignee]:
"""Don't show task assignees to customers."""
user = self.request.user

Expand All @@ -234,7 +238,7 @@ class ProjectAsssigneeViewSet(ReadOnlyModelViewSet):
serializer_class = serializers.ProjectAssigneeSerializer
filterset_class = filters.ProjectAssigneeFilterSet

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.ProjectAssignee]:
"""Don't show project assignees to customers."""
user = self.request.user

Expand All @@ -250,7 +254,7 @@ class CustomerAsssigneeViewSet(ReadOnlyModelViewSet):
serializer_class = serializers.CustomerAssigneeSerializer
filterset_class = filters.CustomerAssigneeFilterSet

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.CustomerAssignee]:
"""Don't show customer assignees to customers."""
user = self.request.user

Expand Down
25 changes: 21 additions & 4 deletions timed/reports/views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from __future__ import annotations

import re
from collections import defaultdict
from datetime import date
from io import BytesIO
from typing import TYPE_CHECKING
from zipfile import ZipFile

from django.conf import settings
Expand All @@ -23,6 +26,13 @@

from . import filters

if TYPE_CHECKING:
from typing import Iterable

from ezodf.document import FlatXMLDocument, PackagedDocument

from timed.employment.models import User


class YearStatisticViewSet(AggregateQuerysetMixin, ReadOnlyModelViewSet):
"""Year statistics calculates total reported time per year."""
Expand Down Expand Up @@ -273,7 +283,7 @@ def _parse_query_params(self, queryset, request):
form.is_valid()
return form.cleaned_data

def _clean_filename(self, name):
def _clean_filename(self, name: str) -> str:
"""Clean name so it can be used in file paths.
To accomplish this it will remove all special chars and
Expand All @@ -282,7 +292,7 @@ def _clean_filename(self, name):
escaped = re.sub(r"[^\w\s-]", "", name)
return re.sub(r"\s+", "_", escaped)

def _generate_workreport_name(self, from_date, project):
def _generate_workreport_name(self, from_date: date, project: Project) -> str:
"""Generate workreport name.
Name is in format: YYMM-YYYYMMDD-$Customer-$Project.ods
Expand All @@ -296,7 +306,14 @@ def _generate_workreport_name(self, from_date, project):
self._clean_filename(project.name),
)

def _create_workreport(self, from_date, to_date, project, reports, user): # noqa: PLR0913
def _create_workreport( # noqa: PLR0913
self,
from_date: date,
to_date: date,
project: Project,
reports: Iterable[Report],
user: User,
) -> tuple[str, PackagedDocument | FlatXMLDocument]:
"""Create ods workreport.
:rtype: tuple
Expand All @@ -312,7 +329,7 @@ def _create_workreport(self, from_date, to_date, project, reports, user): # noq
)

tmpl = settings.WORK_REPORT_PATH
doc = opendoc(tmpl)
doc: PackagedDocument | FlatXMLDocument = opendoc(tmpl)
table = doc.sheets[0]
tasks = defaultdict(int)
date_style = table["C5"].style_name
Expand Down
13 changes: 10 additions & 3 deletions timed/subscription/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
from __future__ import annotations

from typing import TYPE_CHECKING

from django.db.models import Q
from rest_framework import decorators, exceptions, response, status, viewsets
from rest_framework_json_api.serializers import ValidationError
Expand All @@ -16,6 +20,9 @@

from . import filters, models, serializers

if TYPE_CHECKING:
from django.db.models import QuerySet


class SubscriptionProjectViewSet(viewsets.ReadOnlyModelViewSet):
"""Subscription specific project view.
Expand All @@ -31,7 +38,7 @@ class SubscriptionProjectViewSet(viewsets.ReadOnlyModelViewSet):
"id",
)

def get_queryset(self):
def get_queryset(self) -> QuerySet[Project]:
user = self.request.user
queryset = Project.objects.filter(archived=False, customer_visible=True)
current_employment = user.get_active_employment()
Expand All @@ -53,7 +60,7 @@ class PackageViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = serializers.PackageSerializer
filterset_class = filters.PackageFilter

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.Package]:
return models.Package.objects.select_related("billing_type")


Expand Down Expand Up @@ -111,7 +118,7 @@ def confirm(self, request, pk=None): # noqa: ARG002

return response.Response(status=status.HTTP_204_NO_CONTENT)

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.Order]:
return models.Order.objects.select_related("project")

def destroy(self, _request, pk=None): # noqa: ARG002
Expand Down
26 changes: 12 additions & 14 deletions timed/tracking/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"""Viewsets for the tracking app."""

from __future__ import annotations

from datetime import date
from typing import TYPE_CHECKING

import django_excel
from django.conf import settings
Expand Down Expand Up @@ -34,6 +37,9 @@

from . import tasks

if TYPE_CHECKING:
from django.db.models import QuerySet


class ActivityViewSet(ModelViewSet):
"""Activity view set."""
Expand All @@ -50,12 +56,8 @@ class ActivityViewSet(ModelViewSet):
),
)

def get_queryset(self):
"""Filter the queryset by the user of the request.
:return: The filtered activities
:rtype: QuerySet
"""
def get_queryset(self) -> QuerySet[models.Activity]:
"""Filter the queryset by the user of the request."""
return models.Activity.objects.select_related(
"task", "user", "task__project", "task__project__customer"
).filter(user=self.request.user)
Expand All @@ -77,12 +79,8 @@ class AttendanceViewSet(ModelViewSet):
),
)

def get_queryset(self):
"""Filter the queryset by the user of the request.
:return: The filtered attendances
:rtype: QuerySet
"""
def get_queryset(self) -> QuerySet[models.Attendance]:
"""Filter the queryset by the user of the request."""
return models.Attendance.objects.select_related("user").filter(
user=self.request.user
)
Expand Down Expand Up @@ -128,7 +126,7 @@ class ReportViewSet(ModelViewSet):
"rejected",
)

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.Report]:
"""Get filtered reports for external employees."""
user = self.request.user
queryset = super().get_queryset()
Expand Down Expand Up @@ -375,7 +373,7 @@ class AbsenceViewSet(ModelViewSet):
),
)

def get_queryset(self):
def get_queryset(self) -> QuerySet[models.Absence]:
"""Get absences only for internal employees.
User should be able to create an absence on a public holiday if the
Expand Down

0 comments on commit 76f3a32

Please sign in to comment.