Skip to content

Commit

Permalink
Add requested changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Arashfa0301 committed May 8, 2023
1 parent 7b743f1 commit a2295e2
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 78 deletions.
6 changes: 5 additions & 1 deletion lego/apps/events/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,11 @@ def get_earliest_registration_time(
if self.heed_penalties:
if penalties is None:
penalties = user.number_of_penalties()
return reg_time + timedelta(hours=5) if penalties >= 1 else reg_time
return (
reg_time + timedelta(hours=settings.PENALTY_DELAY_DURATION)
if penalties >= 1
else reg_time
)
return reg_time

def get_possible_pools(
Expand Down
25 changes: 20 additions & 5 deletions lego/apps/events/tests/test_penalties.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from datetime import timedelta
from django.conf import settings

from django.utils import timezone

Expand Down Expand Up @@ -42,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):
def test_get_earliest_registration_time_one_or_more_penalty(self):
"""Test method calculating the earliest
registration time for user with one or more penalties"""
event = Event.objects.get(title="POOLS_NO_REGISTRATIONS")
Expand All @@ -57,6 +58,15 @@ def test_get_earliest_registration_time_one_penalty(self):
Penalty.objects.create(
user=user, reason="first test penalty", weight=1, 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=settings.PENALTY_DELAY_DURATION),
)
Penalty.objects.create(
user=user, reason="second test penalty", weight=2, source_event=event
)
Expand All @@ -65,9 +75,12 @@ def test_get_earliest_registration_time_one_penalty(self):
earliest_reg = event.get_earliest_registration_time(
user, [webkom_pool], penalties
)
self.assertEqual(earliest_reg, current_time + timedelta(hours=5))
self.assertEqual(
earliest_reg,
current_time + timedelta(hours=settings.PENALTY_DELAY_DURATION),
)

def test_cant_register_with_one_penalty_before_delay(self):
def test_cant_register_with_one_or_more_penalty_before_delay(self):
"""Test that user can not register
before (5 hour) delay when having one or more penalties"""
event = Event.objects.get(title="POOLS_NO_REGISTRATIONS")
Expand All @@ -90,14 +103,16 @@ def test_cant_register_with_one_penalty_before_delay(self):
registration = Registration.objects.get_or_create(event=event, user=user)[0]
event.register(registration)

