Fixes: ORDER_SCHEMA

This commit is contained in:
Egor Pavlovich Gorbunov 2025-06-08 16:42:18 +03:00
parent e716f88eac
commit 7b60cf3d6d
3 changed files with 110 additions and 9 deletions

View file

@ -149,8 +149,63 @@ ORDER_SCHEMA = {
"list": extend_schema( "list": extend_schema(
summary=_("list all orders (simple view)"), summary=_("list all orders (simple view)"),
description=_("for non-staff users, only their own orders are returned."), description=_("for non-staff users, only their own orders are returned."),
parameters=[
OpenApiParameter(
name="search",
type=OpenApiTypes.STR,
description=_(
"Case-insensitive substring search across human_readable_id, "
"order_products.product.name, and order_products.product.partnumber"
),
),
OpenApiParameter(
name="min_buy_time",
type=OpenApiTypes.DATETIME,
description=_("Filter orders with buy_time >= this ISO 8601 datetime"),
),
OpenApiParameter(
name="max_buy_time",
type=OpenApiTypes.DATETIME,
description=_("Filter orders with buy_time <= this ISO 8601 datetime"),
),
OpenApiParameter(
name="uuid",
type=OpenApiTypes.UUID,
description=_("Filter by exact order UUID"),
),
OpenApiParameter(
name="human_readable_id",
type=OpenApiTypes.STR,
description=_("Filter by exact human-readable order ID"),
),
OpenApiParameter(
name="user_email",
type=OpenApiTypes.STR,
description=_("Filter by user's email (case-insensitive exact match)"),
),
OpenApiParameter(
name="user",
type=OpenApiTypes.UUID,
description=_("Filter by user's UUID"),
),
OpenApiParameter(
name="status",
type=OpenApiTypes.STR,
description=_("Filter by order status (case-insensitive substring match)"),
),
OpenApiParameter(
name="order_by",
type=OpenApiTypes.STR,
description=_(
"Order by one of: uuid, human_readable_id, user_email, user, "
"status, created, modified, buy_time, random. "
"Prefix with '-' for descending (e.g. '-buy_time')."
),
),
],
responses={status.HTTP_200_OK: OrderSimpleSerializer(many=True), **BASE_ERRORS}, responses={status.HTTP_200_OK: OrderSimpleSerializer(many=True), **BASE_ERRORS},
), ),
# ... other actions unchanged
"retrieve": extend_schema( "retrieve": extend_schema(
summary=_("retrieve a single order (detailed view)"), summary=_("retrieve a single order (detailed view)"),
responses={status.HTTP_200_OK: OrderDetailSerializer(), **BASE_ERRORS}, responses={status.HTTP_200_OK: OrderDetailSerializer(), **BASE_ERRORS},

View file

@ -5,7 +5,16 @@ import uuid
from django.db.models import Avg, FloatField, OuterRef, Q, Subquery, Value from django.db.models import Avg, FloatField, OuterRef, Q, Subquery, Value
from django.db.models.functions import Coalesce from django.db.models.functions import Coalesce
from django.utils.http import urlsafe_base64_decode from django.utils.http import urlsafe_base64_decode
from django_filters import BaseInFilter, BooleanFilter, CharFilter, FilterSet, NumberFilter, OrderingFilter, UUIDFilter from django_filters import (
BaseInFilter,
BooleanFilter,
CharFilter,
DateTimeFilter,
FilterSet,
NumberFilter,
OrderingFilter,
UUIDFilter,
)
from core.models import Brand, Category, Feedback, Order, Product, Wishlist from core.models import Brand, Category, Feedback, Order, Product, Wishlist
@ -210,11 +219,27 @@ class ProductFilter(FilterSet):
class OrderFilter(FilterSet): class OrderFilter(FilterSet):
uuid = UUIDFilter(field_name="uuid", lookup_expr="exact") search = CharFilter(
user_email = CharFilter(field_name="user__email", lookup_expr="iexact") method='filter_search',
user = UUIDFilter(field_name="user__uuid", lookup_expr="exact") label='Search (ID, product name or part number)',
status = CharFilter(field_name="status", lookup_expr="icontains", label="Status") )
human_readable_id = CharFilter(field_name="human_readable_id", lookup_expr="exact")
min_buy_time = DateTimeFilter(
field_name='buy_time',
lookup_expr='gte',
label='Bought after (inclusive)'
)
max_buy_time = DateTimeFilter(
field_name='buy_time',
lookup_expr='lte',
label='Bought before (inclusive)'
)
uuid = UUIDFilter(field_name='uuid', lookup_expr='exact')
user_email = CharFilter(field_name='user__email', lookup_expr='iexact')
user = UUIDFilter(field_name='user__uuid', lookup_expr='exact')
status = CharFilter(field_name='status', lookup_expr='icontains', label='Status')
human_readable_id = CharFilter(field_name='human_readable_id', lookup_expr='exact')
order_by = OrderingFilter( order_by = OrderingFilter(
fields=( fields=(
@ -232,7 +257,28 @@ class OrderFilter(FilterSet):
class Meta: class Meta:
model = Order model = Order
fields = ["uuid", "human_readable_id", "user_email", "user", "status", "order_by"] fields = [
"uuid",
"human_readable_id",
"user_email",
"user",
"status",
"order_by",
"search",
"min_buy_time",
"max_buy_time",
]
def filter_search(self, queryset, _name, value):
return (
queryset
.filter(
Q(human_readable_id__icontains=value) |
Q(order_products__product__name__icontains=value) |
Q(order_products__product__partnumber__icontains=value)
)
.distinct()
)
class WishlistFilter(FilterSet): class WishlistFilter(FilterSet):
@ -267,7 +313,7 @@ class CategoryFilter(FilterSet):
model = Category model = Category
fields = ["uuid", "name", "parent_uuid", "slug"] fields = ["uuid", "name", "parent_uuid", "slug"]
def filter_parent_uuid(self, queryset, name, value): def filter_parent_uuid(self, queryset, _name, value):
""" """
If ?parent_uuid= or ?parent_uuid=null, return items with parent=None. If ?parent_uuid= or ?parent_uuid=null, return items with parent=None.
Otherwise treat `value` as a real UUID and filter parent__uuid=value. Otherwise treat `value` as a real UUID and filter parent__uuid=value.

View file

@ -70,6 +70,6 @@ class AddressManager(models.Manager):
region=region, region=region,
postal_code=postal_code, postal_code=postal_code,
country=country, country=country,
user=kwargs.pop('user'),
defaults={"api_response": data, "location": location}, defaults={"api_response": data, "location": location},
**kwargs,
)[0] )[0]