Coverage for src/products/views/product.py: 80%

64 statements  

« prev     ^ index     » next       coverage.py v7.9.2, created at 2025-08-04 12:59 +0300

1""" 

2This module contains views for product listing, detail, attribute retrieval, and review management. 

3 

4It provides: 

5- List and detail views for each product type (Earwear, Neckwear, Wristwear, Fingerwear) 

6- Attribute views for product properties like color, metal, stone, and collection 

7- Both synchronous and asynchronous endpoints for attribute retrieval 

8- Custom permission for reviewer access to all product reviews 

9- Review management endpoints for products 

10""" 

11 

12from src.common.permissions import IsOrderManager 

13from src.products.models.product import Color, Metal, Stone, Collection 

14 

15from src.products.serializers.product import ( 

16 CollectionSerializer, 

17 ColorSerializer, 

18 EarwearItemSerializer, 

19 FingerwearItemSerializer, 

20 MetalSerializer, 

21 NeckwearItemSerializer, 

22 NeckwearListSerializer, 

23 EarwearListSerializer, 

24 StoneSerializer, 

25 WristwearItemSerializer, 

26 WristwearListSerializer, 

27 FingerwearListSerializer, 

28) 

29 

30from src.products.models import Earwear, Neckwear, Wristwear, Fingerwear 

31 

32from src.products.views.base import ( 

33 BaseAttributeView, 

34 BaseProductItemView, 

35 BaseProductListView, 

36) 

37 

38from rest_framework.views import APIView 

39from rest_framework.permissions import IsAuthenticated 

40from rest_framework.response import Response 

41from src.products.models.review import Review 

42from src.products.serializers.review import ReviewSerializer 

43from django.contrib.contenttypes.models import ContentType 

44from rest_framework import status 

45 

46 

47class EarwearListView(BaseProductListView): 

48 model = Earwear 

49 serializer_class = EarwearListSerializer 

50 

51 

52class NeckwearListView(BaseProductListView): 

53 model = Neckwear 

54 serializer_class = NeckwearListSerializer 

55 

56 

57class WristwearListView(BaseProductListView): 

58 model = Wristwear 

59 serializer_class = WristwearListSerializer 

60 

61 

62class FingerwearListView(BaseProductListView): 

63 model = Fingerwear 

64 serializer_class = FingerwearListSerializer 

65 

66 

67class EarwearItemView(BaseProductItemView): 

68 model = Earwear 

69 serializer_class = EarwearItemSerializer 

70 

71 

72class NeckwearItemView(BaseProductItemView): 

73 model = Neckwear 

74 serializer_class = NeckwearItemSerializer 

75 

76 

77class WristwearItemView(BaseProductItemView): 

78 model = Wristwear 

79 serializer_class = WristwearItemSerializer 

80 

81 

82class FingerwearItemView(BaseProductItemView): 

83 model = Fingerwear 

84 serializer_class = FingerwearItemSerializer 

85 

86 

87class CollectionRetrieveView(BaseAttributeView): 

88 model = Collection 

89 serializer_class = CollectionSerializer 

90 

91 

92class ColorRetrieveView(BaseAttributeView): 

93 model = Color 

94 serializer_class = ColorSerializer 

95 

96 

97class MetalRetrieveView(BaseAttributeView): 

98 model = Metal 

99 serializer_class = MetalSerializer 

100 

101 

102class StoneRetrieveView(BaseAttributeView): 

103 model = Stone 

104 serializer_class = StoneSerializer 

105 

106 

107class ProductAllReviewsView(APIView): 

108 permission_classes = [IsAuthenticated, IsOrderManager] 

109 

110 def get(self, request, category, pk): 

111 # Map category to model 

112 from src.products.models.product import ( 

113 Earwear, 

114 Neckwear, 

115 Fingerwear, 

116 Wristwear, 

117 ) 

118 

119 model_map = { 

120 'earwear': Earwear, 

121 'neckwear': Neckwear, 

122 'fingerwear': Fingerwear, 

123 'wristwear': Wristwear, 

124 } 

125 model = model_map.get(category.lower()) 

126 if not model: 

127 return Response( 

128 {'detail': 'Invalid category.'}, 

129 status=status.HTTP_400_BAD_REQUEST, 

130 ) 

131 try: 

132 product = model.objects.get(pk=pk) 

133 except model.DoesNotExist: 

134 return Response( 

135 {'detail': 'Product not found.'}, 

136 status=status.HTTP_404_NOT_FOUND, 

137 ) 

138 # Get all reviews for this product 

139 content_type = ContentType.objects.get_for_model(model) 

140 reviews = Review.objects.filter( 

141 content_type=content_type, object_id=product.id 

142 ).order_by('-created_at') 

143 serializer = ReviewSerializer(reviews, many=True) 

144 

145 return Response({'reviews': serializer.data})