Browse Source

Mapa de atuação do Interlegis repaginado

pull/66/head
Sesostris Vieira 4 years ago
parent
commit
91c761081c
  1. 45
      sigi/apps/convenios/models.py
  2. 35
      sigi/apps/metas/management/commands/gera_map_data.py
  3. 58
      sigi/apps/metas/static/metas/css/openmap.css
  4. 93
      sigi/apps/metas/templates/metas/lista_casas.html
  5. 129
      sigi/apps/metas/templates/metas/openmap.html
  6. 6
      sigi/apps/metas/urls.py
  7. 493
      sigi/apps/metas/views.py
  8. BIN
      sigiStatic/img/interlegis.png
  9. 32
      templates/base_report.html
  10. 2
      templates/index.html

45
sigi/apps/convenios/models.py

@ -241,17 +241,40 @@ class Convenio(models.Model):
verbose_name = _(u'convênio') verbose_name = _(u'convênio')
def __unicode__(self): def __unicode__(self):
if self.data_retorno_assinatura is not None: # if self.data_retorno_assinatura is not None:
return _(u"Convênio {project}{number} assinado em {date}. Status: {status}".format( # return _(u"Convênio {project} nº {number} assinado em {date}. Status: {status}".format(
number=self.num_convenio, # number=self.num_convenio,
project=self.projeto.sigla, # project=self.projeto.sigla,
date=self.data_retorno_assinatura, # date=self.data_retorno_assinatura,
status=self.get_status())) # status=self.get_status()))
else: # else:
return _(u"Adesão ao projeto %(project)s, em %(date)s") % dict( # return _(u"Adesão ao projeto %(project)s, em %(date)s") % dict(
project=self.projeto.sigla, # project=self.projeto.sigla,
date=self.data_adesao) # date=self.data_adesao)
if ((self.data_retorno_assinatura is None) and
(self.equipada and self.data_termo_aceite is not None)):
return _(u"Equipada em {date} pelo {project}").format(
date=self.data_termo_aceite.strftime('%d/%m/%Y'),
project=self.projeto.sigla)
elif self.data_retorno_assinatura is None:
return _(u"Adesão ao projeto {project}, em {date}").format(
project=self.projeto.sigla, date=self.data_adesao)
if ((self.data_retorno_assinatura is not None) and not
(self.equipada and self.data_termo_aceite is not None)):
return _(u"Conveniada ao {project} em {date}. "
u"Status: {status}").format(
project=self.projeto.sigla,
date=self.data_retorno_assinatura.strftime('%d/%m/%Y'),
status=self.get_status())
if ((self.data_retorno_assinatura is not None) and
(self.equipada and self.data_termo_aceite is not None)):
return _(u"Conveniada ao {project} em {date} e equipada em "
u"{equipped_date}. Status: {status}").format(
project=self.projeto.sigla,
date=self.data_retorno_assinatura.strftime('%d/%m/%Y'),
equipped_date=self.data_termo_aceite.strftime('%d/%m/%Y'),
status=self.get_status())
class EquipamentoPrevisto(models.Model): class EquipamentoPrevisto(models.Model):

35
sigi/apps/metas/management/commands/gera_map_data.py

@ -1,35 +0,0 @@
# -*- coding: utf-8 -*-
#
# sigi.apps.servicos.management.commands.atualiza_uso_servico
#
# Copyright (c) 2012 by Interlegis
#
# GNU General Public License (GPL)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
#
from django.core.management.base import BaseCommand
from django.utils.translation import ugettext as _
from sigi.apps.metas.views import gera_map_data_file
class Command(BaseCommand):
help = _(u'Gera arquivo de dados de plotagem do mapa de atuação do Interlegis.')
def handle(self, *args, **options):
result = gera_map_data_file(cronjob=True)
self.stdout.write(result + "\n")

58
sigi/apps/metas/static/metas/css/openmap.css

@ -0,0 +1,58 @@
body, html, .mapbox, #map {
height: 100%;
}
.filterwrap {
background-color: rgba(255,255,255,0.5);
position: absolute;
top: 0;
left: 0;
z-index: 314159;
height: 100%;
max-height: 100%;
overflow-y: auto;
}
.sigi-logo {
pointer-events: none;
position: absolute;
top: 0;
left: 0;
z-index: 314159;
background-color: transparent;
width: 100%;
text-align: right;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
padding-right: 20px;
}
.sigi-logo h3 {
font-weight: bolder;
margin-bottom: 0px;
}
.sigi-logo a {
pointer-events: auto;
}
.sigi-logo div {
float: right;
}
.sigi-logo img {
margin: 15px;
width: 60px;
height: 60px;
}
.region-ufs {
margin-left: 15px;
}
#search-text {
min-width: 300px;
}
.ui-autocomplete {
max-width: 300px;
-webkit-box-shadow: 0 1px 2px rgba(0,0,0,.05);
box-shadow: 0 1px 2px rgba(0,0,0,.05);
border-color: #ddd;
margin-bottom: 20px;
background-color: #fff;
border: 1px solid transparent;
border-radius: 4px;
padding: 15px;
font-size: 10px;
}

93
sigi/apps/metas/templates/metas/lista_casas.html

