Browse Source

Relatório de ACTs duplicados

master
Sesóstris Vieira 1 week ago
parent
commit
af9e6e3586
  1. 114
      sigi/apps/convenios/templates/convenios/report/duplicados.html
  2. 99
      sigi/apps/convenios/templates/convenios/report/duplicados_pdf.html
  3. 5
      sigi/apps/convenios/urls.py
  4. 141
      sigi/apps/convenios/views.py
  5. 2
      sigi/menu_conf.yaml

114
sigi/apps/convenios/templates/convenios/report/duplicados.html

@ -0,0 +1,114 @@
{% extends "utils/report/report.html" %}
{% load i18n djbs_extras %}
{% block csv_link %}{% endblock %}
{% block datacard %}
<p class="lead">
{% blocktrans %}
As datas de início e término da vigência dos contratos do Gescon estão no
formato ISO-8601, que é AAAA-MM-DD, pois são recebidas asssim do webservice,
que obedece aos padrões de normalização para troca e comunicação de dados.
{% endblocktrans %}
</p>
<p class="lead">
<strong>
{% blocktrans with total=duplicados|length %}
{{ total }} processos duplicados no SIGI
{% endblocktrans %}
</strong>
</p>
{% for processo, sigad_url, convenios, contratos_gescon in duplicados %}
<div class="card mb-2">
<div class="card-header">
<h5 class="mb-0">{% trans "Nº do Processo:" %} {{ sigad_url }}</h5>
</div>
<div class="card-body">
<h6 class="card-subtitle my-2 text-body-secondary">
{% blocktrans with total=convenios|length%}
{{ total }} convênios com este mesmo número de processo no SIGI
{% endblocktrans %}
</h6>
<table class="table table-sm mb-4">
<thead>
<tr>
<th rowspan="2">{% trans "Projeto" %}</th>
<th rowspan="2">{% trans "Nº convênio" %}</th>
<th rowspan="2">{% trans "CNPJ" %}</th>
<th rowspan="2">{% trans "Casa Legislativa" %}</th>
<th rowspan="2">{% trans "Observação" %}</th>
<th colspan="2">{% trans "Vigência" %}</th>
<th rowspan="2">{% trans "Origem" %}</th>
<th rowspan="2">{% trans "Action" %}</th>
</tr>
<tr>
<th>{% trans "Início" %}</th>
<th>{% trans "Término" %}</th>
</tr>
</thead>
<tbody>
{% for convenio, origem in convenios %}
<tr>
<td>{{ convenio.projeto.sigla }}</td>
<td>{{ convenio.num_convenio }}</td>
<td>{{ convenio.casa_legislativa.cnpj }}</td>
<td>{{ convenio.casa_legislativa.nome }}</td>
<td>{{ convenio.observacao|default:"" }}</td>
<td>{{ convenio.data_retorno_assinatura }}</td>
<td>{{ convenio.data_termino_vigencia }}</td>
<td>{{ origem }}</td>
<td>
<a href="{% url "admin:convenios_convenio_delete" convenio.id %}" target="_blank" title="{% translate "Delete" %}">
{% icon "delete" %}
</a>
<a href="{% url "admin:convenios_convenio_change" convenio.id %}" target="_blank" title="{% translate "Change" %}">
{% icon "edit" %}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<h6 class="card-subtitle my-2 text-body-secondary">
{% blocktrans count total=contratos_gescon|length%}
Um contrato com este número de processo no Gescon
{% plural %}
{{ total }} contratos com este mesmo número de processo no Gescon
{% endblocktrans %}
</h6>
<table class="table table-sm mb-2">
<thead>
<tr>
<th rowspan="2">{% trans "ID" %}</th>
<th rowspan="2">{% trans "Subespécie" %}</th>
<th rowspan="2">{% trans "Nº convênio" %}</th>
<th rowspan="2">{% trans "CNPJ" %}</th>
<th rowspan="2">{% trans "Nome do fornecedor" %}</th>
<th rowspan="2">{% trans "Objeto" %}</th>
<th colspan="2">{% trans "Vigência" %}</th>
</tr>
<tr>
<th>{% trans "Início" %}</th>
<th>{% trans "Término" %}</th>
</tr>
</thead>
<tbody>
{% for contrato in contratos_gescon %}
<tr>
<td>{{ contrato.id|stringformat:"d" }}</td>
<td>{{ contrato.subEspecie }}</td>
<td>{{ contrato.numero }}</td>
<td>{{ contrato.cnpjCpfFornecedor }}</td>
<td>{{ contrato.nomeFornecedor }}</td>
<td>{{ contrato.objeto }}</td>
<td>{{ contrato.inicioVigencia }}</td>
<td>{{ contrato.terminoVigencia }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endfor %}
{% endblock %}

