promotions/apps/promotions/views_application.py
Sayyid Hamid Mahdavi 3320ff93e3 temp
2026-07-07 12:10:19 +03:30

286 lines
11 KiB
Python

from drf_spectacular.utils import extend_schema
from rest_framework import mixins, status
from rest_framework.decorators import action
from rest_framework import exceptions
from rest_framework.generics import CreateAPIView, get_object_or_404, RetrieveAPIView, ListAPIView
from rest_framework.response import Response
from rest_framework.settings import api_settings
from rest_framework.viewsets import GenericViewSet
from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRequirements, TokenMatchesViewSetActions
from apps.gooyal_oauth2.utils import get_application
from utils.exceptions import UnprocessableEntity
from .models import Plan, Promotion, EventSaver
from .serializers import PlanSerializer, PromotionSerializer, EventSerializer, PromoteSerializer, UserPlanSerializer
from .tasks import analyze_event_task
from ..users.models import User
class ApplicationUserPlanViewSet(
mixins.RetrieveModelMixin,
mixins.ListModelMixin,
# mixins.CreateModelMixin,
GenericViewSet
):
serializer_class = UserPlanSerializer
permission_classes = [TokenMatchesViewSetActions]
required_action_scopes = {
"promote": [["promotions.application.user-plan:promote"]],
"retrieve": [["promotions.application.user-plan:list-retrieve"]],
"list": [["promotions.application.user-plan:list-retrieve"]],
}
def get_queryset(self):
application = get_application(self.request)
# TODO: get user from accounts
user_uuid = self.kwargs.get('user_uuid')
# return Promotion.objects.filter(application=application)
return Plan.objects.all()
# def perform_create(self, serializer):
# user = self.get_user()
# application = get_application(self.request)
#
# plan = serializer.validated_data['plan']
#
# promotion_args = dict(user=user, application=application, **serializer.validated_data)
# promotion_amount = plan.calculate_promotion(**promotion_args)
# if promotion_amount:
# promotion = serializer.save(promotion_amount=promotion_amount, user=user, application=application)
# promotion.promote(**promotion_args)
@action(detail=True, methods=['POST'], serializer_class=PromoteSerializer)
def promote(self, request, *args, pk=None, **kwargs):
plan = self.get_object()
application = get_application(self.request)
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
event_saver: EventSaver = EventSaver.objects.filter(event_label=serializer.validated_data['label']).first()
# TODO
# try:
event = event_saver.save_event(user=user_uuid, application=application, **serializer.validated_data)
# except Exception as e:
# raise exceptions.ValidationError(str(e))
result_list = plan.process_event(event)
data["promotions"] = result_list
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def get_success_headers(self, data):
try:
return {'Location': str(data[api_settings.URL_FIELD_NAME])}
except (TypeError, KeyError):
return {}
class ApplicationEventViewSet(
mixins.CreateModelMixin,
GenericViewSet
):
serializer_class = EventSerializer
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"POST": [["promotions.application.event:submit"]],
}
def perform_create(self, serializer: EventSerializer):
if hasattr(self.request, 'user'):
user = self.request.user
else:
user = None
application = get_application(self.request)
# EventSaver.objects.first(event_label=serializer.validated_data['event_label'], valid_application__contains=application.uuid)
event_saver: EventSaver = EventSaver.objects.filter(event_label=serializer.validated_data['label']).first()
try:
event = event_saver.save_event(user=user, application=application, **serializer.validated_data)
except Exception as e:
raise exceptions.ValidationError(str(e))
analyze_event_task.delay(event.uuid)
serializer.instance = event
class ApplicationPlanViewSet(
GenericViewSet
):
serializer_class = PlanSerializer
permission_classes = [TokenMatchesViewSetActions]
required_action_scopes = {
"retrieve": [["promotions.application.plan:list-retrieve"]],
"list": [["promotions.application.plan:list-retrieve"]],
}
def get_queryset(self):
application = get_application(self.request)
# return Promotion.objects.filter(application=application)
return Plan.objects.all()
# NOT
class UserPlanViewSet(mixins.RetrieveModelMixin,
# mixins.ListModelMixin,
# mixins.CreateModelMixin,
GenericViewSet):
serializer_class = UserPlanSerializer
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
# required_alternate_scopes = {
# "GET": [["promotions.user.plans:list-retrieve"]],
# "POST": [["promotions.user.plans:list-retrieve"]],
# }
required_alternate_scopes = {
"GET": [[]],
"POST": [[]],
}
def get_queryset(self):
user = self.request.user
application = get_application(self.request)
queryset = Plan.objects.all()
return queryset
# @extend_schema(responses=PlanSerializer(many=True))
# @action(detail=False, methods=['POST'], serializer_class=PlanSerializer)
# def available(self, request):
# serializer = self.get_serializer(data=self.request.data)
# serializer.is_valid(raise_exception=True)
# print(serializer.validated_data)
# plans = self.paginate_queryset(self.filter_queryset(self.get_queryset()))
# for plan in plans:
# plan.calculate_promotion(**serializer.validated_data)
# serializer = self.get_serializer(plans, many=True)
# return self.get_paginated_response(serializer.data)
class ApplicationPromoteUserApiView(CreateAPIView):
model = Promotion
serializer_class = PromoteSerializer
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"POST": [[]],
}
def get_plan(self):
plan_uuid = self.kwargs.get('plan')
plan = get_object_or_404(Plan, uuid=plan_uuid)
return plan
def create(self, request, *args, **kwargs):
plan = self.get_plan()
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
application = get_application(self.request)
event_saver: EventSaver = EventSaver.objects.filter(event_label=serializer.validated_data['label']).first()
user = self.request.user.pk or serializer.validated_data['user']
# try:
event = event_saver.save_event(user=user, application=application, **serializer.validated_data)
# except Exception as e:
# raise exceptions.ValidationError(str(e))
result_list = list(plan.process_event(event))
# data["promotions"] = list(result_list)
serializer = self.get_serializer(instance=plan)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
class ApplicationPromotionListApiView(ListAPIView):
model = Promotion
serializer_class = PromotionSerializer
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"GET": [[]],
}
def get_plan(self):
plan_uuid = self.kwargs.get('plan')
plan = get_object_or_404(Plan, uuid=plan_uuid)
return plan
def get_queryset(self):
user = self.request.user
plan = self.get_plan()
qs = Promotion.objects.filter(user_uuid=user.uuid, plan=plan)
return qs
# def create(self, request, *args, **kwargs):
# plan = self.get_plan()
# serializer = self.get_serializer(data=request.data)
# serializer.is_valid(raise_exception=True)
# data = serializer.validated_data
# application = get_application(self.request)
# event_saver: EventSaver = EventSaver.objects.filter(event_label=serializer.validated_data['label']).first()
# # try:
# event = event_saver.save_event(user=None, application=application, **serializer.validated_data)
# # except Exception as e:
# # raise exceptions.ValidationError(str(e))
#
# result_list = plan.process_event(event)
# data["promotions"] = result_list
#
# headers = self.get_success_headers(serializer.data)
# return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
class ApplicationEventSubmitAPIView(CreateAPIView):
model = Promotion
serializer_class = PromoteSerializer
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"POST": [[]],
}
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
application = get_application(self.request)
event_saver: EventSaver = EventSaver.objects.filter(event_label=serializer.validated_data['label']).first()
user = self.request.user.pk or serializer.validated_data['user']
try:
event = event_saver.save_event(user=user, application=application, **serializer.validated_data)
except Exception as e:
raise UnprocessableEntity(str(e))
analyze_event_task.delay(event.uuid)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
# class ApplicationEventRetrieveAPIView(RetrieveAPIView):
# model = Promotion
# serializer_class = PromoteSerializer
#
# def create(self, request, *args, **kwargs):
# serializer = self.get_serializer(data=request.data)
# serializer.is_valid(raise_exception=True)
# data = serializer.validated_data
# application = get_application(self.request)
# event_saver: EventSaver = EventSaver.objects.filter(event_label=serializer.validated_data['label']).first()
# event = event_saver.save_event(user=None, application=application, **serializer.validated_data)
#
# analyze_event_task.delay(event.uuid)
#
# headers = self.get_success_headers(serializer.data)
# return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
#