schon/core/docs/drf/viewsets.py

674 lines
25 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from django.utils.translation import gettext_lazy as _
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiParameter, extend_schema
from rest_framework import status
from core.docs.drf import BASE_ERRORS
from core.serializers import (
AddOrderProductSerializer,
AddressSerializer,
AddWishlistProductSerializer,
AttributeDetailSerializer,
AttributeGroupDetailSerializer,
AttributeGroupSimpleSerializer,
AttributeSimpleSerializer,
AttributeValueDetailSerializer,
AttributeValueSimpleSerializer,
BulkAddOrderProductsSerializer,
BulkAddWishlistProductSerializer,
BulkRemoveOrderProductsSerializer,
BulkRemoveWishlistProductSerializer,
BuyOrderSerializer,
BuyUnregisteredOrderSerializer,
CategoryDetailSerializer,
CategorySimpleSerializer,
FeedbackDetailSerializer,
FeedbackSimpleSerializer,
OrderDetailSerializer,
OrderProductDetailSerializer,
OrderProductSimpleSerializer,
OrderSimpleSerializer,
ProductDetailSerializer,
ProductSimpleSerializer,
RemoveOrderProductSerializer,
RemoveWishlistProductSerializer,
WishlistDetailSerializer,
WishlistSimpleSerializer,
)
from core.serializers.utility import AddressCreateSerializer, AddressSuggestionSerializer, DoFeedbackSerializer
from payments.serializers import TransactionProcessSerializer
ATTRIBUTE_GROUP_SCHEMA = {
"list": extend_schema(
summary=_("list all attribute groups (simple view)"),
responses={status.HTTP_200_OK: AttributeGroupSimpleSerializer(many=True), **BASE_ERRORS},
),
"retrieve": extend_schema(
summary=_("retrieve a single attribute group (detailed view)"),
responses={status.HTTP_200_OK: AttributeGroupDetailSerializer(), **BASE_ERRORS},
),
"create": extend_schema(
summary=_("create an attribute group"),
responses={status.HTTP_201_CREATED: AttributeGroupDetailSerializer(), **BASE_ERRORS},
),
"destroy": extend_schema(
summary=_("delete an attribute group"),
responses={status.HTTP_204_NO_CONTENT: {}, **BASE_ERRORS},
),
"update": extend_schema(
summary=_("rewrite an existing attribute group saving non-editables"),
responses={status.HTTP_200_OK: AttributeGroupDetailSerializer(), **BASE_ERRORS},
),
"partial_update": extend_schema(
summary=_("rewrite some fields of an existing attribute group saving non-editables"),
responses={status.HTTP_200_OK: AttributeGroupDetailSerializer(), **BASE_ERRORS},
),
}
ATTRIBUTE_SCHEMA = {
"list": extend_schema(
summary=_("list all attributes (simple view)"),
responses={status.HTTP_200_OK: AttributeSimpleSerializer(many=True), **BASE_ERRORS},
),
"retrieve": extend_schema(
summary=_("retrieve a single attribute (detailed view)"),
responses={status.HTTP_200_OK: AttributeDetailSerializer(), **BASE_ERRORS},
),
"create": extend_schema(
summary=_("create an attribute"),
responses={status.HTTP_201_CREATED: AttributeDetailSerializer(), **BASE_ERRORS},
),
"destroy": extend_schema(
summary=_("delete an attribute"),
responses={status.HTTP_204_NO_CONTENT: {}, **BASE_ERRORS},
),
"update": extend_schema(
summary=_("rewrite an existing attribute saving non-editables"),
responses={status.HTTP_200_OK: AttributeDetailSerializer(), **BASE_ERRORS},
),
"partial_update": extend_schema(
summary=_("rewrite some fields of an existing attribute saving non-editables"),
responses={status.HTTP_200_OK: AttributeDetailSerializer(), **BASE_ERRORS},
),
}
ATTRIBUTE_VALUE_SCHEMA = {
"list": extend_schema(
summary=_("list all attribute values (simple view)"),
responses={status.HTTP_200_OK: AttributeValueSimpleSerializer(many=True), **BASE_ERRORS},
),
"retrieve": extend_schema(
summary=_("retrieve a single attribute value (detailed view)"),
responses={status.HTTP_200_OK: AttributeValueDetailSerializer(), **BASE_ERRORS},
),
"create": extend_schema(
summary=_("create an attribute value"),
responses={status.HTTP_201_CREATED: AttributeValueDetailSerializer(), **BASE_ERRORS},
),
"destroy": extend_schema(
summary=_("delete an attribute value"),
responses={status.HTTP_204_NO_CONTENT: {}, **BASE_ERRORS},
),
"update": extend_schema(
summary=_("rewrite an existing attribute value saving non-editables"),
responses={status.HTTP_200_OK: AttributeValueDetailSerializer(), **BASE_ERRORS},
),
"partial_update": extend_schema(
summary=_("rewrite some fields of an existing attribute value saving non-editables"),
responses={status.HTTP_200_OK: AttributeValueDetailSerializer(), **BASE_ERRORS},
),
}
CATEGORY_SCHEMA = {
"list": extend_schema(
summary=_("list all categories (simple view)"),
responses={status.HTTP_200_OK: CategorySimpleSerializer(many=True), **BASE_ERRORS},
),
"retrieve": extend_schema(
summary=_("retrieve a single category (detailed view)"),
responses={status.HTTP_200_OK: CategoryDetailSerializer(), **BASE_ERRORS},
),
"create": extend_schema(
summary=_("create a category"),
responses={status.HTTP_201_CREATED: CategoryDetailSerializer(), **BASE_ERRORS},
),
"destroy": extend_schema(
summary=_("delete a category"),
responses={status.HTTP_204_NO_CONTENT: {}, **BASE_ERRORS},
),
"update": extend_schema(
summary=_("rewrite an existing category saving non-editables"),
responses={status.HTTP_200_OK: CategoryDetailSerializer(), **BASE_ERRORS},
),
"partial_update": extend_schema(
summary=_("rewrite some fields of an existing category saving non-editables"),
responses={status.HTTP_200_OK: CategoryDetailSerializer(), **BASE_ERRORS},
),
}
ORDER_SCHEMA = {
"list": extend_schema(
summary=_("list all orders (simple view)"),
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},
),
"retrieve": extend_schema(
summary=_("retrieve a single order (detailed view)"),
responses={status.HTTP_200_OK: OrderDetailSerializer(), **BASE_ERRORS},
),
"create": extend_schema(
summary=_("create an order"),
description=_("doesn't work for non-staff users."),
responses={status.HTTP_201_CREATED: OrderDetailSerializer(), **BASE_ERRORS},
),
"destroy": extend_schema(
summary=_("delete an order"),
responses={status.HTTP_204_NO_CONTENT: {}, **BASE_ERRORS},
),
"update": extend_schema(
summary=_("rewrite an existing order saving non-editables"),
responses={status.HTTP_200_OK: OrderDetailSerializer(), **BASE_ERRORS},
),
"partial_update": extend_schema(
summary=_("rewrite some fields of an existing order saving non-editables"),
responses={status.HTTP_200_OK: OrderDetailSerializer(), **BASE_ERRORS},
),
"buy": extend_schema(
summary=_("purchase an order"),
description=_(
"finalizes the order purchase. if `force_balance` is used,"
" the purchase is completed using the user's balance;"
" if `force_payment` is used, a transaction is initiated."
),
request=BuyOrderSerializer(),
responses={
status.HTTP_200_OK: OrderDetailSerializer(),
status.HTTP_202_ACCEPTED: TransactionProcessSerializer(),
**BASE_ERRORS,
},
),
"buy_unregistered": extend_schema(
summary=_("purchase an order without account creation"),
description=_("finalizes the order purchase for a non-registered user."),
request=BuyUnregisteredOrderSerializer(),
responses={
status.HTTP_202_ACCEPTED: TransactionProcessSerializer(),
**BASE_ERRORS,
},
),
"add_order_product": extend_schema(
summary=_("add product to order"),
description=_("adds a product to an order using the provided `product_uuid` and `attributes`."),
request=AddOrderProductSerializer(),
responses={status.HTTP_200_OK: OrderDetailSerializer(), **BASE_ERRORS},
),
"bulk_add_order_products": extend_schema(
summary=_("add a list of products to order, quantities will not count"),
description=_("adds a list of products to an order using the provided `product_uuid` and `attributes`."),
request=BulkAddOrderProductsSerializer(),
responses={status.HTTP_200_OK: OrderDetailSerializer(), **BASE_ERRORS},
),
"remove_order_product": extend_schema(
summary=_("remove product from order"),
description=_("removes a product from an order using the provided `product_uuid` and `attributes`."),
request=RemoveOrderProductSerializer(),
responses={status.HTTP_200_OK: OrderDetailSerializer(), **BASE_ERRORS},
),
"bulk_remove_order_products": extend_schema(
summary=_("remove product from order, quantities will not count"),
description=_("removes a list of products from an order using the provided `product_uuid` and `attributes`"),
request=BulkRemoveOrderProductsSerializer(),
responses={status.HTTP_200_OK: OrderDetailSerializer(), **BASE_ERRORS},
),
}
WISHLIST_SCHEMA = {
"list": extend_schema(
summary=_("list all wishlists (simple view)"),
description=_("for non-staff users, only their own wishlists are returned."),
responses={status.HTTP_200_OK: WishlistSimpleSerializer(many=True), **BASE_ERRORS},
),
"retrieve": extend_schema(
summary=_("retrieve a single wishlist (detailed view)"),
responses={status.HTTP_200_OK: WishlistDetailSerializer(), **BASE_ERRORS},
),
"create": extend_schema(
summary=_("create an wishlist"),
description=_("Doesn't work for non-staff users."),
responses={status.HTTP_201_CREATED: WishlistDetailSerializer(), **BASE_ERRORS},
),
"destroy": extend_schema(
summary=_("delete an wishlist"),
responses={status.HTTP_204_NO_CONTENT: {}, **BASE_ERRORS},
),
"update": extend_schema(
summary=_("rewrite an existing wishlist saving non-editables"),
responses={status.HTTP_200_OK: WishlistDetailSerializer(), **BASE_ERRORS},
),
"partial_update": extend_schema(
summary=_("rewrite some fields of an existing wishlist saving non-editables"),
responses={status.HTTP_200_OK: WishlistDetailSerializer(), **BASE_ERRORS},
),
"add_wishlist_product": extend_schema(
summary=_("add product to wishlist"),
description=_("adds a product to an wishlist using the provided `product_uuid`"),
request=AddWishlistProductSerializer(),
responses={status.HTTP_200_OK: WishlistDetailSerializer(), **BASE_ERRORS},
),
"remove_wishlist_product": extend_schema(
summary=_("remove product from wishlist"),
description=_("removes a product from an wishlist using the provided `product_uuid`"),
request=RemoveWishlistProductSerializer(),
responses={status.HTTP_200_OK: WishlistDetailSerializer(), **BASE_ERRORS},
),
"bulk_add_wishlist_products": extend_schema(
summary=_("add many products to wishlist"),
description=_("adds many products to an wishlist using the provided `product_uuids`"),
request=BulkAddWishlistProductSerializer(),
responses={status.HTTP_200_OK: WishlistDetailSerializer(), **BASE_ERRORS},
),
"bulk_remove_wishlist_products": extend_schema(
summary=_("remove many products from wishlist"),
description=_("removes many products from an wishlist using the provided `product_uuids`"),
request=BulkRemoveWishlistProductSerializer(),
responses={status.HTTP_200_OK: WishlistDetailSerializer(), **BASE_ERRORS},
),
}
ATTRIBUTES_DESC = _(
"Filter by one or more attribute name/value pairs. \n"
"• **Syntax**: `attr_name=method-value[;attr2=method2-value2]…` \n"
"• **Methods** (defaults to `icontains` if omitted): "
"`iexact`, `exact`, `icontains`, `contains`, `isnull`, "
"`startswith`, `istartswith`, `endswith`, `iendswith`, "
"`regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n"
"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), "
"`true`/`false` for booleans, integers, floats; otherwise treated as string. \n"
"• **Base64**: prefix with `b64-` to URL-safe base64-encode the raw value. \n"
"Examples: \n"
'`color=exact-red`, `size=gt-10`, `features=in-["wifi","bluetooth"]`, \n'
"`b64-description=icontains-aGVhdC1jb2xk`"
)
PRODUCT_SCHEMA = {
"list": extend_schema(
summary=_("list all products (simple view)"),
parameters=[
OpenApiParameter(
name="uuid",
location="query",
description=_("(exact) Product UUID"),
type=str,
),
OpenApiParameter(
name="name",
location="query",
description=_("(icontains) Product name"),
type=str,
),
OpenApiParameter(
name="categories",
location="query",
description=_("(list) Category names, case-insensitive"),
type=str,
),
OpenApiParameter(
name="category_uuid",
location="query",
description=_("(exact) Category UUID"),
type=str,
),
OpenApiParameter(
name="tags",
location="query",
description=_("(list) Tag names, case-insensitive"),
type=str,
),
OpenApiParameter(
name="min_price",
location="query",
description=_("(gte) Minimum stock price"),
type=float,
),
OpenApiParameter(
name="max_price",
location="query",
description=_("(lte) Maximum stock price"),
type=float,
),
OpenApiParameter(
name="is_active",
location="query",
description=_("(exact) Only active products"),
type=bool,
),
OpenApiParameter(
name="brand",
location="query",
description=_("(iexact) Brand name"),
type=str,
),
OpenApiParameter(
name="attributes",
location="query",
description=ATTRIBUTES_DESC,
type=str,
),
OpenApiParameter(
name="quantity",
location="query",
description=_("(gt) Minimum stock quantity"),
type=int,
),
OpenApiParameter(
name="is_digital",
location="query",
description=_("(exact) Digital vs. physical"),
type=bool,
),
OpenApiParameter(
name="order_by",
location="query",
description=_(
"Comma-separated list of fields to sort by. "
"Prefix with `-` for descending. \n"
"**Allowed:** uuid, rating, name, slug, created, modified, price, random"
),
required=False,
type=str,
),
],
responses={
status.HTTP_200_OK: ProductSimpleSerializer(many=True),
**BASE_ERRORS,
},
),
"retrieve": extend_schema(
summary=_("retrieve a single product (detailed view)"),
parameters=[
OpenApiParameter(
name="lookup_value",
location="path",
description=_("Product UUID or slug"),
type=str,
),
],
responses={
status.HTTP_200_OK: ProductDetailSerializer(),
**BASE_ERRORS,
},
),
"create": extend_schema(
summary=_("create a product"),
responses={
status.HTTP_201_CREATED: ProductDetailSerializer(),
**BASE_ERRORS,
},
),
"update": extend_schema(
summary=_("rewrite an existing product, preserving non-editable fields"),
parameters=[
OpenApiParameter(
name="lookup",
location="path",
description=_("Product UUID or slug"),
type=str,
),
],
responses={
status.HTTP_200_OK: ProductDetailSerializer(),
**BASE_ERRORS,
},
),
"partial_update": extend_schema(
summary=_("update some fields of an existing product, preserving non-editable fields"),
parameters=[
OpenApiParameter(
name="lookup",
location="path",
description=_("Product UUID or slug"),
type=str,
),
],
responses={
status.HTTP_200_OK: ProductDetailSerializer(),
**BASE_ERRORS,
},
),
"destroy": extend_schema(
summary=_("delete a product"),
parameters=[
OpenApiParameter(
name="lookup",
location="path",
description=_("Product UUID or slug"),
type=str,
),
],
responses={
status.HTTP_204_NO_CONTENT: {},
**BASE_ERRORS,
},
),
"feedbacks": extend_schema(
summary=_("lists all permitted feedbacks for a product"),
parameters=[
OpenApiParameter(
name="lookup",
location="path",
description=_("Product UUID or slug"),
type=str,
),
],
responses={
status.HTTP_200_OK: FeedbackDetailSerializer(many=True),
**BASE_ERRORS,
},
),
}
ADDRESS_SCHEMA = {
"list": extend_schema(
summary=_("list all addresses"),
responses={
status.HTTP_200_OK: AddressSerializer(many=True),
**BASE_ERRORS,
},
),
"retrieve": extend_schema(
summary=_("retrieve a single address"),
responses={
status.HTTP_200_OK: AddressSerializer(),
**BASE_ERRORS,
},
),
"create": extend_schema(
summary=_("create a new address"),
request=AddressCreateSerializer(),
responses={
status.HTTP_201_CREATED: AddressSerializer(),
**BASE_ERRORS,
},
),
"destroy": extend_schema(
summary=_("delete an address"),
responses={
status.HTTP_204_NO_CONTENT: {},
**BASE_ERRORS,
},
),
"update": extend_schema(
summary=_("update an entire address"),
request=AddressSerializer(),
responses={
status.HTTP_200_OK: AddressSerializer(),
**BASE_ERRORS,
},
),
"partial_update": extend_schema(
summary=_("partially update an address"),
request=AddressSerializer(),
responses={
status.HTTP_200_OK: AddressSerializer(),
**BASE_ERRORS,
},
),
"autocomplete": extend_schema(
summary=_("autocomplete address suggestions"),
parameters=[
OpenApiParameter(
name="q",
location="query",
description=_("raw data query string, please append with data from geo-IP endpoint"),
type=str,
),
OpenApiParameter(
name="limit",
location="query",
description=_("limit the results amount, 1 < limit < 10, default: 5"),
type=int,
),
],
responses={
status.HTTP_200_OK: AddressSuggestionSerializer(many=True),
**BASE_ERRORS,
},
),
}
FEEDBACK_SCHEMA = {
"list": extend_schema(
summary=_("list all feedbacks (simple view)"),
responses={status.HTTP_200_OK: FeedbackSimpleSerializer(many=True), **BASE_ERRORS},
),
"retrieve": extend_schema(
summary=_("retrieve a single feedback (detailed view)"),
responses={status.HTTP_200_OK: FeedbackDetailSerializer(), **BASE_ERRORS},
),
"create": extend_schema(
summary=_("create a feedback"),
responses={status.HTTP_201_CREATED: FeedbackDetailSerializer(), **BASE_ERRORS},
),
"destroy": extend_schema(
summary=_("delete a feedback"),
responses={status.HTTP_204_NO_CONTENT: {}, **BASE_ERRORS},
),
"update": extend_schema(
summary=_("rewrite an existing feedback saving non-editables"),
responses={status.HTTP_200_OK: FeedbackDetailSerializer(), **BASE_ERRORS},
),
"partial_update": extend_schema(
summary=_("rewrite some fields of an existing feedback saving non-editables"),
responses={status.HTTP_200_OK: FeedbackDetailSerializer(), **BASE_ERRORS},
),
}
ORDER_PRODUCT_SCHEMA = {
"list": extend_schema(
summary=_("list all orderproduct relations (simple view)"),
responses={
status.HTTP_200_OK: OrderProductSimpleSerializer(many=True),
**BASE_ERRORS,
},
),
"retrieve": extend_schema(
summary=_("retrieve a single orderproduct relation (detailed view)"),
responses={
status.HTTP_200_OK: OrderProductDetailSerializer(),
**BASE_ERRORS,
},
),
"create": extend_schema(
summary=_("create a new orderproduct relation"),
responses={
status.HTTP_201_CREATED: OrderProductDetailSerializer(),
**BASE_ERRORS,
},
),
"update": extend_schema(
summary=_("replace an existing orderproduct relation"),
responses={
status.HTTP_200_OK: OrderProductDetailSerializer(),
**BASE_ERRORS,
},
),
"partial_update": extend_schema(
summary=_("partially update an existing orderproduct relation"),
responses={
status.HTTP_200_OK: OrderProductDetailSerializer(),
**BASE_ERRORS,
},
),
"destroy": extend_schema(
summary=_("delete an orderproduct relation"),
responses={
status.HTTP_204_NO_CONTENT: {},
**BASE_ERRORS,
},
),
"do_feedback": extend_schema(
summary=_("add or remove feedback on an orderproduct relation"),
request=DoFeedbackSerializer,
responses={
status.HTTP_201_CREATED: FeedbackDetailSerializer(),
status.HTTP_204_NO_CONTENT: {},
status.HTTP_400_BAD_REQUEST: {},
status.HTTP_404_NOT_FOUND: {},
**BASE_ERRORS,
},
),
}