@ -0,0 +1,93 @@
{% extends "base_report.html" %}
{% load mapa_tags %}
{% load i18n %}
{% block extra_head %}
<style>
table.data, table.data td, table.data th {
border: 1px solid #CCCCCC;
border-collapse: collapse;
font-size: 10px;
padding: 2px;
}
table.filters, table.filters td, table.filters th {
border-bottom: 1px solid #CCCCCC;
font-size: 10px;
padding-top: 3px;
vertical-align: bottom;
text-align: left;
line-height: 16px;
}
table.filters th {
width: 12%;
}
td.nome_uf {
padding: 0 5px !important;
}
ul {
list-style-type: none;
margin: 0px;
padding: 0px;
}
</style>
{% endblock %}
{% block pagesize %}A4 landscape{% endblock pagesize %}
{% block title %}{% trans 'Lista de Casas atendidas' %}{% endblock title %}
{% block report %}
<h1>{% trans 'Lista de Casas atendidas' %}</h1>
<table class="filters">
{% if tipos_orgao %}
<tr><th>{% trans 'Tipos de órgão' %}</th><td>{% for t in tipos_orgao %}{{ t.nome }}{% if not forloop.last %}, {% endif %}{% endfor %}</td></tr>
{% endif %}
{% if tipos_servico %}
<tr><th>{% trans 'Tipos de serviço' %}</th><td>{% for s in tipos_servico %}{{ s.nome }}{% if not forloop.last %}, {% endif %}{% endfor %}</td></tr>
{% endif %}
{% if tipos_convenio %}
<tr><th>{% trans 'Tipos de convênio' %}</th><td>{% for c in tipos_convenio %}{{ c.nome }}{% if not forloop.last %}, {% endif %}{% endfor %}</td></tr>
{% endif %}
{% if gerentes %}
<tr><th>{% trans 'Gerentes Interlegis' %}</th><td>{% for g in gerentes %}{{ g.nome_completo }}{% if not forloop.last %}, {% endif %}{% endfor %}</td></tr>
{% endif %}
{% if ufs %}
<tr><th>{% trans 'Estados' %}</th><td>{% for uf in ufs %}{{ uf.nome }}{% if not forloop.last %}, {% endif %}{% endfor %}</td></tr>
{% endif %}
</table>
<br/>
<table class="data" repeat="1">
<tr>
<th>{% trans 'Casa Legislativa' %}</th>
<th>{% trans 'Estado' %}</th>
<th>{% trans 'Região' %}</th>
<th>{% trans 'Serviços' %}</th>
<th>{% trans 'Convênios' %}</th>
<th>{% trans 'Gerente(s)' %}</th>
</tr>
{% for casa in casas %}
<tr>
<td>{{ casa.nome }}&nbsp;</td>
<td>{{ casa.municipio.uf.nome }}</td>
<td>{{ casa.municipio.uf.get_regiao_display }}</td>
<td><ul>{% for s in casa.servico_set.all %}
{% if s.data_desativacao == None %}
<li>{{ s }}</li>
{% endif %}
{% endfor %}</ul></td>
<td><ul>{% for c in casa.convenio_set.all %}
<li>{{ c }}</li>
{% endfor %}
</ul></td>
<td><ul>{% for g in casa.gerentes_interlegis.all %}
<li>{{ g }}</li>
{% endfor %}</ul>
</td>
</tr>
{% endfor %}
</table>
{% endblock %}

129
sigi/apps/metas/templates/metas/openmap.html

