Coverage for products/views.py: 58%

120 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-13 14:00 -0600

1from django.db import transaction 

2from rest_framework import status 

3from rest_framework.mixins import ( 

4 ListModelMixin as List, 

5 CreateModelMixin as Create, 

6 UpdateModelMixin as Update, 

7 RetrieveModelMixin as Detail, 

8) 

9from rest_framework.permissions import AllowAny 

10from rest_framework.response import Response 

11from rest_framework.viewsets import GenericViewSet 

12from events.services import send_ticket_purchase_confirmation, send_ticket_to_participants 

13from memberships.mixins import MemberMixin 

14from organizations.mixins import OrganizationAdminMixin 

15from payments.serializers import MemberPaymentIntentSerializer 

16from .filters import ProductFilter, MembershipProductFilter, EventProductFilter 

17from .models import Product, MembershipProduct, EventProduct, ProductPriceVariation 

18from .serializers import ( 

19 ProductPolymorphicSerializer, 

20 ProductPurchaseSerializer, 

21 MembershipProductSerializer, 

22 EventProductSerializer, 

23 MemberEventProductPurchaseSerializer, 

24 PublicEventProductPurchaseSerializer, 

25 ProductPriceVariationSerializer, 

26 BulkProductPurchaseSerializer, 

27) 

28from .utils.purchase_product import ProductPurchaseCreationHandler 

29 

30 

31class ProductViewSet(OrganizationAdminMixin, GenericViewSet, List, Create, Detail): 

32 """ 

33 Product ViewSet 

34 """ 

35 

36 model = Product 

37 serializer_class = ProductPolymorphicSerializer 

38 filterset_class = ProductFilter 

39 search_fields = ["name"] 

40 

41 

42class MembershipProductViewSet(OrganizationAdminMixin, GenericViewSet, List, Update): 

43 """ 

44 ViewSet for MembershipProduct 

45 """ 

46 

47 model = MembershipProduct 

48 serializer_class = MembershipProductSerializer 

49 filterset_class = MembershipProductFilter 

50 search_fields = ["name"] 

51 

52 

53class EventProductViewSet(OrganizationAdminMixin, GenericViewSet, Create, List, Detail, Update): 

54 model = EventProduct 

55 serializer_class = EventProductSerializer 

56 filterset_fields = ["event", "is_active"] 

57 search_fields = ["name"] 

58 

59 

60class MemberEventProductViewSet(MemberMixin, GenericViewSet, List, Detail): 

61 serializer_class = EventProductSerializer 

62 search_fields = ["name"] 

63 queryset = EventProduct.objects.all() 

64 filterset_class = EventProductFilter 

65 

66 

67class PublicEventProductViewSet(GenericViewSet, List, Detail): 

68 model = EventProduct 

69 serializer_class = EventProductSerializer 

70 queryset = EventProduct.objects.filter(event__only_members=False) 

71 permission_classes = [AllowAny] 

72 

73 

74class MemberEventProductPurchaseViewSet(MemberMixin, GenericViewSet, Create): 

75 """ 

76 Event Product Purchase View Set for Member 

77 """ 

78 

79 serializer_class = MemberEventProductPurchaseSerializer 

80 

81 def create(self, request, *args, **kwargs): 

82 """ 

83 Override create to use purchase creation handler and create payment 

84 """ 

85 with transaction.atomic(): 

86 membership = request.data.get("membership") 

87 email = request.data.get("email") 

88 payment_method = request.data.pop("payment_method") 

89 ticket_owner = request.data.pop("ticket_owner") 

90 serializer = ProductPurchaseSerializer(data=request.data) 

91 serializer.is_valid(raise_exception=True) 

92 handler = ProductPurchaseCreationHandler(serializer) 

93 purchase, items_data = handler.create() 

94 charges = purchase.productcharge_set.all() 

95 tickets = purchase.productowner_set.all() 

96 for ticket, ticket_owner in zip(tickets, ticket_owner): 

97 ticket.first_name = ticket_owner.get("first_name") 

98 ticket.last_name = ticket_owner.get("last_name") 

99 ticket.email = ticket_owner.get("email") 

100 ticket.phone = ticket_owner.get("phone") 

101 ticket.save() 

102 try: 

103 payload = {"membership": membership, "payment_method": payment_method, "product_charges": charges} 

104 payment_serializer = MemberPaymentIntentSerializer(data=payload) 

105 payment_serializer.is_valid(raise_exception=True) 

106 payment_intent = payment_serializer.save() 

