Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions promo_code/business/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,3 +538,17 @@ def validate(self, data):
instance=self.instance,
)
return validator.validate()


class CountryStatSerializer(rest_framework.serializers.Serializer):
"""Serializer for activation statistics by country."""

country = rest_framework.serializers.CharField()
activations_count = rest_framework.serializers.IntegerField()


class PromoStatSerializer(rest_framework.serializers.Serializer):
"""Serializer for overall promo code statistics."""

activations_count = rest_framework.serializers.IntegerField()
countries = CountryStatSerializer(many=True)
5 changes: 5 additions & 0 deletions promo_code/business/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,9 @@
business.views.CompanyPromoDetailView.as_view(),
name='promo-detail',
),
django.urls.path(
'promo/<uuid:id>/stat',
business.views.CompanyPromoStatAPIView.as_view(),
name='promo-statistics',
),
]
60 changes: 60 additions & 0 deletions promo_code/business/views.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import re

import django.db.models
import django.shortcuts
import rest_framework.generics
import rest_framework.permissions
import rest_framework.response
import rest_framework.status
import rest_framework.views
import rest_framework_simplejwt.views

import business.models
Expand All @@ -13,6 +15,7 @@
import business.serializers
import business.utils.auth
import business.utils.tokens
import user.models


class CompanySignUpView(rest_framework.generics.CreateAPIView):
Expand Down Expand Up @@ -153,3 +156,60 @@ class CompanyPromoDetailView(rest_framework.generics.RetrieveUpdateAPIView):
# Use an enriched base queryset without pre-filtering by company,
# so that ownership mismatches raise 403 Forbidden (not 404 Not Found).
queryset = business.models.Promo.objects.with_related()


class CompanyPromoStatAPIView(rest_framework.views.APIView):
"""
API endpoint for retrieving promo code statistics.
"""

permission_classes = [
rest_framework.permissions.IsAuthenticated,
business.permissions.IsPromoOwner,
]

def get(self, request, id, *args, **kwargs):
promo = django.shortcuts.get_object_or_404(
business.models.Promo,
id=id,
)

self.check_object_permissions(self.request, promo)

total_activations = promo.activations_history.count()

countries_stats = (
user.models.PromoActivationHistory.objects.filter(promo=promo)
.values(
'user__other__country',
)
.annotate(
activations_count=django.db.models.Count('id'),
)
.order_by(
'user__other__country',
)
)

countries_data = [
{
'country': item['user__other__country'],
'activations_count': item['activations_count'],
}
for item in countries_stats
]

response_data = {
'activations_count': total_activations,
'countries': countries_data,
}

serializer = business.serializers.PromoStatSerializer(
data=response_data,
)
serializer.is_valid(raise_exception=True)

return rest_framework.response.Response(
serializer.validated_data,
status=rest_framework.status.HTTP_200_OK,
)
1 change: 1 addition & 0 deletions promo_code/user/tests/user/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ def tearDown(self):
user.models.PromoLike.objects.all().delete()
user.models.User.objects.all().delete()
tb_models.BlacklistedToken.objects.all().delete()
tb_models.OutstandingToken.objects.all().delete()
django_redis.get_redis_connection('default').flushall()
super().tearDown()

Expand Down