@ -8,6 +8,7 @@
<meta http-equiv="Content-Type" content="text/xhtml; charset=UTF-8" /> <meta http-equiv="Content-Type" content="text/xhtml; charset=UTF-8" />
<link href="{% static "bootstrap/css/bootstrap.min.css" %}" rel="stylesheet"/> <link href="{% static "bootstrap/css/bootstrap.min.css" %}" rel="stylesheet"/>
<link href="{% static "bootstrap/css/bootstrap-theme.min.css" %}" rel="stylesheet"/> <link href="{% static "bootstrap/css/bootstrap-theme.min.css" %}" rel="stylesheet"/>
<link href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
@ -20,61 +21,35 @@
<script src="{% static "bootstrap/js/bootstrap.min.js" %}"></script> <script src="{% static "bootstrap/js/bootstrap.min.js" %}"></script>
<meta name="robots" content="NONE,NOARCHIVE" /> <meta name="robots" content="NONE,NOARCHIVE" />
<script type="text/javascript">
//<![CDATA[
(function($) {
$(document).ready(function() {
$('input[type="submit"]').addClass('btn');
$('[title]').tooltip();
});
}(jQuery));
//]]>
</script>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin=""/> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin=""/>
<link rel="stylesheet" href="{% static 'metas/css/openmap.css' %}" />
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script> <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
<link rel="stylesheet" type="text/css" href="{% static "admin/css/changelists.css" %}" /> <link rel="stylesheet" type="text/css" href="{% static "admin/css/changelists.css" %}" />
<script type="text/javascript" src="{% static "admin/js/core.js" %}"></script> <script type="text/javascript" src="{% static "admin/js/core.js" %}"></script>
<script type="text/javascript" src="{% static "admin/js/jquery.min.js" %}"></script> <script type="text/javascript" src="{% static "admin/js/jquery.min.js" %}"></script>
<script type="text/javascript" src="{% static "admin/js/jquery.init.js" %}"></script> <script type="text/javascript" src="{% static "admin/js/jquery.init.js" %}"></script>
<style> <script type="text/javascript" src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script>
.totalizador {
float:right;
}
#filter_form {
padding: 10px;
}
body, html, .mapbox, #map {
height: 100%;
}
.filterwrap {
background-color: rgba(255,255,255,0.5);
position: absolute;
top: 0;
left: 0;
z-index: 314159;
max-height: 100%;
overflow-y: auto;
}
.region-ufs {
margin-left: 15px;
}
</style>
</head> </head>
<body> <body>
<div class="mapbox"> <div class="mapbox">
<div class="sigi-logo">
<div>
<img src="{% static 'img/interlegis.png' %}" class='img-circle'/>
</div>
<div>
<h3>Interlegis</h3>
<a href="{% url 'admin:index' %}">Voltar ao SIGI</a>
</div>
</div>
<div class="container-fluid filterwrap panel panel-body"> <div class="container-fluid filterwrap panel panel-body">
<a href="#" id="options-toggler" type="button" data-toggle="collapse" data-target="#filterbox" aria-expanded="false" aria-controls="collapseExample"> <a href="#" style="float: right;" id="options-toggler" type="button" data-toggle="collapse" data-target="#filterbox" aria-expanded="false" aria-controls="collapseExample">
Opções <span class="glyphicon glyphicon-chevron-right"></span> <span class="glyphicon glyphicon-chevron-right"></span>
</a> </a>
<div class="collapse" id="filterbox"> <div class="collapse" id="filterbox">
<input type="text" class="form-control" placeholder="Procurar" aria-label="Procurar" aria-describedby="basic-addon2"> <form id="searchform" class="form-inline ui-front">
<input type="text" id="search-text" class="form-control" placeholder="Procurar" aria-label="Procurar" aria-describedby="basic-addon2">
</form>
<div class="accordion" id="accordionExample"> <div class="accordion" id="accordionExample">
<form id="filterForm" action="" method="get" > <form id="filterForm" action="" method="get" >
<h4>Filtros</h4> <h4>Filtros</h4>
@ -104,6 +79,10 @@
</div> </div>
<div id="collapse-servico-filter" class="collapse" aria-labelledby="servico-filter" data-parent="#accordionExample"> <div id="collapse-servico-filter" class="collapse" aria-labelledby="servico-filter" data-parent="#accordionExample">
<div class="card-body"> <div class="card-body">
<div class="form-check">
<input type="checkbox" id="tipo_servico_ignore" name="ignore_tipo_servico" value="ignore" data-controls="tipo_servico" />
<label for="tipo_servico_ignore" class="form-check-label">Ignorar</label>
</div>
<div class="form-check"> <div class="form-check">
<input type="checkbox" id="tipo_servico_none" name="tipo_servico" value="none"/> <input type="checkbox" id="tipo_servico_none" name="tipo_servico" value="none"/>
<label for="tipo_servico_none" class="form-check-label">Nenhum serviço</label> <label for="tipo_servico_none" class="form-check-label">Nenhum serviço</label>
@ -125,6 +104,10 @@
</div> </div>
<div id="collapse-convenio-filter" class="collapse" aria-labelledby="convenio-filter" data-parent="#accordionExample"> <div id="collapse-convenio-filter" class="collapse" aria-labelledby="convenio-filter" data-parent="#accordionExample">
<div class="card-body"> <div class="card-body">
<div class="form-check">
<input type="checkbox" id="tipo_convenio_ignore" name="ignore_tipo_convenio" value="ignore" data-controls="tipo_convenio" />
<label for="tipo_convenio_ignore" class="form-check-label">Ignorar</label>
</div>
<div class="form-check"> <div class="form-check">
<input type="checkbox" id="tipo_convenio_none" name="tipo_convenio" value="none"/> <input type="checkbox" id="tipo_convenio_none" name="tipo_convenio" value="none"/>
<label for="tipo_convenio_none" class="form-check-label">Sem convênio</label> <label for="tipo_convenio_none" class="form-check-label">Sem convênio</label>
@ -171,6 +154,10 @@
</div> </div>
<div id="collapse-gerente-filter" class="collapse" aria-labelledby="gerente-filter" data-parent="#accordionExample"> <div id="collapse-gerente-filter" class="collapse" aria-labelledby="gerente-filter" data-parent="#accordionExample">
<div class="card-body"> <div class="card-body">
<div class="form-check">
<input type="checkbox" id="gerente_ignore" name="gerente_ignore" value="ignore" data-controls="gerente" />
<label for="gerente_ignore" class="form-check-label">Ignorar</label>
</div>
<div class="form-check"> <div class="form-check">
<input type="checkbox" id="gerente_none" name="gerente" value="none"/> <input type="checkbox" id="gerente_none" name="gerente" value="none"/>
<label for="gerente_none" class="form-check-label">Sem gerente</label> <label for="gerente_none" class="form-check-label">Sem gerente</label>
@ -184,19 +171,17 @@
</div> </div>
</div> </div>
</div> </div>
{% comment %} <hr/> <hr/>
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<button class="btn btn-default" type="submit" name="reptype" value="resumo"><span class="glyphicon glyphicon-print"></span> Resumo</a>
<button class="btn btn-default" type="submit" name="reptype" value="lista"><span class="glyphicon glyphicon-print"></span> Listagem</a> <button class="btn btn-default" type="submit" name="reptype" value="lista"><span class="glyphicon glyphicon-print"></span> Listagem</a>
<button class="btn btn-default" type="submit" name="reptype" value="exporta"><span class="glyphicon glyphicon-export"></span>Exportar</a> <button class="btn btn-default" type="submit" name="reptype" value="exporta"><span class="glyphicon glyphicon-export"></span>Exportar</a>
</div> </div>
</div> {% endcomment %} </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
<div id="map"> <div id="map">
<!-- open street map --> <!-- open street map -->
</div> </div>
@ -204,6 +189,43 @@
</div> </div>
<script> <script>
$(document).ready(function(){ $(document).ready(function(){
var options = {color: 'blue', fillColor: 'red', fillOpacity: 0.4, radius: 500};
var unfiltred_options = {color: 'red', fillColor: 'red', fillOpacity: 0, radius: 1000};
$("#search-text").autocomplete({
minLength: 3,
source: function(request, response) {
$.ajax({
url: "{% url "openmapsearch" %}",
data: {q: request.term },
dataType: "json",
appendTo: "#searchform",
success: function(data) {
console.log(data);
response(data);
},
})
},
select: function( event, ui ) {
mymap.flyTo([ui.item.lat, ui.item.lng], 8.5);
var encontrado = false;
mymap.eachLayer(function(layer) {
if (layer instanceof L.Circle) {
if (layer.orgao_id == ui.item.id) {
layer.openPopup();
encontrado = true;
}
}
})
if (!encontrado) {
var mark = L.circle([ui.item.lat, ui.item.lng], unfiltred_options).bindTooltip(ui.item.label).bindPopup("").addTo(mymap);
mark.orgao_id = ui.item.id
mark.openPopup();
}
console.log(ui);
}
});
$("#filterbox").on("shown.bs.collapse", function() { $("#filterbox").on("shown.bs.collapse", function() {
$("#options-toggler span").removeClass("glyphicon-chevron-right").addClass("glyphicon-chevron-left") $("#options-toggler span").removeClass("glyphicon-chevron-right").addClass("glyphicon-chevron-left")
}) })
@ -246,7 +268,11 @@
var name = $(this).attr("name"), var name = $(this).attr("name"),
value = $(this).attr("value"), value = $(this).attr("value"),
checked = $(this).prop("checked"); checked = $(this).prop("checked");
console.log(name, value, checked);
if (value == "ignore") {
controls = $(this).attr("data-controls");
$("input[type=checkbox][name='"+controls+"']").prop("disabled", checked);
}
if (value=="none") { if (value=="none") {
$("input[type=checkbox][name='" + name +"'][value!='none']").prop("checked", !checked); $("input[type=checkbox][name='" + name +"'][value!='none']").prop("checked", !checked);
@ -273,7 +299,6 @@
} }
var formData = $("#filterForm").serializeArray(); var formData = $("#filterForm").serializeArray();
var options = {color: 'blue', fillColor: 'red', fillOpacity: 0.4, radius: 500};
mymap.eachLayer(function(layer) { mymap.eachLayer(function(layer) {
if (layer instanceof L.Circle) { if (layer instanceof L.Circle) {

6
sigi/apps/metas/urls.py

@ -9,9 +9,5 @@ urlpatterns = patterns(
url(r'^openmap/$', 'openmap', name='openmap'), url(r'^openmap/$', 'openmap', name='openmap'),
url(r'^openmapdata/$', 'openmapdata', name='openmapdata'), url(r'^openmapdata/$', 'openmapdata', name='openmapdata'),
url(r'^openmapdetail/(?P<orgao_id>\w+)/$', 'openmapdetail', name='openmapdetail'), url(r'^openmapdetail/(?P<orgao_id>\w+)/$', 'openmapdetail', name='openmapdetail'),
url(r'^mapa/$', 'mapa', name='metas-mapa'), # tagerror url(r'^openmapsearch/$', 'openmapsearch', name='openmapsearch'),
url(r'^mapdata/$', 'map_data', name='metas-map_data'),
url(r'^mapsearch/$', 'map_search', name='metas-map_search'),
url(r'^mapsum/$', 'map_sum', name='metas-map_sum'),
url(r'^maplist/$', 'map_list', name='metas-map_list'),
) )

493
sigi/apps/metas/views.py

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import csv import csv
from datetime import datetime
import json as simplejson # XXX trocar isso por simplesmente import json e refatorar o codigo import json as simplejson # XXX trocar isso por simplesmente import json e refatorar o codigo
import os import os
import time import time
@ -64,16 +65,91 @@ def dashboard(request):
return render_to_response('metas/dashboard.html', extra_context, context_instance=RequestContext(request)) return render_to_response('metas/dashboard.html', extra_context, context_instance=RequestContext(request))
def openmap(request): def openmap(request):
context = { reptype = request.GET.get('reptype', None)
'tipos_orgao': TipoOrgao.objects.filter(legislativo=True),
'tipos_servico': TipoServico.objects.all(),
'tipos_convenio': Projeto.objects.all(),
'gerentes': Servidor.objects.exclude(casas_que_gerencia=None),
'regioes': [(s, n, UnidadeFederativa.objects.filter(regiao=s))
for s, n in UnidadeFederativa.REGIAO_CHOICES],
} if reptype is None:
return render(request, 'metas/openmap.html', context) context = {
'tipos_orgao': TipoOrgao.objects.filter(legislativo=True),
'tipos_servico': TipoServico.objects.all(),
'tipos_convenio': Projeto.objects.all(),
'gerentes': Servidor.objects.exclude(casas_que_gerencia=None),
'regioes': [(s, n, UnidadeFederativa.objects.filter(regiao=s))
for s, n in UnidadeFederativa.REGIAO_CHOICES],
}
return render(request, 'metas/openmap.html', context)
else:
tipos_orgao = request.GET.getlist('tipo_orgao', [])
tipos_servico = request.GET.getlist('tipo_servico', [])
tipos_convenio = request.GET.getlist('tipo_convenio', [])
gerentes = request.GET.getlist('gerente', [])
ufs = request.GET.getlist('uf', [])
casas = openmapdata(request)
context = {
'tipos_orgao': TipoOrgao.objects.filter(legislativo=True,
sigla__in=tipos_orgao),
'tipos_servico': TipoServico.objects.filter(
sigla__in=tipos_servico
),
'tipos_convenio': Projeto.objects.filter(sigla__in=tipos_convenio),
'gerentes': Servidor.objects.exclude(
casas_que_gerencia=None).filter(id__in=gerentes),
'ufs': UnidadeFederativa.objects.filter(sigla__in=ufs),
'casas': casas
}
if reptype == "lista":
return render_to_pdf("metas/lista_casas.html", context)
else:
fieldnames = ['cnpj', 'nome', 'uf', 'regiao', 'endereco', 'bairro',
'cep', 'ult_alt_endereco', 'presidente',
'ult_atualizacao_presidente', 'telefone_presidente',
'email_presidente', 'telefones', 'emails', 'contatos',
'convenios', 'servicos']
response = HttpResponse(content_type='text/csv')
writer = csv.DictWriter(response, fieldnames=fieldnames)
writer.writeheader()
for casa in casas:
row = {
'cnpj': casa.cnpj.encode('utf8'),
'nome': casa.nome.encode('utf8'),
'uf': casa.municipio.uf.nome.encode('utf8'),
'regiao':
casa.municipio.uf.get_regiao_display().encode('utf8'),
'endereco': casa.logradouro.encode('utf8'),
'bairro': casa.bairro.encode('utf8'),
'cep': casa.cep.encode('utf8'),
'ult_alt_endereco': (casa.ult_alt_endereco.strftime(
"%d/%m/%Y").encode('utf8')
if casa.ult_alt_endereco else ""),
'telefones': u", ".join(casa.telefones.values_list('numero',
flat=True)
).encode('utf8'),
'emails': u", ".join([casa.email] + list(
casa.funcionario_set.values_list('email',flat=True))
).encode('utf8'),
'contatos': u", ".join(casa.funcionario_set.values_list(
'nome', flat=True)).encode('utf8'),
'convenios': u", ".join([c.__unicode__() for c in
casa.convenio_set.all()]
).encode('utf8'),
'servicos': u", ".join([u"{tipo} ({url})".format(
tipo=s.tipo_servico.nome, url=s.url)
for s in casa.servico_set.all()]
).encode('utf8')
}
if casa.presidente:
row['presidente'] = casa.presidente.nome.encode('utf8')
row['ult_atualizacao_presidente'] = (
casa.presidente.ult_alteracao.strftime("%d/%m/%Y")
if casa.presidente.ult_alteracao else "")
row['telefone_presidente'] = casa.presidente.nota.encode(
'utf8') if casa.presidente.nota else ""
row['email_presidente'] = casa.presidente.email.encode(
'utf8')
writer.writerow(row)
return response
def openmapdata(request): def openmapdata(request):
tipos_orgao = request.GET.getlist('tipo_orgao', None) tipos_orgao = request.GET.getlist('tipo_orgao', None)
@ -112,381 +188,46 @@ def openmapdata(request):
else: else:
dados = dados.filter(gerentes_interlegis__id__in=gerentes) dados = dados.filter(gerentes_interlegis__id__in=gerentes)
dados = dados.distinct("nome")
if not reptype: if not reptype:
dados = dados.distinct("nome")
dados = dados.values_list("id", "nome", "municipio__latitude", dados = dados.values_list("id", "nome", "municipio__latitude",
"municipio__longitude") "municipio__longitude")
return JsonResponse(list(dados), safe=False) return JsonResponse(list(dados), safe=False)
else: else:
return JsonResponse({'result': 'todo-feature'}) dados = dados.order_by(
'municipio__uf__regiao',
'municipio__uf__nome',
'nome'
).distinct(
'municipio__uf__regiao',
'municipio__uf__nome',
'nome'
).prefetch_related(
'servico_set',
'convenio_set',
'municipio__uf',
'gerentes_interlegis'
)
return dados
def openmapdetail(request, orgao_id): def openmapdetail(request, orgao_id):
orgao = get_object_or_404(Orgao, id=orgao_id) orgao = get_object_or_404(Orgao, id=orgao_id)
return render(request, "metas/openmapdetail.html", {'orgao': orgao}) return render(request, "metas/openmapdetail.html", {'orgao': orgao})
def mapa(request): def openmapsearch(request):
""" q = request.GET.get('q', '')
Mostra o mapa com filtros carregados com valores default if len(q) < 3:
""" return JsonResponse({'result': 'unsearchable'})
projetos = Projeto.objects.all() dados = Orgao.objects.filter(
filters = ( tipo__legislativo=True,
# NAME, HEADING, search_text__icontains=to_ascii(q)
# [(value, label, checked) ...] )[:10]
("seit", _(u'Por Serviços SEIT'), dados = dados.values("id", "nome", "municipio__latitude",
[(x.sigla, x.sigla, x.nome, True) "municipio__longitude")
for x in TipoServico.objects.all()]), dados = [{'id': d['id'],
("convenios", _(u'Por Casas conveniadas'), 'label': d['nome'],
[(x.sigla, 'lat': d['municipio__latitude'],
'convenio_' + x.sigla, 'lng': d['municipio__longitude']} for d in dados]
_(u'ao {projeto}').format(projeto=x.sigla), return JsonResponse(list(dados), safe=False)
x.sigla == 'PML') for x in projetos]),
("equipadas", _(u'Por Casas equipadas'),
[(x.sigla,
'equip_' + x.sigla,
_(u'pelo {projeto}').format(projeto=x.sigla),
False) for x in projetos]),
("diagnosticos", _(u'Por Diagnósticos'),
[('A', 'diagnostico_A', 'Em andamento', False),
('P', 'diagnostico_P', 'Publicados', True)]),
("regioes", _(u'Por região'),
[(x[0], x[0], x[1], True)
for x in UnidadeFederativa.REGIAO_CHOICES]),
("estados", _(u'Por Estado'),
[(x.sigla, x.sigla, x.nome, False)
for x in UnidadeFederativa.objects.all()]),
("gerente", _(u'Por gerente de relacionamento'),
[("", 'gerente_', _(u"Sem gerente"), False)] +
[(g.id, 'gerente_{0}'.format(g.id),
_(u"{firstname} {lastname}").format(
firstname=g.nome_completo.split()[0],
lastname=g.nome_completo.split()[-1])
, False) for g in Servidor.objects.exclude(
casas_que_gerencia=None).order_by('nome_completo')]),
)
return render(request, 'metas/mapa.html', {'filters': filters})
@cache_page(1800) # Cache de 30min
def map_data(request):
"""
Retorna json com todos os dados dos municípios que têm relação com o Interlegis
Tenta ler esse json do arquivo JSON_FILE_NAME. Se não encontrar, chama a rotina
gera_map_data_file().
"""
try:
file = open(JSON_FILE_NAME, 'r')
json = file.read()
except:
json = gera_map_data_file()
return HttpResponse(json, content_type='application/json')
def map_search(request):
response = {'result': 'NOT_FOUND'}
if 'q' in request.GET:
q = request.GET.get('q')
if len(q.split(',')) > 1:
municipio, uf = [s.strip() for s in q.split(',')]
casas = Orgao.objects.filter(search_text__icontains=to_ascii(municipio), municipio__uf__sigla__iexact=uf)
else:
casas = Orgao.objects.filter(search_text__icontains=to_ascii(q))
if casas.count() > 0:
response = {'result': 'FOUND', 'ids': [c.pk for c in casas]}
return HttpResponse(simplejson.dumps(response), content_type='application/json')
@cache_page(86400) # Cache de um dia (24 horas = 86400 segundos)
def map_sum(request):
# Filtrar Casas de acordo com os parâmetros
param = get_params(request)
casas = filtrar_casas(**param)
# Montar registros de totalização
tot_servicos = SortedDict()
tot_projetos = SortedDict()
tot_diagnosticos = SortedDict()
for ts in TipoServico.objects.all():
tot_servicos[ts.sigla] = 0
for pr in Projeto.objects.all():
tot_projetos[pr.sigla] = 0
tot_convenios = tot_projetos.copy()
tot_equipadas = tot_projetos.copy()
tot_diagnosticos['A'] = 0
tot_diagnosticos['P'] = 0
# Montar as linhas do array de resultados com as regiões e os estados
result = {}
for uf in UnidadeFederativa.objects.filter(Q(regiao__in=param['regioes']) | Q(sigla__in=param['estados'])).order_by('regiao', 'nome'):
if uf.regiao not in result:
result[uf.regiao] = {'nome': uf.get_regiao_display(), 'ufs': {}, 'servicos': tot_servicos.copy(),
'convenios': tot_projetos.copy(), 'equipadas': tot_projetos.copy(),
'diagnosticos': tot_diagnosticos.copy()}
result[uf.regiao]['ufs'][uf.codigo_ibge] = {'nome': uf.nome, 'servicos': tot_servicos.copy(),
'convenios': tot_projetos.copy(), 'equipadas': tot_projetos.copy(),
'diagnosticos': tot_diagnosticos.copy()}
# Processar as casas filtradas
for casa in casas.distinct():
uf = casa.municipio.uf
for s in casa.servico_set.all():
tot_servicos[s.tipo_servico.sigla] += 1
result[uf.regiao]['servicos'][s.tipo_servico.sigla] += 1
result[uf.regiao]['ufs'][uf.codigo_ibge]['servicos'][s.tipo_servico.sigla] += 1
for c in casa.convenio_set.all():
tot_convenios[c.projeto.sigla] += 1
result[uf.regiao]['convenios'][c.projeto.sigla] += 1
result[uf.regiao]['ufs'][uf.codigo_ibge]['convenios'][c.projeto.sigla] += 1
if (c.equipada and c.data_termo_aceite is not None):
tot_equipadas[c.projeto.sigla] += 1
result[uf.regiao]['equipadas'][c.projeto.sigla] += 1
result[uf.regiao]['ufs'][uf.codigo_ibge]['equipadas'][c.projeto.sigla] += 1
for d in casa.diagnostico_set.all():
if d.publicado:
tot_diagnosticos['P'] += 1
result[uf.regiao]['diagnosticos']['P'] += 1
result[uf.regiao]['ufs'][uf.codigo_ibge]['diagnosticos']['P'] += 1
else:
tot_diagnosticos['A'] += 1
result[uf.regiao]['diagnosticos']['A'] += 1
result[uf.regiao]['ufs'][uf.codigo_ibge]['diagnosticos']['A'] += 1
extra_context = {
'pagesize': 'a4 landscape',
'servicos': TipoServico.objects.all(),
'projetos': Projeto.objects.all(),
'result': result,
'tot_servicos': tot_servicos,
'tot_convenios': tot_convenios,
'tot_equipadas': tot_equipadas,
'tot_diagnosticos': tot_diagnosticos,
}
return render_to_pdf('metas/map_sum.html', extra_context)
@cache_page(86400) # Cache de um dia (24 horas = 86400 segundos)
def map_list(request):
# Filtrar Casas de acordo com os parâmetros
param = get_params(request)
formato = request.GET.get('fmt', 'pdf')
casas = filtrar_casas(**param)
casas = casas.order_by('municipio__uf__regiao', 'municipio__uf__nome', 'nome').distinct()
if formato == 'csv':
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="maplist.csv"'
writer = csv.writer(response)
srv = {x[0]: x[1] for x in TipoServico.objects.values_list('id', 'nome')}
cnv = {x[0]: x[1] for x in Projeto.objects.values_list('id', 'sigla')}
head = [s.encode('utf-8') for s in
[u'código IBGE', u'nome da casa', u'município', u'UF', u'região', ] +
[x for x in srv.values()] +
reduce(lambda x, y: x + y,
[['conveniada ao %s' % x, 'equipada por %s' % x] for x in cnv.values()])]
writer.writerow(head)
for casa in casas:
row = [casa.municipio.codigo_ibge,
casa.nome.encode('utf-8'),
casa.municipio.nome.encode('utf-8'),
casa.municipio.uf.sigla.encode('utf-8'),
casa.municipio.uf.get_regiao_display().encode('utf-8'), ]
for id in srv.keys():
try:
sv = casa.servico_set.get(tipo_servico__id=id)
row += [sv.data_ativacao, ]
except:
row += [None, ]
for id in cnv.keys():
try:
cv = casa.convenio_set.get(projeto__id=id)
row += [cv.data_retorno_assinatura, cv.data_termo_aceite if cv.equipada else None, ]
except:
row += [None, None, ]
writer.writerow(row)
return response
return render_to_pdf('metas/map_list.html', {'casas': casas})
#----------------------------------------------------------------------------------------------------
# Funções auxiliares - não são views
#----------------------------------------------------------------------------------------------------
def get_params(request):
''' Pegar parâmetros da pesquisa '''
return {
'seit': request.GET.getlist('seit'),
'convenios': request.GET.getlist('convenios'),
'equipadas': request.GET.getlist('equipadas'),
'diagnosticos': request.GET.getlist('diagnosticos'),
'regioes': request.GET.getlist('regioes'),
'estados': request.GET.getlist('estados'),
'gerentes': request.GET.getlist('gerente'),
}
def filtrar_casas(seit, convenios, equipadas, regioes, estados, diagnosticos,
gerentes):
''' Filtrar Casas que atendem aos parâmetros de pesquisa '''
qServico = Q(servico__tipo_servico__sigla__in=seit)
qConvenio = Q(convenio__projeto__sigla__in=convenios)
qEquipada = Q(convenio__projeto__sigla__in=equipadas,
convenio__equipada=True)
qRegiao = Q(municipio__uf__regiao__in=regioes)
qEstado = Q(municipio__uf__sigla__in=estados)
if gerentes:
qGerente = Q(gerentes_interlegis__id__in=gerentes)
else:
qGerente = Q()
if diagnosticos:
qDiagnostico = Q(diagnostico__publicado__in=[p == 'P'
for p in diagnosticos])
else:
qDiagnostico = Q()
casas = Orgao.objects.filter(qRegiao | qEstado).filter(qGerente)
if seit or convenios or equipadas or diagnosticos:
casas = casas.filter(qServico | qConvenio | qEquipada | qDiagnostico)
else:
casas = casas.filter(Q(servico=None) & Q(convenio=None) &
Q(diagnostico=None))
return casas
def gera_map_data_file(cronjob=False):
''' Criar um arquivo json em {settings.MEDIA_ROOT}/apps/metas/ com o nome de map_data.json
Este arquivo será consumido pela view de dados de mapa.
Retorna os dados json caso cronjob seja falso.
Caso cronjob seja True, retorna log de tempo gasto na geração ou a mensagem do erro
que impediu a gravação do arquivo.
'''
start = time.time()
casas = {}
for c in Orgao.objects.prefetch_related('servico_set', 'convenio_set', 'diagnostico_set').all().distinct():
# if c.servico_set.count() == 0 and c.convenio_set.count() == 0 and c.diagnostico_set.count() == 0:
# continue
# # Salta essa casa, pois ela não tem nada com o Interlegis
if c.pk not in casas:
summary = parliament_summary(c)
summary['info'] = "<br/>".join(summary['info'])
casas[c.pk] = summary
json_data = simplejson.dumps(casas)
try:
file = open(JSON_FILE_NAME, 'w')
file.write(json_data)
file.close()
except Exception as e: # A gravação não foi bem sucedida ...
if cronjob: # ... o chamador deseja a mensagem de erro
return str(e)
else:
pass # ... ou os dados poderão ser usados de qualquer forma
if cronjob:
return _(u"Arquivo %(filename)s gerado em %(seconds)d segundos") % dict(
filename=JSON_FILE_NAME,
seconds=time.time() - start)
return json_data
def parliament_summary(parliament):
summary = {
'nome': parliament.nome + ', ' + parliament.municipio.uf.sigla,
'thumb': thumbnail_url(parliament.foto, 'small'),
'foto': (parliament.foto.url if parliament.foto else ''),
'lat': str(parliament.municipio.latitude),
'lng': str(parliament.municipio.longitude),
'estado': parliament.municipio.uf.sigla,
'regiao': parliament.municipio.uf.regiao,
'gerentes': [str(g.id) for g in parliament.gerentes_interlegis.all()],
'diagnosticos': [],
'seit': [],
'convenios': [],
'equipadas': [],
'info': []
}
if parliament.gerentes_interlegis.exists():
summary['info'].append(_(u"Gerentes Interlegis: {lista}").format(
lista=parliament.lista_gerentes(fmt='lista')))
for sv in parliament.servico_set.filter(data_desativacao=None):
summary['info'].append(
_(u"{name} ativado em {date}").format(
name=sv.tipo_servico.nome,
date=sv.data_ativacao.strftime('%d/%m/%Y') if sv.data_ativacao
else _(u'<sem data de ativação>')) +
(u" <a href='{0}' target='_blank'><img src='{1}img/link.gif' "
u"alt='link'></a>").format(sv.url, STATIC_URL))
summary['seit'].append(sv.tipo_servico.sigla)
for cv in parliament.convenio_set.all():
if ((cv.data_retorno_assinatura is None) and
(cv.equipada and cv.data_termo_aceite is not None)):
summary['info'].append(
_(u"Equipada em {date} pelo {project}").format(
date=cv.data_termo_aceite.strftime('%d/%m/%Y'),
project=cv.projeto.sigla))
summary['equipadas'].append(cv.projeto.sigla)
elif cv.data_retorno_assinatura is None:
summary['info'].append(
_(u"Adesão ao projeto {project}, em {date}").format(
project=cv.projeto.sigla, date=cv.data_adesao))
summary['convenios'].append(cv.projeto.sigla)
if ((cv.data_retorno_assinatura is not None) and not
(cv.equipada and cv.data_termo_aceite is not None)):
summary['info'].append(
_(u"Conveniada ao %(project)s em %(date)s").format(
project=cv.projeto.sigla,
date=cv.data_retorno_assinatura.strftime('%d/%m/%Y')))
summary['convenios'].append(cv.projeto.sigla)
if ((cv.data_retorno_assinatura is not None) and
(cv.equipada and cv.data_termo_aceite is not None)):
summary['info'].append(
_(u"Conveniada ao {project} em {date} e equipada em "
u"{equipped_date}").format(
project=cv.projeto.sigla,
date=cv.data_retorno_assinatura.strftime('%d/%m/%Y'),
equipped_date=cv.data_termo_aceite.strftime('%d/%m/%Y')))
summary['equipadas'].append(cv.projeto.sigla)
summary['convenios'].append(cv.projeto.sigla)
for dg in parliament.diagnostico_set.all():
summary['diagnosticos'].append('P' if dg.publicado else 'A')
summary['info'].append(
_(u"Diagnosticada no período de {initial_date} "
u"a {final_date}").format(
initial_date=dg.data_visita_inicio.strftime('%d/%m/%Y')
if dg.data_visita_inicio is not None
else _(u"<sem data de início>"),
final_date=dg.data_visita_fim.strftime('%d/%m/%Y')
if dg.data_visita_fim
else _(u"<sem data de término>")))
return summary

BIN
sigiStatic/img/interlegis.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

32
templates/base_report.html

@ -5,7 +5,7 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>{% trans 'Relatório' %}</title> <title>{% block title %}{% trans 'Relatório' %}{% endblock title %}</title>
<style type="text/css"> <style type="text/css">
td.logo { td.logo {
text-align: center; text-align: center;
@ -34,6 +34,22 @@
line-height: 1em; line-height: 1em;
} }
#footer {
width: 100%;
}
#footer table {
border: 0px;
}
.footer-left {
text-align: left;
}
.footer-center {
text-align: center;
}
.footer-right {
text-align: right;
}
div.new_page { div.new_page {
page-break-before: always; page-break-before: always;
} }
@ -41,7 +57,7 @@
-pdf-keep-with-next: true; -pdf-keep-with-next: true;
} }
@page { @page {
size: {{ pagesize }}; size: {% block pagesize %}{{ pagesize }}{% endblock pagesize %};
margin: 4cm 1cm 1cm 2cm; margin: 4cm 1cm 1cm 2cm;
font-family: "Helvetica, Arial, sans-serif"; font-family: "Helvetica, Arial, sans-serif";
font-size: 2em; font-size: 2em;
@ -52,9 +68,9 @@
@frame footer { @frame footer {
-pdf-frame-content: footer; -pdf-frame-content: footer;
bottom: 0cm; bottom: 0cm;
margin-left: 9cm;
margin-right: 9cm;
height: 1cm; height: 1cm;
margin-left: 2cm;
margin-right: 1cm;
} }
} }
</style> </style>
@ -79,7 +95,13 @@
{% endblock %} {% endblock %}
<div id="footer"> <div id="footer">
{%block page_foot%} {%block page_foot%}
{% trans 'Página' %} <pdf:pagenumber> <table>
<tr>
<td class="footer-left">{% trans 'Emissão:' %} {% now "d/m/Y H:i:s" %}</td>
<td class="footer-center">&nbsp;</td>
<td class="footer-right">{% trans 'Página:' %} <pdf:pagenumber/> </td>
</tr>
</table>
{%endblock%} {%endblock%}
</div> </div>
</body> </body>

2
templates/index.html

@ -18,7 +18,7 @@
{% block content_title %} {% block content_title %}
<h1 class="pull-left">{% trans 'Dashboard' %}</h1> <h1 class="pull-left">{% trans 'Dashboard' %}</h1>
<div class="pull-right"><a href="/dashboard/mapa/"><img src="{% static 'img/mapicon.png' %}" /> {% trans 'Mapa de atuação do Interlegis' %}</a></div> <div class="pull-right"><a href="{% url 'openmap' %}"><img src="{% static 'img/mapicon.png' %}" /> {% trans 'Mapa de atuação do Interlegis' %}</a></div>
{% endblock %} {% endblock %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/dashboard.css" %}" />{% endblock %} {% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/dashboard.css" %}" />{% endblock %}

Loading…
Cancel
Save