mirror of https://github.com/interlegis/sigi.git
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
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
|
|
|
|
"""
|
|
|