diff --git a/doorcontrol/admin.py b/doorcontrol/admin.py index 15b7611..2f0b038 100644 --- a/doorcontrol/admin.py +++ b/doorcontrol/admin.py @@ -11,41 +11,24 @@ class DoorAdmin(admin.ModelAdmin): pass -class IsRedFilter(admin.SimpleListFilter): - title = "Is Red" - parameter_name = "is_red" - - def lookups(self, request, model_admin): - return ( - ("1", "Yes"), - ("0", "No"), - ) - - def queryset(self, request, queryset): - if self.value() is None: - return queryset - else: - return queryset.filter(is_red=(self.value() == "1")) - - @admin.register(HIDEvent) class HIDEventAdmin(DjangoObjectActions, admin.ModelAdmin): search_fields = ["forename", "surname", "cardholder_id"] - list_display = ["timestamp", "door", "event_type", "description", "is_red"] + list_display = ["timestamp", "door", "event_type", "description", "_is_red"] list_filter = [ "timestamp", "door", "event_type", - IsRedFilter, + "is_red", ] readonly_fields = ["decoded_card_number"] changelist_actions = ("refresh_all_doors",) def get_queryset(self, request): - return super().get_queryset(request).with_is_red().with_decoded_card_number() + return super().get_queryset(request).with_decoded_card_number() @admin.display(boolean=True) - def is_red(self, obj): + def _is_red(self, obj): return obj.is_red def has_add_permission(self, request, obj=None): diff --git a/doorcontrol/migrations/0004_hidevent_is_red.py b/doorcontrol/migrations/0004_hidevent_is_red.py new file mode 100644 index 0000000..8fbcdb4 --- /dev/null +++ b/doorcontrol/migrations/0004_hidevent_is_red.py @@ -0,0 +1,40 @@ +# Generated by Django 5.0 on 2023-12-04 16:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("doorcontrol", "0003_door_ip"), + ] + + operations = [ + migrations.AddField( + model_name="hidevent", + name="is_red", + field=models.GeneratedField( + db_persist=False, + expression=models.Q( + ( + "event_type__in", + [ + 1022, + 1023, + 2024, + 2029, + 2036, + 2042, + 2043, + 2046, + 4041, + 4042, + 4043, + 4044, + 4045, + ], + ) + ), + output_field=models.BooleanField(), + ), + ), + ] diff --git a/doorcontrol/models.py b/doorcontrol/models.py index 62207b6..39031a0 100644 --- a/doorcontrol/models.py +++ b/doorcontrol/models.py @@ -2,7 +2,7 @@ from datetime import datetime from django.conf import settings from django.db import models -from django.db.models import ExpressionWrapper, F, Func, Q +from django.db.models import F, Func, Q from django.db.models.functions import Mod from django.utils import timezone @@ -26,31 +26,6 @@ class Door(models.Model): class HIDEventQuerySet(models.QuerySet): - def with_is_red(self): - """Based on `function isRedEvent` from /html/hid-global.js on a HID EDGE EVO Solo""" - return self.annotate( - is_red=ExpressionWrapper( - Q( - event_type__in=[ - HIDEvent.EventType.DENIED_ACCESS_CARD_NOT_FOUND, - HIDEvent.EventType.DENIED_ACCESS_ACCESS_PIN_NOT_FOUND, - HIDEvent.EventType.DENIED_ACCESS_SCHEDULE, - HIDEvent.EventType.DENIED_ACCESS_WRONG_PIN, - HIDEvent.EventType.DENIED_ACCESS_CARD_EXPIRED, - HIDEvent.EventType.DENIED_ACCESS_PIN_LOCKOUT, - HIDEvent.EventType.DENIED_ACCESS_UNASSIGNED_CARD, - HIDEvent.EventType.DENIED_ACCESS_PIN_EXPIRED, - HIDEvent.EventType.DOOR_FORCED_ALARM, - HIDEvent.EventType.DOOR_HELD_ALARM, - HIDEvent.EventType.TAMPER_SWITCH_ALARM, - HIDEvent.EventType.AC_FAILURE, - HIDEvent.EventType.BATTERY_FAILURE, - ] - ), - output_field=models.BooleanField(), - ) - ) - def with_decoded_card_number(self): # TODO: CONV and BIT_COUNT are MySQL/MariaDB specific class Conv(Func): @@ -137,6 +112,29 @@ class HIDEvent(models.Model): max_length=8, blank=True, null=True, db_column="rawCardNumber" ) + # Based on `function isRedEvent` from /html/hid-global.js on a HID EDGE EVO Solo + is_red = models.GeneratedField( + expression=Q( + event_type__in=[ + EventType.DENIED_ACCESS_CARD_NOT_FOUND, + EventType.DENIED_ACCESS_ACCESS_PIN_NOT_FOUND, + EventType.DENIED_ACCESS_SCHEDULE, + EventType.DENIED_ACCESS_WRONG_PIN, + EventType.DENIED_ACCESS_CARD_EXPIRED, + EventType.DENIED_ACCESS_PIN_LOCKOUT, + EventType.DENIED_ACCESS_UNASSIGNED_CARD, + EventType.DENIED_ACCESS_PIN_EXPIRED, + EventType.DOOR_FORCED_ALARM, + EventType.DOOR_HELD_ALARM, + EventType.TAMPER_SWITCH_ALARM, + EventType.AC_FAILURE, + EventType.BATTERY_FAILURE, + ] + ), + output_field=models.BooleanField(), + db_persist=False, + ) + @classmethod def from_xml_attributes(cls, door: Door, attrib: dict[str:str]): field_lookup = {