Skip to content

Commit

Permalink
feat: add view for buyer's leaderboard data listing
Browse files Browse the repository at this point in the history
sandronadiradze committed Nov 4, 2024
1 parent 8e8d9dc commit 3571a76
Showing 3 changed files with 142 additions and 18 deletions.
6 changes: 6 additions & 0 deletions auction/urls.py
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
BulkDeleteAuctionView,
BuyerAuctionListView,
BuyerDashboardListView,
BuyerLeaderBoardStatisticsListView,
CancelAuctionView,
CreateBookmarkView,
CreateDraftAuctionView,
@@ -64,4 +65,9 @@
),
path("cancel/<uuid:auction_id>/", CancelAuctionView.as_view(), name="cancel-auction"),
path("leave/<uuid:auction_id>/", LeaveAuctionView.as_view(), name="leave-auction"),
path(
"buyer/leaderboard/",
BuyerLeaderBoardStatisticsListView.as_view(),
name="buyer-leaderboard",
),
]
122 changes: 120 additions & 2 deletions auction/views.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
from django.db import DatabaseError, transaction
from django.db.models import BooleanField, Case, Exists, F, OuterRef, Subquery, When
from django.db.models.functions import Greatest
from django.db.models import (
BooleanField,
Case,
Count,
Exists,
F,
OuterRef,
Subquery,
When,
Window,
)
from django.db.models.functions import Greatest, RowNumber
from django.shortcuts import get_object_or_404
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
@@ -1456,3 +1466,111 @@ def post(self, request, auction_id, *args, **kwargs):
{"detail": f"An error occurred: {str(e)}"},
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
)


@extend_schema(
tags=["Statistics"],
)
class BuyerLeaderBoardStatisticsListView(generics.ListAPIView):
permission_classes = [IsAuthenticated, IsBuyer]

def get_queryset(self):
return (
Auction.objects.filter(
status=StatusChoices.COMPLETED,
statistics__winner_bid_object__isnull=False,
)
.values(
"author",
"author_nickname",
"author_avatar",
)
.annotate(
completed_auctions_count=Count("id"),
rank=Window(
expression=RowNumber(), order_by=F("completed_auctions_count").desc()
),
)
.order_by("-completed_auctions_count")
)

def format_users(self, users):
return [
{
"rank": user["rank"],
"author_id": user["author"],
"author_nickname": user["author_nickname"],
"author_avatar": user["author_avatar"],
"completed_auctions_count": user["completed_auctions_count"],
}
for user in users
]

def list(self, request, *args, **kwargs):
requesting_user_id = request.user.id

# Get the complete ordered queryset and materialize it
complete_queryset = list(self.get_queryset())

# Get top 3 users
top_three = complete_queryset[:3]

# Get paginated results
page = self.paginate_queryset(complete_queryset)
formatted_users = self.format_users(page)

# Find user's data in the complete queryset
user_data = None
for item in complete_queryset:
if str(item["author"]) == str(
requesting_user_id
): # Convert both to strings to ensure matching
user_data = item
break

# If user not found in complete_queryset but exists in results, use that data
if not user_data:
for item in formatted_users:
if str(item["author_id"]) == str(requesting_user_id):
user_data = {
"rank": item["rank"],
"author": item["author_id"],
"author_nickname": item["author_nickname"],
"author_avatar": item["author_avatar"],
"completed_auctions_count": item["completed_auctions_count"],
}
break

if user_data:
user_data_response = {
"rank": user_data["rank"],
"author_id": user_data["author"],
"author_nickname": user_data["author_nickname"],
"author_avatar": user_data["author_avatar"],
"completed_auctions_count": user_data["completed_auctions_count"],
}
else:
user_data_response = {
"rank": None,
"author_id": requesting_user_id,
"author_nickname": (
request.user.nickname if hasattr(request.user, "nickname") else None
),
"author_avatar": (
request.user.avatar if hasattr(request.user, "avatar") else None
),
"completed_auctions_count": 0,
}

paginated_response = {
"user_data": user_data_response,
"top_three_users": self.format_users(top_three),
"results": formatted_users,
}

