Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add club diff feature #705

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
28 changes: 28 additions & 0 deletions backend/clubs/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,34 @@ class Meta(ClubMinimalSerializer.Meta):
fields = ClubMinimalSerializer.Meta.fields + ["files"]


class ClubDiffSerializer(serializers.ModelSerializer):
diff = serializers.SerializerMethodField()

class Meta:
model = Club
fields = ["code"]

def to_representation(self, instance):
fields = ["name", "description", "image"]
diff = {}
is_same = True
for field in fields:
diff[field] = {
"old": getattr(instance, f"latest_approved_{field}", None),
"new": getattr(instance, f"latest_{field}", None),
}
if diff[field]["old"] != diff[field]["new"]:
is_same = False

if is_same:
return {
instance.code: "No changes that require approval made"
+ " since last approval"
}

return {instance.code: diff}


class ClubListSerializer(serializers.ModelSerializer):
"""
The club list serializer returns a subset of the information that the full
Expand Down
165 changes: 165 additions & 0 deletions backend/clubs/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@
ExpressionWrapper,
F,
Max,
OuterRef,
Prefetch,
Q,
Subquery,
TextField,
Value,
When,
Expand Down Expand Up @@ -163,6 +165,7 @@
ClubApprovalResponseTemplateSerializer,
ClubBoothSerializer,
ClubConstitutionSerializer,
ClubDiffSerializer,
ClubFairSerializer,
ClubListSerializer,
ClubMembershipSerializer,
Expand Down Expand Up @@ -2127,6 +2130,168 @@ def perform_destroy(self, instance):
reply_to=settings.OSA_EMAILS + [settings.BRANDING_SITE_EMAIL],
)

def _get_club_diff_queryset(self):
"""
Returns a queryset of clubs annotated with the latest and latest approved values
for specific fields (name, description, image) from their historical records.

The annotations include:
- `latest_<field>`: The most recent value of the field.
- `latest_approved_<field>`: The most recent approved value of the field.
"""
latest_version_qs = Club.history.filter(code=OuterRef("code")).order_by(
"-history_date"
)

latest_approved_version_qs = Club.history.filter(
code=OuterRef("code"), approved=True
).order_by("-history_date")

return Club.objects.annotate(
latest_name=Subquery(latest_version_qs.values("name")[:1]),
latest_description=Subquery(latest_version_qs.values("description")[:1]),
latest_image=Subquery(latest_version_qs.values("image")[:1]),
latest_approved_name=Subquery(
latest_approved_version_qs.values("name")[:1]
),
latest_approved_description=Subquery(
latest_approved_version_qs.values("description")[:1]
),
latest_approved_image=Subquery(
latest_approved_version_qs.values("image")[:1]
),
)

@action(detail=True, methods=["GET"])
def club_detail_diff(self, request, *args, **kwargs):
"""
Return old and new data for a club that is pending approval.
---
responses:
"200":
content:
application/json:
schema:
type: object
properties:
club_code:
type: object
description: club code
properties:
name:
type: object
description: Changes in the name field
properties:
old:
type: string
description: >
Old name of the club
new:
type: string
description: >
New name of the club
description:
type: object
description: >
Changes in the club description
properties:
old:
type: string
description: >
Old description of the club
new:
type: string
description: >
New description of the club
image:
type: object
description: >
Changes in the image of the club
properties:
old:
type: string
description: >
Old image URL of the club
new:
type: string
description: >
New image URL of the club
---
"""
club = self.get_object()

club = self._get_club_diff_queryset().get(pk=club.pk)
serializer = ClubDiffSerializer(club)
return Response(serializer.data)

@action(detail=False, methods=["GET"])
rm03 marked this conversation as resolved.
Show resolved Hide resolved
def club_list_diff(self, request, *args, **kwargs):
"""
Return old and new data for clubs that are pending approval.

---
responses:
"200":
content:
application/json:
schema:
type: array
items:
type: object
additionalProperties:
type: object
description: Diff of the club fields.
properties:
name:
type: object
description: Changes in the name field.
properties:
old:
type: string
nullable: true
description: Old name of the club.
new:
type: string
nullable: true
description: New name of the club.
description:
type: object
description: >
Changes in the description field.
properties:
old:
type: string
nullable: true
description: >
Old description of the club.
new:
type: string
nullable: true
description: >
New description of the club.
image:
type: object
description: Changes in the image field.
properties:
old:
type: string
nullable: true
description: >
Old image URL of the club.
new:
type: string
nullable: true
description: >
New image URL of the club.
---
"""

pending_clubs = self._get_club_diff_queryset().filter(
approved=None, active=True
)
serializer = ClubDiffSerializer(pending_clubs, many=True)
return Response(serializer.data)

@action(detail=False, methods=["GET"])
def fields(self, request, *args, **kwargs):
"""
Expand Down
Loading
Loading