Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Доставка #173

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/core/management/commands/load_test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def create_deliveries(self, number_max):

for order, address, delivery_method in zip(orders, addresses, delivery_methods):
DeliveryFactory.create_batch(
number_max, order=order, address=address, delivery_method=delivery_method
1, order=order, address=address, delivery_method=delivery_method
)

def handle(self, *args, **options):
Expand All @@ -71,6 +71,7 @@ def handle(self, *args, **options):
self.create_users(number_max)
self.create_products(number_max)
self.create_baskets_and_orders(number_min)
self.create_deliveries(number_max)

self.stdout.write(self.style.SUCCESS(_("Test data created successfully!")))
except Exception as exp:
Expand Down
24 changes: 24 additions & 0 deletions apps/deliveries/migrations/0002_alter_delivery_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 4.1 on 2023-10-05 05:17

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("orders", "0006_remove_orderproduct_discount_orderproduct_price_and_more"),
("deliveries", "0001_initial"),
]

operations = [
migrations.AlterField(
model_name="delivery",
name="order",
field=models.OneToOneField(
on_delete=django.db.models.deletion.DO_NOTHING,
related_name="delivery_order",
to="orders.order",
verbose_name="Delivery order",
),
),
]
7 changes: 5 additions & 2 deletions apps/deliveries/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def __str__(self):


