Skip to content

Commit

Permalink
Update Membership Requests model and logic to match Ownership Requests
Browse files Browse the repository at this point in the history
  • Loading branch information
gabeweng committed Nov 8, 2024
1 parent 826f54c commit ff1719e
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 61 deletions.
19 changes: 12 additions & 7 deletions backend/clubs/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,21 +264,26 @@ def email(self, obj):


class MembershipRequestAdmin(admin.ModelAdmin):
search_fields = ("person__username", "person__email", "club__name", "club__pk")
list_display = ("person", "club", "email", "withdrew", "is_member")
list_filter = ("withdrew",)
search_fields = (
"requester__username",
"requester__email",
"club__name",
"club__pk",
)
list_display = ("requester", "club", "email", "withdrawn", "is_member")
list_filter = ("withdrawn",)

def person(self, obj):
return obj.person.username
def requester(self, obj):
return obj.requester.username

def club(self, obj):
return obj.club.name

def email(self, obj):
return obj.person.email
return obj.requester.email

def is_member(self, obj):
return obj.club.membership_set.filter(person__pk=obj.person.pk).exists()
return obj.club.membership_set.filter(person__pk=obj.requester.pk).exists()

is_member.boolean = True

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,32 @@ class Migration(migrations.Migration):
to=settings.AUTH_USER_MODEL
),
),
migrations.RenameField(
model_name="membershiprequest",
old_name="withdrew",
new_name="withdrawn",
),
migrations.RenameField(
model_name="membershiprequest",
old_name="person",
new_name="requester",
),
migrations.AlterField(
model_name="membershiprequest",
name="club",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="membership_requests",
to="clubs.club"
),
),
migrations.AlterField(
model_name="membershiprequest",
name="requester",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="membership_requests",
to=settings.AUTH_USER_MODEL
),
),
]
34 changes: 19 additions & 15 deletions backend/clubs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1082,44 +1082,48 @@ class MembershipRequest(models.Model):
Used when users are not in the club but request membership from the owner
"""

person = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
club = models.ForeignKey(Club, on_delete=models.CASCADE)
requester = models.ForeignKey(
get_user_model(), on_delete=models.CASCADE, related_name="membership_requests"
)
club = models.ForeignKey(
Club, on_delete=models.CASCADE, related_name="membership_requests"
)

withdrew = models.BooleanField(default=False)
withdrawn = models.BooleanField(default=False)

created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

def __str__(self):
return "<MembershipRequest: {} for {}, with email {}>".format(
self.person.username, self.club.code, self.person.email
)
return f"<MembershipRequest: {self.requester.username} for {self.club.code}>"

def send_request(self, request=None):
domain = get_domain(request)

edit_url = settings.EDIT_URL.format(domain=domain, club=self.club.code)

club_name = self.club.name

full_name = self.requester.get_full_name()

context = {
"club_name": self.club.name,
"edit_url": "{}/member".format(
settings.EDIT_URL.format(domain=domain, club=self.club.code)
),
"full_name": self.person.get_full_name(),
"club_name": club_name,
"edit_url": f"{edit_url}/member",
"full_name": full_name,
}

emails = self.club.get_officer_emails()

if emails:
send_mail_helper(
name="request",
subject="Membership Request from {} for {}".format(
self.person.get_full_name(), self.club.name
),
subject=f"Membership Request from {full_name} for {club_name}",
emails=emails,
context=context,
)

class Meta:
unique_together = (("person", "club"),)
unique_together = (("requester", "club"),)


class OwnershipRequest(models.Model):
Expand Down
40 changes: 17 additions & 23 deletions backend/clubs/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,9 @@ def update(self, instance, validated_data):
obj.save()

# if a membership request exists, delete it
MembershipRequest.objects.filter(person=user, club=self.instance.club).delete()
MembershipRequest.objects.filter(
requester=user, club=self.instance.club
).delete()

return instance

Expand Down Expand Up @@ -1268,7 +1270,7 @@ def get_is_request(self, obj):
user = self.context["request"].user
if not user.is_authenticated:
return False
return obj.membershiprequest_set.filter(person=user, withdrew=False).exists()
return obj.membership_requests.filter(requester=user, withdrawn=False).exists()

def get_target_years(self, obj):
qset = TargetYear.objects.filter(club=obj).select_related("target_years")
Expand Down Expand Up @@ -1941,20 +1943,22 @@ class MembershipRequestSerializer(serializers.ModelSerializer):
Used by club owners/officers to see who has requested to join the club.
"""

