diff --git a/sigi/apps/casas/api_urls.py b/sigi/apps/casas/api_urls.py new file mode 100644 index 0000000..5387716 --- /dev/null +++ b/sigi/apps/casas/api_urls.py @@ -0,0 +1,8 @@ +from django.urls import path +from sigi.apps.casas import views + +urlpatterns = [ + path("orgaoatendido/", views.ApiOrgaoAtendidoList.as_view()), + path("orgaoatendido//", views.ApiOrgaoAtendidoList.as_view()), + path("orgaoatendido//", views.ApiOrgaoAtendidoList.as_view()), +] diff --git a/sigi/apps/casas/serializers.py b/sigi/apps/casas/serializers.py new file mode 100644 index 0000000..71050e3 --- /dev/null +++ b/sigi/apps/casas/serializers.py @@ -0,0 +1,143 @@ +import base64 +import magic +from pathlib import Path +from rest_framework import serializers +from sigi.apps.casas.models import Orgao +from sigi.apps.convenios.models import Convenio, Anexo +from sigi.apps.eventos.models import Evento +from sigi.apps.servicos.models import Servico + + +class AnexoConvenioSerializer(serializers.ModelSerializer): + class Meta: + model = Anexo + fields = ["arquivo", "descricao"] + + +class ConvenioSerializer(serializers.ModelSerializer): + projeto = serializers.SlugRelatedField(read_only=True, slug_field="nome") + status = serializers.SerializerMethodField("get_status") + inicio_vigencia = serializers.SerializerMethodField("get_inicio_vigencia") + termino_vigencia = serializers.SerializerMethodField( + "get_termino_vigencia" + ) + documento_gescon = serializers.SerializerMethodField( + "get_documento_gescon" + ) + anexo_set = AnexoConvenioSerializer(many=True, read_only=True) + + class Meta: + model = Convenio + fields = [ + "projeto", + "num_convenio", + "status", + "inicio_vigencia", + "termino_vigencia", + "documento_gescon", + "anexo_set", + ] + + def get_status(self, obj): + return obj.get_status() + + def get_inicio_vigencia(self, obj): + return obj.data_retorno_assinatura + + def get_termino_vigencia(self, obj): + return obj.data_termino_vigencia + + def get_documento_gescon(self, obj): + return obj.get_url_gescon() + + +class EventoSerializer(serializers.ModelSerializer): + class Meta: + model = Evento + fields = [ + "nome", + "data_inicio", + "data_termino", + "num_processo", + "total_participantes", + ] + + +class ServicoSerializer(serializers.ModelSerializer): + tipo_servico = serializers.SlugRelatedField( + read_only=True, slug_field="nome" + ) + url = serializers.SerializerMethodField("get_url") + resultado_verificacao = serializers.SerializerMethodField( + "get_resultado_verificacao" + ) + + class Meta: + model = Servico + fields = [ + "tipo_servico", + "data_ativacao", + "url", + "data_verificacao", + "resultado_verificacao", + "data_ultimo_uso", + ] + + def get_url(self, obj): + if not obj.url: + return "" + if "http" in obj.url: + return obj.url + else: + return f"http://{ obj.url }" + + def get_resultado_verificacao(self, obj): + return obj.get_resultado_verificacao_display() + + +class OrgaoAtendidoSerializer(serializers.ModelSerializer): + tipo = serializers.StringRelatedField() + municipio = serializers.SlugRelatedField(read_only=True, slug_field="nome") + uf_nome = serializers.SerializerMethodField("get_uf_nome") + uf_sigla = serializers.SerializerMethodField("get_uf_sigla") + foto_base64 = serializers.SerializerMethodField("get_foto_base64") + convenio_set = ConvenioSerializer(many=True, read_only=True) + evento_set = EventoSerializer(many=True, read_only=True) + servico_set = ServicoSerializer(many=True, read_only=True) + + class Meta: + model = Orgao + fields = [ + "id", + "nome", + "sigla", + "tipo", + "cnpj", + "logradouro", + "bairro", + "municipio", + "uf_nome", + "uf_sigla", + "cep", + "email", + "telefone_geral", + "foto", + "foto_base64", + "convenio_set", + "evento_set", + "servico_set", + ] + + def get_uf_nome(self, obj): + return obj.municipio.uf.nome + + def get_uf_sigla(self, obj): + return obj.municipio.uf.sigla + + def get_foto_base64(self, obj): + if obj.foto and Path(obj.foto.path).exists(): + mime_type = magic.from_file(obj.foto.path, mime=True) + obj.foto.file.seek(0) # Garante que está no início do arquivo + b64str = (base64.b64encode(obj.foto.file.read())).decode("ascii") + return f"data:{mime_type};base64, {b64str}" + return None diff --git a/sigi/apps/casas/views.py b/sigi/apps/casas/views.py index a218b61..e37c700 100644 --- a/sigi/apps/casas/views.py +++ b/sigi/apps/casas/views.py @@ -1,6 +1,6 @@ import csv from functools import reduce -from django.db.models import Count, Q +from django.db.models import Count, Q, Prefetch from django.contrib.admin.sites import site from django.contrib.admin.views.decorators import staff_member_required from django.contrib.auth import get_user_model @@ -21,8 +21,10 @@ from django.views.generic import ( UpdateView, DetailView, ) +from rest_framework import generics, filters from sigi.apps.casas.forms import FuncionarioForm from sigi.apps.casas.models import Funcionario, Orgao, TipoOrgao +from sigi.apps.casas.serializers import OrgaoAtendidoSerializer from sigi.apps.home.mixins import ContatoInterlegisViewMixin from sigi.apps.servidores.models import Servidor from sigi.apps.contatos.models import ( @@ -31,7 +33,9 @@ from sigi.apps.contatos.models import ( Microrregiao, ) from sigi.apps.ocorrencias.models import Ocorrencia -from sigi.apps.servicos.models import TipoServico +from sigi.apps.servicos.models import Servico, TipoServico +from sigi.apps.eventos.models import Evento, TipoEvento +from sigi.apps.convenios.models import Convenio def resumo_carteira(casas): @@ -514,3 +518,53 @@ class FuncionarioDeleteView( self.object.desativado = True self.object.save() return HttpResponseRedirect(success_url) + + +class ApiOrgaoAtendidoList(generics.ListAPIView): + """ + Lista os órgãos legislativos atendidos pelo Interlegis. + """ + + serializer_class = OrgaoAtendidoSerializer + filter_backends = [filters.SearchFilter] + search_fields = ["search_text"] + + def get_queryset(self): + sq_servicos = Servico.objects.filter(data_desativacao=None) + sq_eventos = ( + Evento.objects.exclude(data_inicio=None) + .exclude(data_termino=None) + .exclude(tipo_evento__categoria=TipoEvento.CATEGORIA_VISITA) + .filter(status=Evento.STATUS_REALIZADO) + ) + queryset = ( + Orgao.objects.filter(tipo__legislativo=True) + .filter( + Q( + id__in=sq_eventos.order_by() + .distinct("casa_anfitria") + .values("casa_anfitria_id") + ) + | Q( + id__in=sq_servicos.order_by() + .distinct("casa_legislativa") + .values("casa_legislativa_id") + ) + ) + .select_related("municipio", "municipio__uf", "tipo") + .prefetch_related( + Prefetch("servico_set", queryset=sq_servicos), + Prefetch("evento_set", queryset=sq_eventos), + Prefetch( + "convenio_set", + queryset=Convenio.objects.select_related("projeto"), + ), + ) + ).order_by("municipio__uf__nome", "tipo__nome", "nome") + if "pk" in self.kwargs: + queryset = queryset.filter(id=self.kwargs["pk"]) + elif "uf" in self.kwargs: + queryset = queryset.filter( + municipio__uf__sigla=self.kwargs["uf"].upper() + ) + return queryset diff --git a/sigi/urls.py b/sigi/urls.py index 911c29e..a4038bf 100644 --- a/sigi/urls.py +++ b/sigi/urls.py @@ -66,6 +66,7 @@ urlpatterns = [ ), name="redoc", ), + path("api/casas/", include("sigi.apps.casas.api_urls")), path("api/eventos/", include("sigi.apps.eventos.api_urls")), path("tinymce/", include("tinymce.urls")), path("accounts/", include("sigi.apps.home.accounts_urls")),