class Delivery(models.Model):
order = models.ForeignKey(
order = models.OneToOneField(
Order,
on_delete=models.DO_NOTHING,
related_name="delivery_order",
Expand All @@ -53,4 +53,7 @@ class Meta:
indexes = [models.Index(fields=("order",))]

def __str__(self):
return f"Delivery {self.delivery_method} of the {self.order} to the {self.address}"
return (
f"Delivery {self.delivery_method} of the {self.order} to the {self.address} "
f"{self.delivery_date}"
)
34 changes: 34 additions & 0 deletions apps/deliveries/serializers/deliveries.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from rest_framework import serializers

from apps.deliveries.models import Delivery, DeliveryMethod
from apps.deliveries.serializers.deliverymethods import DeliveryMethodReadSerializer
from apps.users.models import Address
from apps.users.serializers.addresses import AddressSerializer


class DeliveryReadSerializer(serializers.ModelSerializer):
"""Отображение доставок."""

address = AddressSerializer()
delivery_method = DeliveryMethodReadSerializer()

class Meta:
model = Delivery
fields = ("id", "address", "delivery_method", "delivery_date")


class DeliveryWriteSerializer(serializers.ModelSerializer):
"""Оформление доставки."""

address = serializers.CharField()
delivery_method = serializers.PrimaryKeyRelatedField(queryset=DeliveryMethod.objects.all())

class Meta:
model = Delivery
fields = ("address", "delivery_method", "delivery_date")

def validate(self, attrs):
address_data = attrs["address"]
address, _created = Address.objects.get_or_create(address=address_data)
attrs["address"] = address
return attrs
11 changes: 11 additions & 0 deletions apps/deliveries/serializers/deliverymethods.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from rest_framework import serializers

from apps.deliveries.models import DeliveryMethod


class DeliveryMethodReadSerializer(serializers.ModelSerializer):
"""Методы доставки."""

class Meta:
model = DeliveryMethod
fields = ("id", "name", "description", "slug", "price")
9 changes: 9 additions & 0 deletions apps/deliveries/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.urls import include, path
from rest_framework import routers

from apps.deliveries.views import DeliveryMethodViewSet

router = routers.SimpleRouter()
router.register("delivery-methods", DeliveryMethodViewSet, basename="delivery_methods")

urlpatterns = [path("", include(router.urls))]
11 changes: 11 additions & 0 deletions apps/deliveries/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from rest_framework import viewsets

from apps.deliveries.models import DeliveryMethod
from apps.deliveries.serializers.deliverymethods import DeliveryMethodReadSerializer


class DeliveryMethodViewSet(viewsets.ReadOnlyModelViewSet):
"""Методы доставки."""

queryset = DeliveryMethod.objects.all()
serializer_class = DeliveryMethodReadSerializer
5 changes: 5 additions & 0 deletions apps/orders/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class OrderFilter(django_filters.FilterSet):
- sku: артикул товара
- name: название товара
- address: адрес доставки
- delivery_date: дата доставки
"""

id = django_filters.NumberFilter(field_name="id", lookup_expr="exact", help_text="Номер заказа")
Expand All @@ -31,6 +32,9 @@ class OrderFilter(django_filters.FilterSet):
distinct=True,
help_text="Название товара(частичное совпадение)",
)
delivery_date = django_filters.DateFilter(
field_name="delivery_order__delivery_date", lookup_expr="date", help_text="Дата доставки"
)

class Meta:
model = Order
Expand All @@ -40,6 +44,7 @@ class Meta:
"created_at",
"sku",
"name",
"delivery_date",
)


Expand Down
24 changes: 14 additions & 10 deletions apps/orders/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,26 @@


class OrderManager(models.Manager):
def get_related_queryset(self, user):
def get_queryset(self):
return (
self.filter(user=user)
.select_related("user__company", "user__personal")
super()
.get_queryset()
.select_related(
"user__company",
"user__personal",
"delivery_order",
"delivery_order__address",
"delivery_order__delivery_method",
)
.prefetch_related("orders__product__user__company", "orders__product__images")
.order_by("-created_at")
)

def get_related_queryset(self, user):
return self.filter(user=user)

def get_supplier_orders(self, supplier):
return (
self.filter(order_products__user=supplier)
.select_related("user__company")
.prefetch_related("orders__product__user__company", "orders__product__images")
.order_by("-created_at")
.distinct()
)
return self.filter(order_products__user=supplier).distinct()


class Order(BaseModel):
Expand Down
14 changes: 12 additions & 2 deletions apps/orders/serializers/orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
from rest_framework import serializers

from apps.baskets.models import Basket
from apps.deliveries.models import Delivery
from apps.deliveries.serializers.deliveries import (
DeliveryReadSerializer,
DeliveryWriteSerializer,
)
from apps.orders.models import Order
from apps.orders.serializers.orderproducts import (
OrderProductReadSerializer,
Expand All @@ -16,20 +21,22 @@ class OrderReadSerializer(serializers.ModelSerializer):
"""Сериализатор для отображения заказов в личном кабинете покупателя и продавца."""

order_products = OrderProductReadSerializer(many=True, source="orders")
delivery = DeliveryReadSerializer(source="delivery_order")

class Meta:
model = Order
fields = ("id", "user", "status", "created_at", "order_products")
fields = ("id", "user", "status", "created_at", "order_products", "delivery")


class OrderWriteSerializer(serializers.ModelSerializer):
"""Сериализатор для создания заказов покупателем."""

order_products = OrderProductWriteSerializer(many=True)
delivery = DeliveryWriteSerializer()

class Meta:
model = Order
fields = ("order_products",)
fields = ("order_products", "delivery")

def validate(self, attrs):
for order_product in attrs["order_products"]:
Expand Down Expand Up @@ -57,6 +64,7 @@ def _save_obj(self, obj_model, data):

def create_or_update_order(self, validated_data, instance=None):
order_products = validated_data.pop("order_products", None)
delivery_data = validated_data.pop("delivery", None)
sorting_products = self._sort_products_by_sellers(order_products)
basket = Basket.objects.filter(user=validated_data["user"]).first()
orders = []
Expand All @@ -77,6 +85,8 @@ def create_or_update_order(self, validated_data, instance=None):
product.quantity_in_stock -= products.get("quantity", 0)
product.save()

delivery_data["order"] = order
Delivery.objects.update_or_create(**delivery_data)
orders.append(order)

return orders
Expand Down
45 changes: 43 additions & 2 deletions apps/orders/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
from rest_framework.test import APIClient

from apps.baskets.models import Basket, BasketProduct
from apps.deliveries.models import Delivery, DeliveryMethod
from apps.orders.models import Order, OrderProduct
from apps.products.models import Category, Image, Product
from apps.users.models import CustomUser, PhysicalPerson
from apps.users.models import Address, CustomUser, PhysicalPerson


def mock_time_now():
Expand Down Expand Up @@ -136,14 +137,54 @@ def basket(user, product_1, product_2):


@pytest.fixture
def order_1(user, product_1):
def delivery_method():
delivery_method = DeliveryMethod.objects.create(
name="DHL",
description="DHL delivery",
slug="dhl",
price=1000,
)
return delivery_method


@pytest.fixture
def address():
address = Address.objects.create(address="address")
return address


@pytest.fixture
def order_1(user, product_1, delivery_method, address):
order = Order.objects.create(user=user)

OrderProduct.objects.create(order=order, product=product_1, quantity=3, price=100)
return order


@pytest.fixture
def delivery_1(order_1, address, delivery_method):
delivery = Delivery.objects.create(
order=order_1,
address=address,
delivery_method=delivery_method,
delivery_date="2023-10-04T12:38:14.540Z",
)
return delivery


@pytest.fixture
def order_2(user, product_2):
order = Order.objects.create(user=user)
OrderProduct.objects.create(order=order, product=product_2, quantity=3, price=100)
return order


@pytest.fixture
def delivery_2(order_2, address, delivery_method):
delivery = Delivery.objects.create(
order=order_2,
address=address,
delivery_method=delivery_method,
delivery_date="2023-10-04T12:38:14.540Z",
)
return delivery
15 changes: 13 additions & 2 deletions apps/orders/tests/test_00_create_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import pytest
from rest_framework import status

from apps.deliveries.models import Delivery
from apps.orders.tests.conftest import mock_time_now
from apps.orders.tests.utils import response_order

Expand All @@ -12,7 +13,9 @@ class Test00OrderAPI:
orders_url = "/api/v1/orders/"

@mock.patch("django.utils.timezone.now", mock_time_now)
def test_00_create_order(self, guest_client, auth_client, product_1, basket):
def test_00_create_order(
self, guest_client, auth_client, product_1, basket, delivery_method, address
):
order_data = {
"order_products": [
{
Expand All @@ -23,7 +26,12 @@ def test_00_create_order(self, guest_client, auth_client, product_1, basket):
"product": 2,
"quantity": 5,
},
]
],
"delivery": {
"address": "address",
"delivery_method": 1,
"delivery_date": "2023-10-04T12:38:14.540Z",
},
}

response = guest_client.post(self.orders_url, data=order_data, format="json")
Expand All @@ -32,11 +40,14 @@ def test_00_create_order(self, guest_client, auth_client, product_1, basket):

assert basket.basket_products.count() == 2

assert Delivery.objects.count() == 0

response = auth_client.post(self.orders_url, data=order_data, format="json")

assert response.status_code == status.HTTP_201_CREATED
assert len(response.json()) == 2
assert basket.basket_products.count() == 0
assert Delivery.objects.count() == 2

assert response.json() == response_order

Expand Down
24 changes: 24 additions & 0 deletions apps/orders/tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@
"cost": 1500.0,
},
],
"delivery": {
"id": 1,
"address": {"id": 1, "address": "address"},
"delivery_method": {
"id": 1,
"name": "DHL",
"description": "DHL delivery",
"slug": "dhl",
"price": "1000.00",
},
"delivery_date": "2023-10-04T15:38:14.540000+03:00",
},
},
{
"id": 2,
Expand All @@ -38,5 +50,17 @@
"cost": 2500.0,
},
],
"delivery": {
"id": 2,
"address": {"id": 1, "address": "address"},
"delivery_method": {
"id": 1,
"name": "DHL",
"description": "DHL delivery",
"slug": "dhl",
"price": "1000.00",
},
"delivery_date": "2023-10-04T15:38:14.540000+03:00",
},
},
]
Loading