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

Fix/shoppingcart product photo full paths #248

Merged
merged 9 commits into from
Feb 6, 2024
3 changes: 1 addition & 2 deletions .github/workflows/good_food_workflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ jobs:
python -m flake8
- name: Test with pytest
run: |
cd backend
pytest
pytest backend/tests/
- name: send message
if: ${{ github.ref != 'refs/heads/main' }}
uses: appleboy/telegram-action@master
Expand Down
18 changes: 12 additions & 6 deletions backend/api/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,22 @@
from products.models import Product


class CharFilterInFilter(rf_filters.BaseInFilter, rf_filters.CharFilter):
"""Custom char filter allowing comma-separated incoming values."""

pass


class ProductFilter(rf_filters.FilterSet):
"""Class for filtering products."""

name = rf_filters.CharFilter(method="startswith_contains_union_method")
category = rf_filters.AllValuesMultipleFilter(field_name="category__slug")
subcategory = rf_filters.AllValuesMultipleFilter(field_name="subcategory__slug")
producer = rf_filters.AllValuesMultipleFilter(field_name="producer__slug")
components = rf_filters.AllValuesMultipleFilter(field_name="components__slug")
tags = rf_filters.AllValuesMultipleFilter(field_name="tags__slug")
promotions = rf_filters.AllValuesMultipleFilter(field_name="promotions__slug")
category = CharFilterInFilter(field_name="category__slug")
subcategory = CharFilterInFilter(field_name="subcategory__slug")
producer = CharFilterInFilter(field_name="producer__slug")
components = CharFilterInFilter(field_name="components__slug")
tags = CharFilterInFilter(field_name="tags__slug")
promotions = CharFilterInFilter(field_name="promotions__slug")
is_favorited = rf_filters.NumberFilter(method="product_boolean_methods")
min_price = rf_filters.NumberFilter(method="get_min_price")
max_price = rf_filters.NumberFilter(method="get_max_price")
Expand Down
2 changes: 1 addition & 1 deletion backend/api/orders_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ def coupon_apply(self, request):
code = request.data["code"]
try:
coupon = Coupon.objects.get(
Q(code__iexact=code),
Q(code__exact=code),
Q(is_active=True),
Q(start_time__lte=now) | Q(start_time__isnull=True),
Q(end_time__gte=now) | Q(end_time__isnull=True),
Expand Down
11 changes: 2 additions & 9 deletions backend/api/products_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@
Tag,
)

COUPON_PROMOTION_TYPE_API_ERROR_MESSAGE = (
f"Указан неверный тип промоакции, нужно выбрать {Promotion.COUPON}."
)
RATING_DECIMAL_PLACES = 1


Expand Down Expand Up @@ -516,6 +513,8 @@ def setup_eager_loading(cls, queryset, user):
class CouponSerializer(serializers.ModelSerializer):
"""Serializer for coupons representation."""

promotion_type = serializers.ReadOnlyField()

class Meta:
model = Coupon
fields = (
Expand All @@ -533,12 +532,6 @@ class Meta:
"image",
)

def validate_promotion_type(self, value):
"""Checks that promotion_type is correct."""
if value != Promotion.COUPON:
raise serializers.ValidationError(COUPON_PROMOTION_TYPE_API_ERROR_MESSAGE)
return value


class CouponApplySerializer(serializers.ModelSerializer):
"""Serializer to apply coupon promoaction to the order."""
Expand Down
12 changes: 12 additions & 0 deletions backend/api/products_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,12 @@ class CouponViewSet(DestroyWithPayloadMixin, viewsets.ModelViewSet):
serializer_class = CouponSerializer
permission_classes = [IsAdminOrReadOnly]

@transaction.atomic
def perform_create(self, serializer):
"""Sets the correct promotion_type during coupon creation."""
serializer.save(promotion_type=Promotion.COUPON)
return super().perform_create(serializer)


