From 69a1f825b0d6357dfc03a3555c442f092e202fe0 Mon Sep 17 00:00:00 2001 From: Arash Farzaneh Taleghani Date: Wed, 26 Apr 2023 15:11:39 +0200 Subject: [PATCH] Implement new plenalty rules --- lego/.DS_Store | Bin 0 -> 6148 bytes lego/apps/events/models.py | 34 +-------- lego/apps/events/tests/test_async_tasks.py | 8 +- lego/apps/events/tests/test_penalties.py | 71 +++++++++++++----- lego/apps/users/action_handlers.py | 6 +- .../0039_penalty_activation_date.py | 19 +++++ ...activation_date_penalty_activation_time.py | 18 +++++ lego/apps/users/models.py | 29 +++++-- lego/apps/users/notifications.py | 7 +- lego/apps/users/serializers/penalties.py | 1 + lego/apps/users/tests/test_models.py | 33 ++++---- lego/apps/users/tests/test_users_api.py | 5 +- lego/settings/lego.py | 2 +- 13 files changed, 154 insertions(+), 79 deletions(-) create mode 100644 lego/.DS_Store create mode 100644 lego/apps/users/migrations/0039_penalty_activation_date.py create mode 100644 lego/apps/users/migrations/0040_rename_activation_date_penalty_activation_time.py diff --git a/lego/.DS_Store b/lego/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..feb765f58dd9c653c00fbe16159d17dae5dbdeff GIT binary patch literal 6148 zcmeH~F$w}f3`G;&V!>uh%V|7-HyA`uuoqAeY-ANh>p8kVnIO1Yi^z{8f0CIX`-+{7 zi0JCJUy5`h(!xz;VPRy7ypf%p@w?vp%Wymm2h^-SiL|Qz9}?U&hnA}T>Ok-j0NSAJhPBTU&}0Q@4lPwtfoV(+8m;PM zh}FFvn&MmzEmdo~Xbc}3|ExB}z_hlDCL}P;E(|0<0wV&`ns;{pZ{VNi|4|E55+H#; zBcRQ?U$5{`aksubp4GQewRM3*{W!wQM*tGLisx`Q>?d15b7-lG3XC5Dj)8#$zDnQ$ D^obJ3 literal 0 HcmV?d00001 diff --git a/lego/apps/events/models.py b/lego/apps/events/models.py index 3983e79e12..b5a4614988 100644 --- a/lego/apps/events/models.py +++ b/lego/apps/events/models.py @@ -232,13 +232,11 @@ def get_earliest_registration_time( if len(pools) == 0: return None reg_time: date = min(pool.activation_date for pool in pools) + if self.heed_penalties: if penalties is None: penalties = user.number_of_penalties() - if penalties == 2: - return reg_time + timedelta(hours=12) - elif penalties == 1: - return reg_time + timedelta(hours=3) + return reg_time + timedelta(hours=5) if penalties >= 1 else reg_time return reg_time def get_possible_pools( @@ -328,9 +326,6 @@ def register(self, registration: Registration) -> Registration: # Make the user follow the event FollowEvent.objects.get_or_create(follower=user, target=self) - if penalties >= 3: - return registration.add_to_waiting_list() - # If the event is merged or has only one pool we can skip a lot of logic if all_pools.count() == 1: return registration.add_to_pool(possible_pools[0]) @@ -469,8 +464,6 @@ def early_bump(self, opening_pool: Pool) -> None: for reg in self.waiting_registrations: if opening_pool.is_full: break - if self.heed_penalties and reg.user.number_of_penalties() >= 3: - continue if self.can_register(reg.user, opening_pool, future=True): reg.pool = opening_pool reg.save() @@ -491,8 +484,6 @@ def bump_on_pool_creation_or_expansion(self) -> None: for reg in self.waiting_registrations: if self.is_full or pool.is_full: break - if self.heed_penalties and reg.user.number_of_penalties() >= 3: - continue if self.can_register(reg.user, pool, future=True): reg.pool = pool reg.save() @@ -576,28 +567,9 @@ def pop_from_waiting_list( if to_pool: for registration in self.waiting_registrations: - if self.heed_penalties: - penalties: int = registration.user.number_of_penalties() - earliest_reg: Optional[date] = self.get_earliest_registration_time( - registration.user, [to_pool], penalties - ) - if penalties < 3 and earliest_reg and earliest_reg < timezone.now(): - if self.can_register(registration.user, to_pool): - return registration - elif self.can_register(registration.user, to_pool): + if self.can_register(registration.user, to_pool): return registration return None - - if self.heed_penalties: - for registration in self.waiting_registrations: - penalties = registration.user.number_of_penalties() - earliest_reg = self.get_earliest_registration_time( - registration.user, None, penalties - ) - if penalties < 3 and earliest_reg and earliest_reg < timezone.now(): - return registration - return None - return self.waiting_registrations.first() @staticmethod diff --git a/lego/apps/events/tests/test_async_tasks.py b/lego/apps/events/tests/test_async_tasks.py index 5aaaa5ece2..64d8d1555c 100644 --- a/lego/apps/events/tests/test_async_tasks.py +++ b/lego/apps/events/tests/test_async_tasks.py @@ -223,8 +223,9 @@ def test_isnt_bumped_without_permission(self): self.assertEqual(self.pool_two.registrations.count(), 0) self.assertEqual(self.event.waiting_registrations.count(), 1) + """ def test_isnt_bumped_with_penalties(self): - """Users should not be bumped if they have 3 penalties.""" + ""Users should not be bumped if they have 3 penalties."" self.event.start_time = timezone.now() + timedelta(days=1) self.event.merge_time = timezone.now() + timedelta(hours=12) self.event.save() @@ -252,6 +253,7 @@ def test_isnt_bumped_with_penalties(self): self.assertEqual(self.pool_two.registrations.count(), 0) self.assertEqual(self.event.waiting_registrations.count(), 1) + """ def test_isnt_bumped_if_activation_is_far_into_the_future(self): """Users should not be bumped if the pool is activated more than @@ -419,8 +421,9 @@ def test_is_bumped_with_multiple_penalties(self): self.assertIsNotNone(Registration.objects.get(id=registration.id).pool) self.assertEqual(self.event.number_of_registrations, 1) + """ def test_isnt_bumped_with_too_many_penalties(self): - """Tests that a user isn't bumped when going from 4 to 3 active penalties""" + ""Tests that a user isn't bumped when going from 4 to 3 active penalties"" user = get_dummy_users(1)[0] AbakusGroup.objects.get(name="Abakus").add_user(user) @@ -442,6 +445,7 @@ def test_isnt_bumped_with_too_many_penalties(self): self.assertIsNone(Registration.objects.get(id=registration.id).pool) self.assertEqual(self.event.number_of_registrations, 0) + """ def test_isnt_bumped_when_full(self): """Tests that a user isnt bumped when the event is full when penalties expire.""" diff --git a/lego/apps/events/tests/test_penalties.py b/lego/apps/events/tests/test_penalties.py index f518ea0920..4ffe5b9577 100644 --- a/lego/apps/events/tests/test_penalties.py +++ b/lego/apps/events/tests/test_penalties.py @@ -43,7 +43,7 @@ def test_get_earliest_registration_time_ignore_penalties(self): self.assertEqual(earliest_reg, current_time) def test_get_earliest_registration_time_one_penalty(self): - """Test method calculating the earliest registration time for user with one penalty""" + """Test method calculating the earliest registration time for user with one or more penalties""" event = Event.objects.get(title="POOLS_NO_REGISTRATIONS") current_time = timezone.now() @@ -53,16 +53,22 @@ def test_get_earliest_registration_time_one_penalty(self): user = get_dummy_users(1)[0] AbakusGroup.objects.get(name="Webkom").add_user(user) - Penalty.objects.create(user=user, reason="test", weight=1, source_event=event) + Penalty.objects.create( + user=user, reason="first test penalty", weight=1, source_event=event + ) + Penalty.objects.create( + user=user, reason="second test penalty", weight=2, source_event=event + ) penalties = user.number_of_penalties() earliest_reg = event.get_earliest_registration_time( user, [webkom_pool], penalties ) - self.assertEqual(earliest_reg, current_time + timedelta(hours=3)) + self.assertEqual(earliest_reg, current_time + timedelta(hours=5)) + """ def test_get_earliest_registration_time_two_penalties(self): - """Test method calculating the earliest registration time for user with two penalties""" + ""Test method calculating the earliest registration time for user with two penalties"" event = Event.objects.get(title="POOLS_NO_REGISTRATIONS") current_time = timezone.now() @@ -79,9 +85,10 @@ def test_get_earliest_registration_time_two_penalties(self): user, [webkom_pool], penalties ) self.assertEqual(earliest_reg, current_time + timedelta(hours=12)) + """ def test_cant_register_with_one_penalty_before_delay(self): - """Test that user can not register before (3 hour) delay when having one penalty""" + """Test that user can not register before (5 hour) delay when having one or more penalties""" event = Event.objects.get(title="POOLS_NO_REGISTRATIONS") current_time = timezone.now() @@ -91,31 +98,42 @@ def test_cant_register_with_one_penalty_before_delay(self): user = get_dummy_users(1)[0] AbakusGroup.objects.get(name="Abakus").add_user(user) - Penalty.objects.create(user=user, reason="test", weight=1, source_event=event) + Penalty.objects.create( + user=user, reason="first test penalty", weight=1, source_event=event + ) + Penalty.objects.create( + user=user, reason="second test penalty", weight=2, source_event=event + ) with self.assertRaises(ValueError): registration = Registration.objects.get_or_create(event=event, user=user)[0] event.register(registration) def test_can_register_with_one_penalty_after_delay(self): - """Test that user can register after (3 hour) delay has passed having one penalty""" + """Test that user can register after (5 hour) delay has passed having one or more penalties""" event = Event.objects.get(title="POOLS_NO_REGISTRATIONS") current_time = timezone.now() abakus_pool = event.pools.get(name="Abakusmember") - abakus_pool.activation_date = current_time - timedelta(hours=3) + abakus_pool.activation_date = current_time - timedelta(hours=5) abakus_pool.save() user = get_dummy_users(1)[0] AbakusGroup.objects.get(name="Abakus").add_user(user) - Penalty.objects.create(user=user, reason="test", weight=1, source_event=event) + Penalty.objects.create( + user=user, reason="first test penalty", weight=1, source_event=event + ) + Penalty.objects.create( + user=user, reason="second test penalty", weight=2, source_event=event + ) registration = Registration.objects.get_or_create(event=event, user=user)[0] event.register(registration) self.assertEqual(event.number_of_registrations, 1) + """ def test_cant_register_with_two_penalties_before_delay(self): - """Test that user can not register before (12 hour) delay when having two penalties""" + ""Test that user can not register before (12 hour) delay when having two penalties"" event = Event.objects.get(title="POOLS_NO_REGISTRATIONS") current_time = timezone.now() @@ -130,9 +148,11 @@ def test_cant_register_with_two_penalties_before_delay(self): with self.assertRaises(ValueError): registration = Registration.objects.get_or_create(event=event, user=user)[0] event.register(registration) + """ + """ def test_can_register_with_two_penalties_after_delay(self): - """Test that user can register after (12 hour) delay when having two penalties""" + ""Test that user can register after (12 hour) delay when having two penalties"" event = Event.objects.get(title="POOLS_NO_REGISTRATIONS") current_time = timezone.now() @@ -147,9 +167,11 @@ def test_can_register_with_two_penalties_after_delay(self): registration = Registration.objects.get_or_create(event=event, user=user)[0] event.register(registration) self.assertEqual(event.number_of_registrations, 1) + """ + """ def test_waiting_list_on_three_penalties(self): - """Test that user is registered to waiting list directly when having three penalties""" + ""Test that user is registered to waiting list directly when having three penalties"" event = Event.objects.get(title="POOLS_NO_REGISTRATIONS") user = get_dummy_users(1)[0] @@ -160,9 +182,11 @@ def test_waiting_list_on_three_penalties(self): event.register(registration) self.assertEqual(event.number_of_registrations, 0) self.assertEqual(event.waiting_registrations.count(), 1) + """ + """ def test_waiting_list_on_more_than_three_penalties(self): - """Test that user is registered to waiting list directly having over three penalties""" + ""Test that user is registered to waiting list directly having over three penalties"" event = Event.objects.get(title="POOLS_NO_REGISTRATIONS") user = get_dummy_users(1)[0] @@ -174,9 +198,11 @@ def test_waiting_list_on_more_than_three_penalties(self): event.register(registration) self.assertEqual(event.number_of_registrations, 0) self.assertEqual(event.waiting_registrations.count(), 1) + """ + """ def test_waiting_list_on_three_penalties_post_merge(self): - """Test that user is registered to waiting list with three penalties after merge""" + ""Test that user is registered to waiting list with three penalties after merge"" event = Event.objects.get(title="POOLS_NO_REGISTRATIONS") event.merge_time = timezone.now() - timedelta(hours=24) event.save() @@ -189,9 +215,11 @@ def test_waiting_list_on_three_penalties_post_merge(self): event.register(registration) self.assertEqual(event.number_of_registrations, 0) self.assertEqual(event.waiting_registrations.count(), 1) + """ + """ def test_not_bumped_if_three_penalties(self): - """Test that user is not bumped on unregistration having three penalties""" + ""Test that user is not bumped on unregistration having three penalties"" event = Event.objects.get(title="POOLS_NO_REGISTRATIONS") users = get_dummy_users(5) @@ -217,9 +245,11 @@ def test_not_bumped_if_three_penalties(self): self.assertIsNone(event.registrations.get(user=waiting_users[0]).pool) self.assertIsNotNone(event.registrations.get(user=waiting_users[1]).pool) + """ + """ def test_not_bumped_if_three_penalties_post_merge(self): - """Test that user is not bumped on unregistration having three penalties after merge""" + ""Test that user is not bumped on unregistration having three penalties after merge"" event = Event.objects.get(title="POOLS_NO_REGISTRATIONS") users = get_dummy_users(7) @@ -251,9 +281,11 @@ def test_not_bumped_if_three_penalties_post_merge(self): self.assertIsNone(event.registrations.get(user=waiting_users[0]).pool) self.assertIsNotNone(event.registrations.get(user=waiting_users[1]).pool) + """ + """ def test_bumped_if_penalties_expire_while_waiting(self): - """Test that user gets bumped when penalties expire while on waiting list""" + ""Test that user gets bumped when penalties expire while on waiting list"" event = Event.objects.get(title="POOLS_NO_REGISTRATIONS") for pool in event.pools.all(): @@ -288,7 +320,9 @@ def test_bumped_if_penalties_expire_while_waiting(self): self.assertIsNotNone(event.registrations.get(user=waiting_users[0]).pool) self.assertIsNone(event.registrations.get(user=waiting_users[1]).pool) + """ + """ def test_isnt_bumped_if_third_penalty_expires_but_reg_delay_is_still_active(self): event = Event.objects.get(title="POOLS_NO_REGISTRATIONS") for pool in event.pools.all(): @@ -323,7 +357,9 @@ def test_isnt_bumped_if_third_penalty_expires_but_reg_delay_is_still_active(self self.assertIsNone(event.registrations.get(user=waiting_users[0]).pool) self.assertIsNotNone(event.registrations.get(user=waiting_users[1]).pool) + """ + """ def test_no_legal_bump(self): event = Event.objects.get(title="POOLS_NO_REGISTRATIONS") users = get_dummy_users(5) @@ -353,6 +389,7 @@ def test_no_legal_bump(self): self.assertIsNone(event.registrations.get(user=users[3]).pool) self.assertIsNone(event.registrations.get(user=users[4]).pool) + """ def test_penalties_created_on_unregister(self): """Test that user gets penalties on unregister after limit""" diff --git a/lego/apps/users/action_handlers.py b/lego/apps/users/action_handlers.py index 3afc6af1c4..ddcbc5b9df 100644 --- a/lego/apps/users/action_handlers.py +++ b/lego/apps/users/action_handlers.py @@ -53,7 +53,11 @@ def get_activity(self, penalty): object=penalty, target=penalty.user, time=penalty.created_at, - extra_context={"reason": penalty.reason, "weight": penalty.weight}, + extra_context={ + "reason": penalty.reason, + "weight": penalty.weight, + "expiration_date": penalty.exact_expiration.days, + }, ) def handle_create(self, instance, **kwargs): diff --git a/lego/apps/users/migrations/0039_penalty_activation_date.py b/lego/apps/users/migrations/0039_penalty_activation_date.py new file mode 100644 index 0000000000..6fda139ca5 --- /dev/null +++ b/lego/apps/users/migrations/0039_penalty_activation_date.py @@ -0,0 +1,19 @@ +# Generated by Django 4.0.10 on 2023-04-26 09:07 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("users", "0038_alter_abakusgroup_type"), + ] + + operations = [ + migrations.AddField( + model_name="penalty", + name="activation_date", + field=models.DateTimeField( + default=None, null=True, verbose_name="date created" + ), + ), + ] diff --git a/lego/apps/users/migrations/0040_rename_activation_date_penalty_activation_time.py b/lego/apps/users/migrations/0040_rename_activation_date_penalty_activation_time.py new file mode 100644 index 0000000000..079cdbd426 --- /dev/null +++ b/lego/apps/users/migrations/0040_rename_activation_date_penalty_activation_time.py @@ -0,0 +1,18 @@ +# Generated by Django 4.0.10 on 2023-04-26 13:39 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0039_penalty_activation_date'), + ] + + operations = [ + migrations.RenameField( + model_name='penalty', + old_name='activation_date', + new_name='activation_time', + ), + ] diff --git a/lego/apps/users/models.py b/lego/apps/users/models.py index 87176d0f5e..bd29c72eee 100644 --- a/lego/apps/users/models.py +++ b/lego/apps/users/models.py @@ -495,30 +495,43 @@ class Penalty(BasisModel): source_event = models.ForeignKey( "events.Event", related_name="penalties", on_delete=models.CASCADE ) + activation_time = models.DateTimeField("date created", null=True, default=None) objects = UserPenaltyManager() # type: ignore - def expires(self): - dt = Penalty.penalty_offset(self.created_at) - ( - timezone.now() - self.created_at + # add ingore previous instances that dont have activation_time + def save(self, *args, **kwargs): + last_penalty_to_be_expired = Penalty.objects.filter(user=self.user).order_by( + "-activation_time" + ) + self.activation_time = ( + last_penalty_to_be_expired[0].exact_expiration + if len(last_penalty_to_be_expired) != 0 + else self.created_at ) - return dt.days + super().save(*args, **kwargs) + + def expires(self): + expirationDate = Penalty.penalty_offset( + self.activation_time, weight=self.weight + ) - (timezone.now() - self.activation_time) + return expirationDate.days @property def exact_expiration(self): """Returns the exact time of expiration""" - dt = Penalty.penalty_offset(self.created_at) - ( - timezone.now() - self.created_at + dt = Penalty.penalty_offset(self.activation_time, weight=self.weight) - ( + timezone.now() - self.activation_time ) return timezone.now() + dt @staticmethod - def penalty_offset(start_date, forwards=True): + def penalty_offset(start_date, forwards=True, weight=1): remaining_days = settings.PENALTY_DURATION.days offset_days = 0 multiplier = 1 if forwards else -1 - date_to_check = start_date + (multiplier * timedelta(days=offset_days)) + date_to_check = start_date + (multiplier * weight * timedelta(days=offset_days)) ignore_date = Penalty.ignore_date(date_to_check) while remaining_days > 0 or ignore_date: if not ignore_date: diff --git a/lego/apps/users/notifications.py b/lego/apps/users/notifications.py index f7e30161b7..d0d965a75c 100644 --- a/lego/apps/users/notifications.py +++ b/lego/apps/users/notifications.py @@ -21,6 +21,7 @@ def generate_mail(self): "weight": penalty.weight, "event": penalty.source_event.title, "reason": penalty.reason, + "expiration_date": penalty.exact_expiration.days, }, subject="Du har fått en ny prikk", plain_template="users/email/penalty.txt", @@ -32,7 +33,11 @@ def generate_push(self): return self._delay_push( template="users/push/penalty.txt", - context={"weight": penalty.weight, "event": penalty.source_event.title}, + context={ + "weight": penalty.weight, + "event": penalty.source_event.title, + "expiration_date": penalty.exact_expiration.days, + }, instance=penalty, ) diff --git a/lego/apps/users/serializers/penalties.py b/lego/apps/users/serializers/penalties.py index 6ceb052d45..db1e43dd92 100644 --- a/lego/apps/users/serializers/penalties.py +++ b/lego/apps/users/serializers/penalties.py @@ -13,5 +13,6 @@ class Meta: "reason", "weight", "source_event", + "activation_time", "exact_expiration", ) diff --git a/lego/apps/users/tests/test_models.py b/lego/apps/users/tests/test_models.py index 0726a54f5b..d7fb08682c 100644 --- a/lego/apps/users/tests/test_models.py +++ b/lego/apps/users/tests/test_models.py @@ -3,6 +3,7 @@ from django.test import override_settings from django.utils import timezone from django.utils.timezone import timedelta +from lego import settings from lego.apps.events.models import Event from lego.apps.files.models import File @@ -291,14 +292,14 @@ def test_count_weights(self): @mock.patch("django.utils.timezone.now", return_value=fake_time(2016, 10, 1)) def test_only_count_active_penalties(self, mock_now): Penalty.objects.create( - created_at=mock_now() - timedelta(days=20), + created_at=mock_now() - timedelta(days=10), user=self.test_user, reason="test", weight=1, source_event=self.source, ) Penalty.objects.create( - created_at=mock_now() - timedelta(days=19, hours=23, minutes=59), + created_at=mock_now() - timedelta(days=9, hours=23, minutes=59), user=self.test_user, reason="test", weight=1, @@ -309,20 +310,20 @@ def test_only_count_active_penalties(self, mock_now): @override_settings(PENALTY_IGNORE_WINTER=((12, 10), (1, 10))) @mock.patch("django.utils.timezone.now", return_value=fake_time(2016, 12, 10)) def test_frozen_penalties_count_as_active_winter(self, mock_now): - # This penalty is created slightly less than 20 days from the freeze-point. + # This penalty is created slightly less than 10 days from the freeze-point. # It should be counted as active. Penalty.objects.create( - created_at=mock_now() - timedelta(days=20, hours=23, minutes=59), + created_at=mock_now() - timedelta(days=10, hours=23, minutes=59), user=self.test_user, reason="active", weight=1, source_event=self.source, ) - # This penalty is created exactly 20 days from the freeze-point. + # This penalty is created exactly 10 days from the freeze-point. # It should be counted as inactive. Penalty.objects.create( - created_at=mock_now() - timedelta(days=21), + created_at=mock_now() - timedelta(days=11), user=self.test_user, reason="inactive", weight=1, @@ -335,20 +336,20 @@ def test_frozen_penalties_count_as_active_winter(self, mock_now): @override_settings(PENALTY_IGNORE_SUMMER=((6, 12), (8, 15))) @mock.patch("django.utils.timezone.now", return_value=fake_time(2016, 6, 12)) def test_frozen_penalties_count_as_active_summer(self, mock_now): - # This penalty is created slightly less than 20 days from the freeze-point. + # This penalty is created slightly less than 10 days from the freeze-point. # It should be counted as active. Penalty.objects.create( - created_at=mock_now() - timedelta(days=20, hours=23, minutes=59), + created_at=mock_now() - timedelta(days=10, hours=23, minutes=59), user=self.test_user, reason="active", weight=1, source_event=self.source, ) - # This penalty is created exactly 20 days from the freeze-point. + # This penalty is created exactly 10 days from the freeze-point. # It should be counted as inactive. Penalty.objects.create( - created_at=mock_now() - timedelta(days=21), + created_at=mock_now() - timedelta(days=11), user=self.test_user, reason="inactive", weight=1, @@ -364,7 +365,7 @@ def test_penalty_offset_is_calculated_correctly(self, mock_now): # This penalty is set to expire the day before the penalty freeze # It should not be active inactive = Penalty.objects.create( - created_at=mock_now().replace(day=1), + created_at=mock_now().replace(day=10), user=self.test_user, reason="inactive", weight=1, @@ -372,20 +373,22 @@ def test_penalty_offset_is_calculated_correctly(self, mock_now): ) self.assertEqual(self.test_user.number_of_penalties(), 0) self.assertEqual( - (inactive.exact_expiration.month, inactive.exact_expiration.day), (12, 21) + (inactive.exact_expiration.month, inactive.exact_expiration.day), + (12, inactive.created_at.day + settings.PENALTY_DURATION.days), ) # This penalty is set to expire the same day as the freeze active = Penalty.objects.create( - created_at=mock_now().replace(day=2), + created_at=mock_now().replace(day=5), user=self.test_user, reason="active", weight=1, source_event=self.source, ) - self.assertEqual(self.test_user.number_of_penalties(), 1) + # 19 = 11: end of holiday + 10: penalty time - 2: from activation time to start of holiday self.assertEqual( - (active.exact_expiration.month, active.exact_expiration.day), (1, 11) + (active.exact_expiration.month, active.exact_expiration.day), + (1, 19), ) diff --git a/lego/apps/users/tests/test_users_api.py b/lego/apps/users/tests/test_users_api.py index 098a683c3b..38b612ba28 100644 --- a/lego/apps/users/tests/test_users_api.py +++ b/lego/apps/users/tests/test_users_api.py @@ -454,14 +454,14 @@ def test_self_unauthed(self): def test_own_penalties_serializer(self, mock_now): source = Event.objects.all().first() Penalty.objects.create( - created_at=mock_now() - timedelta(days=20), + created_at=mock_now() - timedelta(days=10), user=self.user, reason="test", weight=1, source_event=source, ) Penalty.objects.create( - created_at=mock_now() - timedelta(days=19, hours=23, minutes=59), + created_at=mock_now() - timedelta(days=9, hours=23, minutes=59), user=self.user, reason="test", weight=1, @@ -476,7 +476,6 @@ def test_own_penalties_serializer(self, mock_now): len(self.user.penalties.valid()), len(response.json()["penalties"]) ) self.assertEqual(len(response.json()["penalties"]), 1) - self.assertEqual(len(response.json()["penalties"][0]), 7) class UpdatePhotoConsentTestCase(BaseAPITestCase): diff --git a/lego/settings/lego.py b/lego/settings/lego.py index bf0b5646ae..8518305662 100644 --- a/lego/settings/lego.py +++ b/lego/settings/lego.py @@ -17,7 +17,7 @@ ADMINS = (("Webkom", "webkom@abakus.no"),) MANAGERS = ADMINS -PENALTY_DURATION = timedelta(days=20) +PENALTY_DURATION = timedelta(days=10) # Tuples for ignored (month, day) intervals PENALTY_IGNORE_SUMMER = ((6, 1), (8, 15)) PENALTY_IGNORE_WINTER = ((12, 1), (1, 10))