99
sigi/apps/convenios/templates/convenios/report/duplicados_pdf.html

@ -0,0 +1,99 @@
{% extends "utils/report/report_pdf.html" %}
{% load i18n %}
{% block page_size %}A4 landscape{% endblock %}
{% block main_content %}
<p>
{% blocktrans %}
As datas de início e término da vigência dos contratos do Gescon estão no
formato ISO-8601, que é AAAA-MM-DD, pois são recebidas asssim do webservice,
que obedece aos padrões de normalização para troca e comunicação de dados.
{% endblocktrans %}
</p>
<p class="bold">
{% blocktrans with total=duplicados|length %}
{{ total }} processos duplicados no SIGI
{% endblocktrans %}
</p>
{% for processo, sigad_url, convenios, contratos_gescon in duplicados %}
<div class="title_row" style="margin-top: 12px;">
<h5 style="padding: 12px 0;">{% trans "Nº do Processo:" %} {{ processo }}</h5>
</div>
<h6>
{% blocktrans with total=convenios|length%}
{{ total }} convênios com este mesmo número de processo no SIGI
{% endblocktrans %}
</h6>
<table>
<thead>
<tr>
<th rowspan="2">{% trans "Projeto" %}</th>
<th rowspan="2">{% trans "Nº convênio" %}</th>
<th rowspan="2">{% trans "CNPJ" %}</th>
<th rowspan="2">{% trans "Casa Legislativa" %}</th>
<th rowspan="2">{% trans "Observação" %}</th>
<th colspan="2">{% trans "Vigência" %}</th>
<th rowspan="2">{% trans "Origem" %}</th>
</tr>
<tr>
<th>{% trans "Início" %}</th>
<th>{% trans "Término" %}</th>
</tr>
</thead>
<tbody>
{% for convenio, origem in convenios %}
<tr>
<td>{{ convenio.projeto.sigla }}</td>
<td>{{ convenio.num_convenio }}</td>
<td>{{ convenio.casa_legislativa.cnpj }}</td>
<td>{{ convenio.casa_legislativa.nome }}</td>
<td>{{ convenio.observacao|default:"" }}</td>
<td>{{ convenio.data_retorno_assinatura }}</td>
<td>{{ convenio.data_termino_vigencia }}</td>
<td>{{ origem }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<h6 style="margin-top: 12px;">
{% blocktrans count total=contratos_gescon|length%}
Um contrato com este número de processo no Gescon
{% plural %}
{{ total }} contratos com este mesmo número de processo no Gescon
{% endblocktrans %}
</h6>
<table>
<thead>
<tr>
<th rowspan="2">{% trans "ID" %}</th>
<th rowspan="2">{% trans "Subespécie" %}</th>
<th rowspan="2">{% trans "Nº convênio" %}</th>
<th rowspan="2">{% trans "CNPJ" %}</th>
<th rowspan="2">{% trans "Nome do fornecedor" %}</th>
<th rowspan="2">{% trans "Objeto" %}</th>
<th colspan="2">{% trans "Vigência" %}</th>
</tr>
<tr>
<th>{% trans "Início" %}</th>
<th>{% trans "Término" %}</th>
</tr>
</thead>
<tbody>
{% for contrato in contratos_gescon %}
<tr>
<td>{{ contrato.id|stringformat:"d" }}</td>
<td>{{ contrato.subEspecie }}</td>
<td>{{ contrato.numero }}</td>
<td>{{ contrato.cnpjCpfFornecedor }}</td>
<td>{{ contrato.nomeFornecedor }}</td>
<td>{{ contrato.objeto }}</td>
<td>{{ contrato.inicioVigencia }}</td>
<td>{{ contrato.terminoVigencia }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endfor %}
{% endblock %}

5
sigi/apps/convenios/urls.py

@ -7,6 +7,11 @@ urlpatterns = [
views.ErrosGesconReportView.as_view(), views.ErrosGesconReportView.as_view(),
name="convenios-report_erros_gescon", name="convenios-report_erros_gescon",
), ),
path(
"duplicados/",
views.report_duplicados,
name="convenios-report_duplicados",
),
path( path(
"reportsRegiao/<str:regiao>/", "reportsRegiao/<str:regiao>/",
views.report_regiao, views.report_regiao,

141
sigi/apps/convenios/views.py

@ -1,7 +1,17 @@
import csv import csv
import re
import requests
from docutils.core import publish_parts 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.utils.safestring import mark_safe
from django.http import HttpResponse, HttpResponseForbidden from django.http import (
HttpResponse,
HttpResponseForbidden,
HttpResponseServerError,
)
from django.shortcuts import render, get_list_or_404 from django.shortcuts import render, get_list_or_404
from django.utils.translation import gettext as _, ngettext from django.utils.translation import gettext as _, ngettext
from django.contrib.admin.views.decorators import staff_member_required from django.contrib.admin.views.decorators import staff_member_required
@ -11,6 +21,7 @@ from django_weasyprint.views import WeasyTemplateResponse
from sigi.apps.casas.models import Orgao from sigi.apps.casas.models import Orgao
from sigi.apps.contatos.models import UnidadeFederativa from sigi.apps.contatos.models import UnidadeFederativa
from sigi.apps.convenios.models import Convenio, Gescon, Projeto from sigi.apps.convenios.models import Convenio, Gescon, Projeto
from sigi.apps.utils import get_sigad_url
from sigi.apps.utils.views import ReportListView from sigi.apps.utils.views import ReportListView
@ -107,6 +118,108 @@ def report_regiao(request, regiao):
) )
@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): def casas_estado_to_tabela(casas, convenios, regiao):
estados = get_list_or_404(UnidadeFederativa, regiao=regiao) estados = get_list_or_404(UnidadeFederativa, regiao=regiao)
@ -118,9 +231,7 @@ def casas_estado_to_tabela(casas, convenios, regiao):
for estado in estados: for estado in estados:
linha = LinhaEstado() linha = LinhaEstado()
convenios_est = convenios.filter( convenios_est = convenios.filter(casa_legislativa__municipio__uf=estado)
casa_legislativa__municipio__uf=estado
)
convenios_est_publicados = convenios_est.exclude(data_pub_diario=None) convenios_est_publicados = convenios_est.exclude(data_pub_diario=None)
convenios_est_equipados = convenios_est.exclude(data_termo_aceite=None) convenios_est_equipados = convenios_est.exclude(data_termo_aceite=None)
@ -154,9 +265,7 @@ def casas_estado_to_tabela(casas, convenios, regiao):
convenios_regiao = convenios.filter( convenios_regiao = convenios.filter(
casa_legislativa__municipio__uf__regiao=regiao casa_legislativa__municipio__uf__regiao=regiao
) )
convenios_regiao_publicados = convenios_regiao.exclude( convenios_regiao_publicados = convenios_regiao.exclude(data_pub_diario=None)
data_pub_diario=None
)
convenios_regiao_equipados = convenios_regiao.exclude( convenios_regiao_equipados = convenios_regiao.exclude(
data_termo_aceite=None data_termo_aceite=None
) )
@ -205,25 +314,7 @@ def importar_gescon(request):
return render(request, "convenios/importar_gescon.html", context) return render(request, "convenios/importar_gescon.html", context)
"""
def query_ordena(qs, o, ot):
list_display = ('num_convenio', 'casa_legislativa',
'data_adesao', 'data_retorno_assinatura', 'data_termo_aceite',
'projeto',
)
aux = list_display[(int(o) - 1)]
if ot == 'asc':
qs = qs.order_by(aux)
else:
qs = qs.order_by("-" + aux)
return qs
"""
def normaliza_data(get, nome_param): def normaliza_data(get, nome_param):
import re
if nome_param in get: if nome_param in get:
value = get.get(nome_param, "") value = get.get(nome_param, "")
if value == "": if value == "":

2
sigi/menu_conf.yaml

@ -31,6 +31,8 @@ main_menu:
children: children:
- title: VALIDAÇÃO - Erros importação Gescon - title: VALIDAÇÃO - Erros importação Gescon
view_name: convenios-report_erros_gescon view_name: convenios-report_erros_gescon
- title: VALIDAÇÃO - Convênios duplicados
view_name: convenios-report_duplicados
- title: VALIDAÇÃO - Órgãos com CNPJ duplicado - title: VALIDAÇÃO - Órgãos com CNPJ duplicado
view_name: casas_cnpj_duplicado view_name: casas_cnpj_duplicado
- title: VALIDAÇÃO - Órgãos com CNPJ errado - title: VALIDAÇÃO - Órgãos com CNPJ errado

Loading…
Cancel
Save