Coverage for events/views/checkin.py: 23%
75 statements
« prev ^ index » next coverage.py v6.4.4, created at 2022-11-02 14:35 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2022-11-02 14:35 -0600
1import datetime
2from rest_framework.decorators import action
3from rest_framework.exceptions import ValidationError
4from rest_framework.mixins import ListModelMixin as List
5from rest_framework.response import Response
6from rest_framework.viewsets import GenericViewSet
7from app.pusher import PusherClient
8from app.settings.base import FRONTEND_DOMAIN
9from app.twilio import TwilioClient
10from app.utils import get_image_from_data_url
11from ..models import StationCheckIn, Participant
12from ..serializers import MakeCheckInSerializer
15class CheckInViewSet(GenericViewSet, List):
16 def get_queryset(self):
17 return StationCheckIn.objects.filter(team__members__user=self.request.user)
19 def partial_update(self, request, *args, **kwargs):
20 checkin_instance = self.get_object()
21 station = checkin_instance.station
23 if station.challenge.status != station.challenge.Status.CURRENT:
24 raise ValidationError("Challenge not active")
25 if checkin_instance.has_checkin:
26 raise ValidationError("Already Scanned QR")
27 if station.type_of != station.StationCheckInType.MEDIA:
28 raise ValidationError("This checkin is not allowed")
30 participant = Participant.objects.get(
31 user=request.user, event=station.challenge.event
32 )
34 file = request.data.get("checkin_media")
35 if request.data.get("base64") == "true":
36 file = get_image_from_data_url(file)
37 data = {"checkin_media": file, "participant": participant.random_slug}
39 serializer = MakeCheckInSerializer(checkin_instance, data, partial=True)
40 serializer.is_valid(True)
41 checkin_instance = serializer.save()
43 mcs = station.challenge.event.participants.filter(is_master_of_ceremony=True)
44 twilio = TwilioClient()
45 approve_url = f"{FRONTEND_DOMAIN}/challenges/{station.challenge.random_slug}"
46 for member in mcs:
47 if member.user.phone is not None:
48 twilio.send_message(
49 body=f"{checkin_instance.team.name} just checked in on {station.name}. APPROVAL NEEDED. "
50 f"Go to: {approve_url}",
51 to=member.user.phone.as_e164,
52 )
54 pusher = PusherClient()
55 pusher.update_challenge_detail(station.challenge)
56 pusher.update_event_detail(station.challenge.event)
58 data = {
59 "success": True,
60 "station": checkin_instance.station.name,
61 "random_slug": checkin_instance.random_slug,
62 "datetime": checkin_instance.checkin_timestamp.strftime(
63 "%b %d, %Y at %H:%M"
64 ),
65 }
67 return Response(data)
69 @action(methods=["POST"], detail=True)
70 def approve(self, request, pk):
71 checkin = StationCheckIn.objects.get(random_slug=pk)
72 participant = self._validate_approval(checkin)
74 checkin.is_approved = True
75 checkin.approve_timestamp = datetime.datetime.now()
76 checkin.approved_by = participant
77 checkin.save()
79 return Response()
81 @action(methods=["POST"], detail=True)
82 def reject(self, request, pk):
83 checkin = StationCheckIn.objects.get(random_slug=pk)
84 self._validate_approval(checkin)
86 checkin.participant = None
87 checkin.has_checkin = False
88 checkin.checkin_timestamp = None
89 checkin.checkin_media = None
90 checkin.save()
92 members = checkin.team.members.all()
93 twilio = TwilioClient()
94 challenge_url = f"{FRONTEND_DOMAIN}/challenges/{checkin.station.challenge.random_slug}"
95 for member in members:
96 if member.user.phone is not None:
97 twilio.send_message(
98 body=f"Your checkin for {checkin.station.name} is rejected, please checkin again on {challenge_url} or call the Master of Ceremonies",
99 to=member.user.phone.as_e164,
100 )
102 return Response()
104 def _validate_approval(self, checkin):
105 if not checkin.has_checkin:
106 raise ValidationError("Invalid CheckIn")
107 try:
108 return Participant.objects.get(
109 user=self.request.user,
110 event=checkin.station.challenge.event,
111 is_master_of_ceremony=True,
112 )
113 except Participant.DoesNotExist:
114 raise ValidationError("You can't approve this CheckIn")