def submit_answer(self, answer_data, requested_user):
     session = Session.objects.first()
     if (timezone.now() < session.start_time):
         raise ArkavAPIException(
             detail='This session has not been started.',
             code='is_not_started',
             status_code=status.HTTP_400_BAD_REQUEST,
         )
     if (timezone.now() > session.end_time):
         raise ArkavAPIException(
             detail='This session has been ended.',
             code='is_ended',
             status_code=status.HTTP_400_BAD_REQUEST,
         )
     sub, state = Submission.objects.get_or_create(user=requested_user)
     qt = answer_data['question']
     if (len(answer_data['tag']) == 1):
         choice = get_object_or_404(Choice.objects.all(),
                                    question=qt,
                                    tag=(answer_data['tag']))
         answer, state = Answer.objects.update_or_create(
             submission=sub, question=qt, defaults={"choice": choice})
     elif (Answer.objects.filter(submission=sub, question=qt).exists()):
         Answer.objects.filter(submission=sub, question=qt).delete()
     sub.save()  # Untuk update waktu terakhir kali ngerjain (end_time)
     return sub
    def create_registrant(self, registrant_data, user):
        mainevent = registrant_data['mainevent_id']

        # Only register if registration is open for this mainevent
        if not mainevent.is_registration_open:
            raise ArkavAPIException(
                detail=
                'The event you are trying to register to is not open for registration.',
                code='mainevent_registration_closed',
                status_code=status.HTTP_400_BAD_REQUEST,
            )

        # A user can't register in a mainevent if he/she already participated in the same mainevent
        if Registrant.objects.filter(mainevent=mainevent, user=user).exists():
            raise ArkavAPIException(
                detail=
                'One user can only participate in one registrant per main event.',
                code='mainevent_already_registered',
                status_code=status.HTTP_400_BAD_REQUEST,
            )

        try:
            # Create a new registrant led by the current user
            new_registrant = Registrant.objects.create(
                mainevent=mainevent,
                user=user,
            )
        except ValueError as e:
            raise ArkavAPIException(
                detail=str(e),
                code='create_registrant_fail',
                status_code=status.HTTP_400_BAD_REQUEST,
            )

        return new_registrant
    def create_registrant(self, registrant_data, user):
        preevent = registrant_data['preevent_id']

        # Only register if registration is open for this preevent
        if not preevent.is_registration_open:
            raise ArkavAPIException(
                detail='The preevent you are trying to register to is not open for registration.',
                code='preevent_registration_closed',
                status_code=status.HTTP_400_BAD_REQUEST,
            )

        # A user can't register to a preevent more than once
        if Registrant.objects.filter(preevent=preevent, user=user).exists():
            raise ArkavAPIException(
                detail='User already registered',
                code='preevent_already_registered',
                status_code=status.HTTP_400_BAD_REQUEST,
            )

        try:
            new_registrant = Registrant.objects.create(
                preevent=preevent,
                user=user,
            )

        except ValueError as e:
            raise ArkavAPIException(
                detail=str(e),
                code='create_registrant_fail',
                status_code=status.HTTP_400_BAD_REQUEST,
            )

        return new_registrant
 def get(self, request, *args, **kwargs):
     try:
         # If the password is passed on url param, we check for which event has the password
         # This enable specific token for specific event, because token for each event may duplicated
         # Example use case, "wild token" that can be used to enter multiple mainevent
         password = request.GET.get('password', None)
         attendance = None
         if password is None:
             attendance = CheckInAttendance.objects.filter(
                 token=self.kwargs['token']).first()
         else:
             attendance = CheckInAttendance.objects.filter(
                 token=self.kwargs['token'],
                 event__password=password).first()
         if attendance is None:
             raise ArkavAPIException(
                 detail='Attendance token does not exist',
                 code='wrong_token',
                 status_code=status.HTTP_404_NOT_FOUND,
             )
         response_serializer = CheckInResponseSerializer(attendance)
         return Response(data=response_serializer.data,
                         status=status.HTTP_200_OK)
     except ArkavAPIException as e:
         return e.as_response()
 def get_session(self, session_id, requested_user):
     session = get_object_or_404(Session.objects.all(), id=session_id)
     if (timezone.now() < session.start_time):
         raise ArkavAPIException(
             detail='This session has not been started.',
             code='is_not_started',
             status_code=status.HTTP_400_BAD_REQUEST,
         )
     if (timezone.now() > session.end_time):
         raise ArkavAPIException(
             detail='This session has been ended.',
             code='is_ended',
             status_code=status.HTTP_400_BAD_REQUEST,
         )
     Submission.objects.update_or_create(user=requested_user)
     return session
    def create_team(self, team_data, user):
        competition = team_data['competition_id']
        team_name = team_data['name']
        team_institution = team_data['institution']

        # Only register if registration is open for this competition
        if not competition.is_registration_open:
            raise ArkavAPIException(
                detail=K_COMPETITION_REGISTRATION_CLOSED_DETAIL,
                code=K_COMPETITION_REGISTRATION_CLOSED,
                status_code=status.HTTP_400_BAD_REQUEST,
            )

        # A user can't register in a competition if he/she already participated in the same competition
        if TeamMember.objects.filter(team__competition=competition,
                                     user=user).exists():
            raise ArkavAPIException(
                detail=K_COMPETITION_ALREADY_REGISTERED_DETAIL,
                code=K_COMPETITION_ALREADY_REGISTERED,
                status_code=status.HTTP_400_BAD_REQUEST,
            )

        try:
            # Create a new team led by the current user
            new_team = Team.objects.create(
                competition=competition,
                name=team_name,
                institution=team_institution,
                team_leader=user,
            )

            # Add the current user as team member
            TeamMember.objects.create(
                team=new_team,
                user=user,
                invitation_full_name=user.full_name,
                invitation_email=user.email,
            )
        except ValueError as e:
            raise ArkavAPIException(
                detail=str(e),
                code='create_team_fail',
                status_code=status.HTTP_400_BAD_REQUEST,
            )

        return new_team
    def checkin(self, token, password=''):
        attendance = CheckInAttendance.objects.filter(token=token, event__password=password).first()
        if attendance is None:
            raise ArkavAPIException(
                detail='Attendance token does not exist or wrong password',
                code='wrong_token_or_password',
                status_code=status.HTTP_404_NOT_FOUND,
            )

        if attendance.is_fully_checked_in:
            raise ArkavAPIException(
                detail='Attendee can only check in once',
                code='attendee_already_checkin',
                status_code=status.HTTP_400_BAD_REQUEST,
            )

        attendance.pax_checked_in += 1
        attendance.save()
        return attendance
    def validate(self, attrs):
        try:
            data = super().validate(attrs)
            refresh = self.get_token(self.user)
            data['token'] = str(refresh.access_token)
        except exceptions.AuthenticationFailed:
            raise ArkavAPIException(
                detail='Wrong email / password',
                code=K_LOGIN_FAILED,
                status_code=status.HTTP_401_UNAUTHORIZED,
            )

        if (not self.user.is_email_confirmed):
            raise ArkavAPIException(
                detail='User email is not confirmed',
                code=K_ACCOUNT_EMAIL_NOT_CONFIRMED,
                status_code=status.HTTP_401_UNAUTHORIZED,
            )

        data['user'] = UserSerializer(self.user).data
        data['exp'] = refresh.payload['exp']

        return data
 def post(self, request, format=None, *args, **kwargs):
     request_serializer = RegisterRegistrantRequestSerializer(data=request.data)
     try:
         request_serializer.is_valid(raise_exception=True)
         if request.user.has_completed_profile:
             new_registrant = RegistrantService().create_registrant(request_serializer.validated_data, request.user)
             response_serializer = RegistrantSerializer(new_registrant)
             return Response(data=response_serializer.data)
         else:
             raise ArkavAPIException(
                 detail='User profile details are incomplete.',
                 code=K_PROFILE_INCOMPLETE,
                 status_code=status.HTTP_400_BAD_REQUEST,
             )
     except ArkavAPIException as e:
         return e.as_response()
    def submit_task_response(self, task_response_data, registrant_id, task_id, user):
        # Only registrant members can submit a response
        registrant = get_object_or_404(
            Registrant.objects.all(),
            id=registrant_id,
            user=user,
        )

        if not registrant.is_participating:
            raise ArkavAPIException(
                detail='Your registrant is no longer participating in this preevent.',
                code='registrant_not_participating',
                status_code=status.HTTP_400_BAD_REQUEST,
            )

        # A registrant can only respond to tasks in the currently active stage
        task = get_object_or_404(
            Task.objects.all(),
            id=task_id,
            stage=registrant.active_stage,
        )

        response = task_response_data['response']

        # Create or update this TaskResponse, setting its status to awaiting_validation or completed
        # according to the whether this task requires validation,
        # and also updating its last_submitted_at.
        if task.requires_validation:
            task_response_status = TaskResponse.AWAITING_VALIDATION
        else:
            task_response_status = TaskResponse.COMPLETED

        new_task_response, created = TaskResponse.objects.update_or_create(
            task=task,
            registrant=registrant,
            defaults={
                'response': response,
                'status': task_response_status,
                'last_submitted_at': timezone.now(),
            },
        )

        return new_task_response
    def submit_task_response(self, task_response_data, team_id, task_id, user):
        # Only team members can submit a response
        team = get_object_or_404(
            Team.objects.all(),
            id=team_id,
            team_members__user=user,
        )
        team_member = get_object_or_404(
            TeamMember.objects.all(),
            team_id=team_id,
            user=user,
        )

        if not team.is_participating:
            raise ArkavAPIException(
                detail=K_TEAM_NOT_PARTICIPATING_DETAIL,
                code=K_TEAM_NOT_PARTICIPATING,
                status_code=status.HTTP_400_BAD_REQUEST,
            )

        # A team can only respond to tasks in the currently active stage
        task = get_object_or_404(
            Task.objects.all(),
            id=task_id,
            stage=team.active_stage,
        )

        response = task_response_data['response']

        # Create or update this TaskResponse, setting its status to awaiting_validation or completed
        # according to the whether this task requires validation,
        # and also updating its last_submitted_at.
        if task.requires_validation:
            task_response_status = AbstractTaskResponse.AWAITING_VALIDATION
        else:
            task_response_status = AbstractTaskResponse.COMPLETED

        new_task_response = None
        if task.is_user_task:
            task_team_member = task_response_data.get('team_member',
                                                      team_member)
            new_task_response, created = UserTaskResponse.objects.update_or_create(
                task=task,
                team=team,
                team_member=task_team_member,
                defaults={
                    'response': response,
                    'status': task_response_status,
                    'last_submitted_at': timezone.now(),
                },
            )
        else:
            new_task_response, created = TaskResponse.objects.update_or_create(
                task=task,
                team=team,
                defaults={
                    'response': response,
                    'status': task_response_status,
                    'last_submitted_at': timezone.now(),
                },
            )

        return new_task_response
    def create_team_member(self, team_member_data, team_id, user):
        full_name = team_member_data['full_name']
        email = team_member_data['email'].lower()

        team = get_object_or_404(
            Team.objects.all(),
            id=team_id,
            team_members__user=user,
        )

        # Check whether registration is open for this competition
        if not team.competition.is_registration_open:
            raise ArkavAPIException(
                detail=K_COMPETITION_REGISTRATION_CLOSED_DETAIL,
                code=K_COMPETITION_REGISTRATION_CLOSED,
                status_code=status.HTTP_400_BAD_REQUEST,
            )

        # Check whether team is still participating in the competition
        if not team.is_participating:
            raise ArkavAPIException(
                detail=K_TEAM_NOT_PARTICIPATING_DETAIL,
                code=K_TEAM_NOT_PARTICIPATING,
                status_code=status.HTTP_400_BAD_REQUEST,
            )

        # Check whether this team is full
        if team.team_members.count() >= team.competition.max_team_members:
            raise ArkavAPIException(
                detail=K_TEAM_FULL_DETAIL,
                code=K_TEAM_FULL,
                status_code=status.HTTP_400_BAD_REQUEST,
            )

        try:
            member_user = User.objects.get(email=email)
            if team.team_members.filter(user=member_user).exists():
                raise ArkavAPIException(
                    detail=K_TEAM_HAS_SELECTED_MEMBER_DETAIL,
                    code=K_TEAM_HAS_SELECTED_MEMBER,
                    status_code=status.HTTP_400_BAD_REQUEST,
                )
            if member_user.teams.filter(competition=team.competition).exists():
                raise ArkavAPIException(
                    detail=K_COMPETITION_ALREADY_REGISTERED_DETAIL,
                    code=K_COMPETITION_ALREADY_REGISTERED,
                    status_code=status.HTTP_400_BAD_REQUEST,
                )
            # The user specified by the email is present, directly add to team
            new_team_member = TeamMember.objects.create(
                team=team,
                user=member_user,
                invitation_full_name=member_user.full_name,
                invitation_email=member_user.email,
            )
        except User.DoesNotExist:
            # The user specified by the email is not present, send invitation
            new_team_member = TeamMember.objects.create(
                team=team,
                invitation_full_name=full_name,
                invitation_email=email,
            )

        self.send_invitation_email(new_team_member)
        return new_team_member