Skip to content

Commit

Permalink
Merge pull request #14 from mohamad-liyaghi/vendor-orders
Browse files Browse the repository at this point in the history
Vendor Orders
  • Loading branch information
mohamad-liyaghi authored Aug 8, 2024
2 parents 1ef831d + 40ce0ea commit 8d4480c
Show file tree
Hide file tree
Showing 7 changed files with 230 additions and 2 deletions.
44 changes: 44 additions & 0 deletions apps/orders/tests/test_views/test_customer/test_set_delievered.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import pytest
from django.urls import reverse
from rest_framework import status
from orders.enums import OrderStatus


@pytest.mark.django_db
class TestOrderDeliverView:
@pytest.fixture(autouse=True)
def setup_method(self, user, api_client, shipped_order):
self.url = reverse("orders:customer-delivered", kwargs={"uuid": shipped_order.uuid})
self.client = api_client
self.user = user
self.order = shipped_order
self.data = {}

def test_set_delivered_unauthorized_fails(self):
response = self.client.post(self.url, self.data)
assert response.status_code == status.HTTP_403_FORBIDDEN

def test_set_delivered_by_another_user_fails(self, another_user):
self.client.force_authenticate(another_user)
response = self.client.post(self.url, self.data)
assert response.status_code == status.HTTP_404_NOT_FOUND

def test_set_delivered_for_paid_order_fails(self, processing_order):
self.client.force_authenticate(self.user)
response = self.client.post(
reverse(
"orders:customer-delivered",
kwargs={"uuid": processing_order.uuid},
),
self.data,
)
assert response.status_code == status.HTTP_404_NOT_FOUND

def test_update_with_valid_data_succeeds(self):
self.client.force_authenticate(self.user)
response = self.client.post(self.url, self.data)
assert response.status_code == status.HTTP_200_OK
self.order.refresh_from_db()
assert self.order.status == OrderStatus.DELIVERED
self.order.status = OrderStatus.SHIPPED
self.order.save()
Empty file.
21 changes: 21 additions & 0 deletions apps/orders/tests/test_views/test_vendor/test_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import pytest
from django.urls import reverse
from rest_framework import status


@pytest.mark.django_db
class TestOrderListView:
@pytest.fixture(autouse=True)
def setup(self, api_client, user):
self.url = reverse("orders:vendor-list")
self.client = api_client
self.user = user

def test_get_unauthorized_fails(self):
response = self.client.get(self.url)
assert response.status_code == status.HTTP_403_FORBIDDEN

def test_get_by_user_succeeds(self):
self.client.force_authenticate(self.user)
response = self.client.get(self.url)
assert response.status_code == status.HTTP_200_OK
41 changes: 41 additions & 0 deletions apps/orders/tests/test_views/test_vendor/test_ship.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import pytest
from django.urls import reverse
from rest_framework import status
from orders.enums import OrderStatus


@pytest.mark.django_db
class TestOrderShipView:
@pytest.fixture(autouse=True)
def setup_method(self, user, api_client, processing_order):
self.url = reverse("orders:vendor-shipped", kwargs={"uuid": processing_order.uuid})
self.client = api_client
self.user = processing_order.restaurant.owner
self.order = processing_order
self.data = {}

def test_ship_unauthorized_fails(self):
response = self.client.post(self.url, self.data)
assert response.status_code == status.HTTP_403_FORBIDDEN

def test_ship_by_another_user_fails(self, another_user):
self.client.force_authenticate(another_user)
response = self.client.post(self.url, self.data)
assert response.status_code == status.HTTP_404_NOT_FOUND

def test_ship_for_paid_order_fails(self, shipped_order):
self.client.force_authenticate(self.user)
response = self.client.post(
reverse("orders:vendor-shipped", kwargs={"uuid": shipped_order.uuid}),
self.data,
)
assert response.status_code == status.HTTP_404_NOT_FOUND

def test_update_with_valid_data_succeeds(self):
self.client.force_authenticate(self.user)
response = self.client.post(self.url, self.data)
assert response.status_code == status.HTTP_200_OK
self.order.refresh_from_db()
assert self.order.status == OrderStatus.SHIPPED
self.order.status = OrderStatus.PROCESSING
self.order.save()
22 changes: 20 additions & 2 deletions apps/orders/urls.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
from django.urls import path, include
from orders.views.customer import OrderListCreateView, OrderPayView, OrderCancelView
from orders.views.customer import (
OrderListCreateView,
OrderPayView,
OrderCancelView,
OrderDeliveredView,
)
from orders.views.vendor import VendorOrderListView, VendorOrderSetShippedView

