Coverage for products/views.py: 58%
120 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-13 14:00 -0600
« 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
31class ProductViewSet(OrganizationAdminMixin, GenericViewSet, List, Create, Detail):
32 """
33 Product ViewSet
34 """
36 model = Product
37 serializer_class = ProductPolymorphicSerializer
38 filterset_class = ProductFilter
39 search_fields = ["name"]
42class MembershipProductViewSet(OrganizationAdminMixin, GenericViewSet, List, Update):
43 """
44 ViewSet for MembershipProduct
45 """
47 model = MembershipProduct
48 serializer_class = MembershipProductSerializer
49 filterset_class = MembershipProductFilter
50 search_fields = ["name"]
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"]
60class MemberEventProductViewSet(MemberMixin, GenericViewSet, List, Detail):
61 serializer_class = EventProductSerializer
62 search_fields = ["name"]
63 queryset = EventProduct.objects.all()
64 filterset_class = EventProductFilter
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]
74class MemberEventProductPurchaseViewSet(MemberMixin, GenericViewSet, Create):
75 """
76 Event Product Purchase View Set for Member
77 """
79 serializer_class = MemberEventProductPurchaseSerializer
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)
114class PublicEventProductPurchaseViewSet(GenericViewSet, Create):
115 """
116 Event Product Purchase View Set for Member
117 """
119 serializer_class = PublicEventProductPurchaseSerializer
120 permission_classes = [AllowAny]
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)
153class PurchaseViewSet(OrganizationAdminMixin, GenericViewSet, List):
154 """
155 Product Purchase View Set
156 """
158 serializer_class = ProductPurchaseSerializer
159 model_organization = "membership__organization"
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)
175class BulkPurchaseViewSet(GenericViewSet, Create):
176 """
177 Bulk Product Purchase View Set
178 """
180 serializer_class = BulkProductPurchaseSerializer
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)
207class ProductPriceVariationViewSet(GenericViewSet, Create, List, Detail, Update):
208 """
209 ViewSet for ProductPriceVariations
210 """
212 serializer_class = ProductPriceVariationSerializer
213 queryset = ProductPriceVariation.objects.all()
214 filterset_fields = ["product", "membership_type", "segments"]