Source code for src.pre_recebimento.ficha_tecnica.api.viewsets

from datetime import datetime

from django_filters import rest_framework as filters
from rest_framework import mixins, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.status import HTTP_200_OK, HTTP_201_CREATED, HTTP_400_BAD_REQUEST

from src.dados_comuns.helpers_autenticidade import (
    verificar_autenticidade_usuario,
)
from src.dados_comuns.permissions import (
    PermissaoParaAnalisarFichaTecnica,
    PermissaoParaDashboardFichaTecnica,
    PermissaoParaRelatorioFichasTecnicas,
    PermissaoParaVisualizarCronograma,
    PermissaoParaVisualizarFichaTecnica,
    UsuarioEhFornecedor,
)
from src.pre_recebimento.ficha_tecnica.api.filters import FichaTecnicaFilter
from src.pre_recebimento.ficha_tecnica.api.serializers.serializer_create import (
    AnaliseFichaTecnicaCreateSerializer,
    AnaliseFichaTecnicaRascunhoSerializer,
    CorrecaoFichaTecnicaSerializer,
    FichaTecnicaAtualizacaoSerializer,
    FichaTecnicaCreateSerializer,
    FichaTecnicaFLVCreateSerializer,
    FichaTecnicaRascunhoSerializer,
)
from src.pre_recebimento.ficha_tecnica.api.serializers.serializers import (
    FichaTecnicaComAnaliseDetalharSerializer,
    FichaTecnicaCronogramaSerializer,
    FichaTecnicaDetalharSerializer,
    FichaTecnicaListagemSerializer,
    FichaTecnicaSimplesSerializer,
    PainelFichaTecnicaSerializer,
    RelatorioFichaTecnicaSerializer,
)
from src.pre_recebimento.ficha_tecnica.api.services import (
    ServiceDashboardFichaTecnica,
)
from src.pre_recebimento.tasks import (
    exporta_relatorio_fichas_tecnicas_xlsx,
)

from ....dados_comuns.api.paginations import DefaultPagination
from ....relatorios.relatorios import get_pdf_ficha_tecnica
from ..models import FichaTecnicaDoProduto


