From 884666c68a4ddebcb5ed97a3c664a6d460360446 Mon Sep 17 00:00:00 2001 From: Romain Le Cellier Date: Tue, 28 Feb 2023 16:18:51 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=A9=B9(schema)=20create=20request/respons?= =?UTF-8?q?e=20serializers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... for OrderViewSet t s Each viewset endpoints take and send differentes values. It's currently defined as Order for all ViewSet endpoints. Here we specify which data will be given in the request body and which data will be sent as response. --- src/backend/joanie/core/api.py | 36 ++++++++++++++++--- .../joanie/core/serializers/__init__.py | 8 +++++ .../serializers/empty_response_serializer.py | 7 ++++ .../serializers/error_response_serializer.py | 10 ++++++ .../model_serializers.py} | 12 +++++-- .../order_abort_body_serializer.py | 12 +++++++ .../order_abort_response_serializer.py | 14 ++++++++ .../order_create_body_serializer.py | 11 ++++++ .../order_create_response_serializer.py | 14 ++++++++ .../order_invoice_query_serializer.py | 10 ++++++ .../product_retrieve_query_serializer.py | 10 ++++++ src/openApiClientJs/package.json | 2 +- src/openApiClientJs/yarn.lock | 2 +- 13 files changed, 139 insertions(+), 9 deletions(-) create mode 100644 src/backend/joanie/core/serializers/__init__.py create mode 100644 src/backend/joanie/core/serializers/empty_response_serializer.py create mode 100644 src/backend/joanie/core/serializers/error_response_serializer.py rename src/backend/joanie/core/{serializers.py => serializers/model_serializers.py} (97%) create mode 100644 src/backend/joanie/core/serializers/order_abort_body_serializer.py create mode 100644 src/backend/joanie/core/serializers/order_abort_response_serializer.py create mode 100644 src/backend/joanie/core/serializers/order_create_body_serializer.py create mode 100644 src/backend/joanie/core/serializers/order_create_response_serializer.py create mode 100644 src/backend/joanie/core/serializers/order_invoice_query_serializer.py create mode 100644 src/backend/joanie/core/serializers/product_retrieve_query_serializer.py diff --git a/src/backend/joanie/core/api.py b/src/backend/joanie/core/api.py index 20dcd2cc59..f44af6d41c 100644 --- a/src/backend/joanie/core/api.py +++ b/src/backend/joanie/core/api.py @@ -114,9 +114,7 @@ def get_serializer_context(self): return context @swagger_auto_schema( - manual_parameters=[ - openapi.Parameter("course", in_=openapi.IN_QUERY, type=openapi.TYPE_STRING) - ], + query_serializer=serializers.ProductRetrieveQuerySerializer, ) def retrieve(self, *args, **kwargs): return super().retrieve(*args, **kwargs) @@ -186,6 +184,10 @@ def perform_create(self, serializer): owner = User.update_or_create_from_request_user(request_user=self.request.user) serializer.save(owner=owner) + @swagger_auto_schema( + request_body=serializers.OrderCreateBodySerializer, + responses={201: serializers.OrderCreateResponseSerializer}, + ) @transaction.atomic def create(self, request, *args, **kwargs): """Try to create an order and a related payment if the payment is fee.""" @@ -257,12 +259,17 @@ def create(self, request, *args, **kwargs): # Return the fresh new order with payment_info return Response( - {**serializer.data, "payment_info": payment_info}, status=201 + {**serializer.data, "payment_info": payment_info}, + status=201, ) # Else return the fresh new order return Response(serializer.data, status=201) + @swagger_auto_schema( + request_body=serializers.OrderAbortBodySerializer, + responses={204: serializers.EmptyResponseSerializer}, + ) @action(detail=True, methods=["POST"]) def abort(self, request, pk=None): # pylint: disable=no-self-use, invalid-name """Abort a pending order and the related payment if there is one.""" @@ -287,6 +294,17 @@ def abort(self, request, pk=None): # pylint: disable=no-self-use, invalid-name return Response(status=204) + @swagger_auto_schema( + query_serializer=serializers.OrderInvoiceQuerySerializer, + responses={ + 200: openapi.Response( + "File Attachment", schema=openapi.Schema(type=openapi.TYPE_FILE) + ), + 400: serializers.ErrorResponseSerializer, + 404: serializers.ErrorResponseSerializer, + }, + produces="application/pdf", + ) @action(detail=True, methods=["GET"]) def invoice(self, request, pk=None): # pylint: disable=no-self-use, invalid-name """ @@ -400,6 +418,16 @@ def get_queryset(self): user = User.update_or_create_from_request_user(request_user=self.request.user) return models.Certificate.objects.filter(order__owner=user) + @swagger_auto_schema( + responses={ + 200: openapi.Response( + "File Attachment", schema=openapi.Schema(type=openapi.TYPE_FILE) + ), + 404: serializers.ErrorResponseSerializer, + 422: serializers.ErrorResponseSerializer, + }, + produces="application/pdf", + ) @action(detail=True, methods=["GET"]) def download(self, request, pk=None): # pylint: disable=no-self-use, invalid-name """ diff --git a/src/backend/joanie/core/serializers/__init__.py b/src/backend/joanie/core/serializers/__init__.py new file mode 100644 index 0000000000..5b16207a5b --- /dev/null +++ b/src/backend/joanie/core/serializers/__init__.py @@ -0,0 +1,8 @@ +from .model_serializers import * +from .empty_response_serializer import * +from .error_response_serializer import * +from .order_create_body_serializer import * +from .order_create_response_serializer import * +from .order_abort_body_serializer import * +from .order_invoice_query_serializer import * +from .product_retrieve_query_serializer import * diff --git a/src/backend/joanie/core/serializers/empty_response_serializer.py b/src/backend/joanie/core/serializers/empty_response_serializer.py new file mode 100644 index 0000000000..188a0b62bd --- /dev/null +++ b/src/backend/joanie/core/serializers/empty_response_serializer.py @@ -0,0 +1,7 @@ +"""Serializers for empty Response""" + +from rest_framework import serializers + + +class EmptyResponseSerializer(serializers.Serializer): + pass diff --git a/src/backend/joanie/core/serializers/error_response_serializer.py b/src/backend/joanie/core/serializers/error_response_serializer.py new file mode 100644 index 0000000000..c5f686b814 --- /dev/null +++ b/src/backend/joanie/core/serializers/error_response_serializer.py @@ -0,0 +1,10 @@ +"""Serializers for core.api.OrderViewSet.abort Body""" + +from rest_framework import serializers + + +class ErrorResponseSerializer(serializers.Serializer): + details = serializers.CharField(required=True) + + class Meta: + fields = ["details"] diff --git a/src/backend/joanie/core/serializers.py b/src/backend/joanie/core/serializers/model_serializers.py similarity index 97% rename from src/backend/joanie/core/serializers.py rename to src/backend/joanie/core/serializers/model_serializers.py index 63697dc362..f1ca1d6e6a 100644 --- a/src/backend/joanie/core/serializers.py +++ b/src/backend/joanie/core/serializers/model_serializers.py @@ -1,4 +1,4 @@ -"""Serializers for api.""" +"""Serializers for core.models""" from django.conf import settings from django.core.cache import cache @@ -7,8 +7,7 @@ from rest_framework import serializers from joanie.core import models, utils - -from .enums import ORDER_STATE_PENDING, ORDER_STATE_VALIDATED +from joanie.core.enums import ORDER_STATE_PENDING, ORDER_STATE_VALIDATED class CertificationDefinitionSerializer(serializers.ModelSerializer): @@ -545,3 +544,10 @@ class Meta: model = models.Certificate fields = ["id"] read_only_fields = ["id"] + + +class PaymentSerializer(serializers.Serializer): + payment_id = serializers.CharField(required=True) + provider = serializers.CharField(required=True) + url = serializers.CharField(required=True) + is_paid = serializers.BooleanField(required=False) diff --git a/src/backend/joanie/core/serializers/order_abort_body_serializer.py b/src/backend/joanie/core/serializers/order_abort_body_serializer.py new file mode 100644 index 0000000000..35fc0b6aeb --- /dev/null +++ b/src/backend/joanie/core/serializers/order_abort_body_serializer.py @@ -0,0 +1,12 @@ +"""Serializers for core.api.OrderViewSet.abort Body""" + +from rest_framework import serializers + +from .model_serializers import OrderSerializer, AddressSerializer + + +class OrderAbortBodySerializer(serializers.Serializer): + payment_id = serializers.CharField(required=True) + + class Meta: + fields = ["payment_id"] diff --git a/src/backend/joanie/core/serializers/order_abort_response_serializer.py b/src/backend/joanie/core/serializers/order_abort_response_serializer.py new file mode 100644 index 0000000000..a0e7bd1874 --- /dev/null +++ b/src/backend/joanie/core/serializers/order_abort_response_serializer.py @@ -0,0 +1,14 @@ +"""Serializers for core.api.OrderViewSet.create Response""" + +from rest_framework import serializers + +from .model_serializers import OrderSerializer, PaymentSerializer + + +class OrderAbortResponseSerializer(OrderSerializer): + id = serializers.CharField(required=True) + payment_info = PaymentSerializer(required=False) + + class Meta(OrderSerializer.Meta): + fields = OrderSerializer.Meta.fields + ["payment_info"] + read_only_fields = OrderSerializer.Meta.fields + ["payment_info"] diff --git a/src/backend/joanie/core/serializers/order_create_body_serializer.py b/src/backend/joanie/core/serializers/order_create_body_serializer.py new file mode 100644 index 0000000000..ece51987e6 --- /dev/null +++ b/src/backend/joanie/core/serializers/order_create_body_serializer.py @@ -0,0 +1,11 @@ +"""Serializers for core.api.OrderViewSet.create Body""" + +from .model_serializers import OrderSerializer, AddressSerializer + + +class OrderCreateBodySerializer(OrderSerializer): + billing_address = AddressSerializer(required=False) + + class Meta(OrderSerializer.Meta): + fields = OrderSerializer.Meta.fields + ["billing_address"] + read_only_fields = OrderSerializer.Meta.fields + ["billing_address"] diff --git a/src/backend/joanie/core/serializers/order_create_response_serializer.py b/src/backend/joanie/core/serializers/order_create_response_serializer.py new file mode 100644 index 0000000000..decccf8baf --- /dev/null +++ b/src/backend/joanie/core/serializers/order_create_response_serializer.py @@ -0,0 +1,14 @@ +"""Serializers for core.api.OrderViewSet.create Response""" + +from rest_framework import serializers + +from .model_serializers import OrderSerializer, PaymentSerializer + + +class OrderCreateResponseSerializer(OrderSerializer): + id = serializers.CharField(required=True) + payment_info = PaymentSerializer(required=False) + + class Meta(OrderSerializer.Meta): + fields = OrderSerializer.Meta.fields + ["payment_info"] + read_only_fields = OrderSerializer.Meta.fields + ["payment_info"] diff --git a/src/backend/joanie/core/serializers/order_invoice_query_serializer.py b/src/backend/joanie/core/serializers/order_invoice_query_serializer.py new file mode 100644 index 0000000000..137b6970d9 --- /dev/null +++ b/src/backend/joanie/core/serializers/order_invoice_query_serializer.py @@ -0,0 +1,10 @@ +"""Serializers for core.api.OrderViewSet.abort Body""" + +from rest_framework import serializers + + +class OrderInvoiceQuerySerializer(serializers.Serializer): + reference = serializers.CharField(required=True) + + class Meta: + fields = ["reference"] diff --git a/src/backend/joanie/core/serializers/product_retrieve_query_serializer.py b/src/backend/joanie/core/serializers/product_retrieve_query_serializer.py new file mode 100644 index 0000000000..0c8f97ecb1 --- /dev/null +++ b/src/backend/joanie/core/serializers/product_retrieve_query_serializer.py @@ -0,0 +1,10 @@ +"""Serializers for core.api.OrderViewSet.abort Body""" + +from rest_framework import serializers + + +class ProductRetrieveQuerySerializer(serializers.Serializer): + course = serializers.CharField(required=True) + + class Meta: + fields = ["course"] diff --git a/src/openApiClientJs/package.json b/src/openApiClientJs/package.json index 0b3e79cc04..fd872a827f 100644 --- a/src/openApiClientJs/package.json +++ b/src/openApiClientJs/package.json @@ -4,7 +4,7 @@ "private": true, "description": "Tool to generate Typescript api client for joanie", "scripts": { - "generate:api:client:local": "./scripts/openapi-typescript-codegen/generate_api_client_local.sh $1" + "generate:api:client:local": "./scripts/openapi-typescript-codegen/generate_api_client_local.sh" }, "repository": { "type": "git", diff --git a/src/openApiClientJs/yarn.lock b/src/openApiClientJs/yarn.lock index 7f73992e97..6ffcf99ac4 100644 --- a/src/openApiClientJs/yarn.lock +++ b/src/openApiClientJs/yarn.lock @@ -101,7 +101,7 @@ neo-async@^2.6.0: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -openapi-typescript-codegen@^0.23.0: +openapi-typescript-codegen@0.23.0: version "0.23.0" resolved "https://registry.yarnpkg.com/openapi-typescript-codegen/-/openapi-typescript-codegen-0.23.0.tgz#702a651eefc536b27e87e4ad54a80a31d36487f0" integrity sha512-gOJXy5g3H3HlLpVNN+USrNK2i2KYBmDczk9Xk34u6JorwrGiDJZUj+al4S+i9TXdfUQ/ZaLxE59Xf3wqkxGfqA==