Fixes: ORDER_SCHEMA
This commit is contained in:
parent
e716f88eac
commit
7b60cf3d6d
3 changed files with 110 additions and 9 deletions
|
|
@ -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},
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue