svthalia/concrexit

View on GitHub
website/sales/api/v2/views.py

Summary

Maintainability
C
1 day
Test Coverage
from django.db.models import Q

from oauth2_provider.contrib.rest_framework import IsAuthenticatedOrTokenHasScope
from rest_framework.exceptions import PermissionDenied
from rest_framework.generics import GenericAPIView
from rest_framework.permissions import DjangoModelPermissionsOrAnonReadOnly
from rest_framework.response import Response
from rest_framework.schemas.openapi import AutoSchema

from sales import services
from sales.api.v2.admin.serializers.order import OrderListSerializer
from sales.api.v2.admin.views import (
    OrderDetailView,
    OrderListView,
    ShiftDetailView,
    ShiftListView,
)
from sales.api.v2.serializers.user_order import UserOrderSerializer
from sales.api.v2.serializers.user_shift import UserShiftSerializer
from sales.models.order import Order
from sales.models.shift import Shift
from thaliawebsite.api.v2.permissions import IsAuthenticatedOrTokenHasScopeForMethod


class UserShiftListView(ShiftListView):
    serializer_class = UserShiftSerializer
    # queryset = SelfOrderPeriod.objects.all()
    permission_classes = [
        IsAuthenticatedOrTokenHasScope,
        DjangoModelPermissionsOrAnonReadOnly,
    ]
    required_scopes = ["sales:read"]


class UserShiftDetailView(ShiftDetailView):
    serializer_class = UserShiftSerializer
    # queryset = SelfOrderPeriod.objects.all()
    permission_classes = [
        IsAuthenticatedOrTokenHasScope,
        DjangoModelPermissionsOrAnonReadOnly,
    ]
    required_scopes = ["sales:read"]


class UserOrderListView(OrderListView):
    permission_classes = [
        IsAuthenticatedOrTokenHasScopeForMethod,
    ]
    required_scopes_per_method = {
        "GET": ["sales:read"],
        "POST": ["sales:order"],
    }
    method_serializer_classes = {
        ("GET",): OrderListSerializer,
        ("POST",): UserOrderSerializer,
    }

    def create(self, request, *args, **kwargs):
        shift = Shift.objects.get(pk=kwargs["pk"])
        if not shift.user_orders_allowed:
            raise PermissionDenied
        return super().create(request, *args, **kwargs)

    def perform_create(self, serializer):
        serializer.save(
            payer_id=self.request.member.pk, created_by_id=self.request.member.pk
        )

    def get_queryset(self):
        queryset = super().get_queryset()
        return queryset.filter(
            Q(payer=self.request.member) | Q(created_by=self.request.member)
        )


class UserOrderDetailView(OrderDetailView):
    serializer_class = UserOrderSerializer
    permission_classes = [
        IsAuthenticatedOrTokenHasScopeForMethod,
    ]
    required_scopes_per_method = {
        "GET": ["sales:read"],
        "PATCH": ["sales:order"],
        "PUT": ["sales:order"],
        "DELETE": ["sales:order"],
    }

    def get_queryset(self):
        queryset = super().get_queryset()
        return queryset.filter(
            Q(payer=self.request.member) | Q(created_by=self.request.member)
        )

    def update(self, request, *args, **kwargs):
        if not self.get_object().shift.user_orders_allowed:
            raise PermissionDenied
        if self.get_object().payment:
            raise PermissionDenied
        return super().update(request, *args, **kwargs)

    def partial_update(self, request, *args, **kwargs):
        if not self.get_object().shift.user_orders_allowed:
            raise PermissionDenied
        if self.get_object().payment:
            raise PermissionDenied
        return super().partial_update(request, *args, **kwargs)

    def destroy(self, request, *args, **kwargs):
        if not self.get_object().shift.user_orders_allowed:
            raise PermissionDenied
        if self.get_object().payment:
            raise PermissionDenied


class OrderClaimView(GenericAPIView):
    """Claims an order to be paid by the current user."""

    class OrderClaimViewSchema(AutoSchema):
        def get_request_serializer(self, path, method):
            # This endpoint does not expect any content in the request body.
            return None

    queryset = Order.objects.all()
    serializer_class = UserOrderSerializer
    schema = OrderClaimViewSchema(operation_id_base="claimOrder")
    permission_classes = [IsAuthenticatedOrTokenHasScope]
    required_scopes = ["sales:order"]

    def patch(self, request, *args, **kwargs):
        if request.member is None:
            raise PermissionDenied(
                detail="You need to be a member to pay for an order."
            )

        order = self.get_object()
        if order.payment:
            raise PermissionDenied(detail="This order was already paid for.")

        if order.payer is not None and order.payer != request.member:
            raise PermissionDenied(detail="This order is not yours.")

        order.payer = request.member
        order.save()

        if order.age_restricted and not services.is_adult(request.member):
            raise PermissionDenied(
                "The age restrictions on this order do not allow you to pay for this order."
            )

        serializer = self.get_serializer(order)
        return Response(serializer.data)