doorcontrol: Add busiest time of day/week reports

This commit is contained in:
Adam Goldsmith 2023-11-30 12:06:16 -05:00
parent 70691ff972
commit a177ff1ed6
2 changed files with 53 additions and 23 deletions

View File

@ -1,23 +1,5 @@
from django.urls import path
from . import views from . import views
app_name = "doorcontrol" app_name = "doorcontrol"
urlpatterns = [ urlpatterns = [report._urlpattern() for report in views.REPORTS]
path(
"reports/access-per-<unit_time>",
views.AccessPerUnitTime.as_view(),
name="access-per-unit-time",
),
path(
"reports/denied-access",
views.DeniedAccess.as_view(),
name="denied-access",
),
path(
"reports/most-active-members",
views.MostActiveMembers.as_view(),
name="most-active-members",
),
]

View File

@ -1,3 +1,4 @@
import calendar
import datetime import datetime
from django.contrib.auth.mixins import PermissionRequiredMixin from django.contrib.auth.mixins import PermissionRequiredMixin
@ -5,7 +6,7 @@ from django.core.paginator import Page
from django.core.exceptions import BadRequest from django.core.exceptions import BadRequest
from django.db.models import Count from django.db.models import Count
from django.db.models.functions import Trunc from django.db.models.functions import Trunc
from django.urls import reverse_lazy from django.urls import reverse_lazy, path
from django.utils import dateparse from django.utils import dateparse
from django.utils.formats import date_format from django.utils.formats import date_format
from django.utils.text import slugify from django.utils.text import slugify
@ -15,11 +16,11 @@ from django.views.generic.list import ListView
from .models import HIDEvent from .models import HIDEvent
REPORT_TYPES = [] REPORTS = []
def register_report(cls: "BaseAccessReport"): def register_report(cls: "BaseAccessReport"):
REPORT_TYPES.extend(cls._report_types()) REPORTS.append(cls)
return cls return cls
@ -39,6 +40,11 @@ class BaseAccessReport(PermissionRequiredMixin, ListView):
reverse_lazy("doorcontrol:" + slugify(cls._report_name)), reverse_lazy("doorcontrol:" + slugify(cls._report_name)),
] ]
@classmethod
def _urlpattern(cls):
slug = slugify(cls._report_name)
return path(f"reports/{slug}", cls.as_view(), name=slug)
def _selected_report(self): def _selected_report(self):
return self._report_name return self._report_name
@ -69,7 +75,9 @@ class BaseAccessReport(PermissionRequiredMixin, ListView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context["report_types"] = REPORT_TYPES context["report_types"] = [
rt for report in REPORTS for rt in report._report_types()
]
page: Page = context["page_obj"] page: Page = context["page_obj"]
context["paginator_range"] = page.paginator.get_elided_page_range(page.number) context["paginator_range"] = page.paginator.get_elided_page_range(page.number)
@ -100,6 +108,14 @@ class AccessPerUnitTime(BaseAccessReport):
reverse_lazy("doorcontrol:access-per-unit-time", args=[unit_time]), reverse_lazy("doorcontrol:access-per-unit-time", args=[unit_time]),
) )
@classmethod
def _urlpattern(cls):
return path(
"reports/access-per-<unit_time>",
cls.as_view(),
name="access-per-unit-time",
)
def _selected_report(self) -> str: def _selected_report(self) -> str:
return "Access per " + self.kwargs["unit_time"].title() return "Access per " + self.kwargs["unit_time"].title()
@ -204,3 +220,35 @@ class MostActiveMembers(BaseAccessReport):
} }
for count in counts for count in counts
] ]
@register_report
class BusiestDayOfWeek(BaseAccessReport):
_report_name = "Busiest Day of the Week"
def get_queryset(self):
return [
{
"week day": calendar.day_name[(count["timestamp__week_day"] - 2) % 7],
"events": count["events"],
}
for count in super()
.get_queryset()
.values("timestamp__week_day")
.annotate(events=Count("timestamp"))
]
@register_report
class BusiestTimeOfDay(BaseAccessReport):
_report_name = "Busiest Time of Day"
paginate_by = 24
def get_queryset(self):
return [
{"hour": f'{count["timestamp__hour"]}:00', "events": count["events"]}
for count in super()
.get_queryset()
.values("timestamp__hour")
.annotate(events=Count("timestamp"))
]