Skip to content

Commit

Permalink
added ticket description
Browse files Browse the repository at this point in the history
  • Loading branch information
Porcupine1 committed Jan 2, 2025
1 parent 56b9394 commit c97c7eb
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 11 deletions.
18 changes: 18 additions & 0 deletions backend/clubs/migrations/0118_ticket_description.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.0.4 on 2025-01-02 00:24

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("clubs", "0117_clubapprovalresponsetemplate"),
]

operations = [
migrations.AddField(
model_name="ticket",
name="description",
field=models.TextField(blank=True, null=True),
),
]
1 change: 1 addition & 0 deletions backend/clubs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1879,6 +1879,7 @@ class Ticket(models.Model):
blank=True,
null=True,
)
description = models.TextField(null=True, blank=True)
holding_expiration = models.DateTimeField(null=True, blank=True, db_index=True)
carts = models.ManyToManyField(Cart, related_name="tickets", blank=True)
price = models.DecimalField(max_digits=5, decimal_places=2)
Expand Down
2 changes: 1 addition & 1 deletion backend/clubs/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1794,7 +1794,7 @@ def get_owner_name(self, obj):

class Meta:
model = Ticket
fields = ("id", "event", "type", "owner", "attended", "price")
fields = ("id", "event", "description", "type", "owner", "attended", "price")


class UserUUIDSerializer(serializers.ModelSerializer):
Expand Down
48 changes: 38 additions & 10 deletions backend/clubs/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2724,6 +2724,9 @@ def create_tickets(self, request, *args, **kwargs):
type: integer
price:
type: number
description:
type: string
required: false
group_size:
type: number
required: false
Expand Down Expand Up @@ -2847,6 +2850,7 @@ def create_tickets(self, request, *args, **kwargs):
event=event,
type=item["type"],
price=item.get("price", 0),
description=item.get("description", None),
group_discount=item.get("group_discount", 0),
group_size=item.get("group_size", None),
transferable=item.get("transferable", True),
Expand Down Expand Up @@ -5206,7 +5210,7 @@ def _calculate_cart_total(cart) -> float:

def partial_update(self, request, *args, **kwargs):
"""
Update a ticket's attendance (only accessible by club officers)
Update a ticket's description or attendance (only accessible by club officers)
---
requestBody:
content:
Expand All @@ -5216,6 +5220,8 @@ def partial_update(self, request, *args, **kwargs):
properties:
attended:
type: boolean
description:
type: string
responses:
"200":
content:
Expand All @@ -5232,16 +5238,38 @@ def partial_update(self, request, *args, **kwargs):
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)

# Get request data
attended = request.data.get("attended")
description = request.data.get("description")

# attendance update
if attended is not None:
if not isinstance(attended, bool):
return Response(

Check warning on line 5250 in backend/clubs/views.py

View check run for this annotation

Codecov / codecov/patch

backend/clubs/views.py#L5250

Added line #L5250 was not covered by tests
{"detail": "Missing boolean attribute 'attended'."},
status=status.HTTP_400_BAD_REQUEST,
)
ticket.attended = attended
ticket.save()
return Response(TicketSerializer(ticket).data)

# description update
if description is not None:
if ticket.owner is not None:
return Response(
{"detail": "Cannot update description of a sold ticket."},
status=status.HTTP_400_BAD_REQUEST,
)
ticket.description = description
ticket.save()
return Response(TicketSerializer(ticket).data)

return Response(

Check warning on line 5269 in backend/clubs/views.py

View check run for this annotation

Codecov / codecov/patch

backend/clubs/views.py#L5269

Added line #L5269 was not covered by tests
{"detail": "No valid update parameters provided."},
status=status.HTTP_400_BAD_REQUEST,
)

@transaction.atomic
@update_holds
Expand Down
94 changes: 94 additions & 0 deletions backend/tests/clubs/test_ticketing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1660,6 +1660,100 @@ def test_update_attendance_non_officer(self):
self.assertEqual(resp.status_code, 404, resp.content)
self.assertFalse(ticket.attended)

def test_create_ticket_with_description(self):
self.client.login(username=self.user1.username, password="test")
qts = {
"quantities": [
{
"type": "_normal",
"count": 20,
"price": 10,
"description": "This is a normal ticket.",
},
{
"type": "_premium",
"count": 10,
"price": 20,
"description": "This is a premium ticket.",
},
]
}

resp = self.client.put(
reverse("club-events-tickets", args=(self.club1.code, self.event1.pk)),
qts,
format="json",
)

normal_tickets = Ticket.objects.filter(event=self.event1, type="_normal")
premium_tickets = Ticket.objects.filter(event=self.event1, type="_premium")

self.assertEqual(resp.status_code, 200, resp.content)
self.assertEqual(normal_tickets.first().description, "This is a normal ticket.")
self.assertEqual(
premium_tickets.first().description, "This is a premium ticket."
)

def test_update_ticket_description(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.save()

resp = self.client.patch(
reverse("tickets-detail", args=(ticket.id,)),
{"description": "This is a test description."},
format="json",
)

ticket.refresh_from_db()
self.assertEqual(resp.status_code, 200, resp.content)
self.assertEqual(ticket.description, "This is a test description.")

def test_update_description_sold_ticket(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 was sold to user2
ticket.owner = self.user2
ticket.save()

resp = self.client.patch(
reverse("tickets-detail", args=(ticket.id,)),
{"description": "This is a test description."},
format="json",
)

ticket.refresh_from_db()
self.assertEqual(resp.status_code, 400, resp.content)
self.assertIsNone(ticket.description)

def test_update_ticket_description_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,)),
{"description": "This is a test description."},
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 c97c7eb

Please sign in to comment.