Skip to content

Commit

Permalink
Set and enforce order limit on ticket purchases (#654)
Browse files Browse the repository at this point in the history
* Set & enforce order limit on ticket purchases

* Add migration

* Default tix order limit to 10

* Consolidate migrations

* Check each carted event's order limit

* Move limit validation to `add_to_cart`

* Fix typo 😔

* Address nits with validation logic

* Minor refactor
  • Loading branch information
aviupadhyayula committed Apr 14, 2024
1 parent 428dd7e commit b911872
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 1 deletion.
18 changes: 18 additions & 0 deletions backend/clubs/migrations/0102_event_ticket_order_limit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.0.4 on 2024-04-14 22:08

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("clubs", "0101_merge_20240414_1708"),
]

operations = [
migrations.AddField(
model_name="event",
name="ticket_order_limit",
field=models.IntegerField(default=10),
),
]
1 change: 1 addition & 0 deletions backend/clubs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -924,6 +924,7 @@ class Event(models.Model):
parent_recurring_event = models.ForeignKey(
RecurringEvent, on_delete=models.CASCADE, blank=True, null=True
)
ticket_order_limit = models.IntegerField(default=10)

OTHER = 0
RECRUITMENT = 1
Expand Down
32 changes: 31 additions & 1 deletion backend/clubs/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2396,6 +2396,19 @@ def add_to_cart(self, request, *args, **kwargs):
cart, _ = Cart.objects.get_or_create(owner=self.request.user)

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

View check run for this annotation

Codecov / codecov/patch

backend/clubs/views.py#L2395-L2396

Added lines #L2395 - L2396 were not covered by tests

quantities = request.data.get("quantities")

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

View check run for this annotation

Codecov / codecov/patch

backend/clubs/views.py#L2398

Added line #L2398 was not covered by tests

num_requested = sum(item["count"] for item in quantities)
num_carted = cart.tickets.filter(event=event).count()

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

View check run for this annotation

Codecov / codecov/patch

backend/clubs/views.py#L2400-L2401

Added lines #L2400 - L2401 were not covered by tests

if num_requested + num_carted > event.ticket_order_limit:
return Response(

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

View check run for this annotation

Codecov / codecov/patch

backend/clubs/views.py#L2403-L2404

Added lines #L2403 - L2404 were not covered by tests
{
"detail": f"Order exceeds the maximum ticket limit of "
f"{event.ticket_order_limit}."
},
status=status.HTTP_403_FORBIDDEN,
)

for item in quantities:
type = item["type"]
count = item["count"]

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

View check run for this annotation

Codecov / codecov/patch

backend/clubs/views.py#L2412-L2414

Added lines #L2412 - L2414 were not covered by tests
Expand Down Expand Up @@ -2573,6 +2586,9 @@ def create_tickets(self, request, *args, **kwargs):
type: string
count:
type: integer
order_limit:
type: int
required: false
responses:
"200":
content:
Expand All @@ -2599,6 +2615,11 @@ def create_tickets(self, request, *args, **kwargs):

Ticket.objects.bulk_create(tickets)

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

View check run for this annotation

Codecov / codecov/patch

backend/clubs/views.py#L2616

Added line #L2616 was not covered by tests

order_limit = request.data.get("order_limit", None)
if order_limit is not None:
event.ticket_order_limit = order_limit
event.save()

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

View check run for this annotation

Codecov / codecov/patch

backend/clubs/views.py#L2618-L2621

Added lines #L2618 - L2621 were not covered by tests

return Response({"detail": "success"})

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

View check run for this annotation

Codecov / codecov/patch

backend/clubs/views.py#L2623

Added line #L2623 was not covered by tests

@action(detail=True, methods=["post"])
Expand Down Expand Up @@ -4764,14 +4785,23 @@ def initiate_checkout(self, request, *args, **kwargs):
"""
cart = get_object_or_404(Cart, owner=self.request.user)

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

View check run for this annotation

Codecov / codecov/patch

backend/clubs/views.py#L4786

Added line #L4786 was not covered by tests

if not cart.tickets.exists():
return Response(

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

View check run for this annotation

Codecov / codecov/patch

backend/clubs/views.py#L4788-L4789

Added lines #L4788 - L4789 were not covered by tests
{
"success": False,
"detail": "No tickets selected for checkout.",
},
status=status.HTTP_400_BAD_REQUEST,
)

# skip_locked is important here because if any of the tickets in cart
# are locked, we shouldn't block.
tickets = cart.tickets.select_for_update(skip_locked=True).filter(

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

View check run for this annotation

Codecov / codecov/patch

backend/clubs/views.py#L4799

Added line #L4799 was not covered by tests
Q(holder__isnull=True) | Q(holder=self.request.user), owner__isnull=True
)

# Assert that the filter succeeded in freezing all the tickets for checkout
if tickets.count() != cart.tickets.all().count():
if tickets.count() != cart.tickets.count():
return Response(

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

View check run for this annotation

Codecov / codecov/patch

backend/clubs/views.py#L4804-L4805

Added lines #L4804 - L4805 were not covered by tests
{
"success": False,
Expand Down

0 comments on commit b911872

Please sign in to comment.