From 317bb059ffe2b5c3620021ebcef4a813f5a77599 Mon Sep 17 00:00:00 2001 From: Floris272 Date: Wed, 31 Jul 2024 16:58:54 +0200 Subject: [PATCH] fix api workflows --- .../workflows/generate-postman-collection.yml | 8 +- .github/workflows/generate-sdks.yml | 16 +- .github/workflows/lint-oas.yml | 8 +- src/open_producten/producttypes/router.py | 6 + .../producttypes/serializers/category.py | 52 +- .../producttypes/serializers/producttype.py | 36 +- .../tests/test_category_viewset.py | 65 + .../tests/test_producttype_viewset.py | 1 + src/open_producten/producttypes/views.py | 24 +- src/openapi.yaml | 1480 ++++++----------- 10 files changed, 730 insertions(+), 966 deletions(-) create mode 100644 src/open_producten/producttypes/tests/test_category_viewset.py diff --git a/.github/workflows/generate-postman-collection.yml b/.github/workflows/generate-postman-collection.yml index d6f1778..f695fdc 100644 --- a/.github/workflows/generate-postman-collection.yml +++ b/.github/workflows/generate-postman-collection.yml @@ -12,11 +12,11 @@ on: jobs: run: runs-on: ubuntu-latest - strategy: - matrix: - version: [ 'v1' ] + # strategy: + # matrix: + # version: [ 'v1' ] - name: Run with version $ + name: Run with version v1 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/generate-sdks.yml b/.github/workflows/generate-sdks.yml index 21e9806..180db8c 100644 --- a/.github/workflows/generate-sdks.yml +++ b/.github/workflows/generate-sdks.yml @@ -12,11 +12,11 @@ on: jobs: run: runs-on: ubuntu-latest - strategy: - matrix: - version: [ 'v1' ] + # strategy: + # matrix: + # version: [ 'v1' ] - name: Run with version $ + name: Run with version v1 steps: - uses: actions/checkout@v4 @@ -30,13 +30,13 @@ jobs: id: vars run: echo ::set-output name=oas::./src/openapi.yaml - name: Validate schema - run: openapi-generator-cli validate -i $ + run: openapi-generator-cli validate -i ${{ steps.vars.outputs.oas }} - name: Generate Java client - run: openapi-generator-cli generate -i $ --global-property=modelTests=false,apiTests=false,modelDocs=false,apiDocs=false \ + run: openapi-generator-cli generate -i ${{ steps.vars.outputs.oas }} --global-property=modelTests=false,apiTests=false,modelDocs=false,apiDocs=false \ -o ./sdks/java -g java --additional-properties=dateLibrary=java8,java8=true,optionalProjectFile=false,optionalAssemblyInfo=false - name: Generate .NET client - run: openapi-generator-cli generate -i $ --global-property=modelTests=false,apiTests=false,modelDocs=false,apiDocs=false \ + run: openapi-generator-cli generate -i ${{ steps.vars.outputs.oas }} --global-property=modelTests=false,apiTests=false,modelDocs=false,apiDocs=false \ -o ./sdks/net -g csharp --additional-properties=optionalProjectFile=false,optionalAssemblyInfo=false - name: Generate Python client - run: openapi-generator-cli generate -i $ --global-property=modelTests=false,apiTests=false,modelDocs=false,apiDocs=false \ + run: openapi-generator-cli generate -i ${{ steps.vars.outputs.oas }} --global-property=modelTests=false,apiTests=false,modelDocs=false,apiDocs=false \ -o ./sdks/python -g python --additional-properties=optionalProjectFile=false,optionalAssemblyInfo=false+ diff --git a/.github/workflows/lint-oas.yml b/.github/workflows/lint-oas.yml index 6204f0c..d7b453c 100644 --- a/.github/workflows/lint-oas.yml +++ b/.github/workflows/lint-oas.yml @@ -12,11 +12,11 @@ on: jobs: run: runs-on: ubuntu-latest - strategy: - matrix: - version: [ 'v1' ] + # strategy: + # matrix: + # version: [ 'v1' ] - name: Run with version $ + name: Run with version v1 steps: - uses: actions/checkout@v4 diff --git a/src/open_producten/producttypes/router.py b/src/open_producten/producttypes/router.py index 0701f25..823a98a 100644 --- a/src/open_producten/producttypes/router.py +++ b/src/open_producten/producttypes/router.py @@ -1,6 +1,7 @@ from rest_framework.routers import DefaultRouter from open_producten.producttypes.views import ( + CategoryQuestionViewSet, CategoryViewSet, ProductTypeFieldViewSet, ProductTypeLinkViewSet, @@ -33,3 +34,8 @@ ) ProductTypesRouter.register("categories", CategoryViewSet, basename="category") +ProductTypesRouter.register( + "categories/(?P[^/.]+)/questions", + CategoryQuestionViewSet, + basename="category-question", +) diff --git a/src/open_producten/producttypes/serializers/category.py b/src/open_producten/producttypes/serializers/category.py index 7cbb261..1dd9531 100644 --- a/src/open_producten/producttypes/serializers/category.py +++ b/src/open_producten/producttypes/serializers/category.py @@ -1,7 +1,6 @@ from rest_framework import serializers from open_producten.producttypes.models import Category, ProductType - from .children import QuestionSerializer, UpnSerializer @@ -14,9 +13,56 @@ class Meta: class CategorySerializer(serializers.ModelSerializer): + parent_category = serializers.PrimaryKeyRelatedField( + queryset=Category.objects.all(), + allow_null=True, + write_only=True, + ) product_types = SimpleProductTypeSerializer(many=True, read_only=True) - questions = QuestionSerializer(many=True) + questions = QuestionSerializer(many=True, read_only=True) + + product_type_ids = serializers.PrimaryKeyRelatedField( + many=True, + queryset=ProductType.objects.all(), + default=[], + write_only=True, + ) class Meta: model = Category - exclude = ("id", "path", "depth", "numchild") + exclude = ("path", "depth", "numchild") + + def create(self, validated_data): + product_types = validated_data.pop("product_type_ids") + parent_category = validated_data.pop("parent_category") + + if parent_category: + category = parent_category.add_child(**validated_data) + else: + category = Category.add_root(**validated_data) + + category.product_types.set(product_types) + category.save() + + return category + + def update(self, instance, validated_data): + product_types = validated_data.pop("product_type_ids") + parent_category = validated_data.pop("parent_category") + + instance_parent = instance.get_parent() + + if parent_category is None and instance_parent is not None: + last_root = Category.get_last_root_node() + instance.move(last_root, "last-sibling") + + elif parent_category != instance_parent: + instance.move(parent_category, "last-child") + + instance.refresh_from_db() + + instance = super().update(instance, validated_data) + instance.product_types.set(product_types) + instance.save() + + return instance diff --git a/src/open_producten/producttypes/serializers/producttype.py b/src/open_producten/producttypes/serializers/producttype.py index d70a429..64c0fb4 100644 --- a/src/open_producten/producttypes/serializers/producttype.py +++ b/src/open_producten/producttypes/serializers/producttype.py @@ -22,7 +22,7 @@ class Meta: class ProductTypeSerializer(serializers.ModelSerializer): tags = TagSerializer(many=True, read_only=True) tag_ids = serializers.PrimaryKeyRelatedField( - many=True, queryset=Tag.objects.all(), default=[] + many=True, queryset=Tag.objects.all(), default=[], write_only=True ) related_product_types = serializers.PrimaryKeyRelatedField( @@ -33,7 +33,7 @@ class ProductTypeSerializer(serializers.ModelSerializer): queryset=UniformProductName.objects.all() ) - conditions = ConditionSerializer(many=True, default=[], read_only=True) + conditions = ConditionSerializer(many=True, read_only=True) condition_ids = serializers.PrimaryKeyRelatedField( many=True, write_only=True, queryset=Condition.objects.all(), default=[] ) @@ -59,36 +59,36 @@ class Meta: def create(self, validated_data): uniform_product_name_id = validated_data.pop("uniform_product_name") - related_product_type_ids = validated_data.pop("related_product_types") - category_ids = validated_data.pop("category_ids") - condition_ids = validated_data.pop("condition_ids") - tag_ids = validated_data.pop("tag_ids") + related_product_types = validated_data.pop("related_product_types") + categories = validated_data.pop("category_ids") + conditions = validated_data.pop("condition_ids") + tags = validated_data.pop("tag_ids") product_type = ProductType.objects.create( **validated_data, uniform_product_name=uniform_product_name_id ) - product_type.related_product_types.set(related_product_type_ids) - product_type.categories.set(category_ids) - product_type.tags.set(tag_ids) - product_type.conditions.set(condition_ids) + product_type.related_product_types.set(related_product_types) + product_type.categories.set(categories) + product_type.tags.set(tags) + product_type.conditions.set(conditions) product_type.save() return product_type def update(self, instance, validated_data): - related_product_type_ids = validated_data.pop("related_product_types") - category_ids = validated_data.pop("category_ids") - condition_ids = validated_data.pop("condition_ids") - tag_ids = validated_data.pop("tag_ids") + related_product_types = validated_data.pop("related_product_types") + categories = validated_data.pop("category_ids") + conditions = validated_data.pop("condition_ids") + tags = validated_data.pop("tag_ids") instance = super().update(instance, validated_data) - instance.related_product_types.set(related_product_type_ids) - instance.categories.set(category_ids) - instance.tags.set(tag_ids) - instance.conditions.set(condition_ids) + instance.related_product_types.set(related_product_types) + instance.categories.set(categories) + instance.tags.set(tags) + instance.conditions.set(conditions) instance.save() diff --git a/src/open_producten/producttypes/tests/test_category_viewset.py b/src/open_producten/producttypes/tests/test_category_viewset.py new file mode 100644 index 0000000..5f5034b --- /dev/null +++ b/src/open_producten/producttypes/tests/test_category_viewset.py @@ -0,0 +1,65 @@ +from rest_framework.test import APITestCase + +from .factories import CategoryFactory, ProductTypeFactory +from ..models import Category + + +class TestCategoryViewSet(APITestCase): + + def setUp(self): + self.data = { + "name": "test-category", + "parent_category": None, + } + + def test_create_minimal_category(self): + response = self.client.post("/api/v1/categories/", self.data, format="json") + + self.assertEqual(response.status_code, 201) + self.assertEqual(Category.objects.count(), 1) + + def test_create_category_with_parent(self): + parent = CategoryFactory.create() + data = self.data | {"parent_category": parent.id} + + response = self.client.post("/api/v1/categories/", data, format="json") + + self.assertEqual(response.status_code, 201) + self.assertEqual(Category.objects.count(), 2) + self.assertEqual(Category.objects.get(id=response.data["id"]).get_parent(), parent) + + def test_create_category_with_product_type(self): + product_type = ProductTypeFactory.create() + data = self.data | {"product_type_ids": [product_type.id]} + + response = self.client.post("/api/v1/categories/", data, format="json") + + self.assertEqual(response.status_code, 201) + self.assertEqual(Category.objects.count(), 1) + self.assertEqual(Category.objects.first().product_types.first(), product_type) + + def test_change_parent(self): + new_parent = CategoryFactory.create() + category = CategoryFactory.create() + + data = self.data | {"parent_category": new_parent.id} + response = self.client.put( + f"/api/v1/categories/{category.id}/", data, format="json" + ) + + category.refresh_from_db() + + self.assertEqual(response.status_code, 200) + self.assertEqual(category.get_parent(), new_parent) + + def test_add_question_to_product_type(self): + category = CategoryFactory.create() + + data = {"question": "18?", "answer": "eligible"} + response = self.client.post( + f"/api/v1/categories/{category.id}/questions/", data, format="json" + ) + + self.assertEqual(response.status_code, 201) + self.assertEqual(Category.objects.count(), 1) + self.assertEqual(category.questions.first().question, "18?") diff --git a/src/open_producten/producttypes/tests/test_producttype_viewset.py b/src/open_producten/producttypes/tests/test_producttype_viewset.py index c0b62f2..8e766d0 100644 --- a/src/open_producten/producttypes/tests/test_producttype_viewset.py +++ b/src/open_producten/producttypes/tests/test_producttype_viewset.py @@ -17,6 +17,7 @@ class TestProducttypeViewSet(APITestCase): + def setUp(self): upn = UniformProductNameFactory.create() diff --git a/src/open_producten/producttypes/views.py b/src/open_producten/producttypes/views.py index e328e23..4cbb25e 100644 --- a/src/open_producten/producttypes/views.py +++ b/src/open_producten/producttypes/views.py @@ -20,13 +20,17 @@ from open_producten.producttypes.serializers.producttype import ProductTypeSerializer -class ProductTypeViewSet(ModelViewSet): +class BaseModelViewSet(ModelViewSet): + http_method_names = ["get", "post", "put", "delete"] + + +class ProductTypeViewSet(BaseModelViewSet): queryset = ProductType.objects.all() serializer_class = ProductTypeSerializer lookup_field = "id" -class ProductTypeChildViewSet(ModelViewSet): +class ProductTypeChildViewSet(BaseModelViewSet): def get_queryset(self): return self.queryset.filter(product_type_id=self.kwargs["id"]) @@ -57,7 +61,21 @@ class ProductTypeQuestionViewSet(ProductTypeChildViewSet): serializer_class = QuestionSerializer -class CategoryViewSet(ModelViewSet): +class CategoryViewSet(BaseModelViewSet): queryset = Category.objects.all() serializer_class = CategorySerializer lookup_field = "id" + + +class CategoryChildViewSet(BaseModelViewSet): + + def get_queryset(self): + return self.queryset.filter(category_id=self.kwargs["id"]) + + def perform_create(self, serializer): + serializer.save(category=get_object_or_404(Category, id=self.kwargs["id"])) + + +class CategoryQuestionViewSet(CategoryChildViewSet): + queryset = Question.objects.all() + serializer_class = QuestionSerializer diff --git a/src/openapi.yaml b/src/openapi.yaml index b97f9fc..95557ff 100644 --- a/src/openapi.yaml +++ b/src/openapi.yaml @@ -10,11 +10,11 @@ paths: get: operationId: categories_list tags: - - categories + - categories security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: @@ -27,7 +27,7 @@ paths: post: operationId: categories_create tags: - - categories + - categories requestBody: content: application/json: @@ -35,9 +35,9 @@ paths: $ref: '#/components/schemas/Category' required: true security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '201': content: @@ -45,22 +45,23 @@ paths: schema: $ref: '#/components/schemas/Category' description: '' - /api/v1/categories/{slug}/: + /api/v1/categories/{id}/: get: operationId: categories_retrieve parameters: - - in: path - name: slug - schema: - type: string - description: Slug of the category - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Category. + required: true tags: - - categories + - categories security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: @@ -71,14 +72,15 @@ paths: put: operationId: categories_update parameters: - - in: path - name: slug - schema: - type: string - description: Slug of the category - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Category. + required: true tags: - - categories + - categories requestBody: content: application/json: @@ -86,9 +88,9 @@ paths: $ref: '#/components/schemas/Category' required: true security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: @@ -96,48 +98,149 @@ paths: schema: $ref: '#/components/schemas/Category' description: '' - patch: - operationId: categories_partial_update + delete: + operationId: categories_destroy parameters: - - in: path - name: slug - schema: - type: string - description: Slug of the category + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Category. + required: true + tags: + - categories + security: + - cookieAuth: [ ] + - basicAuth: [ ] + - { } + responses: + '204': + description: No response body + /api/v1/categories/{id}/questions/: + get: + operationId: categories_questions_list + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Question. + required: true + tags: + - categories + security: + - cookieAuth: [ ] + - basicAuth: [ ] + - { } + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Question' + description: '' + post: + operationId: categories_questions_create + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Question. + required: true + tags: + - categories + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Question' required: true + security: + - cookieAuth: [ ] + - basicAuth: [ ] + - { } + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/Question' + description: '' + /api/v1/categories/{id}/questions/{id}/: + get: + operationId: categories_questions_retrieve + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Question. + required: true + tags: + - categories + security: + - cookieAuth: [ ] + - basicAuth: [ ] + - { } + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/Question' + description: '' + put: + operationId: categories_questions_update + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Question. + required: true tags: - - categories + - categories requestBody: content: application/json: schema: - $ref: '#/components/schemas/PatchedCategory' + $ref: '#/components/schemas/Question' + required: true security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: application/json: schema: - $ref: '#/components/schemas/Category' + $ref: '#/components/schemas/Question' description: '' delete: - operationId: categories_destroy + operationId: categories_questions_destroy parameters: - - in: path - name: slug - schema: - type: string - description: Slug of the category - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Question. + required: true tags: - - categories + - categories security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '204': description: No response body @@ -145,11 +248,11 @@ paths: get: operationId: producttypes_list tags: - - producttypes + - producttypes security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: @@ -162,7 +265,7 @@ paths: post: operationId: producttypes_create tags: - - producttypes + - producttypes requestBody: content: application/json: @@ -170,9 +273,9 @@ paths: $ref: '#/components/schemas/ProductType' required: true security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '201': content: @@ -180,22 +283,23 @@ paths: schema: $ref: '#/components/schemas/ProductType' description: '' - /api/v1/producttypes/{slug}/: + /api/v1/producttypes/{id}/: get: operationId: producttypes_retrieve parameters: - - in: path - name: slug - schema: - type: string - description: Slug of the product type - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Product type. + required: true tags: - - producttypes + - producttypes security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: @@ -206,14 +310,15 @@ paths: put: operationId: producttypes_update parameters: - - in: path - name: slug - schema: - type: string - description: Slug of the product type - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Product type. + required: true tags: - - producttypes + - producttypes requestBody: content: application/json: @@ -221,36 +326,9 @@ paths: $ref: '#/components/schemas/ProductType' required: true security: - - cookieAuth: [] - - basicAuth: [] - - {} - responses: - '200': - content: - application/json: - schema: - $ref: '#/components/schemas/ProductType' - description: '' - patch: - operationId: producttypes_partial_update - parameters: - - in: path - name: slug - schema: - type: string - description: Slug of the product type - required: true - tags: - - producttypes - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/PatchedProductType' - security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: @@ -261,36 +339,39 @@ paths: delete: operationId: producttypes_destroy parameters: - - in: path - name: slug - schema: - type: string - description: Slug of the product type - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Product type. + required: true tags: - - producttypes + - producttypes security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '204': description: No response body - /api/v1/producttypes/{slug}/fields/: + /api/v1/producttypes/{id}/fields/: get: operationId: producttypes_fields_list parameters: - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Field. + required: true tags: - - producttypes + - producttypes security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: @@ -303,13 +384,15 @@ paths: post: operationId: producttypes_fields_create parameters: - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Field. + required: true tags: - - producttypes + - producttypes requestBody: content: application/json: @@ -317,9 +400,9 @@ paths: $ref: '#/components/schemas/Field' required: true security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '201': content: @@ -327,27 +410,23 @@ paths: schema: $ref: '#/components/schemas/Field' description: '' - /api/v1/producttypes/{slug}/fields/{id}/: + /api/v1/producttypes/{id}/fields/{id}/: get: operationId: producttypes_fields_retrieve parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this Field. - required: true - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Field. + required: true tags: - - producttypes + - producttypes security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: @@ -358,19 +437,15 @@ paths: put: operationId: producttypes_fields_update parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this Field. - required: true - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Field. + required: true tags: - - producttypes + - producttypes requestBody: content: application/json: @@ -378,41 +453,9 @@ paths: $ref: '#/components/schemas/Field' required: true security: - - cookieAuth: [] - - basicAuth: [] - - {} - responses: - '200': - content: - application/json: - schema: - $ref: '#/components/schemas/Field' - description: '' - patch: - operationId: producttypes_fields_partial_update - parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this Field. - required: true - - in: path - name: slug - schema: - type: string - required: true - tags: - - producttypes - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/PatchedField' - security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: @@ -423,41 +466,39 @@ paths: delete: operationId: producttypes_fields_destroy parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this Field. - required: true - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Field. + required: true tags: - - producttypes + - producttypes security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '204': description: No response body - /api/v1/producttypes/{slug}/links/: + /api/v1/producttypes/{id}/links/: get: operationId: producttypes_links_list parameters: - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Product type link. + required: true tags: - - producttypes + - producttypes security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: @@ -470,13 +511,15 @@ paths: post: operationId: producttypes_links_create parameters: - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Product type link. + required: true tags: - - producttypes + - producttypes requestBody: content: application/json: @@ -484,9 +527,9 @@ paths: $ref: '#/components/schemas/Link' required: true security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '201': content: @@ -494,27 +537,23 @@ paths: schema: $ref: '#/components/schemas/Link' description: '' - /api/v1/producttypes/{slug}/links/{id}/: + /api/v1/producttypes/{id}/links/{id}/: get: operationId: producttypes_links_retrieve parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this Product type link. - required: true - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Product type link. + required: true tags: - - producttypes + - producttypes security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: @@ -525,19 +564,15 @@ paths: put: operationId: producttypes_links_update parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this Product type link. - required: true - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Product type link. + required: true tags: - - producttypes + - producttypes requestBody: content: application/json: @@ -545,41 +580,9 @@ paths: $ref: '#/components/schemas/Link' required: true security: - - cookieAuth: [] - - basicAuth: [] - - {} - responses: - '200': - content: - application/json: - schema: - $ref: '#/components/schemas/Link' - description: '' - patch: - operationId: producttypes_links_partial_update - parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this Product type link. - required: true - - in: path - name: slug - schema: - type: string - required: true - tags: - - producttypes - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/PatchedLink' - security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: @@ -590,41 +593,39 @@ paths: delete: operationId: producttypes_links_destroy parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this Product type link. - required: true - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Product type link. + required: true tags: - - producttypes + - producttypes security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '204': description: No response body - /api/v1/producttypes/{slug}/prices/: + /api/v1/producttypes/{id}/prices/: get: operationId: producttypes_prices_list parameters: - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Price. + required: true tags: - - producttypes + - producttypes security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: @@ -637,13 +638,15 @@ paths: post: operationId: producttypes_prices_create parameters: - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Price. + required: true tags: - - producttypes + - producttypes requestBody: content: application/json: @@ -651,9 +654,9 @@ paths: $ref: '#/components/schemas/Price' required: true security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '201': content: @@ -661,27 +664,23 @@ paths: schema: $ref: '#/components/schemas/Price' description: '' - /api/v1/producttypes/{slug}/prices/{id}/: + /api/v1/producttypes/{id}/prices/{id}/: get: operationId: producttypes_prices_retrieve parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this Price. - required: true - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Price. + required: true tags: - - producttypes + - producttypes security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: @@ -692,19 +691,15 @@ paths: put: operationId: producttypes_prices_update parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this Price. - required: true - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Price. + required: true tags: - - producttypes + - producttypes requestBody: content: application/json: @@ -712,41 +707,9 @@ paths: $ref: '#/components/schemas/Price' required: true security: - - cookieAuth: [] - - basicAuth: [] - - {} - responses: - '200': - content: - application/json: - schema: - $ref: '#/components/schemas/Price' - description: '' - patch: - operationId: producttypes_prices_partial_update - parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this Price. - required: true - - in: path - name: slug - schema: - type: string - required: true - tags: - - producttypes - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/PatchedPrice' - security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: @@ -757,41 +720,39 @@ paths: delete: operationId: producttypes_prices_destroy parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this Price. - required: true - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Price. + required: true tags: - - producttypes + - producttypes security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '204': description: No response body - /api/v1/producttypes/{slug}/questions/: + /api/v1/producttypes/{id}/questions/: get: operationId: producttypes_questions_list parameters: - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Question. + required: true tags: - - producttypes + - producttypes security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: @@ -804,13 +765,15 @@ paths: post: operationId: producttypes_questions_create parameters: - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Question. + required: true tags: - - producttypes + - producttypes requestBody: content: application/json: @@ -818,9 +781,9 @@ paths: $ref: '#/components/schemas/Question' required: true security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '201': content: @@ -828,27 +791,23 @@ paths: schema: $ref: '#/components/schemas/Question' description: '' - /api/v1/producttypes/{slug}/questions/{id}/: + /api/v1/producttypes/{id}/questions/{id}/: get: operationId: producttypes_questions_retrieve parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this Question. - required: true - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Question. + required: true tags: - - producttypes + - producttypes security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: @@ -859,19 +818,15 @@ paths: put: operationId: producttypes_questions_update parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this Question. - required: true - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Question. + required: true tags: - - producttypes + - producttypes requestBody: content: application/json: @@ -879,41 +834,9 @@ paths: $ref: '#/components/schemas/Question' required: true security: - - cookieAuth: [] - - basicAuth: [] - - {} - responses: - '200': - content: - application/json: - schema: - $ref: '#/components/schemas/Question' - description: '' - patch: - operationId: producttypes_questions_partial_update - parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this Question. - required: true - - in: path - name: slug - schema: - type: string - required: true - tags: - - producttypes - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/PatchedQuestion' - security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '200': content: @@ -924,23 +847,19 @@ paths: delete: operationId: producttypes_questions_destroy parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this Question. - required: true - - in: path - name: slug - schema: - type: string - required: true + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Question. + required: true tags: - - producttypes + - producttypes security: - - cookieAuth: [] - - basicAuth: [] - - {} + - cookieAuth: [ ] + - basicAuth: [ ] + - { } responses: '204': description: No response body @@ -949,6 +868,15 @@ components: Category: type: object properties: + id: + type: string + format: uuid + readOnly: true + parent_category: + type: string + format: uuid + writeOnly: true + nullable: true product_types: type: array items: @@ -958,31 +886,32 @@ components: type: array items: $ref: '#/components/schemas/Question' + readOnly: true + product_type_ids: + type: array + items: + type: string + format: uuid + writeOnly: true + default: [ ] published: type: boolean - description: Whether the object is accessible with the api. + description: Whether the object is accessible through the API. created_on: type: string format: date-time readOnly: true - description: The date the object was created. This field is automatically - set. + description: The datetime at which the object was created. updated_on: type: string format: date-time readOnly: true - description: The date when the object was last changed. This field is automatically - set. + description: The datetime at which the object was last changed. name: type: string title: Naam description: Name of the category maxLength: 100 - slug: - type: string - description: Slug of the category - maxLength: 100 - pattern: ^[-a-zA-Z0-9_]+$ description: type: string description: Description of the category @@ -998,30 +927,16 @@ components: title: Afbeelding description: Image of the category required: - - created_on - - name - - product_types - - questions - - slug - - updated_on + - created_on + - id + - name + - parent_category + - product_types + - questions + - updated_on Condition: type: object properties: - published: - type: boolean - description: Whether the object is accessible with the api. - created_on: - type: string - format: date-time - readOnly: true - description: The date the object was created. This field is automatically - set. - updated_on: - type: string - format: date-time - readOnly: true - description: The date when the object was last changed. This field is automatically - set. name: type: string title: Naam @@ -1037,12 +952,10 @@ components: type: string description: Description how not to meet the condition required: - - created_on - - name - - negative_text - - positive_text - - question - - updated_on + - name + - negative_text + - positive_text + - question Field: type: object properties: @@ -1050,14 +963,14 @@ components: type: string title: Naam description: The name of the field - maxLength: 100 + maxLength: 255 description: type: string description: Short description of the field maxLength: 300 type: allOf: - - $ref: '#/components/schemas/TypeEnum' + - $ref: '#/components/schemas/TypeEnum' description: |- The formio type of the field @@ -1092,8 +1005,8 @@ components: nullable: true description: The Choices that can be selected in the form required: - - description - - name + - description + - name Link: type: object properties: @@ -1108,267 +1021,8 @@ components: description: Url of the link maxLength: 200 required: - - name - - url - PatchedCategory: - type: object - properties: - product_types: - type: array - items: - $ref: '#/components/schemas/SimpleProductType' - readOnly: true - questions: - type: array - items: - $ref: '#/components/schemas/Question' - published: - type: boolean - description: Whether the object is accessible with the api. - created_on: - type: string - format: date-time - readOnly: true - description: The date the object was created. This field is automatically - set. - updated_on: - type: string - format: date-time - readOnly: true - description: The date when the object was last changed. This field is automatically - set. - name: - type: string - title: Naam - description: Name of the category - maxLength: 100 - slug: - type: string - description: Slug of the category - maxLength: 100 - pattern: ^[-a-zA-Z0-9_]+$ - description: - type: string - description: Description of the category - icon: - type: string - format: uri - nullable: true - description: Icon of the category - image: - type: string - format: uri - nullable: true - title: Afbeelding - description: Image of the category - PatchedField: - type: object - properties: - name: - type: string - title: Naam - description: The name of the field - maxLength: 100 - description: - type: string - description: Short description of the field - maxLength: 300 - type: - allOf: - - $ref: '#/components/schemas/TypeEnum' - description: |- - The formio type of the field - - * `bsn` - Bsn - * `checkbox` - Checkbox - * `Cosign` - Cosign - * `currency` - Currency - * `date` - Date - * `datetime` - Datetime - * `email` - Email - * `file` - File - * `iban` - Iban - * `licenseplate` - License Plate - * `map` - Map - * `number` - Number - * `password` - Password - * `phoneNumber` - Phone Number - * `postcode` - Postcode - * `radio` - Radio - * `select` - Select - * `selectBoxes` - Select Boxes - * `signature` - Signature - * `textfield` - Textfield - * `time` - Time - is_required: - type: boolean - choices: - type: array - items: - type: string - maxLength: 100 - nullable: true - description: The Choices that can be selected in the form - PatchedLink: - type: object - properties: - name: - type: string - title: Naam - description: Name for the link - maxLength: 100 - url: - type: string - format: uri - description: Url of the link - maxLength: 200 - PatchedPrice: - type: object - properties: - options: - type: array - items: - $ref: '#/components/schemas/PriceOption' - default: [] - start_date: - type: string - format: date - description: The start date for this price - PatchedProductType: - type: object - properties: - tags: - type: array - items: - $ref: '#/components/schemas/Tag' - readOnly: true - tag_slugs: - type: array - items: - type: string - description: Slug of the tag - default: [] - default: [] - related_product_types: - type: array - items: - type: string - description: Slug of the product type - default: [] - default: [] - uniform_product_name: - type: integer - conditions: - type: array - items: - $ref: '#/components/schemas/Condition' - readOnly: true - default: [] - condition_ids: - type: array - items: - type: integer - writeOnly: true - default: [] - writeOnly: true - default: [] - categories: - type: array - items: - $ref: '#/components/schemas/SimpleCategory' - readOnly: true - category_slugs: - type: array - items: - type: string - description: Slug of the category - writeOnly: true - default: [] - writeOnly: true - default: [] - questions: - type: array - items: - $ref: '#/components/schemas/Question' - readOnly: true - fields: - type: array - items: - $ref: '#/components/schemas/Field' - readOnly: true - prices: - type: array - items: - $ref: '#/components/schemas/Price' - readOnly: true - links: - type: array - items: - $ref: '#/components/schemas/Link' - readOnly: true - published: - type: boolean - description: Whether the object is accessible with the api. - created_on: - type: string - format: date-time - readOnly: true - description: The date the object was created. This field is automatically - set. - updated_on: - type: string - format: date-time - readOnly: true - description: The date when the object was last changed. This field is automatically - set. - name: - type: string - title: Naam - description: Name of the product type - maxLength: 100 - slug: - type: string - description: Slug of the product type - maxLength: 100 - pattern: ^[-a-zA-Z0-9_]+$ - summary: - type: string - title: Samenvatting - description: Short description of the product, limited to 300 characters. - maxLength: 300 - icon: - type: string - format: uri - nullable: true - description: Icon of the product type - image: - type: string - format: uri - nullable: true - title: Afbeelding - description: Main image of the product type - form_link: - type: string - format: uri - description: Action link to request the product. - maxLength: 200 - content: - type: string - description: Product content with build-in WYSIWYG editor. - keywords: - type: array - items: - type: string - maxLength: 100 - description: List of keywords for search - PatchedQuestion: - type: object - properties: - question: - type: string - maxLength: 250 - answer: - type: string + - name + - url Price: type: object properties: @@ -1376,81 +1030,84 @@ components: type: array items: $ref: '#/components/schemas/PriceOption' - default: [] - start_date: + default: [ ] + valid_from: type: string format: date - description: The start date for this price + title: Start date + description: The date at which this price is valid required: - - start_date + - valid_from PriceOption: type: object properties: id: - type: integer - cost: + type: string + format: uuid + amount: type: string format: decimal pattern: ^-?\d{0,6}(?:\.\d{0,2})?$ + title: Price description: The cost of the price option description: type: string description: Short description of the option maxLength: 100 required: - - description + - description ProductType: type: object properties: + id: + type: string + format: uuid + readOnly: true tags: type: array items: $ref: '#/components/schemas/Tag' readOnly: true - tag_slugs: + tag_ids: type: array items: type: string - description: Slug of the tag - default: [] - default: [] + format: uuid + writeOnly: true + default: [ ] related_product_types: type: array items: type: string - description: Slug of the product type - default: [] - default: [] + format: uuid + default: [ ] uniform_product_name: - type: integer + type: string + format: uuid conditions: type: array items: $ref: '#/components/schemas/Condition' readOnly: true - default: [] condition_ids: type: array items: - type: integer - writeOnly: true - default: [] + type: string + format: uuid writeOnly: true - default: [] + default: [ ] categories: type: array items: $ref: '#/components/schemas/SimpleCategory' readOnly: true - category_slugs: + category_ids: type: array items: type: string - description: Slug of the category - writeOnly: true - default: [] + format: uuid writeOnly: true - default: [] + default: [ ] questions: type: array items: @@ -1473,33 +1130,26 @@ components: readOnly: true published: type: boolean - description: Whether the object is accessible with the api. + description: Whether the object is accessible through the API. created_on: type: string format: date-time readOnly: true - description: The date the object was created. This field is automatically - set. + description: The datetime at which the object was created. updated_on: type: string format: date-time readOnly: true - description: The date when the object was last changed. This field is automatically - set. + description: The datetime at which the object was last changed. name: type: string title: Naam description: Name of the product type maxLength: 100 - slug: - type: string - description: Slug of the product type - maxLength: 100 - pattern: ^[-a-zA-Z0-9_]+$ summary: type: string title: Samenvatting - description: Short description of the product, limited to 300 characters. + description: Short description of the product type, limited to 300 characters. maxLength: 300 icon: type: string @@ -1515,11 +1165,11 @@ components: form_link: type: string format: uri - description: Action link to request the product. + description: Action link to request the product type. maxLength: 200 content: type: string - description: Product content with build-in WYSIWYG editor. + description: Product type content with build-in WYSIWYG editor. keywords: type: array items: @@ -1527,19 +1177,19 @@ components: maxLength: 100 description: List of keywords for search required: - - categories - - conditions - - content - - created_on - - fields - - links - - name - - prices - - questions - - slug - - tags - - uniform_product_name - - updated_on + - categories + - conditions + - content + - created_on + - fields + - id + - links + - name + - prices + - questions + - tags + - uniform_product_name + - updated_on Question: type: object properties: @@ -1549,36 +1199,29 @@ components: answer: type: string required: - - answer - - question + - answer + - question SimpleCategory: type: object properties: published: type: boolean - description: Whether the object is accessible with the api. + description: Whether the object is accessible through the API. created_on: type: string format: date-time readOnly: true - description: The date the object was created. This field is automatically - set. + description: The datetime at which the object was created. updated_on: type: string format: date-time readOnly: true - description: The date when the object was last changed. This field is automatically - set. + description: The datetime at which the object was last changed. name: type: string title: Naam description: Name of the category maxLength: 100 - slug: - type: string - description: Slug of the category - maxLength: 100 - pattern: ^[-a-zA-Z0-9_]+$ description: type: string description: Description of the category @@ -1594,10 +1237,9 @@ components: title: Afbeelding description: Image of the category required: - - created_on - - name - - slug - - updated_on + - created_on + - name + - updated_on SimpleProductType: type: object properties: @@ -1605,33 +1247,26 @@ components: $ref: '#/components/schemas/Upn' published: type: boolean - description: Whether the object is accessible with the api. + description: Whether the object is accessible through the API. created_on: type: string format: date-time readOnly: true - description: The date the object was created. This field is automatically - set. + description: The datetime at which the object was created. updated_on: type: string format: date-time readOnly: true - description: The date when the object was last changed. This field is automatically - set. + description: The datetime at which the object was last changed. name: type: string title: Naam description: Name of the product type maxLength: 100 - slug: - type: string - description: Slug of the product type - maxLength: 100 - pattern: ^[-a-zA-Z0-9_]+$ summary: type: string title: Samenvatting - description: Short description of the product, limited to 300 characters. + description: Short description of the product type, limited to 300 characters. maxLength: 300 icon: type: string @@ -1647,11 +1282,11 @@ components: form_link: type: string format: uri - description: Action link to request the product. + description: Action link to request the product type. maxLength: 200 content: type: string - description: Product content with build-in WYSIWYG editor. + description: Product type content with build-in WYSIWYG editor. keywords: type: array items: @@ -1659,12 +1294,11 @@ components: maxLength: 100 description: List of keywords for search required: - - content - - created_on - - name - - slug - - uniform_product_name - - updated_on + - content + - created_on + - name + - uniform_product_name + - updated_on Tag: type: object properties: @@ -1675,20 +1309,14 @@ components: title: Naam description: Name of the tag maxLength: 100 - slug: - type: string - description: Slug of the tag - maxLength: 100 - pattern: ^[-a-zA-Z0-9_]+$ icon: type: string format: uri nullable: true description: Icon of the tag required: - - name - - slug - - type + - name + - type TagType: type: object properties: @@ -1698,30 +1326,30 @@ components: description: Name of the tag type maxLength: 100 required: - - name + - name TypeEnum: enum: - - bsn - - checkbox - - Cosign - - currency - - date - - datetime - - email - - file - - iban - - licenseplate - - map - - number - - password - - phoneNumber - - postcode - - radio - - select - - selectBoxes - - signature - - textfield - - time + - bsn + - checkbox + - Cosign + - currency + - date + - datetime + - email + - file + - iban + - licenseplate + - map + - number + - password + - phoneNumber + - postcode + - radio + - select + - selectBoxes + - signature + - textfield + - time type: string description: |- * `bsn` - Bsn @@ -1759,7 +1387,7 @@ components: description: Url to the upn definition. maxLength: 200 required: - - name + - name securitySchemes: basicAuth: type: http