[docs] class FichaTecnicaRascunhoViewSet( mixins.CreateModelMixin, mixins.UpdateModelMixin, viewsets.GenericViewSet ): lookup_field = "uuid" serializer_class = FichaTecnicaRascunhoSerializer queryset = FichaTecnicaDoProduto.objects.all().order_by("-criado_em") permission_classes = (UsuarioEhFornecedor,)
[docs] class FichaTecnicaModelViewSet( mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.CreateModelMixin, mixins.UpdateModelMixin, viewsets.GenericViewSet, ): lookup_field = "uuid" serializer_class = FichaTecnicaRascunhoSerializer queryset = FichaTecnicaDoProduto.objects.all().order_by("-criado_em") permission_classes = (PermissaoParaVisualizarFichaTecnica,) pagination_class = DefaultPagination filter_backends = (filters.DjangoFilterBackend,) filterset_class = FichaTecnicaFilter
[docs] def get_queryset(self): user = self.request.user if user.eh_fornecedor: return FichaTecnicaDoProduto.objects.filter( empresa=user.vinculo_atual.instituicao ).order_by("-criado_em") return FichaTecnicaDoProduto.objects.all().order_by("-criado_em")
[docs] def get_serializer_class(self): serializer_classes_map = { "list": FichaTecnicaListagemSerializer, "retrieve": FichaTecnicaDetalharSerializer, "create": self._get_create_update_serializer(), "update": self._get_create_update_serializer(), "listagem_relatorio": RelatorioFichaTecnicaSerializer, } return serializer_classes_map.get(self.action, FichaTecnicaRascunhoSerializer)
def _get_create_update_serializer(self): if self.action == "update": ficha = self.get_object() if ficha.categoria == "FLV": return FichaTecnicaFLVCreateSerializer elif self.action == "create": categoria = self.request.data.get("categoria") if categoria == "FLV": return FichaTecnicaFLVCreateSerializer return FichaTecnicaCreateSerializer
[docs] def create(self, request, *args, **kwargs): if auth_response := verificar_autenticidade_usuario(request): return auth_response return super().create(request, *args, **kwargs)
[docs] def update(self, request, *args, **kwargs): if auth_response := verificar_autenticidade_usuario(request): return auth_response return super().update(request, *args, **kwargs)
[docs] @action( detail=False, methods=["GET"], url_path="dashboard", permission_classes=(PermissaoParaDashboardFichaTecnica,), ) def dashboard(self, request): qs = FichaTecnicaDoProduto.objects.order_by("-alterado_em") dashboard_service = ServiceDashboardFichaTecnica( qs, FichaTecnicaFilter, PainelFichaTecnicaSerializer, request, ) return Response({"results": dashboard_service.get_dados_dashboard()})
[docs] @action( detail=False, methods=["GET"], url_path="lista-simples", permission_classes=(PermissaoParaVisualizarFichaTecnica,), ) def lista_simples(self, request, **kwargs): usuario = self.request.user qs = ( self.get_queryset().filter(empresa=usuario.vinculo_atual.instituicao) if usuario.eh_empresa else self.get_queryset() ) qs = qs.exclude(status=FichaTecnicaDoProduto.workflow_class.RASCUNHO) return Response({"results": FichaTecnicaSimplesSerializer(qs, many=True).data})
[docs] @action( detail=False, methods=["GET"], url_path="lista-simples-aprovadas", permission_classes=(PermissaoParaVisualizarFichaTecnica,), ) def lista_simples_aprovadas(self, request, **kwargs): usuario = self.request.user qs = ( self.get_queryset().filter(empresa=usuario.vinculo_atual.instituicao) if usuario.eh_empresa else self.get_queryset() ) qs = qs.filter(status=FichaTecnicaDoProduto.workflow_class.APROVADA) return Response({"results": FichaTecnicaSimplesSerializer(qs, many=True).data})
[docs] @action( detail=False, methods=["GET"], url_path="lista-simples-sem-cronograma", permission_classes=(PermissaoParaVisualizarFichaTecnica,), ) def lista_simples_sem_cronograma(self, request, **kwargs): qs = ( self.get_queryset() .exclude(status=FichaTecnicaDoProduto.workflow_class.RASCUNHO) .exclude(cronograma__isnull=False) ) return Response({"results": FichaTecnicaSimplesSerializer(qs, many=True).data})
[docs] @action( detail=False, methods=["GET"], url_path="lista-simples-sem-layout-embalagem", permission_classes=(PermissaoParaVisualizarFichaTecnica,), ) def lista_simples_sem_layout_embalagem(self, request, **kwargs): usuario = self.request.user qs = ( self.get_queryset().filter(empresa=usuario.vinculo_atual.instituicao) if usuario.eh_empresa else self.get_queryset() ) qs = qs.exclude(status=FichaTecnicaDoProduto.workflow_class.RASCUNHO).exclude( layout_embalagem__isnull=False ) return Response({"results": FichaTecnicaSimplesSerializer(qs, many=True).data})
[docs] @action( detail=False, methods=["GET"], url_path="lista-simples-sem-questoes-conferencia", permission_classes=(PermissaoParaVisualizarFichaTecnica,), ) def lista_simples_sem_questoes_conferencia(self, request, **kwargs): usuario = self.request.user qs = ( self.get_queryset().filter(empresa=usuario.vinculo_atual.instituicao) if usuario.eh_empresa else self.get_queryset() ) qs = qs.exclude(status=FichaTecnicaDoProduto.workflow_class.RASCUNHO).exclude( questoes_conferencia__isnull=False ) return Response({"results": FichaTecnicaSimplesSerializer(qs, many=True).data})
[docs] @action( detail=True, methods=["GET"], url_path="dados-cronograma", permission_classes=(PermissaoParaVisualizarCronograma,), ) def dados_cronograma(self, request, **kwargs): return Response(FichaTecnicaCronogramaSerializer(self.get_object()).data)
[docs] @action( detail=True, methods=["GET"], url_path="detalhar-com-analise", permission_classes=(PermissaoParaVisualizarFichaTecnica,), ) def detalhar_com_analise(self, request, **kwargs): return Response( FichaTecnicaComAnaliseDetalharSerializer( self.get_object(), context=self.get_serializer_context(), ).data )
[docs] @action( detail=True, methods=["POST", "PUT"], url_path="rascunho-analise-gpcodae", permission_classes=(PermissaoParaAnalisarFichaTecnica,), ) def rascunho_analise_gpcodae(self, request, *args, **kwargs): ficha_tecnica = self.get_object() analise = ficha_tecnica.analises.last() criado_por = self.request.user serializer = AnaliseFichaTecnicaRascunhoSerializer( instance=analise, data=request.data, context={ "ficha_tecnica": ficha_tecnica, "criado_por": criado_por, }, ) serializer.is_valid(raise_exception=True) serializer.save() return Response( serializer.data, status=HTTP_201_CREATED if analise is None else HTTP_200_OK, )
[docs] @action( detail=True, methods=["POST", "PUT"], url_path="analise-gpcodae", permission_classes=(PermissaoParaAnalisarFichaTecnica,), ) def analise_gpcodae(self, request, *args, **kwargs): ficha_tecnica = self.get_object() analise = ficha_tecnica.analises.last() criado_por = self.request.user serializer = AnaliseFichaTecnicaCreateSerializer( instance=analise, data=request.data, context={ "ficha_tecnica": ficha_tecnica, "criado_por": criado_por, }, ) serializer.is_valid(raise_exception=True) serializer.save() return Response(status=HTTP_201_CREATED if analise is None else HTTP_200_OK)
[docs] @action( detail=True, methods=["PATCH"], url_path="correcao-fornecedor", permission_classes=(UsuarioEhFornecedor,), ) def correcao_fornecedor(self, request, *args, **kwargs): if auth_response := verificar_autenticidade_usuario(request): return auth_response return self._processa_correcao(request, *args, **kwargs)
def _processa_correcao(self, request, *args, **kwargs): serializer = CorrecaoFichaTecnicaSerializer( instance=self.get_object(), data=request.data, context={"request": request}, ) serializer.is_valid(raise_exception=True) serializer.save() return Response(HTTP_200_OK)
[docs] @action( detail=True, methods=["PATCH"], url_path="atualizacao-fornecedor", permission_classes=(UsuarioEhFornecedor,), ) def atualizacao_fornecedor(self, request, *args, **kwargs): if auth_response := verificar_autenticidade_usuario(request): return auth_response return self._processa_atualizacao(request, *args, **kwargs)
def _processa_atualizacao(self, request, *args, **kwargs): serializer = FichaTecnicaAtualizacaoSerializer( instance=self.get_object(), data=request.data, context={"request": request}, ) serializer.is_valid(raise_exception=True) serializer.save() return Response(HTTP_200_OK) def _calcular_totalizadores(self, qs): workflow = FichaTecnicaDoProduto.workflow_class return { "Total de Fichas Aprovadas": qs.filter( status=workflow.APROVADA ).count(), "Total de Fichas Enviadas para Correção": qs.filter( status=workflow.ENVIADA_PARA_CORRECAO ).count(), "Total de Fichas Pendentes de Aprovação": qs.filter( status=workflow.ENVIADA_PARA_ANALISE ).count(), }
[docs] @action(detail=True, methods=["GET"], url_path="gerar-pdf-ficha") def gerar_pdf_ficha(self, request, uuid=None): ficha = self.get_object() try: return get_pdf_ficha_tecnica(request, ficha) except Exception: return Response( dict( detail="Ocorreu um erro durante a geração do pdf de Ficha Técnica" ), status=HTTP_400_BAD_REQUEST, )
[docs] @action( detail=False, methods=["GET"], url_path="listagem-relatorio", permission_classes=(PermissaoParaRelatorioFichasTecnicas,), ) def listagem_relatorio(self, request): queryset = self._queryset_relatorio() page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) response = self.get_paginated_response(serializer.data) response.data["totalizadores"] = self._calcular_totalizadores(queryset) return response serializer = self.get_serializer(queryset, many=True) return Response( { "results": serializer.data, "totalizadores": self._calcular_totalizadores(queryset), } )
[docs] @action( detail=False, methods=["GET"], url_path="exportar-excel", permission_classes=(PermissaoParaRelatorioFichasTecnicas,), ) def exportar_excel(self, request): queryset = self._queryset_relatorio() nome_arquivo = datetime.now().strftime( "Relatorio_Fichas_Tecnicas_%Y-%m-%d_%H%M%S.xlsx" ) exporta_relatorio_fichas_tecnicas_xlsx.delay( user=request.user.get_username(), nome_arquivo=nome_arquivo, fichas_ids=list(queryset.values_list("id", flat=True)), ) return Response( {"detail": "Solicitação de geração de arquivo recebida com sucesso."}, status=HTTP_200_OK, )
def _queryset_relatorio(self): """Queryset do relatório: mesmos filtros da tela, excluindo fichas da categoria FLV.""" return self.filter_queryset( self.get_queryset().exclude(categoria=FichaTecnicaDoProduto.CATEGORIA_FLV) )