107 except Exception as e: 

108 raise e 

109 send_ticket_purchase_confirmation(email, purchase, payment_intent, tickets, charges.first()) 

110 send_ticket_to_participants(request, tickets, purchase) 

111 return Response(payment_serializer.data) 

112 

113 

114class PublicEventProductPurchaseViewSet(GenericViewSet, Create): 

115 """ 

116 Event Product Purchase View Set for Member 

117 """ 

118 

119 serializer_class = PublicEventProductPurchaseSerializer 

120 permission_classes = [AllowAny] 

121 

122 def create(self, request, *args, **kwargs): 

123 """ 

124 Override create to use purchase creation handler and create payment 

125 """ 

126 ticket_owner = request.data.pop("ticket_owner") 

127 with transaction.atomic(): 

128 email = request.data.get("email") 

129 serializer = ProductPurchaseSerializer(data=request.data) 

130 serializer.is_valid(raise_exception=True) 

131 handler = ProductPurchaseCreationHandler(serializer) 

132 purchase, items_data = handler.create() 

133 charges = purchase.productcharge_set.all() 

134 tickets = purchase.productowner_set.all() 

135 for ticket, ticket_owner in zip(tickets, ticket_owner): 

136 ticket.first_name = ticket_owner.get("first_name") 

137 ticket.last_name = ticket_owner.get("last_name") 

138 ticket.email = ticket_owner.get("email") 

139 ticket.phone = ticket_owner.get("phone") 

140 ticket.save() 

141 # try: 

142 # payload = {"payment_method": payment_method, "product_charges": charges} 

143 # payment_serializer = MemberPaymentIntentSerializer(data=payload) 

144 # payment_serializer.is_valid(raise_exception=True) 

145 # payment_intent = payment_serializer.save() 

146 # except Exception as e: 

147 # raise e 

148 # send_ticket_purchase_confirmation(email, purchase, payment_intent, tickets, charges.first()) 

149 # send_ticket_to_participants(request, tickets, purchase) 

150 # return Response(payment_serializer.data) 

151 

152 

153class PurchaseViewSet(OrganizationAdminMixin, GenericViewSet, List): 

154 """ 

155 Product Purchase View Set 

156 """ 

157 

158 serializer_class = ProductPurchaseSerializer 

159 model_organization = "membership__organization" 

160 

161 def create(self, request, *args, **kwargs): 

162 """ 

163 Override create to use purchase creation handler 

164 """ 

165 serializer = ProductPurchaseSerializer(data=request.data) 

166 serializer.is_valid(raise_exception=True) 

167 handler = ProductPurchaseCreationHandler(serializer) 

168 purchase, items_data = handler.create() 

169 response_serializer = ProductPurchaseSerializer(purchase) 

170 data = response_serializer.data 

171 data["items"] = items_data 

172 return Response(data, status=status.HTTP_201_CREATED) 

173 

174 

175class BulkPurchaseViewSet(GenericViewSet, Create): 

176 """ 

177 Bulk Product Purchase View Set 

178 """ 

179 

180 serializer_class = BulkProductPurchaseSerializer 

181 

182 def create(self, request, *args, **kwargs): 

183 """ 

184 Override create to use purchase creation handler 

185 """ 

186 bulk_serializer = BulkProductPurchaseSerializer(data=request.data) 

187 bulk_serializer.is_valid(raise_exception=True) 

188 product = bulk_serializer.validated_data.get("product") 

189 memberships = bulk_serializer.validated_data.get("memberships") 

190 for membership in memberships: 

191 data = { 

192 "membership": membership.random_slug, 

193 "product": product.random_slug, 

194 "quantity": 1, 

195 "installments": 1, 

196 "owner_relation": [], 

197 } 

198 serializer = ProductPurchaseSerializer(data=data) 

199 serializer.is_valid(raise_exception=True) 

200 handler = ProductPurchaseCreationHandler(serializer) 

201 purchase, items_data = handler.create() 

202 data = bulk_serializer.data 

203 data["products_installed"] = len(memberships) 

204 return Response(data, status=status.HTTP_201_CREATED) 

205 

206 

207class ProductPriceVariationViewSet(GenericViewSet, Create, List, Detail, Update): 

208 """ 

209 ViewSet for ProductPriceVariations 

210 """ 

211 

212 serializer_class = ProductPriceVariationSerializer 

213 queryset = ProductPriceVariation.objects.all() 

214 filterset_fields = ["product", "membership_type", "segments"]