[docs]defis_user_stickied(self,user:AbstractBaseUser)->bool:
+"""Check if the given user is stickied to this activity.
+
+ Args:
+ user: The user to check for stickiness.
+ """
+ returnself.is_activity_sticky()orself.sticky_students.filter(pk=user.pk).exists()
+
+
[docs]defis_activity_sticky(self)->bool:
+"""Check if the scheduled activity or activity is sticky
+
+ .. warning::
+
+ This method does NOT take into account individual user stickies.
+ In 99.9% of cases, you should use :meth:`is_user_stickied` instead.
+ """
+ returnself.stickyorself.activity.sticky
+
[docs]defget_true_sponsors(self)->Union[QuerySet,Collection[EighthSponsor]]:# pylint: disable=unsubscriptable-object"""Retrieves the sponsors for the scheduled activity, taking into account activity defaults and overrides.
@@ -1043,13 +1068,6 @@
[docs]defget_sticky(self)->bool:
-"""Gets whether this scheduled activity is sticky.
- Returns:
- Whether this scheduled activity is sticky.
- """
- returnself.stickyorself.activity.sticky
-
[docs]defget_finance(self)->str:"""Retrieves the name of this activity's account with the finance office, if any.
@@ -1220,10 +1238,50 @@
Source code for intranet.apps.eighth.models
[waitlist.user.primary_email_address],)
+
[docs]defset_sticky_students(self,users:"Sequence[AbstractBaseUser]")->None:
+"""Sets the given users to the sticky students list for this activity.
+
+ This also sends emails to students.
+
+ Args:
+ users: The users to add to the sticky students list.
+
+ Returns:
+ A tuple of the new stickied students and the unstickied students.
+ """
+ foruserinusers:
+ signup=EighthSignup.objects.filter(user=user,scheduled_activity__block=self.block).first()
+ ifsignupisnotNone:
+ signup.remove_signup(user,force=True)
+ self.add_user(user,force=True)
+
+ old_sticky_students=self.sticky_students.all()
+ self.sticky_students.set(users)
+
+ # note: this will send separate emails to each student for each activity they are stickied in
+ new_stickied_students=[user.notification_emailforuserinusersifusernotinold_sticky_students]
+ unstickied_students=[user.notification_emailforuserinold_sticky_studentsifusernotinusers]
+ email_send_task.delay(
+ "eighth/emails/students_stickied.txt",
+ "eighth/emails/students_stickied.html",
+ data={"activity":self},
+ subject="You have been stickied into an activity",
+ emails=new_stickied_students,
+ bcc=True,
+ )
+ email_send_task.delay(
+ "eighth/emails/students_unstickied.txt",
+ "eighth/emails/students_unstickied.html",
+ data={"activity":self},
+ subject="You have been unstickied from an activity",
+ emails=unstickied_students,
+ bcc=True,
+ )
+
[docs]@transaction.atomic# This MUST be run in a transaction. Do NOT remove this decorator.defadd_user(self,
- user:"get_user_model()",
+ user:AbstractBaseUser,request:Optional[HttpRequest]=None,force:bool=False,no_after_deadline:bool=False,
@@ -1283,8 +1341,9 @@
ifself.activity.users_blacklisted.filter(username=user).exists():exception.Blacklisted=True
- ifself.get_sticky():
+ ifself.is_user_stickied(user):EighthWaitlist.objects.filter(user_id=user.id,block_id=self.block.id).delete()success_message="Successfully added to waitlist for activity."ifwaitlistelse"Successfully signed up for activity."
@@ -1820,7 +1879,7 @@
Source code for intranet.apps.eighth.views.admin.scheduling
messages.error(request,f"Did not unschedule {name} because there is {count} student signed up.")else:messages.error(request,f"Did not unschedule {name} because there are {count} students signed up.")
- instance.save()
+
+ ifinstance:
+ instance.save()
+ instance.set_sticky_students(form.cleaned_data["sticky_students"])messages.success(request,"Successfully updated schedule.")
@@ -324,7 +327,10 @@
Source code for intranet.apps.eighth.views.admin.scheduling
Signs up a user to this scheduled activity if possible. This is where the magic happens.
Raises an exception if there’s a problem signing the user up
unless the signup is forced and the requesting user has permission.
@@ -4265,13 +4289,6 @@