def test_can_register_with_one_penalty_after_delay(self):
def test_can_register_with_one_or_more_penalty_after_delay(self):
"""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=5)
abakus_pool.activation_date = current_time - timedelta(
hours=settings.PENALTY_DELAY_DURATION
)
abakus_pool.save()

user = get_dummy_users(1)[0]
Expand Down
4 changes: 3 additions & 1 deletion lego/apps/users/managers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from django.contrib.auth.models import UserManager
from django.db.models import Q
from django.db.models import Q, F, DateTimeField, ExpressionWrapper
from django.utils import timezone
from django.conf import settings


from mptt.managers import TreeManager

Expand Down
7 changes: 7 additions & 0 deletions lego/apps/users/migrations/0039_penalty_activation_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ class Migration(migrations.Migration):
("users", "0038_alter_abakusgroup_type"),
]

def update_current_ative_penalties(apps, schema_editor):
from django.db.models import F

Penalty = apps.get_model("users", "Penalty")
Penalty.objects.all().update(activation_time=F("created_at"))

operations = [
migrations.AddField(
model_name="penalty",
Expand All @@ -16,4 +22,5 @@ class Migration(migrations.Migration):
default=None, null=True, verbose_name="date created"
),
),
migrations.RunPython(update_current_ative_penalties),
]
100 changes: 56 additions & 44 deletions lego/apps/users/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,29 +487,39 @@ def unanswered_surveys(self) -> list:
)
return list(unanswered_surveys.values_list("id", flat=True))

def check_for_deletable_penalty(self):
from lego.apps.events.models import Event
def check_for_expirable_penalty(self):
from lego.apps.events.models import Event, Pool
from django.db.models import Subquery

# TODO: filter so that only one penalty is returned. the penalty now() is at
current_active_penalty = (
Penalty.objects.valid().filter(user=self).order_by("activation_time")
Penalty.objects.valid()
.filter(
user=self,
activation_time__lte=timezone.now(),
activation_time__gte=timezone.now()
- F("weight") * timedelta(days=settings.PENALTY_DURATION.days),
)
.first()
)
if current_active_penalty is None:
return

# TODO: add test for this
pools = Pool.objects.filter(permission_groups__in=self.all_groups).distinct()

# TODO: add check for all he events the user can be registered at
# get a list of all penalties and in the Event.filter()
# and check that the event is in the penalties events
eligable_passed_events = Event.objects.filter(
number_of_eligable_passed_events = Event.objects.filter(
heed_penalties=True,
start_time__range=(
current_active_penalty[0].activation_time
current_active_penalty.activation_time
- timedelta(hours=1) * F("unregistration_deadline_hours"),
current_active_penalty[0].exact_expiration
current_active_penalty.exact_expiration
- timedelta(hours=1) * F("unregistration_deadline_hours"),
),
)
pools__in=Subquery(pools.values("pk")),
).count()

if len(eligable_passed_events) >= 6:
current_active_penalty[0].delete_and_adjust_future_activation_times()
if number_of_eligable_passed_events >= 6:
current_active_penalty.expire_and_adjust_future_activation_times()


class Penalty(BasisModel):
Expand All @@ -519,51 +529,48 @@ 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)
activation_time = models.DateTimeField(null=True, default=None)
# add weightZ

objects = UserPenaltyManager() # type: ignore

def save(self, *args, **kwargs):
last_penalty_to_be_expired = Penalty.objects.filter(
user=self.user, activation_time__lte=timezone.now()
).order_by("-activation_time")
def save(self, manual_activation_time=False, *args, **kwargs):
if not manual_activation_time:
current_and_future_penalties = Penalty.objects.filter(
user=self.user,
activation_time__gte=timezone.now()
- F("weight") * settings.PENALTY_DURATION.days * timedelta(days=1),
).order_by("-activation_time")

self.activation_time = (
current_and_future_penalties.first().exact_expiration
if current_and_future_penalties.exists()
else self.created_at
)

self.activation_time = (
last_penalty_to_be_expired[0].exact_expiration
if len(last_penalty_to_be_expired) != 0
else self.created_at
)
super().save(*args, **kwargs)

def default_save(self, *args, **kwargs):
super().save(*args, **kwargs)
def expire_and_adjust_future_activation_times(self):
new_activation_time = timezone.now()
future_penalties = Penalty.objects.filter(
user=self.user, activation_time__gt=new_activation_time
).order_by("activation_time")

def delete_and_adjust_future_activation_times(self):
if self.weight == 1:
new_activation_time = timezone.now()
future_penalties = Penalty.objects.filter(
user=self.user, activation_time__gt=new_activation_time
).order_by("activation_time")
self.activation_time = timezone.now() - timedelta(days=30)
self.created_at = timezone.now() - timedelta(days=30)

for penalty in future_penalties:
penalty.activation_time = new_activation_time
penalty.default_save()
new_activation_time = penalty.exact_expiration

self.delete()
else:
self.weight -= 1
self.activation_time = timezone.now()
future_penalties = Penalty.objects.filter(
user=self.user, activation_time__gt=self.activation_time
).order_by("activation_time")
new_activation_time = self.exact_expiration
self.default_save()

for penalty in future_penalties:
penalty.activation_time = new_activation_time
penalty.default_save()
new_activation_time = penalty.exact_expiration
self.save(manual_activation_time=True)

for penalty in future_penalties:
penalty.activation_time = new_activation_time
penalty.save(manual_activation_time=True)
new_activation_time = penalty.exact_expiration

@property
def exact_expiration(self):
Expand Down Expand Up @@ -603,6 +610,11 @@ def ignore_date(date):
return True


# Generated by Django 4.0.10 on 2023-05-01 16:33

from django.db import models


class PhotoConsent(BasisModel):
user = models.ForeignKey(
User, related_name="photo_consents", on_delete=models.CASCADE
Expand Down
6 changes: 6 additions & 0 deletions lego/apps/users/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,9 @@ def send_inactive_reminder_mail_and_delete_users(self, logger_context=None):

for user in users_to_notifiy_montly:
send_inactive_notification(user)


@celery_app.task(serializer="json", bind=True, base=AbakusTask)
def expire_penalties_if_six_events_has_passed(self, logger_context=None):
me = "happy"
# go through all users with penalties and run the expire penalty function on them
Loading

0 comments on commit a2295e2

Please sign in to comment.