from itertools import groupby from django.db.models import F, Func, Sum, Value from django.db.models.functions import Concat, TruncDay, TruncMonth, TruncYear from rest_framework.response import Response from rest_framework.views import APIView from core.apps.eggs.models import Order from core.http.permissions import IsRole class WeekOfMonth(Func): function = "EXTRACT" template = "(%(function)s('day' from %(expressions)s) - 1) / 7 + 1" def as_postgresql(self, compiler, connection): self.template = ( "ROUND((EXTRACT('day' from %(expressions)s) - 1) / 7 + 1)" ) return super().as_sql(compiler, connection) class DayName(Func): function = "to_char" template = "%(function)s(%(expressions)s, 'Day')" class TopCourierView(APIView): permission_classes = [IsRole(["admin"])] def get(self, request): top_couriers = ( Order.objects.annotate( year=TruncYear("created_at"), month=TruncMonth("created_at"), day=TruncDay("created_at"), day_name=DayName("created_at"), full_name=Concat( F("courier_id__user_id__first_name"), Value(" "), F("courier_id__user_id__last_name"), ), ) .values( "year", "month", "day", "day_name", "full_name", ) .annotate(value=Sum("order_items__count")) .order_by("year", "month", "day", "-value") )[:3] data = [] for year, year_data in groupby(top_couriers, key=lambda x: x["year"]): year_dict = {"Year": year.year, "Months": []} for month, month_data in groupby( year_data, key=lambda x: x["month"] ): month_dict = {"month": month.strftime("%B"), "days": []} for day, day_data in groupby( month_data, key=lambda x: x["day"] ): day_data_list = list(day_data) people_list = [ { "full_name": person["full_name"], "value": person["value"], } for person in day_data_list ] day_dict = { "day": day.day, "day_name": day_data_list[0]["day_name"].strip(), "people": people_list, } month_dict["days"].append(day_dict) year_dict["Months"].append(month_dict) data.append(year_dict) return Response(data)