response = self.get_paginated_response(paginated_response)
response.data["user_data"] = paginated_response["user_data"]
response.data["top_three_users"] = paginated_response["top_three_users"]
response.data["results"] = paginated_response["results"]

return response
32 changes: 16 additions & 16 deletions locale/ka/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-04 05:05+0000\n"
"POT-Creation-Date: 2024-11-04 08:27+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -74,74 +74,74 @@ msgstr "თქვენ არ შეგიძლიათ შეცვალო
msgid "There was an error during the update of the auction. Please try again."
msgstr "აუქციონის შექმნისას პრობლემამ იჩინა თავი. გთხოვთ სცადოთ თავიდან."

#: auction/views.py:597
#: auction/views.py:601
msgid "Auction deleted successfully."
msgstr "აუქციონი წარმატებით წაიშალა."

#: auction/views.py:707
#: auction/views.py:711
#, python-brace-format
msgid "Auction with UUID {id} does not exist."
msgstr "აუქციონი მოცემული იდენტიფიკატორით {id} არ არსებობს."

#: auction/views.py:716
#: auction/views.py:720
#, python-brace-format
msgid ""
"{deleted} auctions deleted and {marked_deleted} auctions marked as deleted."
msgstr ""
"წაიშალა {deleted} აუქციონი და {marked_deleted} აუქციონი მონიშნულია, როგორც "
"წაშლილი."

#: auction/views.py:1087
#: auction/views.py:1091
msgid ""
"Only the bids with a status of either Pending or Approved can be declared as "
"winner bids."
msgstr ""
"მხოლოდ დაეფრუვებული ან მომლოდინე რეჟიმის მქონე ბიდები შეიძლება გამოცხადნენ "
"გამარჯვებულებად."

#: auction/views.py:1103
#: auction/views.py:1107
msgid "You can only declare a winner after the auction has been completed."
msgstr ""
"გამარჯვებულის გამოცხადება მხოლოდ აუქციონის დასრულების შემდეგ შეგიძლიათ."

#: auction/views.py:1145
#: auction/views.py:1149
msgid "Winner of this auction has successfully been declared"
msgstr "აუქციონის გამარჯვებული წარმატებით გამოვლინდა."

#: auction/views.py:1245
#: auction/views.py:1249
msgid "You can not cancel draft auctions."
msgstr "თქვენ არ შეგიძლიათ დრაფტ სტატუსის მქონე აუქციონის გაუქმება."

#: auction/views.py:1246
#: auction/views.py:1250
msgid "This auction is already canceled."
msgstr "ეს აუქციონი უკვე გაუქმებულია."

#: auction/views.py:1247
#: auction/views.py:1251
msgid "You can not cancel deleted auctions."
msgstr "თქვენ არ შეგიძლიათ წაშლილი აუქციონის გაუქმება."

#: auction/views.py:1249
#: auction/views.py:1253
msgid "You can not cancel auctions that have already been completed."
msgstr "თქვენ არ შეგიძლიათ გააუქომთ აუქციონი, რომელიც უკვე დასრულებულია."

#: auction/views.py:1271
#: auction/views.py:1275
msgid "Auction was successfully canceled."
msgstr "აუქციონის გაუქმება წარმატებით განხორციელდა."

#: auction/views.py:1363
#: auction/views.py:1367
msgid "You can not leave an auction that has already been completed."
msgstr "თქვენ არ შეგიძლიათ დატოვოთ აუქციონი რომელიც უკვე დასრულდა."

#: auction/views.py:1367
#: auction/views.py:1371
msgid "You can not leave an auction that has not started yet."
msgstr "თქვენ არ შეგიძლიათ დატოვოთ აუქციონი, რომელიც ჯერ არ დაწყებულა."

#: auction/views.py:1371
#: auction/views.py:1375
msgid "You can not leave an auction that has been cancelled, drafted."
msgstr ""
"თქვენ არ შეგიძლიათ გაუქმებული ან drafter სტატუსის მქონე აუქციონის დატოვება."

#: auction/views.py:1376
#: auction/views.py:1380
msgid "As a winner of an auction, you can not leave it."
msgstr "როგორც გამარჯვებული, თქვენ ვერ დატოვებთ აუქციონს."

0 comments on commit 3571a76

Please sign in to comment.