Skip to content

Commit

Permalink
Fix(registration)/waitlist limit (#729)
Browse files Browse the repository at this point in the history
* users from wait list get bumped up if event limit is increased, and users from queue get bumped down if the limit is decreased. Priority is respected

* format

* altered test with bigger dicrease, and to test if priority is respected
  • Loading branch information
MadsNyl authored Oct 26, 2023
1 parent f0dbfa8 commit 8112c50
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 3 deletions.
14 changes: 14 additions & 0 deletions app/content/models/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,20 @@ def waiting_list_count(self):
"""Number of users on the waiting list"""
return self.get_waiting_list().count()

def move_users_from_waiting_list_to_queue(self, count):
"""Moves the first x users from waiting list to queue"""
waiting_list = self.get_waiting_list().order_by("created_at")
for registration in waiting_list[:count]:
moved_registration = registration.move_from_waiting_list_to_queue()
moved_registration.save()

def move_users_from_queue_to_waiting_list(self, count):
"""Moves the last created x users from queue to waiting list"""
queue = self.get_participants().order_by("-created_at")
for registration in queue[:count]:
moved_registration = registration.move_from_queue_to_waiting_list()
moved_registration.save()

def get_has_attended(self):
return self.get_participants().filter(has_attended=True)

Expand Down
15 changes: 15 additions & 0 deletions app/content/models/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,21 @@ def move_from_waiting_list_to_queue(self):
registration_move_to_queue.is_on_wait = False
return registration_move_to_queue

def move_from_queue_to_waiting_list(self):
registrations_in_queue = self.event.get_participants().order_by("-created_at")

if registrations_in_queue:
registration_move_to_waiting_list = next(
(
registration
for registration in registrations_in_queue
if not registration.is_prioritized
),
registrations_in_queue[0],
)
registration_move_to_waiting_list.is_on_wait = True
return registration_move_to_waiting_list

def clean(self):
"""
Validates model fields. Is called upon instance save.
Expand Down
12 changes: 12 additions & 0 deletions app/content/serializers/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,19 @@ def create(self, validated_data):
def update(self, instance, validated_data):
priority_pools_data = validated_data.pop("priority_pools", None)
paid_information_data = validated_data.pop("paid_information", None)
limit = validated_data.get("limit")
limit_difference = 0
if limit:
limit_difference = limit - instance.limit

event = super().update(instance, validated_data)

if limit_difference > 0 and event.waiting_list_count > 0:
event.move_users_from_waiting_list_to_queue(limit_difference)

if limit_difference < 0:
event.move_users_from_queue_to_waiting_list(abs(limit_difference))

if paid_information_data and not event.is_paid_event:
PaidEvent.objects.create(
event=event,
Expand Down
4 changes: 3 additions & 1 deletion app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,9 @@

DEFAULT_AUTO_FIELD = "django.db.models.AutoField"

CELERY_BROKER_URL = os.environ.get("CELERY_BROKER_URL") or "amqp://guest:guest@rabbitmq:5672"
CELERY_BROKER_URL = (
os.environ.get("CELERY_BROKER_URL") or "amqp://guest:guest@rabbitmq:5672"
)

if ENVIRONMENT == EnvironmentOptions.LOCAL:
CELERY_TASK_ALWAYS_EAGER = False
26 changes: 26 additions & 0 deletions app/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
NewsFactory,
PageFactory,
ParentPageFactory,
PriorityPoolFactory,
RegistrationFactory,
ShortLinkFactory,
UserFactory,
Expand All @@ -30,6 +31,12 @@
from app.util.test_utils import add_user_to_group_with_name, get_api_client


def _add_user_to_group(user, group):
return MembershipFactory(
user=user, group=group, membership_type=MembershipType.MEMBER
)


@pytest.fixture()
def request_factory():
return APIRequestFactory()
Expand Down Expand Up @@ -200,3 +207,22 @@ def banner():
@pytest.fixture()
def toddel():
return ToddelFactory()


@pytest.fixture()
def priority_group():
return GroupFactory(name="Prioritized group", slug="prioritized_group")


@pytest.fixture()
def user_in_priority_pool(priority_group):
user = UserFactory()
_add_user_to_group(user, priority_group)
return user


@pytest.fixture()
def event_with_priority_pool(priority_group):
event = EventFactory(limit=1)
PriorityPoolFactory(event=event, groups=(priority_group,))
return event
90 changes: 88 additions & 2 deletions app/tests/content/test_event_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ def get_events_url_detail(event=None):


def get_event_data(
title="New Title", location="New Location", organizer=None, contact_person=None
title="New Title",
location="New Location",
organizer=None,
contact_person=None,
limit=0,
):
start_date = timezone.now() + timedelta(days=10)
end_date = timezone.now() + timedelta(days=11)
Expand All @@ -37,6 +41,7 @@ def get_event_data(
"start_date": start_date,
"end_date": end_date,
"is_paid_event": False,
"limit": limit,
}
if organizer:
data["organizer"] = organizer
Expand Down Expand Up @@ -224,7 +229,9 @@ def test_update_event_as_admin(permission_test_util):

client = get_api_client(user=user)
url = get_events_url_detail(event)
data = get_event_data(title=expected_title, organizer=new_organizer)
data = get_event_data(
title=expected_title, organizer=new_organizer, limit=event.limit
)

response = client.put(url, data)
event.refresh_from_db()
Expand All @@ -233,6 +240,85 @@ def test_update_event_as_admin(permission_test_util):
assert event.title == expected_title


@pytest.mark.django_db
def test_update_event_with_increased_limit(admin_user, event):
"""
Admins should be able to update the limit of an event.
Then the first person on the waiting list should be moved to the queue.
Priorities should be respected.
"""

event.limit = 1
event.save()

registration = RegistrationFactory(event=event)
waiting_registration = RegistrationFactory(event=event)

assert not registration.is_on_wait
assert waiting_registration.is_on_wait
assert event.waiting_list_count == 1

client = get_api_client(user=admin_user)
url = get_events_url_detail(event)
data = get_event_data(limit=2)

response = client.put(url, data)
event.refresh_from_db()
registration.refresh_from_db()
waiting_registration.refresh_from_db()

assert response.status_code == status.HTTP_200_OK
assert event.limit == 2
assert event.waiting_list_count == 0
assert not waiting_registration.is_on_wait


@pytest.mark.django_db
def test_update_event_with_decreased_limit(
admin_user, event_with_priority_pool, user_in_priority_pool
):
"""
Admins should be able to update the limit of an event.
Then the first person on the queue should be moved to the waiting list.
Priorities should be respected.
"""

event_with_priority_pool.limit = 4
event_with_priority_pool.save()

registration = RegistrationFactory(event=event_with_priority_pool)
first_queue_registration = RegistrationFactory(event=event_with_priority_pool)
second_queue_registration = RegistrationFactory(event=event_with_priority_pool)
third_queue_registration = RegistrationFactory(
event=event_with_priority_pool, user=user_in_priority_pool
)

assert not registration.is_on_wait
assert not first_queue_registration.is_on_wait
assert not second_queue_registration.is_on_wait
assert not third_queue_registration.is_on_wait
assert event_with_priority_pool.waiting_list_count == 0

client = get_api_client(user=admin_user)
url = get_events_url_detail(event_with_priority_pool)
data = get_event_data(limit=1)

response = client.put(url, data)
event_with_priority_pool.refresh_from_db()
registration.refresh_from_db()
first_queue_registration.refresh_from_db()
second_queue_registration.refresh_from_db()
third_queue_registration.refresh_from_db()

assert response.status_code == status.HTTP_200_OK
assert event_with_priority_pool.limit == 1
assert event_with_priority_pool.waiting_list_count == 3
assert registration.is_on_wait
assert first_queue_registration.is_on_wait
assert second_queue_registration.is_on_wait
assert not third_queue_registration.is_on_wait


@pytest.mark.django_db
def test_create_as_anonymous_user(default_client):
"""An anonymous user should not be able to create an event entity."""
Expand Down

0 comments on commit 8112c50

Please sign in to comment.