From 726d801d6f8c8080c6c84cdd5c6b343c7b696c2e Mon Sep 17 00:00:00 2001 From: WellingtonLFaria Date: Sun, 20 Oct 2024 20:21:44 -0300 Subject: [PATCH] docs: documentando os endpoints de alertas, estacoes e usuarios --- src/tupan/alertas/serializers.py | 11 ++++- src/tupan/alertas/views.py | 72 +++++++++++++++++++++++++++++-- src/tupan/estacoes/serializers.py | 3 ++ src/tupan/estacoes/views.py | 15 +++++++ src/tupan/tupan/urls.py | 2 +- src/tupan/usuarios/urls.py | 6 +-- src/tupan/usuarios/views.py | 67 +++++++++++++++------------- 7 files changed, 136 insertions(+), 40 deletions(-) diff --git a/src/tupan/alertas/serializers.py b/src/tupan/alertas/serializers.py index ec025cf..5ff8ba7 100644 --- a/src/tupan/alertas/serializers.py +++ b/src/tupan/alertas/serializers.py @@ -1,5 +1,6 @@ from rest_framework import serializers -from .models import Alerta, Medicao +from .models import Alerta, Medicao, HistoricoAlerta +from estacoes.serializers import EstacaoParametroSerializer class AlertaSerializer(serializers.ModelSerializer): class Meta: @@ -8,6 +9,12 @@ class Meta: read_only_fields = ['estacao_parametro'] class MedicaoSerializer(serializers.ModelSerializer): + estacao_parametro = EstacaoParametroSerializer() class Meta: model = Medicao - fields = ('id', 'timestamp', 'timestamp_convertido', 'dados', 'estacao_parametro') \ No newline at end of file + fields = ('id', 'timestamp', 'timestamp_convertido', 'dados', 'estacao_parametro') + +class HistoricoAlertaSerializer(serializers.ModelSerializer): + class Meta: + model = HistoricoAlerta + fields = '__all__' \ No newline at end of file diff --git a/src/tupan/alertas/views.py b/src/tupan/alertas/views.py index 99d2445..7191bd5 100644 --- a/src/tupan/alertas/views.py +++ b/src/tupan/alertas/views.py @@ -1,16 +1,22 @@ from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status +from drf_spectacular.utils import extend_schema, OpenApiRequest, OpenApiResponse from django.http import JsonResponse import json from estacoes.models import EstacaoParametro -from .serializers import AlertaSerializer, MedicaoSerializer +from .serializers import AlertaSerializer, MedicaoSerializer, HistoricoAlertaSerializer from .models import Alerta, HistoricoAlerta, Medicao from django.core.exceptions import ValidationError class AlertasView(APIView): - + @extend_schema( + responses={ + 200: OpenApiResponse(AlertaSerializer(many=True)), + 400: OpenApiResponse(description="Parâmetro inválido para 'ativo'") + } + ) def get(self, request, *args, **kwargs): try: # Obtém o valor do parâmetro 'ativo' da requisição, se disponível @@ -40,7 +46,13 @@ def get(self, request, *args, **kwargs): 'data': f"{e}" }, status=500) - + @extend_schema( + request=OpenApiRequest(AlertaSerializer), + responses={ + 201: OpenApiResponse(AlertaSerializer), + 400: OpenApiResponse(description="Erro ao cadastrar um novo alerta") + } + ) def post(self, request, *args, **kwargs): try: data = json.loads(request.body) @@ -64,6 +76,13 @@ def post(self, request, *args, **kwargs): class AlertasDetalhesView(APIView): + @extend_schema( + responses={ + 200: OpenApiResponse(AlertaSerializer), + 404: OpenApiResponse(description="Alerta não encontrado ou inativo"), + 500: OpenApiResponse(description="Erro ao buscar dados, tente novamente") + } + ) def get(self, request, id, *args, **kwargs): try: alerta = Alerta.objects.filter(id=id, ativo=True).values().first() @@ -74,6 +93,15 @@ def get(self, request, id, *args, **kwargs): except: return JsonResponse({'error': 'Erro ao buscar dados, tente novamente'}, status=500) + @extend_schema( + request=OpenApiRequest(AlertaSerializer), + responses={ + 200: OpenApiResponse(AlertaSerializer), + 400: OpenApiResponse(description="Erro ao atualizar o alerta"), + 404: OpenApiResponse(description="Alerta não encontrado ou inativo"), + 500: OpenApiResponse(description="Erro ao atualizar alerta, tente novamente") + } + ) def put(self, request, id, *args, **kwargs): try: alerta = Alerta.objects.filter(id=id, ativo=True).first() @@ -90,6 +118,13 @@ def put(self, request, id, *args, **kwargs): except: return JsonResponse({'error': 'Erro ao atualizar alerta, tente novamente'}, status=500) + @extend_schema( + responses={ + 200: OpenApiResponse(description="Alerta desativado com sucesso"), + 404: OpenApiResponse(description="Alerta não encontrado"), + 500: OpenApiResponse(description="Erro ao desativar alerta") + } + ) def delete(self, request, id, *args, **kwargs): try: alerta = Alerta.objects.filter(id=id).first() @@ -104,6 +139,12 @@ def delete(self, request, id, *args, **kwargs): class HistoricoAlertaView(APIView): + @extend_schema( + responses={ + 200: OpenApiResponse(HistoricoAlertaSerializer(many=True)), + 500: OpenApiResponse("Erro ao buscar dados") + } + ) def get(self, request, *args, **kwargs): try: historico = HistoricoAlerta.objects.get() @@ -111,6 +152,15 @@ def get(self, request, *args, **kwargs): except: return JsonResponse({'error': 'Erro ao buscar dados, tente novamente'}, status=500) + @extend_schema( + request=OpenApiRequest(HistoricoAlertaSerializer), + responses={ + 200: OpenApiResponse(HistoricoAlertaSerializer), + 400: OpenApiResponse(description="Campos obrigatórios: timestamp, alerta | Dados inválidos"), + 404: OpenApiResponse(description="Alerta não encontrado"), + 500: OpenApiResponse(description="Erro ao salvar histórico") + } + ) def post(self, request, *args, **kwargs): try: data = json.loads(request.body) @@ -139,18 +189,32 @@ def post(self, request, *args, **kwargs): class MedicaoView(APIView): + @extend_schema( + responses={ + 302: OpenApiResponse(MedicaoSerializer(many=True)), + 404: OpenApiResponse(description="Nenhuma medição cadastrada"), + 500: OpenApiResponse(description="Erro ao buscar dados") + } + ) def get(self, request, *args, **kwargs): try: medicoes = Medicao.objects.all() if not medicoes.exists(): return Response({"mensagem": "Nenhuma medição cadastrada"}, status=status.HTTP_404_NOT_FOUND) serializer = MedicaoSerializer(medicoes, many=True) - return Response(serializer.data) + return Response(serializer.data, status=status.HTTP_302_FOUND) except Exception as e: return Response({'error': f'Erro ao buscar dados, tente novamente {e}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) class MedicaoDetalhesView(APIView): + @extend_schema( + responses={ + 302: OpenApiResponse(MedicaoSerializer), + 404: OpenApiResponse(description="Nenhuma medição cadastrada"), + 500: OpenApiResponse(description="Erro ao buscar dados") + } + ) def get(self, request, id, *args, **kwargs): try: medicao = Medicao.objects.get(pk=id) diff --git a/src/tupan/estacoes/serializers.py b/src/tupan/estacoes/serializers.py index d702b33..f155964 100644 --- a/src/tupan/estacoes/serializers.py +++ b/src/tupan/estacoes/serializers.py @@ -12,11 +12,14 @@ class Meta: fields = ('id', 'logradouro', 'bairro', 'cidade', 'estado', 'numero', 'complemento', 'cep', 'latitude', 'longitude', 'criado', 'modificado') class EstacaoSerializer(serializers.ModelSerializer): + endereco = EnderecoSerializer() class Meta: model = Estacao fields = ('id', 'nome', 'endereco', 'topico', 'ativo', 'parametros', 'criado', 'modificado') class EstacaoParametroSerializer(serializers.ModelSerializer): + estacao = EstacaoSerializer() + parametro = ParametroSerializer() class Meta: model = EstacaoParametro fields = ('id', 'estacao', 'parametro') diff --git a/src/tupan/estacoes/views.py b/src/tupan/estacoes/views.py index 2ec303a..a0cbec9 100644 --- a/src/tupan/estacoes/views.py +++ b/src/tupan/estacoes/views.py @@ -19,6 +19,7 @@ def get(self, request, *args, **kwargs): estacoes = estacoes.filter(ativo=ativo) serializer = EstacaoSerializer(estacoes, many=True) return Response(serializer.data) + @extend_schema( request=OpenApiRequest(EstacaoSerializer), responses={ @@ -94,6 +95,7 @@ def put(self, request, pk, *args, **kwargs): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + @extend_schema( responses={ 204: OpenApiResponse(description="Estação deletada com sucesso"), @@ -119,6 +121,7 @@ def get(self, request, *args, **kwargs): enderecos = Endereco.objects.all() serializer = EnderecoSerializer(enderecos, many=True) return Response(serializer.data) + @extend_schema( request=OpenApiRequest(EnderecoSerializer), responses={ @@ -147,6 +150,7 @@ def get(self, request, pk, *args, **kwargs): return Response(status=status.HTTP_404_NOT_FOUND) serializer = EnderecoSerializer(endereco) return Response(serializer.data) + @extend_schema( request=OpenApiRequest(EnderecoSerializer), responses={ @@ -165,6 +169,7 @@ def put(self, request, pk, *args, **kwargs): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + @extend_schema( responses={ 204: OpenApiResponse(description="Endereço deletado com sucesso"), @@ -189,6 +194,7 @@ def get(self, request, *args, **kwargs): parametros = Parametro.objects.all() serializer = ParametroSerializer(parametros, many=True) return Response(serializer.data) + @extend_schema( request=OpenApiRequest(ParametroSerializer), responses={ @@ -217,6 +223,7 @@ def get(self, request, pk, *args, **kwargs): return Response(status=status.HTTP_404_NOT_FOUND) serializer = ParametroSerializer(parametro) return Response(serializer.data) + @extend_schema( request=OpenApiRequest(ParametroSerializer), responses={ @@ -235,6 +242,7 @@ def put(self, request, pk, *args, **kwargs): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + @extend_schema( responses={ 204: OpenApiResponse(description="Parâmetro deletado com sucesso"), @@ -250,6 +258,13 @@ def delete(self, request, pk, *args, **kwargs): return Response(status=status.HTTP_204_NO_CONTENT) class CategoriasView(APIView): + @extend_schema( + request=OpenApiRequest(CategoriaSerializer), + responses={ + 201: OpenApiResponse(CategoriaSerializer), + 400: OpenApiResponse(description="Erro ao cadastrar a categoria") + } + ) def post (self, request, *args, **kwargs): serializer = CategoriaSerializer(data=request.data) if serializer.is_valid(): diff --git a/src/tupan/tupan/urls.py b/src/tupan/tupan/urls.py index 8d2d7b5..b74eaf8 100644 --- a/src/tupan/tupan/urls.py +++ b/src/tupan/tupan/urls.py @@ -28,6 +28,6 @@ path('api/schema/', SpectacularAPIView.as_view(), name='schema'), path('api/schema/swagger-ui/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'), path('api/schema/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'), - path('usuarios', include('usuarios.urls')), + path('', include('usuarios.urls')), path('api-token-auth', CustomAuthToken.as_view(), name='api_token_auth'), ] diff --git a/src/tupan/usuarios/urls.py b/src/tupan/usuarios/urls.py index 4540819..d35ef07 100644 --- a/src/tupan/usuarios/urls.py +++ b/src/tupan/usuarios/urls.py @@ -1,8 +1,8 @@ from django.urls import path from rest_framework.urlpatterns import format_suffix_patterns -from usuarios.views import UsuarioList +from usuarios.views import UsuariosView, UsuariosDetalhesView urlpatterns = [ - path('', UsuarioList.as_view()), - path('/', UsuarioList.as_view()) + path('usuarios', UsuariosView.as_view()), + path('usuarios/', UsuariosDetalhesView.as_view()) ] diff --git a/src/tupan/usuarios/views.py b/src/tupan/usuarios/views.py index 8f7997a..cda8f35 100644 --- a/src/tupan/usuarios/views.py +++ b/src/tupan/usuarios/views.py @@ -1,20 +1,14 @@ from .models import Usuario from usuarios.serializer import UsuarioSerializer -from django.http import Http404 from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from rest_framework.permissions import IsAuthenticated, AllowAny from drf_spectacular.utils import extend_schema, OpenApiResponse, OpenApiParameter, OpenApiTypes -class UsuarioList(APIView): - """ - Lista, cria, atualiza e deleta os usuários. - """ +class UsuariosView(APIView): def get_permissions(self): - if self.request.method in ['DELETE', 'PUT']: - self.permission_classes = [IsAuthenticated] - elif self.request.method == 'POST': + if self.request.method == 'POST': self.permission_classes = [AllowAny] else: self.permission_classes = [IsAuthenticated] @@ -24,21 +18,49 @@ def get_permissions(self): description="Lista todos os usuários ativos", responses={200: UsuarioSerializer(many=True), 404: OpenApiResponse(description="Nenhum usuário cadastrado")} ) - def get(self, request, format=None): + def get(self, request): usuarios = Usuario.objects.all().filter(ativo=True) if not usuarios.exists(): return Response({"mensagem": "Nenhum usuário cadastrado"}, status=status.HTTP_404_NOT_FOUND) serializer = UsuarioSerializer(usuarios, many=True) return Response(serializer.data) + + @extend_schema( + description="Cria um novo usuário", + request=UsuarioSerializer, + responses={201: UsuarioSerializer, 400: OpenApiResponse(description="Erro na requisição")} + ) + def post(self, request): + serializer = UsuarioSerializer(data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) +class UsuariosDetalhesView(APIView): @extend_schema( - description="Deleta um usuário pelo seu id", - parameters=[ - OpenApiParameter("pk", OpenApiTypes.INT, description="Id do usuário", required=True) - ], + description="Busca um usuário ativo pelo seu id", + responses={ + 302: OpenApiResponse(UsuarioSerializer), + 404: OpenApiResponse(description="Usuário não encontrado"), + 500: OpenApiResponse(description="Erro ao buscar usuário") + } + ) + def get(self, request, pk): + try: + usuario = Usuario.objects.all().filter(pk=pk).filter(ativo=True) + serializer = UsuarioSerializer(usuario, many=True) + if len(usuario) <= 0: + return Response({"mensagem": "Usuário não encontrado"}, status=status.HTTP_404_NOT_FOUND) + return Response(serializer.data[0], status=status.HTTP_302_FOUND) + except Exception as e: + return Response({"mensagem": f"Erro ao buscar usuário: {e}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + @extend_schema( + description="Inativa um usuário pelo seu id", responses={200: UsuarioSerializer, 404: OpenApiResponse(description="Usuário não encontrado"), 400: OpenApiResponse(description="Erro na requisição")} ) - def delete(self, pk): + def delete(self, request, pk): try: usuario = Usuario.objects.get(pk=pk) usuario.ativo = False @@ -49,31 +71,16 @@ def delete(self, pk): return Response(status=status.HTTP_404_NOT_FOUND) except Exception as e: return Response({"message": str(e)}, status=status.HTTP_400_BAD_REQUEST) - - @extend_schema( - description="Cria um novo usuário", - request=UsuarioSerializer, - responses={201: UsuarioSerializer, 400: OpenApiResponse(description="Erro na requisição")} - ) - def post(self, request): - serializer = UsuarioSerializer(data=request.data) - if serializer.is_valid(): - serializer.save() - return Response(serializer.data, status=status.HTTP_201_CREATED) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @extend_schema( description="Atualiza um usuário pelo seu id", - parameters=[ - OpenApiParameter("pk", OpenApiTypes.INT, description="Id do usuário", required=True) - ], request=UsuarioSerializer, responses={200: UsuarioSerializer, 404: OpenApiResponse(description="Usuário não encontrado"), 400: OpenApiResponse(description="Erro na requisição")} ) def put(self, request, pk): try: new_data = request.data - user = Usuario.objects.get(pk=pk) + user = Usuario.objects.get(id=pk) user.email = new_data["email"] user.password = new_data["password"] user.save()