Skip to content

Commit 37ccc42

Browse files
committed
feat(coupons): add fixed and percentage coupon endpoints
1 parent 851cd7e commit 37ccc42

File tree

2 files changed

+134
-4
lines changed

2 files changed

+134
-4
lines changed

apps/coupons/urls.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,20 @@
22

33
from django.urls import path
44

5-
from .views import FixedCouponListAPIView, CheckCouponAPIView
5+
from .views import (
6+
FixedCouponListAPIView, FixedCouponDetailAPIView,
7+
PercentageCouponListAPIView, PercentageCouponDetailAPIView,
8+
CheckCouponAPIView
9+
)
610

711

812
urlpatterns = [
913
path("api/v1/coupons/fixed-coupons/", FixedCouponListAPIView.as_view()),
14+
path("api/v1/coupons/fixed-coupons/<uuid:fixed_coupon_id>",
15+
FixedCouponDetailAPIView.as_view()),
16+
path("api/v1/coupons/percentage-coupons/",
17+
PercentageCouponListAPIView.as_view()),
18+
path("api/v1/coupons/percentage-coupons/<uuid:percentage_coupon_id>",
19+
PercentageCouponDetailAPIView.as_view()),
1020
path("api/v1/coupons/check-coupons/", CheckCouponAPIView.as_view())
1121
]

apps/coupons/views.py

Lines changed: 123 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from django.db import transaction
44
from django.core.cache import cache
5+
from django.shortcuts import get_object_or_404
56
from rest_framework.views import APIView
67
from rest_framework.response import Response
78
from rest_framework.permissions import IsAuthenticated
@@ -15,14 +16,14 @@
1516

1617

1718
class FixedCouponListAPIView(APIView):
18-
"""Pending."""
19+
"""APIView for listing and creating fixed coupons."""
1920
permission_classes = [IsAuthenticated]
2021
serializer_class = FixedCouponSerializer
2122
pagination_class = MediumSetPagination
2223
CACHE_TIMEOUT = 7200 # Cache for 2 hours
2324

2425
def get(self, request, format=None):
25-
# Pending
26+
# Get a list of available fixed coupons
2627
cache_key = f"fixed_coupon_{request.user.id}"
2728
cached_data = cache.get(cache_key)
2829

@@ -41,7 +42,7 @@ def get(self, request, format=None):
4142

4243
@transaction.atomic
4344
def post(self, request, format=None):
44-
# Pending
45+
# Create a new fixed coupon
4546
serializer = self.serializer_class(data=request.data)
4647
if serializer.is_valid():
4748
serializer.save()
@@ -58,6 +59,125 @@ def post(self, request, format=None):
5859
)
5960

6061

