Skip to content

Commit

Permalink
Add route for attendance tracking (#684)
Browse files Browse the repository at this point in the history
* attendance tracking

* add comment
  • Loading branch information
rm03 committed Apr 25, 2024
1 parent da6abe0 commit b57d797
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 1 deletion.
17 changes: 17 additions & 0 deletions backend/clubs/migrations/0107_ticket_attended.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 5.0.4 on 2024-04-25 07:56

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("clubs", "0106_remove_ticket_transaction_record_ticket_transferable_and_more"),
]

operations = [
migrations.AddField(
model_name="ticket",
name="attended",
field=models.BooleanField(default=False),
),
]
1 change: 1 addition & 0 deletions backend/clubs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1845,6 +1845,7 @@ class Ticket(models.Model):
)
group_size = models.PositiveIntegerField(null=True, blank=True)
transferable = models.BooleanField(default=True)
attended = models.BooleanField(default=False)
objects = TicketManager()

def get_qr(self):
Expand Down
51 changes: 50 additions & 1 deletion backend/clubs/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4973,6 +4973,9 @@ class TicketViewSet(viewsets.ModelViewSet):
list:
List all tickets owned by a user
partial_update:
Update attendance for a ticket
cart:
List all unowned/unheld tickets currently in a user's cart
Expand All @@ -4991,7 +4994,7 @@ class TicketViewSet(viewsets.ModelViewSet):

permission_classes = [IsAuthenticated]
serializer_class = TicketSerializer
http_method_names = ["get", "post"]
http_method_names = ["get", "post", "patch"]
lookup_field = "id"

@staticmethod
Expand All @@ -5018,6 +5021,45 @@ def _calculate_cart_total(cart) -> float:
)
return cart_total

def partial_update(self, request, *args, **kwargs):
"""
Update a ticket's attendance (only accessible by club officers)
---
requestBody:
content:
application/json:
schema:
type: object
properties:
attendance:
type: boolean
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Ticket'
"400":
content:
application/json:
schema:
type: object
properties:
detail:
type: string
---
"""
attended = request.data.get("attended")
if attended is None or not isinstance(attended, bool):
return Response(
{"detail": "Missing boolean attribute 'attended'."},
status=status.HTTP_400_BAD_REQUEST,
)
ticket = self.get_object()
ticket.attended = attended
ticket.save()
return Response(TicketSerializer(ticket).data)

@transaction.atomic
@update_holds
@action(detail=False, methods=["get"])
Expand Down Expand Up @@ -5505,6 +5547,13 @@ def transfer(self, request, *args, **kwargs):
return Response({"detail": "Successfully transferred ownership of ticket"})

def get_queryset(self):
if self.action == "partial_update":
officer_clubs = Membership.objects.filter(
person=self.request.user, role__lte=Membership.ROLE_OFFICER
).values_list("club", flat=True)
return Ticket.objects.filter(event__club__in=officer_clubs).select_related(
"event__club"
)
return Ticket.objects.filter(owner=self.request.user.id)


Expand Down
38 changes: 38 additions & 0 deletions backend/tests/clubs/test_ticketing.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
Cart,
Club,
Event,
Membership,
Ticket,
TicketTransactionRecord,
TicketTransferRecord,
Expand Down Expand Up @@ -1312,6 +1313,43 @@ def test_transfer_ticket_to_self(self):
)
self.assertEqual(resp.status_code, 403, resp.content)

def test_update_attendance(self):
self.client.login(username=self.user1.username, password="test")
Membership.objects.create(
person=self.user1,
club=self.club1,
title="Officer",
role=Membership.ROLE_OFFICER,
)
ticket = self.tickets1[0]
ticket.owner = self.user2
ticket.save()

resp = self.client.patch(
reverse("tickets-detail", args=(ticket.id,)),
{"attended": True},
format="json",
)
ticket.refresh_from_db()
self.assertEqual(resp.status_code, 200, resp.content)
self.assertTrue(ticket.attended)

def test_update_attendance_non_officer(self):
# user1 is no longer an officer for the ticket's club
self.client.login(username=self.user1.username, password="test")
ticket = self.tickets1[0]
ticket.owner = self.user1
ticket.save()

resp = self.client.patch(
reverse("tickets-detail", args=(ticket.id,)),
{"attended": True},
format="json",
)
ticket.refresh_from_db()
self.assertEqual(resp.status_code, 404, resp.content)
self.assertFalse(ticket.attended)


class TicketModelTestCase(TestCase):
"""
Expand Down

0 comments on commit b57d797

Please sign in to comment.