Skip to content

Commit

Permalink
feat(prices): new stats endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
raphodn committed Sep 16, 2024
1 parent f662710 commit 0d1bb56
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 1 deletion.
7 changes: 7 additions & 0 deletions open_prices/api/prices/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,10 @@ class PriceUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = Price
fields = Price.UPDATE_FIELDS


class PriceStatsSerializer(serializers.Serializer):
price__count = serializers.IntegerField()
price__min = serializers.DecimalField(max_digits=10, decimal_places=2)
price__max = serializers.DecimalField(max_digits=10, decimal_places=2)
price__avg = serializers.DecimalField(max_digits=10, decimal_places=2)
42 changes: 42 additions & 0 deletions open_prices/api/prices/tests.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from decimal import Decimal

from django.test import TestCase
from django.urls import reverse

from open_prices.locations.models import Location
from open_prices.prices import constants as price_constants
from open_prices.prices.factories import PriceFactory
from open_prices.prices.models import Price
from open_prices.products.factories import ProductFactory
from open_prices.products.models import Product
from open_prices.proofs import constants as proof_constants
from open_prices.proofs.factories import ProofFactory
Expand Down Expand Up @@ -491,3 +494,42 @@ def test_price_delete(self):
self.assertEqual(
Price.objects.filter(owner=self.user_session_1.user.user_id).count(), 0
)


class PriceStatsApiTest(TestCase):
@classmethod
def setUpTestData(cls):
cls.url = reverse("api:prices-stats")
cls.product = ProductFactory()
PriceFactory(
product_code=cls.product.code,
price=15,
price_is_discounted=True,
price_without_discount=20,
)
PriceFactory(product_code=cls.product.code, price=25)
PriceFactory(product_code=cls.product.code, price=30)
PriceFactory(
product_code=None,
category_tag="en:apples",
price=2,
price_per=price_constants.PRICE_PER_KILOGRAM,
)

def test_price_stats(self):
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data["price__count"], 4)
self.assertEqual(response.data["price__min"], 2.00)
self.assertEqual(response.data["price__max"], 30.00)
self.assertEqual(response.data["price__avg"], Decimal(18.00))
url = self.url + "?price_is_discounted=False"
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data["price__count"], 3)
self.assertEqual(response.data["price__avg"], Decimal(19.00))
url = self.url + f"?price_is_discounted=false&product_code={self.product.code}"
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data["price__count"], 2)
self.assertEqual(response.data["price__avg"], Decimal(27.50))
9 changes: 9 additions & 0 deletions open_prices/api/prices/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from django_filters.rest_framework import DjangoFilterBackend
from drf_spectacular.utils import extend_schema
from rest_framework import filters, mixins, status, viewsets
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from rest_framework.request import Request
from rest_framework.response import Response
Expand All @@ -8,6 +10,7 @@
from open_prices.api.prices.serializers import (
PriceCreateSerializer,
PriceFullSerializer,
PriceStatsSerializer,
PriceUpdateSerializer,
)
from open_prices.common.authentication import CustomAuthentication
Expand Down Expand Up @@ -63,3 +66,9 @@ def create(self, request: Request, *args, **kwargs):
return Response(
self.serializer_class(price).data, status=status.HTTP_201_CREATED
)

@extend_schema(responses=PriceStatsSerializer, filters=True)
@action(detail=False, methods=["GET"])
def stats(self, request: Request) -> Response:
qs = self.filter_queryset(self.get_queryset())
return Response(qs.calculate_stats(), status=200)
2 changes: 1 addition & 1 deletion open_prices/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ class StatusView(APIView):

@extend_schema(responses=StatusSerializer, tags=["status"])
def get(self, request: Request) -> Response:
return Response({"status": "running"})
return Response({"status": "running"}, status=200)

0 comments on commit 0d1bb56

Please sign in to comment.