Sistema de Informações Gerenciais do Interlegis
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

522 lines
17 KiB

import csv
import re
import requests
from docutils.core import publish_parts
from django.contrib.admin.models import LogEntry, ADDITION
from django.contrib.contenttypes.models import ContentType
from django.utils import timezone
from django.utils.formats import localize
from django.utils.safestring import mark_safe
from django.http import (
HttpResponse,
HttpResponseForbidden,
HttpResponseServerError,
)
from django.shortcuts import render, get_list_or_404
from django.utils.translation import gettext as _, ngettext
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django_weasyprint.views import WeasyTemplateResponse
from sigi.apps.casas.models import Orgao
from sigi.apps.contatos.models import UnidadeFederativa
from sigi.apps.convenios.models import Convenio, Projeto
from sigi.apps.utils import get_sigad_url
from sigi.apps.utils.views import ReportListView
class ErrosGesconReportView(
LoginRequiredMixin, UserPassesTestMixin, ReportListView
):
title = _("Convênios com erros no Gescon")
empty_message = _("Nenhum convênio com erro de importação do Gescon!")
queryset = Convenio.objects.filter(erro_gescon=True).prefetch_related(
"casa_legislativa", "casa_legislativa__municipio__uf"
)
ordering = [
"num_processo_sf",
"projeto",
"num_convenio",
"casa_legislativa__nome",
]
list_fields = [
"id",
"num_processo_sf",
"num_convenio",
"projeto__nome",
"casa_legislativa__nome",
"casa_legislativa__municipio__uf__sigla",
"observacao_gescon",
]
list_labels = [
_("id SIGI"),
_("NUP sigad"),
_("Número"),
_("Projeto"),
_("Órgão conveniado"),
_("UF"),
_("Erro encontrado"),
]
def test_func(self):
return self.request.user.is_staff
def get_title(self):
count = self.get_queryset().count()
return ngettext(
"Um convênio com erro no Gescon",
f"{count} convênios com erros no Gescon",
count,
)
@login_required
@staff_member_required
def report_regiao(request, regiao):
REGIAO_CHOICES = dict(UnidadeFederativa.REGIAO_CHOICES)
projetos = Projeto.objects.all()
camaras = Orgao.objects.filter(tipo__sigla="CM")
tabelas = list()
convenios = Convenio.objects.filter(casa_legislativa__tipo__sigla="CM")
tabela = casas_estado_to_tabela(camaras, convenios, regiao)
tabela["projeto"] = _("Geral")
tabelas.append(tabela)
for projeto in projetos:
convenios_proj = convenios.filter(projeto=projeto)
tabela = casas_estado_to_tabela(camaras, convenios_proj, regiao)
tabela["projeto"] = projeto.nome
tabelas.append(tabela)
context = {
"tabelas": tabelas,
"regiao": REGIAO_CHOICES[regiao],
}
return WeasyTemplateResponse(
filename=f"relatorio_regiao_{ regiao }.pdf",
request=request,
template="convenios/tabela_regiao.html",
context=context,
content_type="application/pdf",
)
@login_required
@staff_member_required
def report_duplicados(request):
format = request.GET.get("fmt", "html")
ct = ContentType.objects.get_for_model(Convenio)
# Buscar dados de ACT no Gescon
response = requests.get(
"https://adm.senado.gov.br/gestao-contratos/api/contratos/busca"
"?subespecie=AC"
)
if response.status_code != 200:
return HttpResponseServerError(
f"Erro de comunicação {response.status_code}: {response.reason}"
)
if "json" not in response.headers["content-type"]:
return HttpResponseServerError(
f"Gescon não retornou um json: {response.headers['content-type']}"
)
jdata = response.json()
# Encontrar ACTs duplicados
acts = {
c.num_processo_sf: [c]
for c in Convenio.objects.filter(projeto__sigla="ACT").exclude(
num_processo_sf=""
)
}
for c in Convenio.objects.exclude(num_processo_sf=""):
if c.num_processo_sf in acts and not any(
[a.id == c.id for a in acts[c.num_processo_sf]]
):
acts[c.num_processo_sf].append(c)
duplicados = [
[k, get_sigad_url(k), [[c] for c in v]]
for k, v in acts.items()
if len(v) > 1
]
for r in duplicados:
# Juntar dados do Gescon com os duplicados
processo = processo = re.sub(r"\D", "", r[0])
contratos = list(filter(lambda d: d["processo"] in processo, jdata))
r.append(contratos)
# Adicionar informação de origem em cada convênio
for t in r[2]:
log = LogEntry.objects.filter(
content_type=ct, object_id=t[0].id, action_flag=ADDITION
).first()
if log:
fragment = ""
if t[0].atualizacao_gescon:
if t[0].id_gescon:
fragment = _(
"Atualizado com dados do Gescon em {date}. ID no Gescon: {id}"
).format(
date=localize(t[0].atualizacao_gescon),
id=t[0].id_gescon,
)
else:
fragment = _(
"Atualizado com dados do Gescon em {date}."
).format(date=localize(t[0].atualizacao_gescon))
t.append(
_("Cadastrado por {username} em {date}. {fragment}").format(
username=log.user.get_full_name(),
date=localize(log.action_time),
fragment=fragment,
)
)
else:
if t[0].id_gescon:
t.append(
_("Importado do Gescon em {date}, do ID {id}").format(
date=localize(t[0].atualizacao_gescon),
id=t[0].id_gescon,
)
)
else:
t.append(
_("Importado do Gescon em {date}").format(
date=localize(t[0].atualizacao_gescon)
)
)
context = {
"duplicados": duplicados,
"report_title": _("Relação de Convênios duplicados no SIGI"),
}
if format == "pdf":
return WeasyTemplateResponse(
filename=f"duplicados-{timezone.localdate():%Y-%m-%d}.pdf",
request=request,
template="convenios/report/duplicados_pdf.html",
context=context,
content_type="application/pdf",
)
return render(request, "convenios/report/duplicados.html", context)
def casas_estado_to_tabela(casas, convenios, regiao):
estados = get_list_or_404(UnidadeFederativa, regiao=regiao)
class LinhaEstado:
pass
lista = []
for estado in estados:
linha = LinhaEstado()
convenios_est = convenios.filter(casa_legislativa__municipio__uf=estado)
convenios_est_publicados = convenios_est.exclude(data_pub_diario=None)
convenios_est_equipados = convenios_est.exclude(data_termo_aceite=None)
casas_est = casas.filter(municipio__uf=estado)
casas_est_nao_aderidas = casas_est.exclude(
convenio__in=convenios_est
).distinct()
casas_est_aderidas = casas_est.filter(
convenio__in=convenios_est
).distinct()
casas_est_conveniadas = casas_est.filter(
convenio__in=convenios_est_publicados
).distinct()
casas_est_equipadas = casas_est.filter(
convenio__in=convenios_est_equipados
).distinct()
linha.lista = (
casas_est.count(),
casas_est_nao_aderidas.count(),
casas_est_aderidas.count(),
casas_est_conveniadas.count(),
casas_est_equipadas.count(),
)
linha.estado = estado
lista.append(linha)
casas_regiao = casas.filter(municipio__uf__regiao=regiao)
convenios_regiao = convenios.filter(
casa_legislativa__municipio__uf__regiao=regiao
)
convenios_regiao_publicados = convenios_regiao.exclude(data_pub_diario=None)
convenios_regiao_equipados = convenios_regiao.exclude(
data_termo_aceite=None
)
sumario = (
casas_regiao.count(),
casas_regiao.exclude(convenio__in=convenios_regiao).distinct().count(),
casas_regiao.filter(convenio__in=convenios_regiao).distinct().count(),
casas_regiao.filter(convenio__in=convenios_regiao_publicados)
.distinct()
.count(),
casas_regiao.filter(convenio__in=convenios_regiao_equipados)
.distinct()
.count(),
)
cabecalho_topo = (
_("UF"),
_("Câmaras municipais"),
_("Não Aderidas"),
_("Aderidas"),
_("Conveniadas"),
_("Equipadas"),
)
return {
"linhas": lista,
"cabecalho": cabecalho_topo,
"sumario": sumario,
}
def normaliza_data(get, nome_param):
if nome_param in get:
value = get.get(nome_param, "")
if value == "":
del get[nome_param]
elif re.match("^\d*$", value): # Year only
# Complete with january 1st
get[nome_param] = "%s-01-01" % value
elif re.match("^\d*\D\d*$", value): # Year and month
# Complete with 1st day of month
get[nome_param] = "%s-01" % value
"""
def get_for_qs(get, qs):
kwargs = {}
ids = 0
get._mutable = True
normaliza_data(get, 'data_retorno_assinatura__gte')
normaliza_data(get, 'data_retorno_assinatura__lte')
normaliza_data(get, 'data_sigad__gte')
normaliza_data(get, 'data_sigad__lte')
normaliza_data(get, 'data_sigi__gte')
normaliza_data(get, 'data_sigi__lte')
normaliza_data(get, 'data_solicitacao__gte')
normaliza_data(get, 'data_solicitacao__lte')
get._mutable = False
for k, v in get.iteritems():
if k not in ['page', 'pop', 'q', '_popup']:
if not k == 'o':
if k == "ot":
qs = query_ordena(qs, get["o"], get["ot"])
else:
kwargs[str(k)] = v
if(str(k) == 'ids'):
ids = 1
break
qs = qs.filter(**kwargs)
if ids:
query = 'id IN (' + kwargs['ids'].__str__() + ')'
qs = Convenio.objects.extra(where=[query])
return qs
def carrinhoOrGet_for_qs(request):
if 'carrinho_convenios' in request.session:
ids = request.session['carrinho_convenios']
qs = Convenio.objects.filter(pk__in=ids)
qs = qs.order_by("casa_legislativa__municipio__uf", "casa_legislativa__municipio")
qs = get_for_qs(request.GET, qs)
else:
qs = Convenio.objects.all()
if request.GET:
qs = qs.order_by("casa_legislativa__municipio__uf", "casa_legislativa__municipio")
qs = get_for_qs(request.GET, qs)
return qs
def adicionar_convenios_carrinho(request, queryset=None, id=None):
if request.method == 'POST':
ids_selecionados = request.POST.getlist('_selected_action')
if 'carrinho_convenios' not in request.session:
request.session['carrinho_convenios'] = ids_selecionados
else:
lista = request.session['carrinho_convenios']
# Verifica se id já não está adicionado
for id in ids_selecionados:
if id not in lista:
lista.append(id)
request.session['carrinho_convenios'] = lista
@login_required
def excluir_carrinho(request):
if 'carrinho_convenios' in request.session:
del request.session['carrinho_convenios']
messages.info(request, 'O carrinho foi esvaziado')
return HttpResponseRedirect('../../')
@login_required
def deleta_itens_carrinho(request):
if request.method == 'POST':
ids_selecionados = request.POST.getlist('_selected_action')
if 'carrinho_convenios' in request.session:
lista = request.session['carrinho_convenios']
for item in ids_selecionados:
lista.remove(item)
if lista:
request.session['carrinho_convenios'] = lista
else:
del lista
del request.session['carrinho_convenios']
return HttpResponseRedirect('.')
@login_required
def visualizar_carrinho(request):
qs = carrinhoOrGet_for_qs(request)
paginator = Paginator(qs, 100)
# Make sure page request is an int. If not, deliver first page.
# Esteja certo de que o `page request` é um inteiro. Se não, mostre a primeira página.
try:
page = int(request.GET.get('page', '1'))
except ValueError:
page = 1
# Se o page request (9999) está fora da lista, mostre a última página.
try:
paginas = paginator.page(page)
except (EmptyPage, InvalidPage):
paginas = paginator.page(paginator.num_pages)
carrinhoIsEmpty = not('carrinho_convenios' in request.session)
return render(
request,
'convenios/carrinho.html',
{
'carIsEmpty': carrinhoIsEmpty,
'paginas': paginas,
'query_str': '?' + request.META['QUERY_STRING']
}
)
@login_required
def report(request, id=None):
if id:
qs = Convenio.objects.filter(pk=id)
else:
qs = carrinhoOrGet_for_qs(request)
if not qs:
return HttpResponseRedirect('../')
tipo = ''
data_aceite_has = ''
report = None
if request.POST:
if 'filtro_casa' in request.POST:
tipo = request.POST['filtro_casa']
if 'data_aceite' in request.POST:
data_aceite_has = request.POST['data_aceite']
# filtro adicional pela seleção do usuário
if tipo == 'al':
qs = qs.filter(casa_legislativa__tipo__sigla='AL')
# Verifica se é com data de aceite
if data_aceite_has == 'nao':
report = ConvenioReportSemAceiteAL(queryset=qs)
else:
report = ConvenioPorALReport(queryset=qs)
elif tipo == 'cm':
qs = qs.filter(casa_legislativa__tipo__sigla='CM')
if data_aceite_has == 'nao':
report = ConvenioReportSemAceiteCM(queryset=qs)
else:
report = ConvenioPorCMReport(queryset=qs)
else:
if data_aceite_has == 'nao':
report = ConvenioReportSemAceite(queryset=qs)
else:
report = ConvenioReport(queryset=qs)
response = HttpResponse(content_type='application/pdf')
if report:
report.generate_by(PDFGenerator, filename=response)
else:
return HttpResponseRedirect('../')
return response
@login_required
def export_csv(request):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=convenios.csv'
csv_writer = csv.writer(response)
convenios = carrinhoOrGet_for_qs(request)
if not convenios:
return HttpResponseRedirect('../')
atributos = [_("No. Processo"), _("No. Convênio"), _("Projeto"), _("Casa Legislativa"), _("Data de Adesão"), _("Data de Convênio"),
_("Data da Publicacao no D.O."), _("Data Equipada"), ]
if request.POST:
atributos = request.POST.getlist("itens_csv_selected")
col_titles = atributos
if _("Casa Legislativa") in col_titles:
pos = col_titles.index(_("Casa Legislativa")) + 1
col_titles.insert(pos, _("uf"))
csv_writer.writerow([s.encode("utf-8") for s in col_titles])
for convenio in convenios:
lista = []
for atributo in atributos:
if _("No. Processo") == atributo:
lista.append(convenio.num_processo_sf.encode("utf-8"))
elif _("No. Convênio") == atributo:
lista.append(convenio.num_convenio.encode("utf-8"))
elif _("Projeto") == atributo:
lista.append(convenio.projeto.nome.encode("utf-8"))
elif _("Casa Legislativa") == atributo:
lista.append(convenio.casa_legislativa.nome.encode("utf-8"))
lista.append(convenio.casa_legislativa.municipio.uf.sigla.encode("utf-8"))
elif _("Data de Adesão") == atributo:
data = ''
if convenio.data_adesao:
data = convenio.data_adesao.strftime("%d/%m/%Y")
lista.append(data.encode("utf-8"))
elif _("Data de Convênio") == atributo:
data = ''
if convenio.data_retorno_assinatura:
data = convenio.data_retorno_assinatura.strftime("%d/%m/%Y")
lista.append(data.encode("utf-8"))
elif _("Data da Publicacao no D.O.") == atributo:
data = ''
if convenio.data_pub_diario:
data = convenio.data_pub_diario.strftime("%d/%m/%Y")
lista.append(data.encode("utf-8"))
data = ''
elif _("Data Equipada") == atributo:
if convenio.data_termo_aceite:
data = convenio.data_termo_aceite.strftime("%d/%m/%Y")
lista.append(data.encode("utf-8"))
else:
pass
csv_writer.writerow(lista)
return response
"""