app_name = "orders"

VENDOR_URLS = []
VENDOR_URLS = [
path("", VendorOrderListView.as_view(), name="vendor-list"),
path(
"<uuid:uuid>/shipped/",
VendorOrderSetShippedView.as_view(),
name="vendor-shipped",
),
]
CUSTOMER_URLS = [
path("", OrderListCreateView.as_view(), name="customer-list-create"),
path("<uuid:uuid>/pay/", OrderPayView.as_view(), name="customer-pay"),
path("<uuid:uuid>/cancel/", OrderCancelView.as_view(), name="customer-cancel"),
path(
"<uuid:uuid>/delivered/",
OrderDeliveredView.as_view(),
name="customer-delivered",
),
]

urlpatterns = [
Expand Down
32 changes: 32 additions & 0 deletions apps/orders/views/customer.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,37 @@ def post(self, request, *args, **kwargs):
return Response({"error": "Insufficient balance"}, status=status.HTTP_400_BAD_REQUEST)


@extend_schema_view(
post=extend_schema(
summary="Set As Delivered",
description="Set an order as delivered",
responses={
200: OrderSerializer(),
400: OpenApiResponse(description="Bad Request"),
403: OpenApiResponse(description="Unauthorized"),
404: OpenApiResponse(description="Not Found"),
},
tags=["Customer Orders"],
),
)
class OrderDeliveredView(APIView):
permission_classes = (IsAuthenticated,)

def get_object(self):
return get_object_or_404(
Order,
uuid=self.kwargs["uuid"],
user=self.request.user,
status=OrderStatus.SHIPPED,
)

def post(self, request, *args, **kwargs):
order = self.get_object()
order.status = OrderStatus.DELIVERED
order.save()
return Response({"message": "Order is being processed"}, status=status.HTTP_200_OK)


@extend_schema_view(
delete=extend_schema(
summary="Cancel an order",
Expand All @@ -92,6 +123,7 @@ def post(self, request, *args, **kwargs):
204: OpenApiResponse(description="Cancelled"),
400: OpenApiResponse(description="Bad Request"),
403: OpenApiResponse(description="Unauthorized"),
404: OpenApiResponse(description="Not Found"),
},
tags=["Customer Orders"],
),
Expand Down
72 changes: 72 additions & 0 deletions apps/orders/views/vendor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from django.shortcuts import get_object_or_404
from rest_framework.generics import ListAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from drf_spectacular.utils import extend_schema_view, OpenApiResponse, extend_schema
from restaurants.models import Restaurant
from orders.models import Order
from orders.enums import OrderStatus
from orders.serializers import OrderSerializer


@extend_schema_view(
get=extend_schema(
summary="List Of Customer Orders",
description="List of all orders placed by the customer",
responses={
200: OrderSerializer(many=True),
403: OpenApiResponse(description="Unauthorized"),
},
tags=["Vendor Orders"],
),
)
class VendorOrderListView(ListAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = OrderSerializer

def get_queryset(self):
restaurant = Restaurant.objects.filter(owner=self.request.user, is_soft_deleted=False)

if not restaurant.exists():
return Order.objects.none()

return (
Order.objects.select_related("restaurant", "user")
.prefetch_related("items", "items__product")
.filter(restaurant__in=restaurant, status=OrderStatus.PENDING_PAYMENT)
.order_by("-created_at")
)


@extend_schema_view(
post=extend_schema(
summary="Set Order As Shipped",
description="Set the order as shipped",
responses={
200: OrderSerializer(),
400: OpenApiResponse(description="Bad Request"),
403: OpenApiResponse(description="Unauthorized"),
404: OpenApiResponse(description="Not Found"),
},
tags=["Customer Orders"],
),
)
class VendorOrderSetShippedView(APIView):
permission_classes = (IsAuthenticated,)

def get_object(self):
return get_object_or_404(
Order,
uuid=self.kwargs["uuid"],
restaurant__owner=self.request.user,
status=OrderStatus.PROCESSING,
)

def post(self, request, *args, **kwargs):
order = self.get_object()

order.status = OrderStatus.SHIPPED
order.save()
return Response({"message": "Order has been shipped"}, status=status.HTTP_200_OK)

0 comments on commit 8d4480c

Please sign in to comment.