person = serializers.HiddenField(default=serializers.CurrentUserDefault())
requester = serializers.HiddenField(default=serializers.CurrentUserDefault())
club = serializers.SlugRelatedField(queryset=Club.objects.all(), slug_field="code")
name = serializers.SerializerMethodField("get_full_name")
username = serializers.CharField(source="person.username", read_only=True)
email = serializers.EmailField(source="person.email", read_only=True)
username = serializers.CharField(source="requester.username", read_only=True)
email = serializers.EmailField(source="requester.email", read_only=True)

school = SchoolSerializer(many=True, source="person.profile.school", read_only=True)
major = MajorSerializer(many=True, source="person.profile.major", read_only=True)
school = SchoolSerializer(
many=True, source="requester.profile.school", read_only=True
)
major = MajorSerializer(many=True, source="requester.profile.major", read_only=True)
graduation_year = serializers.IntegerField(
source="person.profile.graduation_year", read_only=True
source="requester.profile.graduation_year", read_only=True
)

def get_full_name(self, obj):
return obj.person.get_full_name()
return obj.requester.get_full_name()

class Meta:
model = MembershipRequest
Expand All @@ -1965,13 +1969,13 @@ class Meta:
"graduation_year",
"major",
"name",
"person",
"requester",
"school",
"username",
)
validators = [
validators.UniqueTogetherValidator(
queryset=MembershipRequest.objects.all(), fields=["club", "person"]
queryset=MembershipRequest.objects.all(), fields=["club", "requester"]
)
]

Expand All @@ -1981,23 +1985,13 @@ class UserMembershipRequestSerializer(serializers.ModelSerializer):
Used by the UserSerializer to return the clubs that the user has sent request to.
"""

person = serializers.HiddenField(default=serializers.CurrentUserDefault())
requester = serializers.HiddenField(default=serializers.CurrentUserDefault())
club = serializers.SlugRelatedField(queryset=Club.objects.all(), slug_field="code")
club_name = serializers.CharField(source="club.name", read_only=True)

def create(self, validated_data):
"""
Send an email when a membership request is created.
"""
obj = super().create(validated_data)

obj.send_request(self.context["request"])

return obj

class Meta:
model = MembershipRequest
fields = ("club", "club_name", "person")
fields = ("club", "club_name", "requester")


class OwnershipRequestSerializer(serializers.ModelSerializer):
Expand Down
41 changes: 25 additions & 16 deletions backend/clubs/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3735,15 +3735,24 @@ def create(self, request, *args, **kwargs):
If a membership request object already exists, reuse it.
"""
club = request.data.get("club", None)
obj = MembershipRequest.objects.filter(
club__code=club, person=request.user
).first()
if obj is not None:
obj.withdrew = False
obj.save(update_fields=["withdrew"])
return Response(UserMembershipRequestSerializer(obj).data)

return super().create(request, *args, **kwargs)
club_instance = Club.objects.get(code=club)

create_defaults = {"club": club_instance, "requester": request.user}

obj, created = MembershipRequest.objects.update_or_create(
club__code=club,
requester=request.user,
defaults={"withdrawn": False, "created_at": timezone.now()},
create_defaults=create_defaults,
)

if created:
obj.send_request(request)

serializer = self.get_serializer(obj, many=False)

return Response(serializer.data, status=status.HTTP_201_CREATED)

def destroy(self, request, *args, **kwargs):
"""
Expand All @@ -3753,15 +3762,15 @@ def destroy(self, request, *args, **kwargs):
owners with requests.
"""
obj = self.get_object()
obj.withdrew = True
obj.save(update_fields=["withdrew"])
obj.withdrawn = True
obj.save(update_fields=["withdrawn"])

return Response({"success": True})
return Response(status=status.HTTP_204_NO_CONTENT)

def get_queryset(self):
return MembershipRequest.objects.filter(
person=self.request.user,
withdrew=False,
requester=self.request.user,
withdrawn=False,
club__archived=False,
)

Expand All @@ -3778,11 +3787,11 @@ class MembershipRequestOwnerViewSet(XLSXFormatterMixin, viewsets.ModelViewSet):
serializer_class = MembershipRequestSerializer
permission_classes = [MembershipRequestPermission | IsSuperuser]
http_method_names = ["get", "post", "delete"]
lookup_field = "person__username"
lookup_field = "requester__username"

def get_queryset(self):
return MembershipRequest.objects.filter(
club__code=self.kwargs["club_code"], withdrew=False
club__code=self.kwargs["club_code"], withdrawn=False
)

@action(detail=True, methods=["post"])
Expand All @@ -3806,7 +3815,7 @@ def accept(self, request, *ages, **kwargs):
"""
request_object = self.get_object()
Membership.objects.get_or_create(
person=request_object.person, club=request_object.club
person=request_object.requester, club=request_object.club
)
request_object.delete()
return Response({"success": True})
Expand Down

0 comments on commit ff1719e

Please sign in to comment.