62+
class FixedCouponDetailAPIView(APIView):
63+
"""APIView to retrieve, update, and delete a fixed coupon."""
64+
permission_classes = [IsAuthenticated]
65+
serializer_class = FixedCouponSerializer
66+
67+
def get_object(self, fixed_coupon_id):
68+
# Get a fixed coupon instance by id
69+
return get_object_or_404(FixedCoupon, pk=fixed_coupon_id)
70+
71+
def get(self, request, fixed_coupon_id):
72+
# Get details of a fixed coupon
73+
fixed_coupon = self.get_object(fixed_coupon_id)
74+
serializer = self.serializer_class(fixed_coupon)
75+
return Response(serializer.data, status=status.HTTP_200_OK)
76+
77+
@transaction.atomic
78+
def put(self, request, fixed_coupon_id):
79+
# Update a fixed coupon
80+
fixed_coupon = self.get_object(fixed_coupon_id)
81+
serializer = self.serializer_class(fixed_coupon, data=request.data)
82+
if serializer.is_valid():
83+
serializer.save()
84+
return Response(serializer.data, status=status.HTTP_200_OK)
85+
return Response(
86+
serializer.errors,
87+
status=status.HTTP_400_BAD_REQUEST
88+
)
89+
90+
@transaction.atomic
91+
def delete(self, request, fixed_coupon_id):
92+
# Delete a fixed coupon
93+
fixed_coupon = self.get_object(fixed_coupon_id)
94+
fixed_coupon.delete()
95+
return Response(status=status.HTTP_204_NO_CONTENT)
96+
97+
98+
class PercentageCouponListAPIView(APIView):
99+
"""APIView for listing and creating percentage coupons."""
100+
permission_classes = [IsAuthenticated]
101+
serializer_class = PercentageCouponSerializer
102+
pagination_class = MediumSetPagination
103+
CACHE_TIMEOUT = 7200 # Cache for 2 hours
104+
105+
def get(self, request, format=None):
106+
# Get a list of available percentage coupons
107+
cache_key = f"percentage_coupon_{request.user.id}"
108+
cached_data = cache.get(cache_key)
109+
110+
if cached_data is None:
111+
coupons = PercentageCoupon.objects.filter(
112+
available=True).order_by("id")
113+
if coupons.exists():
114+
serializer = self.serializer_class(coupons, many=True)
115+
# Set cache
116+
cache.set(cache_key, serializer.data, self.CACHE_TIMEOUT)
117+
return Response(serializer.data, status=status.HTTP_200_OK)
118+
return Response(
119+
{"detail": "No percentage coupons available."},
120+
status=status.HTTP_404_NOT_FOUND
121+
)
122+
return Response(cached_data, status=status.HTTP_200_OK)
123+
124+
@transaction.atomic
125+
def post(self, request, format=None):
126+
# Create a new percentage coupon
127+
serializer = self.serializer_class(data=request.data)
128+
if serializer.is_valid():
129+
serializer.save()
130+
# Invalidate cache
131+
cache_key = f"percentage_coupon_{request.user.id}"
132+
cache.delete(cache_key)
133+
return Response(
134+
serializer.data,
135+
status=status.HTTP_201_CREATED
136+
)
137+
return Response(
138+
serializer.errors,
139+
status=status.HTTP_400_BAD_REQUEST
140+
)
141+
142+
143+
class PercentageCouponDetailAPIView(APIView):
144+
"""APIView to retrieve, update, and delete a percentage coupon."""
145+
permission_classes = [IsAuthenticated]
146+
serializer_class = PercentageCouponSerializer
147+
148+
def get_object(self, percentage_coupon_id):
149+
# Get a percentage coupon instance by id
150+
return get_object_or_404(PercentageCoupon, pk=percentage_coupon_id)
151+
152+
def get(self, request, percentage_coupon_id):
153+
# Get details of a percentage coupon
154+
percentage_coupon = self.get_object(percentage_coupon_id)
155+
serializer = self.serializer_class(percentage_coupon)
156+
return Response(serializer.data, status=status.HTTP_200_OK)
157+
158+
@transaction.atomic
159+
def put(self, request, percentage_coupon_id):
160+
# Update a percentage coupon
161+
percentage_coupon = self.get_object(percentage_coupon_id)
162+
serializer = self.serializer_class(
163+
percentage_coupon, data=request.data
164+
)
165+
if serializer.is_valid():
166+
serializer.save()
167+
return Response(serializer.data, status=status.HTTP_200_OK)
168+
return Response(
169+
serializer.errors,
170+
status=status.HTTP_400_BAD_REQUEST
171+
)
172+
173+
@transaction.atomic
174+
def delete(self, request, percentage_coupon_id):
175+
# Delete a percentage coupon
176+
percentage_coupon = self.get_object(percentage_coupon_id)
177+
percentage_coupon.delete()
178+
return Response(status=status.HTTP_204_NO_CONTENT)
179+
180+
61181
class CheckCouponAPIView(APIView):
62182
"""APIView to check the validity of a coupon code."""
63183

0 commit comments

Comments
 (0)