Compare commits
No commits in common. "d4670a7d02d56dc29a3ee3d9d5eb8bce9182cb0d" and "7fd9181da1c8c7feafeef02ead8db4332231d60a" have entirely different histories.
d4670a7d02
...
7fd9181da1
@ -2,12 +2,10 @@ from datetime import datetime
|
|||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import F, Func, OuterRef, Q, Subquery
|
from django.db.models import F, Func, Q
|
||||||
from django.db.models.functions import Mod
|
from django.db.models.functions import Mod
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from membershipworks.models import Member
|
|
||||||
|
|
||||||
from .hid.DoorController import DoorController
|
from .hid.DoorController import DoorController
|
||||||
|
|
||||||
|
|
||||||
@ -27,25 +25,6 @@ class Door(models.Model):
|
|||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class DoorCardholderMember(models.Model):
|
|
||||||
door = models.ForeignKey(Door, on_delete=models.CASCADE)
|
|
||||||
cardholder_id = models.IntegerField()
|
|
||||||
member = models.ForeignKey(Member, on_delete=models.CASCADE, db_constraint=False)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
constraints = (
|
|
||||||
models.UniqueConstraint(
|
|
||||||
fields=("door", "cardholder_id"), name="unique_door_cardholder_id"
|
|
||||||
),
|
|
||||||
models.UniqueConstraint(
|
|
||||||
fields=("door", "member"), name="unique_door_member"
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return f"{self.door} [{self.cardholder_id}]: {self.member}"
|
|
||||||
|
|
||||||
|
|
||||||
class HIDEventQuerySet(models.QuerySet):
|
class HIDEventQuerySet(models.QuerySet):
|
||||||
def with_decoded_card_number(self):
|
def with_decoded_card_number(self):
|
||||||
# TODO: CONV and BIT_COUNT are MySQL/MariaDB specific
|
# TODO: CONV and BIT_COUNT are MySQL/MariaDB specific
|
||||||
@ -83,15 +62,6 @@ class HIDEventQuerySet(models.QuerySet):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def with_member_id(self):
|
|
||||||
return self.annotate(
|
|
||||||
member_id=Subquery(
|
|
||||||
DoorCardholderMember.objects.filter(
|
|
||||||
door=OuterRef("door"), cardholder_id=OuterRef("cardholder_id")
|
|
||||||
).values("member_id"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class HIDEvent(models.Model):
|
class HIDEvent(models.Model):
|
||||||
objects = HIDEventQuerySet.as_manager()
|
objects = HIDEventQuerySet.as_manager()
|
||||||
|
@ -6,33 +6,11 @@ from django.utils import timezone
|
|||||||
from django_q.tasks import async_task
|
from django_q.tasks import async_task
|
||||||
|
|
||||||
from cmsmanage.django_q2_helper import q_task_group
|
from cmsmanage.django_q2_helper import q_task_group
|
||||||
from doorcontrol.models import Door, DoorCardholderMember, HIDEvent
|
from doorcontrol.models import Door, HIDEvent
|
||||||
|
|
||||||
|
|
||||||
def get_cardholders(door: Door):
|
|
||||||
def make_ch_member(cardholder):
|
|
||||||
return DoorCardholderMember(
|
|
||||||
door=door,
|
|
||||||
cardholder_id=cardholder.attrib["cardholderID"],
|
|
||||||
member_id=cardholder.attrib.get("custom2"),
|
|
||||||
)
|
|
||||||
|
|
||||||
DoorCardholderMember.objects.bulk_create(
|
|
||||||
(
|
|
||||||
make_ch_member(cardholder)
|
|
||||||
for cardholder in door.controller.get_cardholders()
|
|
||||||
if "custom2" in cardholder.attrib
|
|
||||||
),
|
|
||||||
update_conflicts=True,
|
|
||||||
update_fields=("member",),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@transaction.atomic()
|
@transaction.atomic()
|
||||||
def getMessages(door: Door):
|
def getMessages(door: Door):
|
||||||
# TODO: this should in the cardholder syncing task
|
|
||||||
get_cardholders(door)
|
|
||||||
|
|
||||||
last_event = door.hidevent_set.order_by("timestamp").last()
|
last_event = door.hidevent_set.order_by("timestamp").last()
|
||||||
if last_event is not None:
|
if last_event is not None:
|
||||||
last_ts = timezone.make_naive(last_event.timestamp)
|
last_ts = timezone.make_naive(last_event.timestamp)
|
||||||
|
@ -13,8 +13,6 @@ from django.views.generic.list import ListView
|
|||||||
import django_filters
|
import django_filters
|
||||||
import django_tables2 as tables
|
import django_tables2 as tables
|
||||||
from django_filters.views import BaseFilterView
|
from django_filters.views import BaseFilterView
|
||||||
from django_mysql.models import GroupConcat
|
|
||||||
from django_mysql.models.functions import ConcatWS
|
|
||||||
from django_tables2 import SingleTableMixin
|
from django_tables2 import SingleTableMixin
|
||||||
from django_tables2.export.views import ExportMixin
|
from django_tables2.export.views import ExportMixin
|
||||||
|
|
||||||
@ -179,10 +177,9 @@ class AccessPerUnitTime(BaseAccessReport):
|
|||||||
super()
|
super()
|
||||||
.get_table_data()
|
.get_table_data()
|
||||||
.filter(event_type__in=granted_event_types)
|
.filter(event_type__in=granted_event_types)
|
||||||
.with_member_id()
|
|
||||||
.values(unit_time=Trunc("timestamp", unit_time))
|
.values(unit_time=Trunc("timestamp", unit_time))
|
||||||
.annotate(
|
.annotate(
|
||||||
members=Count("member_id", distinct=True),
|
members=Count("cardholder_id", distinct=True),
|
||||||
members_delta=(
|
members_delta=(
|
||||||
F("members")
|
F("members")
|
||||||
/ Window(
|
/ Window(
|
||||||
@ -245,7 +242,10 @@ class DeniedAccess(BaseAccessReport):
|
|||||||
|
|
||||||
|
|
||||||
class MostActiveMembersTable(tables.Table):
|
class MostActiveMembersTable(tables.Table):
|
||||||
name = tables.Column()
|
cardholder_id = tables.Column()
|
||||||
|
name = tables.TemplateColumn(
|
||||||
|
"{{ record.forename|default:'' }} {{ record.surname|default:'' }}"
|
||||||
|
)
|
||||||
access_count = tables.Column()
|
access_count = tables.Column()
|
||||||
|
|
||||||
|
|
||||||
@ -258,51 +258,16 @@ class MostActiveMembers(BaseAccessReport):
|
|||||||
return (
|
return (
|
||||||
super()
|
super()
|
||||||
.get_table_data()
|
.get_table_data()
|
||||||
.with_member_id()
|
.values("cardholder_id", "forename", "surname")
|
||||||
.filter(member_id__isnull=False)
|
.order_by()
|
||||||
.values("member_id")
|
.annotate(access_count=Count("cardholder_id"))
|
||||||
.annotate(
|
|
||||||
access_count=Count("member_id"),
|
|
||||||
name=GroupConcat(
|
|
||||||
ConcatWS("forename", "surname", separator=" "), distinct=True
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.order_by("-access_count")
|
.order_by("-access_count")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class DetailByDayTable(tables.Table):
|
|
||||||
timestamp__date = tables.DateColumn(verbose_name="Date")
|
|
||||||
name = tables.Column()
|
|
||||||
access_count = tables.Column()
|
|
||||||
|
|
||||||
|
|
||||||
@register_report
|
|
||||||
class DetailByDay(BaseAccessReport):
|
|
||||||
_report_name = "Detail by Day"
|
|
||||||
table_class = DetailByDayTable
|
|
||||||
|
|
||||||
def get_table_data(self):
|
|
||||||
return (
|
|
||||||
super()
|
|
||||||
.get_table_data()
|
|
||||||
.with_member_id()
|
|
||||||
.values("timestamp__date", "member_id")
|
|
||||||
.filter(member_id__isnull=False)
|
|
||||||
.annotate(
|
|
||||||
access_count=Count("member_id"),
|
|
||||||
name=GroupConcat(
|
|
||||||
ConcatWS("forename", "surname", separator=" "), distinct=True
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.order_by("-timestamp__date")
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class BusiestDayOfWeekTable(tables.Table):
|
class BusiestDayOfWeekTable(tables.Table):
|
||||||
timestamp__week_day = tables.Column("Week Day")
|
timestamp__week_day = tables.Column("Week Day")
|
||||||
events = tables.Column()
|
events = tables.Column()
|
||||||
members = tables.Column()
|
|
||||||
|
|
||||||
def render_timestamp__week_day(self, value):
|
def render_timestamp__week_day(self, value):
|
||||||
return calendar.day_name[(value - 2) % 7]
|
return calendar.day_name[(value - 2) % 7]
|
||||||
@ -318,18 +283,14 @@ class BusiestDayOfWeek(BaseAccessReport):
|
|||||||
return (
|
return (
|
||||||
super()
|
super()
|
||||||
.get_table_data()
|
.get_table_data()
|
||||||
.with_member_id()
|
|
||||||
.values("timestamp__week_day")
|
.values("timestamp__week_day")
|
||||||
.annotate(
|
.annotate(events=Count("timestamp"))
|
||||||
events=Count("timestamp"), members=Count("member_id", distinct=True)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class BusiestTimeOfDayTable(tables.Table):
|
class BusiestTimeOfDayTable(tables.Table):
|
||||||
timestamp__hour = tables.TemplateColumn("{{ value }}:00", verbose_name="Hour")
|
timestamp__hour = tables.TemplateColumn("{{ value }}:00", verbose_name="Hour")
|
||||||
events = tables.Column()
|
events = tables.Column()
|
||||||
members = tables.Column()
|
|
||||||
|
|
||||||
|
|
||||||
@register_report
|
@register_report
|
||||||
@ -342,9 +303,6 @@ class BusiestTimeOfDay(BaseAccessReport):
|
|||||||
return (
|
return (
|
||||||
super()
|
super()
|
||||||
.get_table_data()
|
.get_table_data()
|
||||||
.with_member_id()
|
|
||||||
.values("timestamp__hour")
|
.values("timestamp__hour")
|
||||||
.annotate(
|
.annotate(events=Count("timestamp"))
|
||||||
events=Count("timestamp"), members=Count("member_id", distinct=True)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user