@method_decorator(
name="list",
Expand Down Expand Up @@ -664,13 +670,19 @@ def get_queryset(self):

@transaction.atomic
def perform_create(self, serializer):
"""
Sets the correct category for the given subcategory during product creation.
"""
subcategory_id = serializer._kwargs["data"]["subcategory"]
subcategory = Subcategory.objects.get(id=subcategory_id)
serializer.save(category=subcategory.parent_category)
return super().perform_create(serializer)

@transaction.atomic
def perform_update(self, serializer):
"""
Sets the correct category for the given subcategory during product editing.
"""
subcategory_id = serializer._kwargs["data"].get("subcategory")
if subcategory_id:
subcategory = Subcategory.objects.get(id=subcategory_id)
Expand Down
2 changes: 2 additions & 0 deletions backend/api/reviews_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,12 @@ def get_queryset(self):
).select_related("product", "author")

def perform_create(self, serializer):
"""Sets the correct author and product during review creation."""
product = get_object_or_404(Product, pk=self.kwargs.get("product_id"))
serializer.save(author=self.request.user, product=product)

def perform_update(self, serializer):
"""Updates pub_date and was_edited fields during review editing."""
serializer.save(pub_date=timezone.now(), was_edited=True)
return super().perform_update(serializer)

Expand Down
18 changes: 17 additions & 1 deletion backend/api/users_serializers.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
from dateutil.relativedelta import relativedelta
from django.contrib.auth import get_user_model
from django.db import transaction
from django.utils import timezone
from djoser.serializers import UserCreateSerializer as DjoserUserCreateSerializer
from djoser.serializers import UserDeleteSerializer as DjoserUserDeleteSerializer
from djoser.serializers import UserSerializer as DjoserUserSerializer
from rest_framework import serializers
from rest_framework.validators import UniqueValidator

from users.models import Address
from users.models import (
BIRTH_DATE_TOO_OLD_ERROR_MESSAGE,
BIRTH_DATE_TOO_YOUNG_ERROR_MESSAGE,
MAX_USER_AGE,
MIN_USER_AGE,
Address,
)
from users.utils import city_choices

User = get_user_model()
Expand Down Expand Up @@ -69,6 +77,14 @@ class Meta:
"photo",
)

def validate_birth_date(self, value):
now = timezone.now()
if value and value + relativedelta(years=MIN_USER_AGE) > now.date():
raise serializers.ValidationError(BIRTH_DATE_TOO_YOUNG_ERROR_MESSAGE)
if value and value + relativedelta(years=MAX_USER_AGE) < now.date():
raise serializers.ValidationError(BIRTH_DATE_TOO_OLD_ERROR_MESSAGE)
return value

def get_address_quantity(self, obj) -> int:
return obj.addresses.count()

Expand Down
21 changes: 11 additions & 10 deletions backend/orders/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@

@admin.register(Delivery)
class DeliveryAdmin(admin.ModelAdmin):
list_display = ("id", "delivery_point")
list_display_links = ("delivery_point",)
list_display = ["id", "delivery_point"]
list_display_links = ["delivery_point"]


class OrderProductInline(admin.TabularInline):
model = OrderProduct
list_display = ("id", "product", "quantity")
list_editable = ("product", "quantity")
list_display = ["id", "product", "quantity"]
list_editable = ["product", "quantity"]


@admin.register(Order)
class OrderAdmin(admin.ModelAdmin):
inlines = (OrderProductInline,)
list_display = (
inlines = [OrderProductInline]
list_display = [
"id",
"order_number",
"user",
Expand All @@ -30,10 +30,11 @@ class OrderAdmin(admin.ModelAdmin):
"total_price",
"coupon_applied",
"coupon_discount",
)
list_display_links = ("ordering_date",)
list_editable = ("payment_method", "delivery_method")
list_filter = ("status", "ordering_date")
]
list_display_links = ["ordering_date"]
list_editable = ["payment_method", "delivery_method"]
list_filter = ["status", "ordering_date"]
readonly_fields = ["coupon_applied", "coupon_discount"]

def get_queryset(self, request):
queryset = super().get_queryset(request)
Expand Down
4 changes: 1 addition & 3 deletions backend/orders/shopping_carts.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
from django.utils import timezone

from core.loggers import logger
from products.models import Coupon, Product

PRICE_DECIMAL_PLACES = 2
from products.models import PRICE_DECIMAL_PLACES, Coupon, Product


class ShopCart(object):
Expand Down
Loading