Browse Source

Finalizando a migração

pull/159/head
Sesostris Vieira 3 years ago
parent
commit
e9bab3610e
  1. 5
      sigi/apps/casas/templates/casas/painel.html
  2. 67
      sigi/apps/casas/templates/casas/resumo_carteira_snippet.html
  3. 5
      sigi/apps/casas/urls.py
  4. 464
      sigi/apps/casas/views.py
  5. 178
      sigi/apps/convenios/templates/convenios/tabela_regiao.html
  6. 25
      sigi/apps/convenios/urls.py
  7. 225
      sigi/apps/convenios/views.py
  8. 58
      sigi/apps/eventos/templates/eventos/calendario.html
  9. 42
      sigi/apps/eventos/urls.py
  10. 831
      sigi/apps/eventos/views.py
  11. 44
      sigi/apps/home/static/home/css/openmap.css
  12. 35
      sigi/apps/home/templates/home/dashboard/gerentes_snippet.html
  13. 57
      sigi/apps/home/templates/home/dashboard/resumo_convenios.html
  14. 41
      sigi/apps/home/templates/home/dashboard/resumo_seit.html
  15. 60
      sigi/apps/home/templates/home/lista_casas.html
  16. 173
      sigi/apps/home/templates/home/mapfilter.html
  17. 375
      sigi/apps/home/templates/home/openmap.html
  18. 23
      sigi/apps/home/templates/home/openmapdetail.html
  19. 95
      sigi/apps/home/templates/home/sem_convenio.html
  20. 34
      sigi/apps/home/templatetags/smart_pagination.py
  21. 43
      sigi/apps/home/urls.py
  22. 494
      sigi/apps/home/views.py
  23. 52
      sigi/apps/ocorrencias/admin.py
  24. 14
      sigi/apps/ocorrencias/filters.py
  25. 49
      sigi/apps/ocorrencias/forms.py
  26. 21
      sigi/apps/ocorrencias/migrations/0007_remove_comentario_encaminhar_setor_and_more.py
  27. 17
      sigi/apps/ocorrencias/migrations/0008_remove_categoria_setor_responsavel.py
  28. 22
      sigi/apps/ocorrencias/models.py
  29. 198
      sigi/apps/ocorrencias/templates/ocorrencias/painel-old.html
  30. 399
      sigi/apps/ocorrencias/templates/ocorrencias/painel.html
  31. 49
      sigi/apps/ocorrencias/urls.py
  32. 143
      sigi/apps/ocorrencias/views.py
  33. 1
      sigi/apps/parlamentares/templates/admin/parlamentares/parlamentar/change_form.html
  34. 7
      sigi/apps/servidores/models.py
  35. 3
      sigi/apps/utils/__init__.py
  36. 7
      sigi/settings/base.py
  37. 2
      sigi/settings/menu_conf.yaml
  38. 37
      sigi/static/css/dashboard.css
  39. BIN
      sigi/static/img/ilsombra.png
  40. 72
      sigi/static/js/dashboard.js
  41. 29
      sigi/templates/admin/base_site.html
  42. 152
      sigi/templates/admin/change_list.html
  43. 21
      sigi/templates/material/admin/index.html
  44. 44
      sigi/templates/material/admin/side_nav.html
  45. 21
      sigi/templates/material/admin/user_picture.html
  46. 11
      sigi/templates/pdf/base_report.html
  47. 27
      sigi/templates/sigi/snippets/base_card.html
  48. 18
      sigi/templates/sigi/snippets/base_card_chart.html
  49. 8
      sigi/templates/sigi/snippets/base_card_text.html
  50. 57
      sigi/templates/sigi/snippets/dashboard.html
  51. 7
      sigi/urls.py
  52. 63
      sigiStatic/js/dashboard.js
  53. 38
      templates/snippets/modules/resumo_seit.html

5
sigi/apps/casas/templates/casas/painel.html

@ -22,19 +22,18 @@
{% block extrahead %}{{ block.super }}
<script type="text/javascript">
console.log("Cheguei a executar");
$(document).ready(function(){
$("select[name='servidor']").on('change', function() {
var form = $(this.form);
form.submit();
});
listeners();
function listeners() {
$(":checkbox[name|=servico]").on('change', filter_list);
$("#filter-panel a").on("click", geo_filter);
}
function geo_filter( e ) {
e.preventDefault();
var url = $(this).attr('href');

67
sigi/apps/casas/templates/casas/resumo_carteira_snippet.html

@ -1,35 +1,64 @@
{% load i18n %}
{% load static i18n %}
<div class="panel panel-primary flex-col table-responsive">
<div class="panel-heading">
<h3 class="panel-title">
{% if seletor == 'sim' %}
{% trans "Resumo da carteira de" %}
<mark class="dropdown">
<a data-toggle="dropdown" href="">{{ gerente.nome_completo|default:_("todo o Interlegis") }}</a>
<ul class="dropdown-menu">
<li><a href="{% url "casas-carteira" %}?servidor=_all&snippet={{ snippet }}&s={{ seletor }}" data-target="resumo">{% trans "Todo o Interlegis" %}</a></li>
{% if seletor == 'sim' %}
<ul class="collapsible gerente_selector" style="width: 100%;">
<li>
<div class="collapsible-header">
{% if gerente %}
{% if gerente.foto %}
<img src="{{ gerente.foto.url }}" class="circle user_thumb" alt="{% trans "Foto do servidor" %}">
{% else %}
<i class="material-icons circle">account_circle</i>
{% endif %}
{{ gerente.nome_completo }}
{% else %}
<img src="{% static "img/interlegis_60x60.png" %}" class="circle user_thumb" alt="{% trans "Logo Interlegis" %}">
{% trans "Todo o Interlegis" %}
{% endif %}
</div>
<div class="collapsible-body">
<ul>
<li>
<a href="{% url "casas-carteira" %}?servidor=_all&snippet={{ snippet }}&s={{ seletor }}" data-target="card-carteira">
{% trans "Todo o Interlegis" %}
</a>
</li>
{% for g in gerentes %}
<li><a href="{% url "casas-carteira" %}?servidor={{ g.pk }}&snippet={{ snippet }}&s={{ seletor }}" data-target="resumo">{{g.nome_completo }}</a></li>
<li>
<a href="{% url "casas-carteira" %}?servidor={{ g.pk|safe }}&snippet={{ snippet }}&s={{ seletor }}" data-target="card-carteira">
{{g.nome_completo }}
</a>
</li>
{% endfor %}
</ul>
</mark>
{% else %}
{% trans "Resumo da carteira" %}
{% endif %}
</h3>
</div>
<table class="table table-hover resumo">
</div>
</li>
</ul>
{% endif %}
<table class="numeros resumo-carteira">
{% for row in resumo %}
{% if forloop.first %}
<tr>
{% for col in row %}
<th>{{ col }}</th>
{% endfor %}
</tr>
{% else %}
<tr>
{% if row.subtitle %}
<th colspan="7">{{ row.subtitle }}</th>
{% else %}
{% for col in row %}
<td{% if forloop.counter > 2 %} class="hidden-xs"{% endif %}>{{ col }}</td>
{% if forloop.first %}
<th>{{ col }}</th>
{% else %}
<td>{{ col }}</td>
{% endif %}
{% endfor %}
{% endif %}
</tr>
{% endif %}
{% endfor %}
</table>
</div>

5
sigi/apps/casas/urls.py

@ -1,9 +1,10 @@
from django.urls import path, include
from sigi.apps.casas.views import CasasSemConvenioReport
from sigi.apps.casas import views
urlpatterns = [
path('orgao/casas_sem_convenio_report/', CasasSemConvenioReport.as_view(),
path('orgao/casas_sem_convenio_report/', views.CasasSemConvenioReport.as_view(),
name='casas-sem-convenio-report'),
path('carteira/', views.painel_relacionamento, name='casas-carteira'),
]

464
sigi/apps/casas/views.py

@ -22,11 +22,12 @@ from sigi.apps.servidores.models import Servidor
# from sigi.shortcuts import render_to_pdf
# from sigi.apps.casas.reports import (CasasLegislativasLabels,
# CasasLegislativasLabelsSemPresidente)
# from sigi.apps.contatos.models import (UnidadeFederativa, Municipio,
# Mesorregiao, Microrregiao)
# from sigi.apps.ocorrencias.models import Ocorrencia
from sigi.apps.contatos.models import (UnidadeFederativa, Mesorregiao,
Microrregiao)
# , Municipio
from sigi.apps.ocorrencias.models import Ocorrencia
# from sigi.apps.parlamentares.reports import ParlamentaresLabels
# from sigi.apps.servicos.models import TipoServico
from sigi.apps.servicos.models import TipoServico
class CasasSemConvenioReport(WeasyTemplateView):
template_name = "casas/casas_sem_convenio_pdf.html"
@ -910,206 +911,265 @@ def query_ordena(qs, o):
# return render(request, 'casas/portfolio.html', data)
# def resumo_carteira(casas):
# regioes = {r[0]: 0 for r in UnidadeFederativa.REGIAO_CHOICES}
# regioes['total'] = 0
# total = regioes.copy()
# sem_produto = regioes.copy()
# tipos_servico = TipoServico.objects.all()
# dados = {ts.id: regioes.copy() for ts in tipos_servico}
# for r in casas.values('municipio__uf__regiao').annotate(quantidade=Count('id')).order_by():
# regiao = r['municipio__uf__regiao']
# quantidade = r['quantidade']
# total[regiao] = quantidade
# total['total'] += quantidade
# for r in casas.values('municipio__uf__regiao', 'servico__tipo_servico__id').annotate(quantidade=Count('id')).order_by():
# regiao = r['municipio__uf__regiao']
# servico = r['servico__tipo_servico__id']
# quantidade = r['quantidade']
# if servico is None:
# sem_produto[regiao] = quantidade
# sem_produto['total'] += quantidade
# else:
# dados[servico][regiao] = quantidade
# dados[servico]['total'] += quantidade
# dados_ocorrencia = {
# 'registradas': regioes.copy(),
# 'pendentes': regioes.copy(),
# 'sem': regioes.copy(),
# 'media': regioes.copy(),
# }
# for r in casas.values('ocorrencia__status', 'municipio__uf__regiao').annotate(quantidade=Count('id')).order_by():
# status = r['ocorrencia__status']
# regiao = r['municipio__uf__regiao']
# quantidade = r['quantidade']
# if status is None:
# dados_ocorrencia['sem'][regiao] += quantidade
# dados_ocorrencia['sem']['total'] += quantidade
# else:
# dados_ocorrencia['registradas'][regiao] += quantidade
# dados_ocorrencia['registradas']['total'] += quantidade
# if status in [Ocorrencia.STATUS_ABERTO, Ocorrencia.STATUS_REABERTO]:
# dados_ocorrencia['pendentes'][regiao] += quantidade
# dados_ocorrencia['pendentes']['total'] += quantidade
# for r in regioes:
# if (total[r] - dados_ocorrencia['sem'][r]) == 0:
# dados_ocorrencia['media'][r] = 0
# else:
# dados_ocorrencia['media'][r] = (1.0 * dados_ocorrencia['registradas'][r] / (total[r] - dados_ocorrencia['sem'][r]))
# resumo = [[_("Item"), _("Total nacional")] + [r[1] for r in UnidadeFederativa.REGIAO_CHOICES]]
# resumo.append([_("Casas em sua carteira"), total['total']] + [total[r[0]] for r in UnidadeFederativa.REGIAO_CHOICES])
# resumo.append({'subtitle': _("Uso dos produtos Interlegis")})
# resumo.append([_("Casas sem nenhum produto"), sem_produto['total']] + [sem_produto[r[0]] for r in UnidadeFederativa.REGIAO_CHOICES])
# resumo.extend([[ts.nome, dados[ts.id]['total']] + [dados[ts.id][r[0]] for r in UnidadeFederativa.REGIAO_CHOICES] for ts in tipos_servico])
# resumo.append({'subtitle': _("Registros no sistema de ocorrências")})
# resumo.append([_("Casas que nunca registraram ocorrências"), dados_ocorrencia['sem']['total']] + [dados_ocorrencia['sem'][r[0]] for r in UnidadeFederativa.REGIAO_CHOICES])
# resumo.append([_("Total de ocorrências registradas"), dados_ocorrencia['registradas']['total']] + [dados_ocorrencia['registradas'][r[0]] for r in UnidadeFederativa.REGIAO_CHOICES])
# resumo.append([_("Total de ocorrências pendentes"), dados_ocorrencia['pendentes']['total']] + [dados_ocorrencia['pendentes'][r[0]] for r in UnidadeFederativa.REGIAO_CHOICES])
# resumo.append([_("Média de ocorrências por casa"), round(dados_ocorrencia['media']['total'], 2)] + [round(dados_ocorrencia['media'][r[0]], 2) for r in UnidadeFederativa.REGIAO_CHOICES])
# return resumo
# def casas_carteira(request, casas, context):
# servicos = request.GET.getlist('servico')
# sigla_regiao = request.GET.get('r', None)
# sigla_uf = request.GET.get('uf', None)
# meso_id = request.GET.get('meso', None)
# micro_id = request.GET.get('micro', None)
# servicos = request.GET.getlist('servico')
# tipos_servico = context['servicos']
# context['qs_regiao'] = ''
# if micro_id is not None:
# context['micro'] = get_object_or_404(Microrregiao, pk=micro_id)
# context['qs_regiao'] = 'micro=%s' % micro_id
# context['meso'] = context['micro'].mesorregiao
# context['uf'] = context['meso'].uf
# context['regiao'] = context['uf'].regiao
# casas = casas.filter(municipio__microrregiao=context['micro'])
# elif meso_id is not None:
# context['meso'] = get_object_or_404(Mesorregiao, pk=meso_id)
# context['qs_regiao'] = 'meso=%s' % meso_id
# context['uf'] = context['meso'].uf
# context['regiao'] = context['uf'].regiao
# casas = casas.filter(municipio__microrregiao__mesorregiao=context['meso'])
# elif sigla_uf is not None:
# context['uf'] = get_object_or_404(UnidadeFederativa, sigla=sigla_uf)
# context['qs_regiao'] = 'uf=%s' % sigla_uf
# context['regiao'] = context['uf'].regiao
# casas = casas.filter(municipio__uf=context['uf'])
# elif sigla_regiao is not None:
# context['regiao'] = sigla_regiao
# context['qs_regiao'] = 'r=%s' % sigla_regiao
# casas = casas.filter(municipio__uf__regiao=sigla_regiao)
# if 'regiao' in context:
# context['ufs'] = UnidadeFederativa.objects.filter(regiao=context['regiao'])
# todos_servicos = ['_none_'] + [s.sigla for s in tipos_servico]
# if not servicos or set(servicos) == set(todos_servicos):
# servicos = todos_servicos
# context['qs_servico'] = ''
# else:
# if '_none_' in servicos:
# casas = casas.filter(Q(servico=None) | Q(servico__tipo_servico__sigla__in=servicos))
# else:
# casas = casas.filter(servico__tipo_servico__sigla__in=servicos)
# casas = casas.distinct('nome', 'municipio__uf')
# context['qs_servico'] = "&".join(['servico=%s' % s for s in servicos])
# context['servicos_check'] = servicos
# casas = casas.select_related('municipio', 'municipio__uf', 'municipio__microrregiao', 'municipio__microrregiao__mesorregiao').prefetch_related('servico_set')
# return casas, context
# @login_required
# def painel_relacionamento(request):
# page = request.GET.get('page', 1)
# snippet = request.GET.get('snippet', '')
# seletor = request.GET.get('s', None)
# servidor = request.GET.get('servidor', None)
# fmt = request.GET.get('f', 'html')
# if servidor is None:
# gerente = request.user.servidor
# elif servidor == '_all':
# gerente = None
# else:
# gerente = get_object_or_404(Servidor, pk=servidor)
# if gerente is not None:
# casas = gerente.casas_que_gerencia.all()
# if gerente is None or not casas.exists():
# casas = Orgao.objects.exclude(gerentes_interlegis=None)
# gerente = None
# tipos_servico = TipoServico.objects.all()
# regioes = UnidadeFederativa.REGIAO_CHOICES
# context = {
# 'seletor': seletor,
# 'snippet': snippet,
# 'regioes': regioes,
# 'servicos': tipos_servico,
# 'gerentes': Servidor.objects.exclude(casas_que_gerencia=None),
# 'gerente': gerente,
# 'qs_servidor': ('servidor=%s' % gerente.pk) if gerente else '',
# }
def resumo_carteira(casas):
regioes = {r[0]: 0 for r in UnidadeFederativa.REGIAO_CHOICES}
regioes['total'] = 0
total = regioes.copy()
sem_produto = regioes.copy()
tipos_servico = TipoServico.objects.all()
dados = {ts.id: regioes.copy() for ts in tipos_servico}
for r in casas.values('municipio__uf__regiao').annotate(
quantidade=Count('id')).order_by():
regiao = r['municipio__uf__regiao']
quantidade = r['quantidade']
total[regiao] = quantidade
total['total'] += quantidade
for r in casas.values('municipio__uf__regiao',
'servico__tipo_servico__id').annotate(
quantidade=Count('id')).order_by():
regiao = r['municipio__uf__regiao']
servico = r['servico__tipo_servico__id']
quantidade = r['quantidade']
if servico is None:
sem_produto[regiao] = quantidade
sem_produto['total'] += quantidade
else:
dados[servico][regiao] = quantidade
dados[servico]['total'] += quantidade
dados_ocorrencia = {
'registradas': regioes.copy(),
'pendentes': regioes.copy(),
'sem': regioes.copy(),
'media': regioes.copy(),
}
for r in casas.values('ocorrencia__status',
'municipio__uf__regiao').annotate(
quantidade=Count('id')).order_by():
status = r['ocorrencia__status']
regiao = r['municipio__uf__regiao']
quantidade = r['quantidade']
if status is None:
dados_ocorrencia['sem'][regiao] += quantidade
dados_ocorrencia['sem']['total'] += quantidade
else:
dados_ocorrencia['registradas'][regiao] += quantidade
dados_ocorrencia['registradas']['total'] += quantidade
if status in [Ocorrencia.STATUS_ABERTO, Ocorrencia.STATUS_REABERTO]:
dados_ocorrencia['pendentes'][regiao] += quantidade
dados_ocorrencia['pendentes']['total'] += quantidade
for r in regioes:
if (total[r] - dados_ocorrencia['sem'][r]) == 0:
dados_ocorrencia['media'][r] = 0
else:
dados_ocorrencia['media'][r] = (
1.0 * dados_ocorrencia['registradas'][r] /
(total[r] - dados_ocorrencia['sem'][r])
)
resumo = [
[_("Item"), _("Total nacional")] +
[r[1] for r in UnidadeFederativa.REGIAO_CHOICES]
]
resumo.append(
[_("Casas em sua carteira"), total['total']] +
[total[r[0]] for r in UnidadeFederativa.REGIAO_CHOICES]
)
resumo.append({'subtitle': _("Uso dos produtos Interlegis")})
resumo.append(
[_("Casas sem nenhum produto"), sem_produto['total']] +
[sem_produto[r[0]] for r in UnidadeFederativa.REGIAO_CHOICES]
)
resumo.extend(
[[ts.nome, dados[ts.id]['total']] +
[dados[ts.id][r[0]] for r in UnidadeFederativa.REGIAO_CHOICES]
for ts in tipos_servico
]
)
resumo.append({'subtitle': _("Registros no sistema de ocorrências")})
resumo.append(
[_("Casas que nunca registraram ocorrências"),
dados_ocorrencia['sem']['total']] +
[dados_ocorrencia['sem'][r[0]]
for r in UnidadeFederativa.REGIAO_CHOICES
]
)
resumo.append(
[_("Total de ocorrências registradas"),
dados_ocorrencia['registradas']['total']] +
[dados_ocorrencia['registradas'][r[0]]
for r in UnidadeFederativa.REGIAO_CHOICES
]
)
resumo.append(
[_("Total de ocorrências pendentes"),
dados_ocorrencia['pendentes']['total']] +
[dados_ocorrencia['pendentes'][r[0]]
for r in UnidadeFederativa.REGIAO_CHOICES
]
)
resumo.append(
[_("Média de ocorrências por casa"),
round(dados_ocorrencia['media']['total'], 2)] +
[round(dados_ocorrencia['media'][r[0]], 2)
for r in UnidadeFederativa.REGIAO_CHOICES
]
)
return resumo
def casas_carteira(request, casas, context):
servicos = request.GET.getlist('servico')
sigla_regiao = request.GET.get('r', None)
sigla_uf = request.GET.get('uf', None)
meso_id = request.GET.get('meso', None)
micro_id = request.GET.get('micro', None)
servicos = request.GET.getlist('servico')
tipos_servico = context['servicos']
context['qs_regiao'] = ''
if micro_id is not None:
context['micro'] = get_object_or_404(Microrregiao, pk=micro_id)
context['qs_regiao'] = 'micro=%s' % micro_id
context['meso'] = context['micro'].mesorregiao
context['uf'] = context['meso'].uf
context['regiao'] = context['uf'].regiao
casas = casas.filter(municipio__microrregiao=context['micro'])
elif meso_id is not None:
context['meso'] = get_object_or_404(Mesorregiao, pk=meso_id)
context['qs_regiao'] = 'meso=%s' % meso_id
context['uf'] = context['meso'].uf
context['regiao'] = context['uf'].regiao
casas = casas.filter(
municipio__microrregiao__mesorregiao=context['meso']
)
elif sigla_uf is not None:
context['uf'] = get_object_or_404(UnidadeFederativa, sigla=sigla_uf)
context['qs_regiao'] = 'uf=%s' % sigla_uf
context['regiao'] = context['uf'].regiao
casas = casas.filter(municipio__uf=context['uf'])
elif sigla_regiao is not None:
context['regiao'] = sigla_regiao
context['qs_regiao'] = 'r=%s' % sigla_regiao
casas = casas.filter(municipio__uf__regiao=sigla_regiao)
if 'regiao' in context:
context['ufs'] = UnidadeFederativa.objects.filter(
regiao=context['regiao']
)
# if snippet != 'lista':
# context['resumo'] = resumo_carteira(casas)
todos_servicos = ['_none_'] + [s.sigla for s in tipos_servico]
if not servicos or set(servicos) == set(todos_servicos):
servicos = todos_servicos
context['qs_servico'] = ''
else:
if '_none_' in servicos:
casas = casas.filter(
Q(servico=None) | Q(servico__tipo_servico__sigla__in=servicos)
)
else:
casas = casas.filter(servico__tipo_servico__sigla__in=servicos)
casas = casas.distinct('nome', 'municipio__uf')
context['qs_servico'] = "&".join(['servico=%s' % s for s in servicos])
context['servicos_check'] = servicos
casas = casas.select_related(
'municipio',
'municipio__uf',
'municipio__microrregiao',
'municipio__microrregiao__mesorregiao'
).prefetch_related('servico_set')
return casas, context
@login_required
def painel_relacionamento(request):
page = request.GET.get('page', 1)
snippet = request.GET.get('snippet', '')
seletor = request.GET.get('s', None)
servidor = request.GET.get('servidor', None)
fmt = request.GET.get('f', 'html')
if servidor is None:
gerente = request.user.servidor
elif servidor == '_all':
gerente = None
else:
gerente = get_object_or_404(Servidor, pk=servidor)
if gerente is not None:
casas = gerente.casas_que_gerencia.all()
if gerente is None or not casas.exists():
casas = Orgao.objects.exclude(gerentes_interlegis=None)
gerente = None
tipos_servico = TipoServico.objects.all()
regioes = UnidadeFederativa.REGIAO_CHOICES
context = {
'seletor': seletor,
'snippet': snippet,
'regioes': regioes,
'servicos': tipos_servico,
'gerentes': Servidor.objects.exclude(casas_que_gerencia=None),
'gerente': gerente,
'qs_servidor': ('servidor=%s' % gerente.pk) if gerente else '',
}
if snippet != 'lista':
context['resumo'] = resumo_carteira(casas)
if snippet != 'resumo':
casas, context = casas_carteira(request, casas, context)
paginator = Paginator(casas, 30)
try:
pagina = paginator.page(page)
except (EmptyPage, InvalidPage):
pagina = paginator.page(paginator.num_pages)
context['page_obj'] = pagina
if snippet == 'lista':
if fmt == 'csv':
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=casas.csv'
writer = csv.writer(response)
writer.writerow([_("Casa legislativa"), _("Região"), _("Estado"),
_("Mesorregião"), _("Microrregião"),
_("Gerentes Interlegis"), _("Serviços"),])
for c in casas:
writer.writerow([
c.nome,
c.municipio.uf.get_regiao_display(),
c.municipio.uf.sigla,
c.municipio.microrregiao.mesorregiao.nome,
c.municipio.microrregiao.nome,
c.lista_gerentes(fmt='lista'),
(", ".join(
[s.tipo_servico.nome for s in c.servico_set.filter(
data_desativacao__isnull=True)
])
),
])
return response
return render(
request,
'casas/lista_casas_carteira_snippet.html',
context
)
if snippet == 'resumo':
return render(request, 'casas/resumo_carteira_snippet.html', context)
# if snippet != 'resumo':
# casas, context = casas_carteira(request, casas, context)
# paginator = Paginator(casas, 30)
# try:
# pagina = paginator.page(page)
# except (EmptyPage, InvalidPage):
# pagina = paginator.page(paginator.num_pages)
# context['page_obj'] = pagina
# if snippet == 'lista':
# if fmt == 'csv':
# response = HttpResponse(content_type='text/csv')
# response['Content-Disposition'] = 'attachment; filename=casas.csv'
# writer = csv.writer(response)
# writer.writerow([
# _("Casa legislativa").encode('utf8'),
# _("Região").encode('utf8'),
# _("Estado").encode('utf8'),
# _("Mesorregião").encode('utf8'),
# _("Microrregião").encode('utf8'),
# _("Gerentes Interlegis").encode('utf8'),
# _("Serviços").encode('utf8'),
# ])
# for c in casas:
# writer.writerow([
# c.nome.encode('utf8'),
# c.municipio.uf.get_regiao_display().encode('utf8'),
# c.municipio.uf.sigla.encode('utf8'),
# c.municipio.microrregiao.mesorregiao.nome.encode('utf8'),
# c.municipio.microrregiao.nome.encode('utf8'),
# c.lista_gerentes(fmt='lista').encode('utf8'),
# (", ".join([s.tipo_servico.nome for s in c.servico_set.filter(data_desativacao__isnull=True)])).encode('utf8'),
# ])
# return response
# return render(request, 'casas/lista_casas_carteira_snippet.html', context)
# if snippet == 'resumo':
# return render(request, 'casas/resumo_carteira_snippet.html', context)
# return render(request, 'casas/painel.html', context)
return render(request, 'casas/painel.html', context)
# @login_required
# def gerentes_interlegis(request):

178
sigi/apps/convenios/templates/convenios/tabela_regiao.html

@ -1,147 +1,37 @@
{% load static from staticfiles %}
{% load i18n %}
<html>
<head>
<title>Relatório por Região</title>
<style>
@page {
size: a4;
margin-top: 6.5cm;
margin-left: 1.5cm;
margin-right: 1cm;
margin-bottom: 3.5cm;
@frame top{
-pdf-frame-content: cabecalho;
top: 2cm;
margin-left: 1cm;
margin-right: 1cm;
/*height: 1cm; */
}
/* @frame midle{
-pdf-frame-content: midle;
top: 6cm;
height: 1cm;
margin: 2cm;
}*/
@frame footer {
-pdf-frame-content: footerContent;
bottom: 2cm;
margin-left: 1cm;
margin-right: 1cm;
height: 1cm;
}
}
body{
font-family: 'Helvetica';
font-size: 9pt;
}
#corpo h1{
text-align: center;
}
#cabecalho {
text-align: center;
font-weight: bold;
font-size: 14pt;
}
#cabecalho .item2{
font-size: 13pt;
}
#cabecalho .titulo{
font-size: 14pt;
}
#footerContent {
border-top: black outset;
padding-top: 0.15cm;
}
#footerContent #esquerda{
text-align: left;
}
#footerContent #direita{
text-align: right;
background-image: url("{% static 'img/logo-senado.png' %}");
}
.tabela {
padding-top: 0.1cm;
padding-left: 0.1cm;
border: black solid;
width: 2cm;
background-color: #B5B5B5;
}
.tabela caption{
text-align: center;
font-weight: bold;
font-size: 11pt;
}
.tabela th{
background-color: #CFCFCF;
text-align: left;
}
.tabela .conteudo {
background-color: white;/*#E8E8E8;*/
}
.tabela .sumario{
font-weight: bold;
background-color: #CFCFCF;
}
.tabela .cabecalho_esquerda{
background-color: #E8E8E8;
font-weight: bold;
}
{% extends 'pdf/base_report.html' %}
{% load static i18n %}
</style>
{% block page_size %}A4 portrait{% endblock %}
{% block report_name %}{% blocktranslate %}Relatório da Região {{ regiao }}{% endblocktranslate %}{% endblock %}
</head>
<body>
<div id="cabecalho">
<table>
<tr>
<td id="imagem1"><img src="{% static 'img/logo-senado.png' %}" width="80" height="80" alt="Logo Senado"/></td>
<td id="centro" colspan="3">{% trans 'SENADO FEDERAL' %}<br/><span class="item2">{% trans 'SINTER - Secretaria Especial do Interlegis' %}</span></td>
<td id="imagem2"><img src="{% static 'img/logo-interlegis.jpg' %}" width="90" height="65" alt="Logo Interlegis"/></td>
</tr>
</table>
<h1 class="titulo">{{regiao}}</h1>
</div>
<div id="midle">
{% for tabela in tabelas %}
<table class="tabela" repeat="1">
<caption>{{tabela.projeto}} - {{regiao}}</caption>
<thead>
<tr>
{%for item in tabela.cabecalho%}
<th>{{item}}</th>
{%endfor%}
</tr>
</thead>
<tbody>
{% for linha in tabela.linhas %}
<tr class="conteudo">
<th class="cabecalho_esquerda">{{linha.estado}}</th>
{% for item in linha.lista %}
<td>{{item}}</td>
{% endfor %}
</tr>
{% endfor %}
<tr>
<th>Total</th>
{% for item in tabela.sumario %}
<th>{{item}}</th>
{% endfor %}
</tr>
</tbody>
</table>
<br />
{% block main_content %}
{% for tabela in tabelas %}
<table class="tabela" repeat="1">
<caption>{{ tabela.projeto }} - {{ regiao }}</caption>
<thead>
<tr>
{% for item in tabela.cabecalho %}
<th>{{ item }}</th>
{% endfor %}
</div>
<div id="footerContent">
<table>
<tr>
<td id="esquerda">{{data}} às {{hora}}</td>
<td id="direita">{% trans 'Página' %} <pdf:pagenumber /> </td>
</tr>
</table>
</div>
</body>
</html>
</tr>
</thead>
<tbody>
{% for linha in tabela.linhas %}
<tr>
<th>{{ linha.estado }}</th>
{% for item in linha.lista %}
<td class="right-align">{{ item }}</td>
{% endfor %}
</tr>
{% endfor %}
<tr>
<th>Total</th>
{% for item in tabela.sumario %}
<th class="right-align">{{item}}</th>
{% endfor %}
</tr>
</tbody>
</table>
<br />
{% endfor %}
{% endblock main_content %}

25
sigi/apps/convenios/urls.py

@ -1,14 +1,17 @@
from django.conf.urls import patterns, url
from django.urls import path
from sigi.apps.convenios import views
urlpatterns = [
path('reportsRegiao/<str:regiao>/', views.report_regiao, name='convenios-report_regiao_pdf'),
]
urlpatterns = patterns(
'sigi.apps.convenios.views',
# urlpatterns = patterns(
# 'sigi.apps.convenios.views',
url(r'^convenio/reports/$', 'report', name='convenios-report'),
url(r'^convenio/carrinho/$', 'visualizar_carrinho', name='visualizar-carrinho'),
url(r'^convenio/carrinho/excluir_carrinho/$', 'excluir_carrinho', name='excluir-carrinho'), # tagerror
url(r'^convenio/carrinho/deleta_itens_carrinho$', 'deleta_itens_carrinho', name='deleta-itens-carrinho'), # tagerror
url(r'^convenio/csv/$', 'export_csv', name='convenios-csv'),
url(r'^reportsRegiao/(?P<regiao>\w+)/$', 'report_regiao', name='convenios-report_regiao_pdf'),
url(r'^importar/$', 'importar_gescon', name='importar-gescon'),
)
# url(r'^convenio/reports/$', 'report', name='convenios-report'),
# url(r'^convenio/carrinho/$', 'visualizar_carrinho', name='visualizar-carrinho'),
# url(r'^convenio/carrinho/excluir_carrinho/$', 'excluir_carrinho', name='excluir-carrinho'), # tagerror
# url(r'^convenio/carrinho/deleta_itens_carrinho$', 'deleta_itens_carrinho', name='deleta-itens-carrinho'), # tagerror
# url(r'^convenio/csv/$', 'export_csv', name='convenios-csv'),
# url(r'^importar/$', 'importar_gescon', name='importar-gescon'),
# )

225
sigi/apps/convenios/views.py

@ -1,18 +1,16 @@
import csv
import datetime
from django.contrib import messages
from django.http.response import HttpResponseForbidden
# import ho.pisa as pisa
from django.conf import settings
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.http import HttpResponse, HttpResponseRedirect
# from django.contrib import messages
# from django.http.response import HttpResponseForbidden
# from django.conf import settings
# from django.core.paginator import Paginator, InvalidPage, EmptyPage
# from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_list_or_404
from django.template import Context, loader
from django.utils.translation import gettext as _
# from geraldo.generators import PDFGenerator
from django.contrib.auth.decorators import login_required
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, Gescon, Projeto
@ -23,6 +21,117 @@ from sigi.apps.convenios.models import Convenio, Gescon, Projeto
# ConvenioReportSemAceiteAL,
# ConvenioReportSemAceiteCM)
@login_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',
)
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 query_ordena(qs, o, ot):
list_display = ('num_convenio', 'casa_legislativa',
@ -209,107 +318,7 @@ def report(request, id=None):
return response
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,
}
@login_required
def report_regiao(request, regiao='NE'):
if request.POST:
if 'regiao' in request.POST:
regiao = request.POST['regiao']
REGIAO_CHOICES = dict(UnidadeFederativa.REGIAO_CHOICES)
projetos = Projeto.objects.all()
camaras = Orgao.objects.filter(tipo__sigla='CM')
tabelas = list()
# Geral
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)
data = datetime.datetime.now().strftime('%d/%m/%Y')
hora = datetime.datetime.now().strftime('%H:%M')
pisa.showLogging()
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename=RelatorioRegiao_' + regiao + '.pdf'
#tabelas = ({'projeto':"PI"},{'projeto':"PML"},)
t = loader.get_template('convenios/tabela_regiao.html')
c = Context({'tabelas': tabelas, 'regiao': REGIAO_CHOICES[regiao], 'data': data, 'hora': hora})
pdf = pisa.CreatePDF(t.render(c), response)
if not pdf.err:
pisa.startViewer(response)
return response
@login_required
def export_csv(request):

58
sigi/apps/eventos/templates/eventos/calendario.html

@ -1,21 +1,68 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_static %}
{% load static from staticfiles %}
{% load thumbnail %}
{% load i18n %}
{% load static %}
{% block coltype %}colMS{% endblock %}
{% block content %}
<div class="row">
<div class="col s12">
<ul class="tabs">
{% for ano in meses %}
<li class="tab col"><a {% if ano == ano_pesquisa %}class="active"{% endif %} href="#tab-{{ ano|safe }}">{{ ano| safe }}</a></li>
{% endfor %}
</ul>
</div>
{% for ano, lista in meses.items %}
<div id="tab-{{ ano|safe }}" class="col s12">
{% for mes, nome in lista.items %}
<a class="waves-effect waves-light btn-flat btn-small{% if ano == ano_pesquisa and mes == mes_pesquisa %} disabled{% endif %}" href="?ano={{ ano|safe }}&mes={{ mes|safe }}">{{ nome }}</a>
{% endfor %}
</div>
{% endfor %}
</div>
{% for evento in eventos %}
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
<span class="card-title">{{ evento.nome }}</span>
<p>Os detalhes virão aqui</p>
</div>
</div>
</div>
</div>
{% endfor %}
{% endblock %}
{% block footer %}
{{ block.super }}
<script>
$(document).ready(function(){
var elements = $('.tabs');
M.Tabs.init(elements, {});
});
</script>
{% endblock %}
{% comment %}
{% block extrastyle %}
<style type="text/css">
th {
text-align: center !important;
vertical-align: bottom !important;
}
.status-P { background-color: #ffffb0}
.status-A { background-color: #a6ebff}
.status-O { background-color: #c2ffc2}
.status-R { background-color: #ffdaa6}
.status-C { background-color: #d98f8d}
</style>
{{ block.super }}
{% endblock %}
@ -41,3 +88,4 @@
{% block content %}
{% include "eventos/calendario_snippet.html" %}
{% endblock %}
{% endcomment %}

42
sigi/apps/eventos/urls.py

@ -1,22 +1,28 @@
# coding: utf-8
from django.conf.urls import patterns, url
from django.urls import path, include
from sigi.apps.eventos import views
urlpatterns = [
path('calendario/', views.calendario, name='eventos-calendario'),
]
urlpatterns = patterns(
'sigi.apps.eventos.views',
# Painel de ocorrencias
url(r'^calendario/$', 'calendario', name='eventos-calendario'),
url(r'^alocacaoequipe/$', 'alocacao_equipe', name='eventos-alocacaoequipe'),
# Carrinho
url(r'^evento/carrinho/$', 'visualizar_carrinho',
name='visualizar-carrinho-evento'),
url(r'^evento/carrinho/excluir_carrinho/$', 'excluir_carrinho',
name='excluir-carrinho-evento'), # Error
url(r'^evento/carrinho/deleta_itens_carrinho$', 'deleta_itens_carrinho',
name='deleta-itens-carrinho-evento'), # Error
url(r'^evento/csv/$', 'export_csv', name='evento-export-csv'), # Error
url(r'^evento/(?P<id>\w+)/declaracao/$', 'declaracao',
name='evento-declaracao'),
# from django.conf.urls import patterns, url
)
# urlpatterns = patterns(
# 'sigi.apps.eventos.views',
# # Painel de ocorrencias
# url(r'^calendario/$', 'calendario', name='eventos-calendario'),
# url(r'^alocacaoequipe/$', 'alocacao_equipe', name='eventos-alocacaoequipe'),
# # Carrinho
# url(r'^evento/carrinho/$', 'visualizar_carrinho',
# name='visualizar-carrinho-evento'),
# url(r'^evento/carrinho/excluir_carrinho/$', 'excluir_carrinho',
# name='excluir-carrinho-evento'), # Error
# url(r'^evento/carrinho/deleta_itens_carrinho$', 'deleta_itens_carrinho',
# name='deleta-itens-carrinho-evento'), # Error
# url(r'^evento/csv/$', 'export_csv', name='evento-export-csv'), # Error
# url(r'^evento/(?P<id>\w+)/declaracao/$', 'declaracao',
# name='evento-declaracao'),
# )

831
sigi/apps/eventos/views.py

@ -1,41 +1,12 @@
# -*- coding: utf-8 -*-
#
# sigi.apps.eventos.views
#
# Copyright (C) 2015 Interlegis
#
# 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.
import calendar
import datetime
import locale
import csv
from django import template
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404, render
from django.utils import translation
from django.utils.translation import ungettext, gettext as _
from django.http.response import JsonResponse, HttpResponse
from django.template import Template, Context
from django.shortcuts import render
from django.utils.translation import to_locale, get_language, gettext as _
from sigi.apps.eventos.models import Evento, Equipe, Convite, Modulo
from sigi.apps.eventos.forms import SelecionaModeloForm
from sigi.apps.servidores.models import Servidor
from sigi.shortcuts import render_to_pdf, pdf_renderer
@login_required
def calendario(request):
@ -43,388 +14,422 @@ def calendario(request):
ano_pesquisa = int(request.GET.get('ano', datetime.date.today().year))
formato = request.GET.get('fmt', 'html')
dia1 = datetime.date(ano_pesquisa, mes_pesquisa, 1)
mes_anterior = dia1 - datetime.timedelta(days=1)
mes_seguinte = dia1.replace(day=28) + datetime.timedelta(days=4) # Ugly hack
mes_seguinte = mes_seguinte.replace(day=1)
data = {'mes_pesquisa': mes_pesquisa, 'ano_pesquisa': ano_pesquisa}
if Evento.objects.filter(data_inicio__year=mes_anterior.year,
data_inicio__month=mes_anterior.month).exists():
data['prev_button'] = {'mes': mes_anterior.month, 'ano': mes_anterior.year }
if Evento.objects.filter(data_inicio__year=mes_seguinte.year,
data_inicio__month=mes_seguinte.month).exists():
data['next_button'] = {'mes': mes_seguinte.month, 'ano': mes_seguinte.year }
c = calendar.Calendar(6)
dates = reduce(lambda x,y: x+y, c.monthdatescalendar(ano_pesquisa, mes_pesquisa))
eventos = []
for evento in Evento.objects.filter(data_inicio__year=ano_pesquisa,
data_inicio__month=mes_pesquisa).order_by('data_inicio'):
start = dates.index(evento.data_inicio.date())
if not evento.data_termino.date() in dates:
lastday = dates[-1]
while lastday < evento.data_termino.date():
lastday = lastday + datetime.timedelta(days=1)
dates.append(lastday)
eventos.append({'evento': evento, 'start': start})
# Calcula a distância dos eventos para as bordas do calendário
for evento in eventos:
end = dates.index(evento['evento'].data_termino.date())
evento['duration'] = end-evento['start']+1
evento['close'] = len(dates)-end-1
# Agrupa os eventos em linhas para melhorar a visualização
linhas = []
for evento in eventos:
encaixado = False
for linha in linhas:
sobrepoe = False
for e in linha:
if (((evento['evento'].data_inicio.date() >= e['evento'].data_inicio.date()) and
(evento['evento'].data_inicio.date() <= e['evento'].data_termino.date())) or
((evento['evento'].data_termino.date() >= e['evento'].data_inicio.date()) and
(evento['evento'].data_termino.date() <= e['evento'].data_termino.date()))):
sobrepoe = True
break
if not sobrepoe:
# Adiona o evento em uma linha que ele não sobrepoe nenhum outro
linha.append(evento)
encaixado = True
break
if not encaixado:
# Adiciona uma nova linha porque este evento não se encaixa em nenhuma existente
linhas.append([evento])
# Recalcula as distâncias dos eventos por linha para encaixar no calendário
for linha in linhas:
anterior = None
for evento in linha:
if anterior is None:
anterior = evento
continue
anterior['close'] = (evento['evento'].data_inicio.date() - anterior['evento'].data_termino.date()).days-1
evento['start'] = 0
anterior = evento
data['dates'] = dates
data['eventos'] = eventos
data['linhas'] = linhas
if formato == 'pdf':
return render_to_pdf('eventos/calendario_pdf.html', data )
return render(request, 'eventos/calendario.html', data)
@login_required
def alocacao_equipe(request):
ano_pesquisa = int(request.GET.get('ano', datetime.date.today().year))
formato = request.GET.get('fmt', 'html')
data = {'ano_pesquisa': ano_pesquisa}
if Evento.objects.filter(data_inicio__year=ano_pesquisa-1).exists():
data['prev_button'] = {'ano': ano_pesquisa - 1 }
if Evento.objects.filter(data_inicio__year=ano_pesquisa+1).exists():
data['next_button'] = {'ano': ano_pesquisa + 1 }
dados = []
for evento in Evento.objects.filter(data_inicio__year=ano_pesquisa).exclude(status='C').prefetch_related('equipe_set'):
for p in evento.equipe_set.all():
registro = None
for r in dados:
if r[0] == p.membro.pk:
registro = r
break
if not registro:
registro = [p.membro.pk, p.membro.nome_completo, [{'dias': 0, 'eventos': 0} for x in range(1,13)]]
dados.append(registro)
registro[2][evento.data_inicio.month-1]['dias'] += (evento.data_termino - evento.data_inicio).days + 1
registro[2][evento.data_inicio.month-1]['eventos'] += 1
dados.sort(lambda x, y: cmp(x[1], y[1]))
lang = (translation.to_locale(translation.get_language())+'.utf8').encode()
meses = {}
lang = to_locale(get_language())+'.UTF-8'
locale.setlocale(locale.LC_ALL, lang)
meses = [calendar.month_name[m] for m in range(1,13)]
linhas = [[_("Servidor")] + meses + ['total']]
for r in dados:
r[2].append(reduce(lambda x,y:{'dias': x['dias'] + y['dias'],
'eventos': x['eventos'] + y['eventos']}, r[2]))
linhas.append([r[1]] +
[_(ungettext("%(dias)s dia", "%(dias)s dias", d['dias']) + " em " +
ungettext("%(eventos)s evento", "%(eventos)s eventos", d['eventos'])
) % d if d['dias'] > 0 or d['eventos'] > 0 else '' for d in r[2]])
# for registro in Servidor.objects.filter(equipe_evento__evento__data_inicio__year=ano_pesquisa).exclude(equipe_evento__evento__status='C').distinct():
# dados = [{'dias': 0, 'eventos': 0} for x in range(1,13)]
# for part in registro.equipe_evento.filter(evento__data_inicio__year=ano_pesquisa).exclude(evento__status='C'):
# dados[part.evento.data_inicio.month-1]['dias'] += (part.evento.data_termino -
# part.evento.data_inicio).days + 1
# dados[part.evento.data_inicio.month-1]['eventos'] += 1
# dados.append([registro.nome_completo] + [_(ungettext("%(dias)s dia", "%(dias)s dias", d['dias']) + " em " + ungettext("%(eventos)s evento", "%(eventos)s eventos", d['eventos'])) % d if d['dias'] > 0 or d['eventos'] > 0 else '' for d in dados])
data['linhas'] = linhas
if formato == 'pdf':
return render_to_pdf('eventos/alocacao_equipe_pdf.html', data)
elif formato == 'csv':
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="alocacao_equipe_%s.csv"' % (ano_pesquisa,)
writer = csv.writer(response)
asc_list = [[s.encode('utf-8') if isinstance(s, unicode) else s for s in l] for l in linhas]
writer.writerows(asc_list)
return response
elif formato == 'json':
result = {'ano': ano_pesquisa,
'equipe': [{'pk': d[0],
'nome_completo': d[1],
'meses': {m[0]: m[1] for m in zip(meses+['total'], d[2])}
} for d in dados]}
return JsonResponse(result)
return render(request, 'eventos/alocacao_equipe.html', data)
# Views e functions para carrinho de exportação
def query_ordena(qs, o):
from sigi.apps.eventos.admin import EventoAdmin
list_display = EventoAdmin.list_display
order_fields = []
for order_number in o.split('.'):
order_number = int(order_number)
order = ''
if order_number != abs(order_number):
order_number = abs(order_number)
order = '-'
order_fields.append(order + list_display[order_number - 1])
qs = qs.order_by(*order_fields)
return qs
def get_for_qs(get, qs):
kwargs = {}
for k, v in get.iteritems():
if str(k) not in ('page', 'pop', 'q', '_popup', 'o', 'ot'):
kwargs[str(k)] = v
qs = qs.filter(**kwargs)
if 'o' in get:
qs = query_ordena(qs, get['o'])
return qs
def carrinhoOrGet_for_qs(request):
if 'carrinho_eventos' in request.session:
ids = request.session['carrinho_eventos']
qs = Evento.objects.filter(pk__in=ids)
else:
qs = Evento.objects.all()
if request.GET:
qs = get_for_qs(request.GET, qs)
return qs
def adicionar_eventos_carrinho(request, queryset=None, id=None):
if request.method == 'POST':
ids_selecionados = request.POST.getlist('_selected_action')
if 'carrinho_eventos' not in request.session:
request.session['carrinho_eventos'] = ids_selecionados
else:
lista = request.session['carrinho_eventos']
# Verifica se id já não está adicionado
for id in ids_selecionados:
if id not in lista:
lista.append(id)
request.session['carrinho_eventos'] = lista
@login_required
def visualizar_carrinho(request):
qs = carrinhoOrGet_for_qs(request)
paginator = Paginator(qs, 100)
try:
page = int(request.GET.get('page', '1'))
except ValueError:
page = 1
try:
paginas = paginator.page(page)
except (EmptyPage, InvalidPage):
paginas = paginator.page(paginator.num_pages)
carrinhoIsEmpty = not('carrinho_eventos' in request.session)
return render(
request,
'eventos/carrinho.html',
{
'carIsEmpty': carrinhoIsEmpty,
'paginas': paginas,
'query_str': '?' + request.META['QUERY_STRING']
}
)
@login_required
def excluir_carrinho(request):
if 'carrinho_eventos' in request.session:
del request.session['carrinho_eventos']
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')
removed = 0
if 'carrinho_eventos' in request.session:
lista = request.session['carrinho_eventos']
for item in ids_selecionados:
lista.remove(item)
removed += 1
if lista:
request.session['carrinho_eventos'] = lista
else:
del lista
del request.session['carrinho_eventos']
messages.info(request, "{0} itens removidos do carrinho".format(removed))
return HttpResponseRedirect('.')
@login_required
def export_csv(request):
def rm_rows(lista,reg):
for a in lista:
if a in lista:
reg.pop(a,None)
else:
pass
def serialize(r, field):
value = (getattr(r, 'get_{0}_display'.format(field.name), None) or
getattr(r, field.name, ""))
if callable(value):
value = value()
if value is None:
value = ""
return unicode(value).encode('utf8')
eventos = carrinhoOrGet_for_qs(request)
eventos.select_related('equipe', 'convite')
if not eventos:
messages.info(request, _("Nenhum evento a exportar"))
return HttpResponseRedirect('../')
max_equipe = max([e.equipe_set.count() for e in eventos])
mun_casa = 'Município da Casa Anfitriã'.encode('utf8')
uf_casa = 'UF da Casa Anfitriã'.encode('utf8')
reg_casa = 'Região da Casa Anfitriã'.encode('utf8')
head = [f.verbose_name.encode('utf8') for f in Evento._meta.fields]
head.extend([mun_casa, uf_casa, reg_casa])
head.extend([f.verbose_name.encode('utf8')+"_{0}".format(i+1)
for i in range(max_equipe) for f in Equipe._meta.fields
if f.name not in ('id', 'evento')])
head.extend([f.verbose_name.encode('utf8') for f in Convite._meta.fields
if f.name not in ('id', 'evento')])
head.extend([f.verbose_name.encode('utf8') for f in Modulo._meta.fields
if f.name not in ('id', 'evento')])
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=eventos.csv'
rm_list = ['Descrição do evento', 'Local do evento', 'Público alvo', 'Motivo do cancelamento', 'Descrição do módulo']
for a in head:
if 'Observações_' in a:
rm_list.append(a)
for a in rm_list:
if a in head:
head.remove(a)
for ano, mes in Evento.objects.values_list(
'data_inicio__year', 'data_inicio__month').order_by(
'data_inicio__year', 'data_inicio__month').distinct(
'data_inicio__year', 'data_inicio__month'):
if ano in meses:
meses[ano][mes] = calendar.month_name[mes]
else:
pass
writer = csv.DictWriter(response, fieldnames=head)
writer.writeheader()
for evento in eventos:
reg = {f.verbose_name.encode('utf8'): serialize(evento, f)
for f in Evento._meta.fields}
if evento.casa_anfitria is None:
reg[mun_casa] = ""
reg[uf_casa] = ""
reg[reg_casa] = ""
else:
reg[mun_casa] = evento.casa_anfitria.municipio.nome.encode('utf8')
reg[uf_casa] = evento.casa_anfitria.municipio.uf.sigla.\
encode('utf8')
reg[reg_casa] = evento.casa_anfitria.municipio.uf.\
get_regiao_display().encode('utf8')
idx = 1
for membro in evento.equipe_set.all():
reg.update(
{
"{0}_{1}".format(f.verbose_name.encode('utf8'), idx):
serialize(membro, f) for f in Equipe._meta.fields
if f.name not in ('id', 'evento')
}
)
idx += 1
for convite in evento.convite_set.all():
reg.update(
{f.verbose_name.encode('utf8'): serialize(convite, f)
for f in Convite._meta.fields
if f.name not in ('id', 'evento')}
)
rm_rows(rm_list,reg)
writer.writerow(reg)
if evento.convite_set.count() == 0:
rm_rows(rm_list,reg)
writer.writerow(reg)
return response
@login_required
def declaracao(request, id):
if request.method == 'POST':
form = SelecionaModeloForm(request.POST)
if form.is_valid():
evento = get_object_or_404(Evento, id=id)
modelo = form.cleaned_data['modelo']
template_string = (
"""
{% extends "eventos/declaracao_pdf.html" %}
{% block text_body %}""" +
modelo.texto + """
{% endblock %}
"""
)
context = Context(
{'pagesize': modelo.formato,
'pagemargin': modelo.margem,
'evento': evento,
'data': datetime.date.today(),
}
)
template = Template(template_string)
# return HttpResponse(template.render(context))
return pdf_renderer(template, context, 'declaracao.pdf')
else:
form = SelecionaModeloForm()
return render(
request,
'eventos/seleciona_modelo.html',
{'form': form, 'evento_id': id}
)
meses[ano] = {mes: calendar.month_name[mes]}
context = {
'ano_pesquisa': ano_pesquisa,
'mes_pesquisa': mes_pesquisa,
'meses': meses,
'eventos': Evento.objects.filter(
data_inicio__year=ano_pesquisa,
data_inicio__month=mes_pesquisa
)
}
return render(request, 'eventos/calendario.html', context)
# @login_required
# def calendario(request):
# mes_pesquisa = int(request.GET.get('mes', datetime.date.today().month))
# ano_pesquisa = int(request.GET.get('ano', datetime.date.today().year))
# formato = request.GET.get('fmt', 'html')
# dia1 = datetime.date(ano_pesquisa, mes_pesquisa, 1)
# mes_anterior = dia1 - datetime.timedelta(days=1)
# mes_seguinte = dia1.replace(day=28) + datetime.timedelta(days=4) # Ugly hack
# mes_seguinte = mes_seguinte.replace(day=1)
# data = {'mes_pesquisa': mes_pesquisa, 'ano_pesquisa': ano_pesquisa}
# if Evento.objects.filter(data_inicio__year=mes_anterior.year,
# data_inicio__month=mes_anterior.month).exists():
# data['prev_button'] = {'mes': mes_anterior.month, 'ano': mes_anterior.year }
# if Evento.objects.filter(data_inicio__year=mes_seguinte.year,
# data_inicio__month=mes_seguinte.month).exists():
# data['next_button'] = {'mes': mes_seguinte.month, 'ano': mes_seguinte.year }
# c = calendar.Calendar(6)
# dates = reduce(lambda x,y: x+y, c.monthdatescalendar(ano_pesquisa, mes_pesquisa))
# eventos = []
# for evento in Evento.objects.filter(data_inicio__year=ano_pesquisa,
# data_inicio__month=mes_pesquisa).order_by('data_inicio'):
# start = dates.index(evento.data_inicio.date())
# if not evento.data_termino.date() in dates:
# lastday = dates[-1]
# while lastday < evento.data_termino.date():
# lastday = lastday + datetime.timedelta(days=1)
# dates.append(lastday)
# eventos.append({'evento': evento, 'start': start})
# # Calcula a distância dos eventos para as bordas do calendário
# for evento in eventos:
# end = dates.index(evento['evento'].data_termino.date())
# evento['duration'] = end-evento['start']+1
# evento['close'] = len(dates)-end-1
# # Agrupa os eventos em linhas para melhorar a visualização
# linhas = []
# for evento in eventos:
# encaixado = False
# for linha in linhas:
# sobrepoe = False
# for e in linha:
# if (((evento['evento'].data_inicio.date() >= e['evento'].data_inicio.date()) and
# (evento['evento'].data_inicio.date() <= e['evento'].data_termino.date())) or
# ((evento['evento'].data_termino.date() >= e['evento'].data_inicio.date()) and
# (evento['evento'].data_termino.date() <= e['evento'].data_termino.date()))):
# sobrepoe = True
# break
# if not sobrepoe:
# # Adiona o evento em uma linha que ele não sobrepoe nenhum outro
# linha.append(evento)
# encaixado = True
# break
# if not encaixado:
# # Adiciona uma nova linha porque este evento não se encaixa em nenhuma existente
# linhas.append([evento])
# # Recalcula as distâncias dos eventos por linha para encaixar no calendário
# for linha in linhas:
# anterior = None
# for evento in linha:
# if anterior is None:
# anterior = evento
# continue
# anterior['close'] = (evento['evento'].data_inicio.date() - anterior['evento'].data_termino.date()).days-1
# evento['start'] = 0
# anterior = evento
# data['dates'] = dates
# data['eventos'] = eventos
# data['linhas'] = linhas
# if formato == 'pdf':
# return render_to_pdf('eventos/calendario_pdf.html', data )
# return render(request, 'eventos/calendario.html', data)
# @login_required
# def alocacao_equipe(request):
# ano_pesquisa = int(request.GET.get('ano', datetime.date.today().year))
# formato = request.GET.get('fmt', 'html')
# data = {'ano_pesquisa': ano_pesquisa}
# if Evento.objects.filter(data_inicio__year=ano_pesquisa-1).exists():
# data['prev_button'] = {'ano': ano_pesquisa - 1 }
# if Evento.objects.filter(data_inicio__year=ano_pesquisa+1).exists():
# data['next_button'] = {'ano': ano_pesquisa + 1 }
# dados = []
# for evento in Evento.objects.filter(data_inicio__year=ano_pesquisa).exclude(status='C').prefetch_related('equipe_set'):
# for p in evento.equipe_set.all():
# registro = None
# for r in dados:
# if r[0] == p.membro.pk:
# registro = r
# break
# if not registro:
# registro = [p.membro.pk, p.membro.nome_completo, [{'dias': 0, 'eventos': 0} for x in range(1,13)]]
# dados.append(registro)
# registro[2][evento.data_inicio.month-1]['dias'] += (evento.data_termino - evento.data_inicio).days + 1
# registro[2][evento.data_inicio.month-1]['eventos'] += 1
# dados.sort(lambda x, y: cmp(x[1], y[1]))
# lang = (translation.to_locale(translation.get_language())+'.utf8').encode()
# locale.setlocale(locale.LC_ALL, lang)
# meses = [calendar.month_name[m] for m in range(1,13)]
# linhas = [[_("Servidor")] + meses + ['total']]
# for r in dados:
# r[2].append(reduce(lambda x,y:{'dias': x['dias'] + y['dias'],
# 'eventos': x['eventos'] + y['eventos']}, r[2]))
# linhas.append([r[1]] +
# [_(ungettext("%(dias)s dia", "%(dias)s dias", d['dias']) + " em " +
# ungettext("%(eventos)s evento", "%(eventos)s eventos", d['eventos'])
# ) % d if d['dias'] > 0 or d['eventos'] > 0 else '' for d in r[2]])
# # for registro in Servidor.objects.filter(equipe_evento__evento__data_inicio__year=ano_pesquisa).exclude(equipe_evento__evento__status='C').distinct():
# # dados = [{'dias': 0, 'eventos': 0} for x in range(1,13)]
# # for part in registro.equipe_evento.filter(evento__data_inicio__year=ano_pesquisa).exclude(evento__status='C'):
# # dados[part.evento.data_inicio.month-1]['dias'] += (part.evento.data_termino -
# # part.evento.data_inicio).days + 1
# # dados[part.evento.data_inicio.month-1]['eventos'] += 1
# # dados.append([registro.nome_completo] + [_(ungettext("%(dias)s dia", "%(dias)s dias", d['dias']) + " em " + ungettext("%(eventos)s evento", "%(eventos)s eventos", d['eventos'])) % d if d['dias'] > 0 or d['eventos'] > 0 else '' for d in dados])
# data['linhas'] = linhas
# if formato == 'pdf':
# return render_to_pdf('eventos/alocacao_equipe_pdf.html', data)
# elif formato == 'csv':
# response = HttpResponse(content_type='text/csv')
# response['Content-Disposition'] = 'attachment; filename="alocacao_equipe_%s.csv"' % (ano_pesquisa,)
# writer = csv.writer(response)
# asc_list = [[s.encode('utf-8') if isinstance(s, unicode) else s for s in l] for l in linhas]
# writer.writerows(asc_list)
# return response
# elif formato == 'json':
# result = {'ano': ano_pesquisa,
# 'equipe': [{'pk': d[0],
# 'nome_completo': d[1],
# 'meses': {m[0]: m[1] for m in zip(meses+['total'], d[2])}
# } for d in dados]}
# return JsonResponse(result)
# return render(request, 'eventos/alocacao_equipe.html', data)
# # Views e functions para carrinho de exportação
# def query_ordena(qs, o):
# from sigi.apps.eventos.admin import EventoAdmin
# list_display = EventoAdmin.list_display
# order_fields = []
# for order_number in o.split('.'):
# order_number = int(order_number)
# order = ''
# if order_number != abs(order_number):
# order_number = abs(order_number)
# order = '-'
# order_fields.append(order + list_display[order_number - 1])
# qs = qs.order_by(*order_fields)
# return qs
# def get_for_qs(get, qs):
# kwargs = {}
# for k, v in get.iteritems():
# if str(k) not in ('page', 'pop', 'q', '_popup', 'o', 'ot'):
# kwargs[str(k)] = v
# qs = qs.filter(**kwargs)
# if 'o' in get:
# qs = query_ordena(qs, get['o'])
# return qs
# def carrinhoOrGet_for_qs(request):
# if 'carrinho_eventos' in request.session:
# ids = request.session['carrinho_eventos']
# qs = Evento.objects.filter(pk__in=ids)
# else:
# qs = Evento.objects.all()
# if request.GET:
# qs = get_for_qs(request.GET, qs)
# return qs
# def adicionar_eventos_carrinho(request, queryset=None, id=None):
# if request.method == 'POST':
# ids_selecionados = request.POST.getlist('_selected_action')
# if 'carrinho_eventos' not in request.session:
# request.session['carrinho_eventos'] = ids_selecionados
# else:
# lista = request.session['carrinho_eventos']
# # Verifica se id já não está adicionado
# for id in ids_selecionados:
# if id not in lista:
# lista.append(id)
# request.session['carrinho_eventos'] = lista
# @login_required
# def visualizar_carrinho(request):
# qs = carrinhoOrGet_for_qs(request)
# paginator = Paginator(qs, 100)
# try:
# page = int(request.GET.get('page', '1'))
# except ValueError:
# page = 1
# try:
# paginas = paginator.page(page)
# except (EmptyPage, InvalidPage):
# paginas = paginator.page(paginator.num_pages)
# carrinhoIsEmpty = not('carrinho_eventos' in request.session)
# return render(
# request,
# 'eventos/carrinho.html',
# {
# 'carIsEmpty': carrinhoIsEmpty,
# 'paginas': paginas,
# 'query_str': '?' + request.META['QUERY_STRING']
# }
# )
# @login_required
# def excluir_carrinho(request):
# if 'carrinho_eventos' in request.session:
# del request.session['carrinho_eventos']
# 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')
# removed = 0
# if 'carrinho_eventos' in request.session:
# lista = request.session['carrinho_eventos']
# for item in ids_selecionados:
# lista.remove(item)
# removed += 1
# if lista:
# request.session['carrinho_eventos'] = lista
# else:
# del lista
# del request.session['carrinho_eventos']
# messages.info(request, "{0} itens removidos do carrinho".format(removed))
# return HttpResponseRedirect('.')
# @login_required
# def export_csv(request):
# def rm_rows(lista,reg):
# for a in lista:
# if a in lista:
# reg.pop(a,None)
# else:
# pass
# def serialize(r, field):
# value = (getattr(r, 'get_{0}_display'.format(field.name), None) or
# getattr(r, field.name, ""))
# if callable(value):
# value = value()
# if value is None:
# value = ""
# return unicode(value).encode('utf8')
# eventos = carrinhoOrGet_for_qs(request)
# eventos.select_related('equipe', 'convite')
# if not eventos:
# messages.info(request, _("Nenhum evento a exportar"))
# return HttpResponseRedirect('../')
# max_equipe = max([e.equipe_set.count() for e in eventos])
# mun_casa = 'Município da Casa Anfitriã'.encode('utf8')
# uf_casa = 'UF da Casa Anfitriã'.encode('utf8')
# reg_casa = 'Região da Casa Anfitriã'.encode('utf8')
# head = [f.verbose_name.encode('utf8') for f in Evento._meta.fields]
# head.extend([mun_casa, uf_casa, reg_casa])
# head.extend([f.verbose_name.encode('utf8')+"_{0}".format(i+1)
# for i in range(max_equipe) for f in Equipe._meta.fields
# if f.name not in ('id', 'evento')])
# head.extend([f.verbose_name.encode('utf8') for f in Convite._meta.fields
# if f.name not in ('id', 'evento')])
# head.extend([f.verbose_name.encode('utf8') for f in Modulo._meta.fields
# if f.name not in ('id', 'evento')])
# response = HttpResponse(content_type='text/csv')
# response['Content-Disposition'] = 'attachment; filename=eventos.csv'
# rm_list = ['Descrição do evento', 'Local do evento', 'Público alvo', 'Motivo do cancelamento', 'Descrição do módulo']
# for a in head:
# if 'Observações_' in a:
# rm_list.append(a)
# for a in rm_list:
# if a in head:
# head.remove(a)
# else:
# pass
# writer = csv.DictWriter(response, fieldnames=head)
# writer.writeheader()
# for evento in eventos:
# reg = {f.verbose_name.encode('utf8'): serialize(evento, f)
# for f in Evento._meta.fields}
# if evento.casa_anfitria is None:
# reg[mun_casa] = ""
# reg[uf_casa] = ""
# reg[reg_casa] = ""
# else:
# reg[mun_casa] = evento.casa_anfitria.municipio.nome.encode('utf8')
# reg[uf_casa] = evento.casa_anfitria.municipio.uf.sigla.\
# encode('utf8')
# reg[reg_casa] = evento.casa_anfitria.municipio.uf.\
# get_regiao_display().encode('utf8')
# idx = 1
# for membro in evento.equipe_set.all():
# reg.update(
# {
# "{0}_{1}".format(f.verbose_name.encode('utf8'), idx):
# serialize(membro, f) for f in Equipe._meta.fields
# if f.name not in ('id', 'evento')
# }
# )
# idx += 1
# for convite in evento.convite_set.all():
# reg.update(
# {f.verbose_name.encode('utf8'): serialize(convite, f)
# for f in Convite._meta.fields
# if f.name not in ('id', 'evento')}
# )
# rm_rows(rm_list,reg)
# writer.writerow(reg)
# if evento.convite_set.count() == 0:
# rm_rows(rm_list,reg)
# writer.writerow(reg)
# return response
# @login_required
# def declaracao(request, id):
# if request.method == 'POST':
# form = SelecionaModeloForm(request.POST)
# if form.is_valid():
# evento = get_object_or_404(Evento, id=id)
# modelo = form.cleaned_data['modelo']
# template_string = (
# """
# {% extends "eventos/declaracao_pdf.html" %}
# {% block text_body %}""" +
# modelo.texto + """
# {% endblock %}
# """
# )
# context = Context(
# {'pagesize': modelo.formato,
# 'pagemargin': modelo.margem,
# 'evento': evento,
# 'data': datetime.date.today(),
# }
# )
# template = Template(template_string)
# # return HttpResponse(template.render(context))
# return pdf_renderer(template, context, 'declaracao.pdf')
# else:
# form = SelecionaModeloForm()
# return render(
# request,
# 'eventos/seleciona_modelo.html',
# {'form': form, 'evento_id': id}
# )

44
sigi/apps/home/static/home/css/openmap.css

@ -0,0 +1,44 @@
body, html, .mapbox, #map {
height: 100%;
width: 100%;
}
#content {
height: 91%;
}
.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;
}
.region-ufs {
margin-left: 15px;
}
.autocomplete-content {
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;
z-index: 99999 !important;
}
.dropdown-content li>span {
font-size: 13px;
line-height: 13px;
padding: 3px 3px;
}
.dropdown-content li {
font-size: 13px;
line-height: 13px;
height: auto;
min-height: unset;
}

35
sigi/apps/home/templates/home/dashboard/gerentes_snippet.html

@ -0,0 +1,35 @@
{% load static i18n %}
<ul class="collapsible gerente_selector">
<li>
<div class="collapsible-header">
{% if gerente %}
{% if gerente.foto %}
<img src="{{ gerente.foto.url }}" class="circle user_thumb" alt="{% trans "Foto do servidor" %}">
{% else %}
<i class="material-icons circle">account_circle</i>
{% endif %}
{{ gerente.nome_completo }}
{% else %}
<img src="{% static "img/interlegis_60x60.png" %}" class="circle user_thumb" alt="{% trans "Logo Interlegis" %}">
{% trans "Todo o Interlegis" %}
{% endif %}
</div>
<div class="collapsible-body">
<ul>
<li>
<a href="{% url "home_chartperformance" %}?servidor=_all" data-target="performance-chart">
{% trans "Todo o Interlegis" %}
</a>
</li>
{% for g in gerentes %}
<li>
<a href="{% url "home_chartperformance" %}?servidor={{ g.pk|safe }}" data-target="performance-chart">
{{g.nome_completo }}
</a>
</li>
{% endfor %}
</ul>
</div>
</li>
</ul>

57
sigi/apps/home/templates/home/dashboard/resumo_convenios.html

@ -0,0 +1,57 @@
{% load i18n %}
<a class="waves-effect waves-light btn-small btn-flat" href="{% url 'convenios-report_regiao_pdf' 'CO' %}">Centro Oeste</a>
<a class="waves-effect waves-light btn-small btn-flat" href="{% url 'convenios-report_regiao_pdf' 'NE' %}">Nordeste</a>
<a class="waves-effect waves-light btn-small btn-flat" href="{% url 'convenios-report_regiao_pdf' 'NO' %}">Norte</a>
<a class="waves-effect waves-light btn-small btn-flat" href="{% url 'convenios-report_regiao_pdf' 'SD' %}">Sudeste</a>
<a class="waves-effect waves-light btn-small btn-flat" href="{% url 'convenios-report_regiao_pdf' 'SL' %}">Sul</a>
<table class="numeros">
<tr>
{% for item in tabela_resumo_camara.cabecalho_topo %}
<th>{{item}}</th>
{% endfor %}
</tr>
{% for cabecalho,lista in tabela_resumo_camara.lista_zip %}
<tr>
<th>{{cabecalho}}</th>
{% for item in lista %}
<td>{{item}}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<table class="numeros">
<tr>
<th>{% trans 'Total de câmaras' %}</th>
<td>{{ tabela_resumo_camara.total_camaras }}</td>
</tr>
<tr>
<th>{% trans 'Câmaras sem processo' %}</th>
<td>{{ tabela_resumo_camara.camaras_sem_processo }}</td>
</tr>
<tr>
<th>{% trans 'Casas sem convenio que utilizam algum serviço de hospedagem' %}
<a href="{% url "home_reportsemconvenio" %}?modo=H" target="_blank" aria-label="{% trans "Listar casas" %}" title="{% trans "Listar casas" %}"><i class="material-icons tiny">list</i></a>
<a href="{% url "home_reportsemconvenio" %}?modo=H&f=csv" aria-label="{% trans "Download csv" %}" title="{% trans "Download csv" %}"><i class="material-icons tiny">file_download</i></a>
</th>
<td>{{ tabela_resumo_camara.sem_convenio.hospedagem|length }}</td>
</tr>
<tr>
<th>{% trans 'Casas sem convenio que utilizam somente serviço de registro' %}
<a href="{% url "home_reportsemconvenio" %}?modo=R" target="_blank" aria-label="{% trans "Listar casas" %}" title="{% trans "Listar casas" %}"><i class="material-icons tiny">list</i></a>
<a href="{% url "home_reportsemconvenio" %}?modo=R&f=csv" aria-label="{% trans "Download csv" %}" title="{% trans "Download csv" %}"><i class="material-icons tiny">file_download</i></a>
</th>
<td>{{ tabela_resumo_camara.sem_convenio.registro|length }}</td>
</tr>
<tr>
<th>{% trans 'Casas sem convenio que utilizam algum serviço de registro e/ou hospedagem' %}
<a href="{% url "home_reportsemconvenio" %}" target="_blank" aria-label="{% trans "Listar casas" %}" title="{% trans "Listar casas" %}"><i class="material-icons tiny">list</i></a>
<a href="{% url "home_reportsemconvenio" %}?f=csv" aria-label="{% trans "Download csv" %}" title="{% trans "Download csv" %}"><i class="material-icons tiny">file_download</i></a>
</th>
<td>{{ tabela_resumo_camara.sem_convenio.total|length }}</td>
</tr>
</table>

41
sigi/apps/home/templates/home/dashboard/resumo_seit.html

@ -0,0 +1,41 @@
{% load static i18n %}
<div class="card-links">
<a class="waves-effect waves-light btn-small btn-flat btn-floating left" href="{% url "home_resumoseit" %}?ano={{ tabela_resumo_seit.mes_anterior.year|safe }}&mes={{ tabela_resumo_seit.mes_anterior.month|safe }}" aria-label="{% trans "Retroceder um mês" %}" data-target="card-resumoseit">
<i class="material-icons left">chevron_left</i>
</a>
<a class="waves-effect waves-light btn-small btn-flat btn-floating right" href="{% url "home_resumoseit" %}?ano={{ tabela_resumo_seit.proximo_mes.year|safe }}&mes={{ tabela_resumo_seit.proximo_mes.month|safe }}" aria-label="{% trans "Avançar um mês" %}" data-target="card-resumoseit">
<i class="material-icons right">chevron_right</i>
</a>
</div>
<table class="numeros servicos">
<tr>
{% for s in tabela_resumo_seit.titulos %}
<th>{{ s }}</th>
{% endfor %}
</tr>
{% for servico in tabela_resumo_seit.servicos %}
<tr>
<th>
<a class="waves-effect waves-light modal-trigger" href="#modal-{{ servico.nome|slugify }}">{{ servico.nome }}</a>
<div id="modal-{{ servico.nome|slugify }}" class="modal">
<div class="modal-content">
<h6>{{ servico.nome }}</h6>
<table class="numeros servicos">
{% for mes in servico.novos_por_mes %}
<tr><th>{{ mes.mes }}</th><td>{{ mes.total }}</td></tr>
{% endfor %}
</table>
</div>
<div class="modal-footer">
<a href="#!" class="modal-close waves-effect waves-green btn-flat">{% translate "Close" %}</a>
</div>
</div>
</th>
<td>{{ servico.total }}</td>
<td>{{ servico.novos_mes_anterior }}</td>
<td>{{ servico.novos_mes_atual }}</td>
</tr>
{% endfor %}
</table>

60
sigi/apps/home/templates/home/lista_casas.html

@ -0,0 +1,60 @@
{% extends "pdf/base_report.html" %}
{% load i18n %}
{% block page_size %}A4 landscape{% endblock page_size %}
{% block title %}{% trans 'Lista de Casas atendidas' %}{% endblock title %}
{% block report_name %}{% trans 'Lista de Casas atendidas'|upper %}{% endblock report_name %}
{% block main_content %}
<table>
<caption>{% trans "Filtros aplicados" %}</caption>
{% 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">
<thead>
<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>
</thead>
{% 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 %}

173
sigi/apps/home/templates/home/mapfilter.html

@ -0,0 +1,173 @@
{% load i18n material %}
<div class="scroll-pane">
{% if not mobile %}
<i class="material-icons minimize nav-bar" aria-hidden="true" title="{% trans 'Minimize' %}">close</i>
{% endif %}
<form id="filterForm" action="" method="get" >
{{ csrftoken }}
</form>
<ul class="collapsible">
<li>
<div class="card">
<div class="card-image">
{% if 'profile/user_picture.html'|template_exists %}
{% include 'profile/user_picture.html' %}
{% else %}
{% include 'material/admin/user_picture.html' %}
{% endif %}
</div>
</div>
</li>
<li>
<div class="card" id="filterbox">
<div class="card-content">
<form id="searchform" class="form-inline ui-front">
<div class="input-field">
<i class="material-icons prefix">search</i>
<input type="text" id="search-text" class="autocomplete" placeholder="Procurar" aria-label="Procurar">
</form>
</div>
</div>
</div>
<small><strong>Total de Órgãos selecionados: </strong><span id="totalOrgao">-</span></small>
</li>
<li>
<div class="collapsible-header">{% trans "Por Tipo de órgão" %}</div>
<div class="collapsible-body">
{% for o in tipos_orgao %}
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_orgao_{{ o.sigla }}" name="tipo_orgao" value="{{ o.sigla }}" checked/>
<span>{{ o.nome }}</span>
</label>
</p>
{% endfor %}
</div>
</li>
<li>
<div class="collapsible-header">{% trans "Por Tipo de serviço" %}</div>
<div class="collapsible-body">
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_servico_ignore" name="ignore_tipo_servico" value="ignore" data-controls="tipo_servico" />
<span>{% trans "Ignorar" %}
</label>
</p>
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_servico_none" name="tipo_servico" value="none"/>
<span>{% trans "Nenhum serviço" %}</span>
</label>
</p>
{% for s in tipos_servico %}
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_servico_{{ s.sigla }}" name="tipo_servico" value="{{ s.sigla }}" checked/>
<span>{{ s.nome }}</span>
</label>
</p>
{% endfor %}
</div>
</li>
<li>
<div class="collapsible-header">{% trans "Por convênio" %}</div>
<div class="collapsible-body">
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_convenio_ignore" name="ignore_tipo_convenio" value="ignore" data-controls="tipo_convenio" />
<span>{% trans "Ignorar" %}</span>
</label>
</p>
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_convenio_none" name="tipo_convenio" value="none"/>
<span>{% trans "Sem convênio" %}</span>
</label>
</p>
{% for c in tipos_convenio %}
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_convenio_{{ c.sigla }}" name="tipo_convenio" value="{{ c.sigla }}" checked/>
<span>{{ c.nome }}</span>
</label>
</p>
{% endfor %}
</div>
</li>
<li>
<div class="collapsible-header">{% trans "Por região/estado" %}</div>
<div class="collapsible-body">
{% for s, n, ufs in regioes %}
<p>
<label>
<input type="checkbox" form="filterForm" id="regiao_{{ s }}" name="regiao" value="{{ s }}"/>
<span>{{ n }}</span>
</label>
</p>
<div class="region-ufs">
{% for uf in ufs %}
<p>
<label>
<input type="checkbox" form="filterForm" id="uf_{{ uf.sigla }}" name="uf" value="{{ uf.sigla }}" data-regiao="{{ s }}" />
<span>{{ uf.nome }}</span>
</label>
</p>
{% endfor %}
</div>
{% endfor %}
</div>
</li>
<li>
<div class="collapsible-header">{% trans "Por gerente Interlegis" %}</div>
<div class="collapsible-body">
<p>
<label>
<input type="checkbox" form="filterForm" id="gerente_ignore" name="gerente_ignore" value="ignore" data-controls="gerente" />
<span>{% trans "Ignorar" %}</span>
</label>
</p>
<p>
<label>
<input type="checkbox" form="filterForm" id="gerente_none" name="gerente" value="none"/>
<span>{% trans "Sem gerente" %}</span>
</label>
</p>
{% for g in gerentes %}
<p>
<label>
<input type="checkbox" form="filterForm" id="gerente_{{ g.id|stringformat:"s" }}" name="gerente" value="{{ g.id|stringformat:"s" }}" checked/>
<span>{{ g.nome_completo }}</span>
</label>
</p>
{% endfor %}
</div>
</li>
<li>
<div class="collapsible-header">{% trans "Exportação de dados" %}</div>
<div class="collapsible-body">
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="lista" type="submit" form="filterForm">
<i class="material-icons">picture_as_pdf</i>
Listagem
</button>
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="exporta" type="submit" form="filterForm">
Exportação completa
</button>
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="exporta_servico" type="submit" form="filterForm">
Exportar serviços
</button>
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="exporta_convenio" type="submit" form="filterForm">
Exportar convênios
</button>
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="exporta_contato" type="submit" form="filterForm">
Exportar contatos
</button>
</div>
</li>
</ul>
</div>

375
sigi/apps/home/templates/home/openmap.html

@ -0,0 +1,375 @@
{% extends "admin/index.html" %}
{% load static %}
{% load i18n %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" />
<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 'home/css/openmap.css' %}" />
<link rel="stylesheet" href="{% static "admin/css/changelists.css" %}" type="text/css"/>
{% endblock %}
{% block extrahead %}
{{ block.super }}
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="Content-Type" content="text/xhtml; charset=UTF-8" />
<meta name="robots" content="NONE,NOARCHIVE" />
<script type="text/javascript">
//<![CDATA[
window.__admin_media_prefix__ = "{% filter escapejs %}{% static "admin/" %}{% endfilter %}";
//]]>
</script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<!-- script src="https://code.jquery.com/ui/1.13.1/jquery-ui.min.js" integrity="sha256-eTyxS0rkjpLEo16uXTS0uVCS4815lc40K2iVpWDvdSY=" crossorigin="anonymous"></script -->
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
<script type="text/javascript" src="{% static "admin/js/core.js" %}"></script>
{% endblock %}
{% block usertools %}
<div id="user-tools">
<a href="{% url 'admin:index' %}">{% trans "Entrar" %}</a>
</div>
{% endblock %}
{% block side_nav %}
{% if not nav_bar_minimized %}
<div id="side-bar" class="hide-on-med-and-down">
{% include 'home/mapfilter.html' %}
</div>
{% endif %}
<div id="mobile-demo" class="sidenav">
{% include 'home/mapfilter.html' with mobile=True %}
</div>
{% endblock %}
{% block content %}
<div id="map">
<!-- open street map -->
</div>
{% endblock %}
{% block sidebar %}{% endblock %}
{% block footer %}
{{ block.super }}
<script>
$(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").each(function() {
var search = M.Autocomplete.init(this, {
minLength: 3,
onAutocomplete: function(label) {
var data = search.options.ajaxdata;
for (k in data) {
if (data[k].label == label) {
mymap.flyTo([data[k].lat, data[k].lng], 8.5);
var encontrado = false;
mymap.eachLayer(function(layer) {
if (layer instanceof L.Circle) {
if (layer.orgao_id == data[k].id) {
layer.openPopup();
encontrado = true;
}
}
})
if (!encontrado) {
var mark = L.circle([data[k].lat, data[k].lng], unfiltred_options).bindTooltip(data[k].label).bindPopup("").addTo(mymap);
mark.orgao_id = data[k].id
mark.openPopup();
}
}
}
}
});
$(this).on("input change", function() {
if (this.value.length < search.options.minLength) {
return;
};
$.ajax({
url: "{% url "openmapsearch" %}",
data: {"q": this.value },
dataType: "json",
appendTo: "#searchform",
success: function(data) {
console.log(data);
var result = {};
for (k in data) {
result[data[k].label] = null;
}
search.updateData(result);
search.options['ajaxdata'] = data;
},
});
});
})
$("input[type=checkbox]").change(filtra);
var mymap = L.map('map', {zoomSnap: 0.01}).setView([-14.235004, -51.92528], 4.5);
mymap.zoomControl.options.zoomInTitle = "{% trans 'Aproximar' %}";
mymap.zoomControl.options.zoomOutTitle = "{% trans 'Afastar' %}";
mymap.zoomControl.setPosition("bottomright");
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18,
attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1
}).addTo(mymap);
mymap.on("popupopen", function(e) {
var popup = e.popup;
mark = popup._source;
$.ajax({
type: "GET",
url: "{% url "openmapdetail" "orgao_id" %}".replace("orgao_id", mark.orgao_id),
encode: true
}).done(function(content) {
popup.setContent(content);
})
})
filtra();
function filtra() {
var name = $(this).attr("name"),
value = $(this).attr("value"),
checked = $(this).prop("checked");
if (name) {
$(`input[type=checkbox][name=${name}][value=${value}]`).prop("checked", checked);
}
if (value == "ignore") {
controls = $(this).attr("data-controls");
$("input[type=checkbox][name='"+controls+"']").prop("disabled", checked);
}
if (value=="none") {
$("input[type=checkbox][name='" + name +"'][value!='none']").prop("checked", !checked);
} else {
if (checked) {
$("input[type=checkbox][name='" + name +"'][value='none']").prop("checked", false);
}
}
if (name=='regiao') {
$("input[type=checkbox][name='uf'][data-regiao='"+value+"']").prop('checked', checked);
}
if (name=='uf') {
var sigla_regiao = $(this).attr('data-regiao'),
regiao = $("input[type=checkbox][value='"+sigla_regiao+"']");
if ($("input[type=checkbox][name='uf'][data-regiao='"+sigla_regiao+"']:checked").length == 0) {
$(regiao).prop('checked', false).prop("indeterminate", false);
} else if ($("input[type=checkbox][name='uf'][data-regiao='"+sigla_regiao+"']:not(:checked)").length == 0) {
$(regiao).prop('checked', true).prop("indeterminate", false);
} else {
$(regiao).prop("indeterminate", true)
}
}
var formData = $("#filterForm").serializeArray();
mymap.eachLayer(function(layer) {
if (layer instanceof L.Circle) {
mymap.removeLayer(layer);
}
})
$.ajax({
type: "GET",
url: "{% url "openmapdata" %}",
data: formData,
dataType: "json",
encode: true,
}).done(function(returnedData) {
$("#totalOrgao").text(returnedData.length);
returnedData.forEach(function(casa) {
if (casa[2] === null || casa[3] === null) {
alert(casa[1]+" está sem coordenadas geográficas e não será plotada");
} else {
var mark = L.circle([casa[2], casa[3]], options).bindTooltip(casa[1]).bindPopup('<div class="preloader-wrapper small active"><div class="spinner-layer spinner-green-only"><div class="circle-clipper left"><div class="circle"></div></div><div class="gap-patch"><div class="circle"></div></div><div class="circle-clipper right"><div class="circle"></div></div></div></div>').addTo(mymap);
mark.orgao_id = casa[0]
}
})
})
}
})
</script>
{% endblock %}
{% comment %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="{{ LANGUAGE_CODE|default:"en-us" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}>
<head>
<title>{% trans 'SIGI' %}</title>
</head>
<body>
<div class="mapbox">
<div class="sigi-logo">
<div>
<img src="{% static 'img/interlegis_60x60.png' %}" class='img-circle'/>
</div>
<div>
<h3>Interlegis</h3>
<a href="{% url 'admin:index' %}">Voltar ao SIGI</a>
</div>
</div>
<div id="map">
<!-- open street map -->
</div>
</div>
<script>
$(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() {
$("#options-toggler span").removeClass("glyphicon-chevron-right").addClass("glyphicon-chevron-left")
})
$("#filterbox").on("hidden.bs.collapse", function() {
$("#options-toggler span").removeClass("glyphicon-chevron-left").addClass("glyphicon-chevron-right")
})
$("input[type=checkbox]").change(filtra);
var mymap = L.map('map', {zoomSnap: 0.01}).setView([-14.235004, -51.92528], 4.5);
mymap.zoomControl.options.zoomInTitle = "{% trans 'Aproximar' %}";
mymap.zoomControl.options.zoomOutTitle = "{% trans 'Afastar' %}";
mymap.zoomControl.setPosition("bottomright");
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18,
attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1
}).addTo(mymap);
mymap.on("popupopen", function(e) {
var popup = e.popup;
mark = popup._source;
$.ajax({
type: "GET",
url: "{% url "openmapdetail" 'orgao_id' %}".replace("orgao_id", mark.orgao_id),
encode: true
}).done(function(content) {
popup.setContent(content);
})
})
filtra();
function filtra() {
var name = $(this).attr("name"),
value = $(this).attr("value"),
checked = $(this).prop("checked");
if (value == "ignore") {
controls = $(this).attr("data-controls");
$("input[type=checkbox][name='"+controls+"']").prop("disabled", checked);
}
if (value=="none") {
$("input[type=checkbox][name='" + name +"'][value!='none']").prop("checked", !checked);
} else {
if (checked) {
$("input[type=checkbox][name='" + name +"'][value='none']").prop("checked", false);
}
}
if (name='regiao') {
$("input[type=checkbox][name='uf'][data-regiao='"+value+"']").prop('checked', checked);
}
if (name='uf') {
var sigla_regiao = $(this).attr('data-regiao'),
regiao = $("input[type=checkbox][value='"+sigla_regiao+"']");
if ($("input[type=checkbox][name='uf'][data-regiao='"+sigla_regiao+"']:checked").length == 0) {
$(regiao).prop('checked', false).prop("indeterminate", false);
} else if ($("input[type=checkbox][name='uf'][data-regiao='"+sigla_regiao+"']:not(:checked)").length == 0) {
$(regiao).prop('checked', true).prop("indeterminate", false);
} else {
$(regiao).prop("indeterminate", true)
}
}
var formData = $("#filterForm").serializeArray();
mymap.eachLayer(function(layer) {
if (layer instanceof L.Circle) {
mymap.removeLayer(layer);
}
})
$.ajax({
type: "GET",
url: "{% url "openmapdata" %}",
data: formData,
dataType: "json",
encode: true,
}).done(function(returnedData) {
$("#totalOrgao").text(returnedData.length);
returnedData.forEach(function(casa) {
if (casa[2] === null || casa[3] === null) {
alert(casa[1]+" está sem coordenadas geográficas e não será plotada");
} else {
var mark = L.circle([casa[2], casa[3]], options).bindTooltip(casa[1]).bindPopup("").addTo(mymap);
mark.orgao_id = casa[0]
}
})
})
}
})
</script>
</body>
</html>
{% endcomment %}

23
sigi/apps/home/templates/home/openmapdetail.html

@ -0,0 +1,23 @@
<div class="card">
<div class="card-header">
<strong>{{ orgao.nome }}</strong> <a href="{% url "admin:casas_orgao_change" orgao.id %}" title="Editar" target="_blank"><span class="glyphicon glyphicon-edit"></span></a>
</div>
<div class="card-body">
<table class="table-condensed">
<tr><th>CNPJ</th><td>{{ orgao.cnpj }}</td></tr>
{% if orgao.data_instalacao %}<tr><th>Data de instalação</th><td>{{ orgao.data_instalacao }}</td></tr>{% endif %}
<tr><th>Endereço</th><td><address>{{ orgao.logradouro }}, {{ orgao.bairro }}, {{ orgao.municipio.nome }}, {{ orgao.municipio.uf.sigla }}, CEP: {{ orgao.cep }}</address></td></tr>
{% if orgao.telefones.all %}<tr><th>Telefones</th><td>{% for telefone in orgao.telefones.all %}<a href="tel:{{ telefone.numero }}">{{ telefone.numero }}</a>{% if not forloop.last %}, {% endif %}{% endfor %}</td></tr>{% endif %}
{% if orgao.email %}<tr><th>E-mail</th><td><a href="mailto:{{ orgao.email }}">{{ orgao.email }}</a></td></tr>{% endif %}
{% if orgao.convenio_set.all %}
<tr><th>Convênios</th><td>{% for c in orgao.convenio_set.all %}<a href="{% url 'admin:convenios_convenio_change' c.id %}" target="_blank">{{ c }}</a>{% if not forloop.last %}, {% endif %}{% endfor %}</td></tr>
{% endif %}
{% if orgao.servico_set.all %}
<tr><th>Serviços</th><td>{% for s in orgao.servico_set.all %}{% if s.url %}<a href="{{ s.url }}" target="_blank">{{ s }}</a>{% else %}{{ s }}{% endif %}{% if not forloop.last %}, {% endif %}{% endfor %}</td></tr>
{% endif %}
{% if orgao.gerentes_interlegis.all %}
<tr><th>Gerentes</th><td>{% for g in orgao.gerentes_interlegis.all %}{{ g.nome_completo }}{% if not forloop.last %}, {% endif %} {% endfor %}</td></tr>
{% endif %}
</table>
</div>
</div>

95
sigi/apps/home/templates/home/sem_convenio.html

@ -1,83 +1,23 @@
{% load static from staticfiles %}
{% load i18n %}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>{{ titulo }}</title>
<style type="text/css">
h1 {
font-size: 2em;
text-align: center;
}
h2 {
font-size: 1.7em;
}
h3 {
margin-top: 10px;
margin-bottom: 0px;
}
body {
font-family: "Helvetica, Arial, sans-serif";
font-size: 1.3em;
line-height: 1em;
}
#header {
text-align: center;
}
th {
text-align: left;
padding: 2px 5px 2px 2px;
background-color: #f5f5f5;
border-left: 2px solid #ffffff;
}
th, td {
padding: 2px 2px 1px 2px;
vertical-align: bottom;
}
td {
border-bottom: 1px solid #ddd;
}
{% extends 'pdf/base_report.html' %}
{% load static i18n %}
@page {
size: {{ pagesize|default:"a4" }};
margin: {{ margin|default:"4cm 1cm 1cm 2cm" }};
font-family: "Helvetica, Arial, sans-serif";
font-size: 2em;
@frame header {
-pdf-frame-content: header;
top: 1cm;
}
@frame footer {
-pdf-frame-content: footer;
bottom: 0cm;
margin-left: 9cm;
margin-right: 9cm;
height: 1cm;
}
}
</style>
</head>
<body>
<div id="header">
<p><strong>{% trans 'SENADO FEDERAL' %}</strong></p>
<p><strong>{% trans 'PROGRAMA INTERLEGIS – SIGI' %}</strong></p>
<p><strong>{{ titulo }}</strong></p>
</div>
{% block page_size %}A4 portrait{% endblock %}
{% block main_content %}
<table repeat="1">
<tr>
<th>{% trans "Nome da Casa" %}</th>
<th width=30>{% trans "UF" %}</th>
<th>{% trans "Gerente de contas" %}</th>
<th>{% trans "Serviços" %}</th>
</tr>
<thead>
<tr>
<th>{% trans "Nome da Casa" %}</th>
<th width=30>{% trans "UF" %}</th>
<th>{% trans "Gerente de contas" %}</th>
<th>{% trans "Serviços" %}</th>
</tr>
</thead>
{% for casa in casas %}
<tr>
<td>{{ casa.nome }}</td>
<td>{{ casa.municipio.uf.sigla }}</td>
<td>{{ casa.lista_gerentes }}</td>
<td>{{ casa.lista_gerentes|safe }}</td>
<td>
{% for s in casa.servico_set.all %}
{% if s.data_desativacao == None %}
@ -88,11 +28,4 @@
</tr>
{% endfor %}
</table>
<div id="footer">
{%block page_foot%}
{% trans 'Página' %} <pdf:pagenumber>
{%endblock%}
</div>
</body>
</html>
{% endblock main_content %}

34
sigi/apps/home/templatetags/smart_pagination.py

@ -1,23 +1,3 @@
# -*- coding: utf-8 -*-
#
# sigi.apps.home.templatetags.smart_pagination
#
# Copyright (C) 2015 Interlegis
#
# 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 import template
register = template.Library()
@ -28,17 +8,17 @@ def smart_paginator(page_obj, querystring=None):
querystring = '?' + querystring + '&'
else:
querystring = '?'
page_range = page_obj.paginator.page_range
mid = len(page_range) / 2
mid = len(page_range) // 2
range = list(set(page_range[:3]) | set(page_range[mid-2:mid+1]) | set(page_range[-3:]) |
set(page_range[page_obj.number-2:page_obj.number+1]))
range.sort()
last = range[0]-1
page_range = []
for p in range:
if p-1 != last:
if p-2 == last:
@ -46,8 +26,8 @@ def smart_paginator(page_obj, querystring=None):
else:
page_range.append(None)
page_range.append(p)
last = p
last = p
return dict(page_obj=page_obj, querystring=querystring, page_range=page_range)
@register.inclusion_tag('menus/menu_item.html')

43
sigi/apps/home/urls.py

@ -1,15 +1,28 @@
# coding: utf-8
from django.conf.urls import patterns, url
urlpatterns = patterns('sigi.apps.home.views',
url(r'^$', 'index', name='sigi_index'),
url(r'^home/resumoconvenios/$', 'resumo_convenios', name="home_resumoconvenios"),
url(r'^home/resumoseit/$', 'resumo_seit', name="home_resumoseit"),
url(r'^home/chartseit/$', 'chart_seit', name="home_chartseit"),
url(r'^home/chartconvenios/$', 'chart_convenios', name="home_chartconvenios"),
url(r'^home/chartcarteira/$', 'chart_carteira', name="home_chartcarteira"),
url(r'^home/chartperformance/$', 'chart_performance', name="home_chartperformance"),
url(r'^home/report/semconvenio/$', 'report_sem_convenio', name="home_reportsemconvenio"),
)
from django.urls import path
from sigi.apps.home import views
urlpatterns = [
path('',views.openmap, name='openmap'),
path('openmapdata/', views.openmapdata, name='openmapdata'),
path('openmapdetail/<orgao_id>/', views.openmapdetail, name='openmapdetail'),
path('openmapsearch/', views.openmapsearch, name='openmapsearch'),
path('home/resumoseit/', views.resumo_seit, name="home_resumoseit"),
path('home/chartseit/', views.chart_seit, name="home_chartseit"),
path('home/chartperformance/', views.chart_performance, name="home_chartperformance"),
path('home/chartcarteira/', views.chart_carteira, name="home_chartcarteira"),
path('home/resumoconvenios/', views.resumo_convenios, name="home_resumoconvenios"),
path('home/report/semconvenio/', views.report_sem_convenio, name="home_reportsemconvenio"),
]
# from django.conf.urls import patterns, url
# urlpatterns = patterns('sigi.apps.home.views',
# url(r'^$', 'index', name='sigi_index'),
# url(r'^home/chartseit/$', 'chart_seit', name="home_chartseit"),
# url(r'^home/chartconvenios/$', 'chart_convenios', name="home_chartconvenios"),
# url(r'^home/chartcarteira/$', 'chart_carteira', name="home_chartcarteira"),
# url(r'^home/chartperformance/$', 'chart_performance', name="home_chartperformance"),
# url(r'^home/report/semconvenio/$', 'report_sem_convenio', name="home_reportsemconvenio"),
# )

494
sigi/apps/home/views.py

@ -1,57 +1,202 @@
# -*- coding: utf-8 -*-
#
# sigi.apps.home.views
#
# Copyright (c) 2016 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.
#
import datetime
import calendar
import csv
import datetime
from itertools import cycle
from django.contrib.admin.sites import site
from django.contrib.auth.decorators import login_required
from django.db.models import Q, Count
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, get_object_or_404
from django.template.loader import render_to_string
from django.utils.translation import gettext as _
from itertools import cycle
from sigi.apps.casas.models import Orgao
from django.views.decorators.cache import never_cache
from django_weasyprint.views import WeasyTemplateResponse
from sigi.apps.casas.models import TipoOrgao, Orgao
from sigi.apps.contatos.models import UnidadeFederativa
from sigi.apps.convenios.models import Convenio, Projeto
from sigi.apps.diagnosticos.models import Diagnostico
from sigi.apps.metas.models import Meta
from sigi.apps.servicos.models import TipoServico
from sigi.apps.servidores.models import Servidor
from django.views.decorators.cache import never_cache
from django.contrib.auth.decorators import login_required
from django.http.response import JsonResponse, HttpResponse
from django.core.urlresolvers import reverse
from django.db.models import Q, Count
from sigi.shortcuts import render_to_pdf
import csv
from sigi.apps.utils import to_ascii
# from django.shortcuts import render, get_object_or_404
# from sigi.apps.casas.models import Orgao
# from sigi.apps.diagnosticos.models import Diagnostico
# from sigi.apps.metas.models import Meta
# from sigi.apps.servicos.models import TipoServico
# from sigi.apps.servidores.models import Servidor
# from django.http.response import JsonResponse, HttpResponse
from django.urls import reverse
# from sigi.shortcuts import render_to_pdf
# import csv
def openmap(request):
reptype = request.GET.get('reptype', None)
context = site.each_context(request)
if reptype is None:
context['tipos_orgao'] = TipoOrgao.objects.filter(legislativo=True)
context['tipos_servico'] = TipoServico.objects.all()
context['tipos_convenio'] = Projeto.objects.all()
context['gerentes'] = Servidor.objects.exclude(casas_que_gerencia=None)
context['regioes'] = [(s, n, UnidadeFederativa.objects.filter(regiao=s))
for s, n in UnidadeFederativa.REGIAO_CHOICES]
return render(request, 'home/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)
context['tipos_servico'] = TipoServico.objects.filter(
sigla__in=tipos_servico
)
context['tipos_convenio'] = Projeto.objects.filter(
sigla__in=tipos_convenio)
context['gerentes'] = Servidor.objects.exclude(
casas_que_gerencia=None).filter(id__in=gerentes)
context['ufs'] = UnidadeFederativa.objects.filter(sigla__in=ufs)
context['casas'] = casas
if reptype == "lista":
return WeasyTemplateResponse(
filename='Lista de Casas atendidas.pdf',
request=request,
template='home/lista_casas.html',
context=context,
content_type='application/pdf',
)
else:
fields = ['cnpj', 'nome', 'municipio__uf__nome',
'municipio__uf__regiao', 'logradouro', 'bairro',
'cep', 'ult_alt_endereco', 'email']
if reptype in ('exporta_servico', 'exporta'):
fields.extend(['servico__tipo_servico__nome', 'servico__url',
'servico__data_ativacao',
'servico__data_desativacao'])
if reptype in ('exporta_convenio', 'exporta'):
fields.extend([
'convenio__num_convenio',
'convenio__num_processo_sf',
'convenio__projeto__sigla',
'convenio__data_adesao',
'convenio__data_termino_vigencia',
'convenio__data_retorno_assinatura'
])
if reptype in ('exporta_contato', 'exporta'):
fields.extend(['funcionario__nome', 'funcionario__setor',
'funcionario__email', 'funcionario__nota',
'funcionario__redes_sociais',
'funcionario__desativado',
'funcionario__ult_alteracao'])
dados = casas.distinct().values(*fields)
response = HttpResponse(content_type='text/csv')
writer = csv.DictWriter(response, fieldnames=fields)
writer.writeheader()
writer.writerows(dados)
return response
def openmapdata(request):
tipos_orgao = request.GET.getlist('tipo_orgao', None)
tipos_servico = request.GET.getlist('tipo_servico', None)
tipos_convenio = request.GET.getlist('tipo_convenio', None)
ufs = request.GET.getlist('uf', None)
gerentes = request.GET.getlist('gerente', None)
reptype = request.GET.get('reptype', None)
dados = Orgao.objects.all()
if tipos_orgao:
dados = dados.filter(tipo__sigla__in=tipos_orgao)
else:
dados = dados.filter(tipo__legislativo=True)
if tipos_servico:
if "none" in tipos_servico:
dados = dados.filter(servico=None)
else:
dados = dados.filter(servico__tipo_servico__sigla__in=tipos_servico,
servico__data_desativacao=None)
if tipos_convenio:
if "none" in tipos_convenio:
dados = dados.filter(convenio=None)
else:
dados = dados.filter(convenio__projeto__sigla__in=tipos_convenio)
if ufs:
dados = dados.filter(municipio__uf__sigla__in=ufs)
if gerentes:
if "none" in gerentes:
dados = dados.filter(gerentes_interlegis=None)
else:
dados = dados.filter(gerentes_interlegis__id__in=gerentes)
if not reptype:
dados = dados.order_by('nome', 'id').distinct('nome', 'id')
dados = dados.values_list("id", "nome", "municipio__latitude",
"municipio__longitude")
return JsonResponse(list(dados), safe=False)
else:
dados = dados.order_by(
'municipio__uf__regiao',
'municipio__uf__nome',
'nome',
'id'
).distinct(
'municipio__uf__regiao',
'municipio__uf__nome',
'nome',
'id'
).prefetch_related(
'servico_set',
'convenio_set',
'municipio__uf',
'gerentes_interlegis'
)
return dados
def openmapdetail(request, orgao_id):
orgao = get_object_or_404(Orgao, id=orgao_id)
return render(request, "home/openmapdetail.html", {'orgao': orgao})
def openmapsearch(request):
q = request.GET.get('q', '')
if len(q) < 3:
return JsonResponse({'result': 'unsearchable'})
dados = Orgao.objects.filter(
tipo__legislativo=True,
search_text__icontains=to_ascii(q)
)[:10]
dados = dados.values("id", "nome", "municipio__latitude",
"municipio__longitude")
dados = [{'id': d['id'],
'label': d['nome'],
'lat': d['municipio__latitude'],
'lng': d['municipio__longitude']} for d in dados]
return JsonResponse(list(dados), safe=False)
@never_cache
@login_required
def index(request):
context = {'gerentes': Servidor.objects.exclude(casas_que_gerencia=None)}
return render(request, 'index.html', context)
# @never_cache
# @login_required
# def index(request):
# context = {'gerentes': Servidor.objects.exclude(casas_que_gerencia=None)}
# return render(request, 'index.html', context)
@never_cache
@login_required
def resumo_convenios(request):
context = {'tabela_resumo_camara': busca_informacoes_camara() }
return render(request, 'snippets/modules/resumo_convenios.html', context)
return render(request, 'home/dashboard/resumo_convenios.html', context)
@never_cache
@login_required
@ -66,36 +211,40 @@ def resumo_seit(request):
tabela_resumo_seit = busca_informacoes_seit()
context = {'tabela_resumo_seit': tabela_resumo_seit}
return render(request, 'snippets/modules/resumo_seit.html', context)
return render(request, 'home/dashboard/resumo_seit.html', context)
@never_cache
@login_required
def chart_seit(request):
mes = request.GET.get('mes', None)
ano = request.GET.get('ano', None)
hoje = datetime.date.today()
mes = request.GET.get('mes', hoje.month)
ano = request.GET.get('ano', hoje.year)
try:
mes = datetime.date(year=int(ano), month=int(mes), day=1)
tabela_resumo_seit = busca_informacoes_seit(mes)
except:
tabela_resumo_seit = busca_informacoes_seit()
mes = datetime.date(year=int(ano), month=int(mes), day=1)
tabela_resumo_seit = busca_informacoes_seit(mes)
data = {
'type': 'line',
'prevlink': reverse('home_chartseit') + ('?ano=%s&mes=%s' %
(tabela_resumo_seit['mes_anterior'].year,
tabela_resumo_seit['mes_anterior'].month)),
'nextlink': reverse('home_chartseit') + ('?ano=%s&mes=%s' %
(tabela_resumo_seit['proximo_mes'].year,
tabela_resumo_seit['proximo_mes'].month)),
'options': {'bezierCurve': False, 'datasetFill': False, 'pointDot': False, 'responsive': True},
'prevlink': reverse('home_chartseit') + (
f"?ano={tabela_resumo_seit['mes_anterior'].year}"
f"&mes={tabela_resumo_seit['mes_anterior'].month}"
),
'nextlink': reverse('home_chartseit') + (
f"?ano={tabela_resumo_seit['proximo_mes'].year}"
f"&mes={tabela_resumo_seit['proximo_mes'].month}"
),
'options': {'bezierCurve': False, 'datasetFill': False,
'pointDot': False, 'responsive': True},
'data': {
'labels': ['%02d/%s' % (mes.month, mes.year) for mes in reversed(tabela_resumo_seit['meses'])],
'labels': [f'{mes: %m/%Y}'
for mes in reversed(tabela_resumo_seit['meses'])],
'datasets': [
{
'label': servico['nome'],
'strokeColor': servico['cor'],
'data': [mes['total'] for mes in reversed(servico['novos_por_mes'])]
'borderColor': servico['cor'],
'backgroundColor': servico['cor'],
'data': [mes['total']
for mes in reversed(servico['novos_por_mes'])]
}
for servico in tabela_resumo_seit['servicos']],
}
@ -103,37 +252,38 @@ def chart_seit(request):
return JsonResponse(data)
@never_cache
@login_required
def chart_convenios(request):
q = request.GET.get('q', 'all')
convenios = Convenio.objects.all()
if q == 'assinados':
convenios = convenios.exclude(data_retorno_assinatura=None)
data = {
'type': 'pie',
'options': {'responsive': False, 'maintainAspectRatio': False},
'data': grafico_convenio_projeto(convenios),
}
return JsonResponse(data)
# @never_cache
# @login_required
# def chart_convenios(request):
# q = request.GET.get('q', 'all')
# convenios = Convenio.objects.all()
# if q == 'assinados':
# convenios = convenios.exclude(data_retorno_assinatura=None)
# data = {
# 'type': 'pie',
# 'options': {'responsive': False, 'maintainAspectRatio': False},
# 'data': grafico_convenio_projeto(convenios),
# }
# return JsonResponse(data)
@never_cache
@login_required
def chart_carteira(request):
colors, highlights = color_palete()
data = {'type': 'pie',
'options': {'responsive': True},
'data': [{'value': r['total_casas'],
'color': colors.next(),
'highlight': highlights.next(),
'label': r['gerentes_interlegis__nome_completo']
}
for r in Orgao.objects.exclude(
gerentes_interlegis=None).values(
'gerentes_interlegis__nome_completo').annotate(
total_casas=Count('pk')).order_by(
'gerentes_interlegis__nome_completo')
]
gerentes = Servidor.objects.exclude(casas_que_gerencia=None).annotate(
total_casas=Count('casas_que_gerencia'))
data = {
'type': 'doughnut',
'data': {
'labels': [g.get_apelido() for g in gerentes],
'datasets': [
{
'data': [g.total_casas for g in gerentes],
'backgroundColor': [next(highlights) for g in gerentes]
}
],
},
}
return JsonResponse(data)
@ -142,24 +292,42 @@ def chart_carteira(request):
@login_required
def chart_performance(request):
servidor = request.GET.get('servidor', None)
gerentes = Servidor.objects.exclude(casas_que_gerencia=None)
gerente = None
if servidor is None:
if (request.user.servidor and
request.user.servidor.casas_que_gerencia.exists()):
gerente = request.user.servidor
else:
servidor = '_all'
if servidor is not None and servidor != '_all':
gerente = get_object_or_404(Servidor, pk=servidor)
if gerente is None:
casas = Orgao.objects.exclude(gerentes_interlegis=None)
else:
gerente = get_object_or_404(Servidor, pk=servidor)
casas = gerente.casas_que_gerencia
data = {
'type': 'pie',
'options': {'responsive': True},
'data': [
{'label': _("Utilizam serviços"),
'value': casas.exclude(servico=None).count(),
'color': '#91e8e1'},
{'label': _("Não utilizam serviços"),
'value': casas.filter(servico=None).count(),
'color': '#f7a35c'},
]
'type': 'doughnut',
'data': {
'labels': [_("Utilizam serviços"), _("Não utilizam serviços")],
'datasets': [
{
'label': 'SeiLaQueIsso',
'data': [casas.exclude(servico=None).count(),
casas.filter(servico=None).count()],
'backgroundColor': ['#91e8e1', '#f7a35c']
}
]
},
'actionblock': render_to_string(
'home/dashboard/gerentes_snippet.html',
context={'gerentes': gerentes, 'gerente': gerente},
request=request
)
}
return JsonResponse(data)
@ -187,20 +355,19 @@ def report_sem_convenio(request):
if fmt == 'csv':
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=casas.csv'
response['Content-Disposition'] = f'attachment; filename={ titulo }.csv'
writer = csv.writer(response)
writer.writerow([titulo.encode('utf8')])
writer.writerow([titulo])
writer.writerow([''])
writer.writerow(['casa', 'uf', 'gerentes',
'serviços'.encode('utf8')])
writer.writerow(['casa', 'uf', 'gerentes', 'serviços'])
for casa in casas:
writer.writerow([
casa.nome.encode('utf8'),
casa.municipio.uf.sigla.encode('utf8'),
casa.lista_gerentes(fmt='lista').encode('utf8'),
casa.nome,
casa.municipio.uf.sigla,
casa.lista_gerentes(fmt='lista'),
(', '.join(casa.servico_set.filter(
data_desativacao__isnull=True).values_list(
'tipo_servico__nome', flat=True))).encode('utf8'),
'tipo_servico__nome', flat=True))),
])
return response
elif fmt == 'json':
@ -219,15 +386,17 @@ def report_sem_convenio(request):
}
return JsonResponse(data, safe=False)
else:
context = {'casas': casas, 'titulo': titulo}
return render_to_pdf('home/sem_convenio.html', context)
context = {'casas': casas, 'title': titulo}
return WeasyTemplateResponse(
filename=f'{ titulo }.pdf',
request=request,
template='home/sem_convenio.html',
context=context,
content_type='application/pdf',
)
def busca_informacoes_camara():
"""
Busca informacoes no banco para montar tabela de resumo de camaras por projeto
Retorna um dicionario de listas
"""
camaras = Orgao.objects.filter(tipo__sigla='CM')
convenios = Convenio.objects.filter(casa_legislativa__tipo__sigla='CM')
projetos = Projeto.objects.all()
@ -261,15 +430,21 @@ def busca_informacoes_camara():
cabecalho_topo.append(projeto.sigla)
lista_total.append(camaras.filter(convenio__projeto=projeto).count())
lista_nao_aderidas.append(camaras.filter(convenio__in=conv_sem_adesao_proj).count())
lista_aderidas.append(camaras.filter(convenio__in=conv_com_adesao_proj).count())
lista_convenios_assinados.append(camaras.filter(convenio__in=conv_assinados_proj).count())
lista_convenios_em_andamento.append(camaras.filter(convenio__in=conv_em_andamento_proj).count())
lista_camaras_equipadas.append(camaras.filter(convenio__in=conv_equipadas_proj).count())
# Monta linhas de diagnosticos
lista_diagnosticos_digitados = ['', '', Diagnostico.objects.count(), '', '', '']
lista_diagnosticos_publicados = ['', '', Diagnostico.objects.filter(publicado=True).count(), '', '', '']
lista_nao_aderidas.append(
camaras.filter(convenio__in=conv_sem_adesao_proj).count()
)
lista_aderidas.append(
camaras.filter(convenio__in=conv_com_adesao_proj).count()
)
lista_convenios_assinados.append(
camaras.filter(convenio__in=conv_assinados_proj).count()
)
lista_convenios_em_andamento.append(
camaras.filter(convenio__in=conv_em_andamento_proj).count()
)
lista_camaras_equipadas.append(
camaras.filter(convenio__in=conv_equipadas_proj).count()
)
# Cabecalho da esquerda na tabela
cabecalho_esquerda = (
@ -279,8 +454,6 @@ def busca_informacoes_camara():
_('Câmaras municipais com convênios assinados'),
_('Câmaras municipais convênios em andamento'),
_('Câmaras municipais equipadas'),
_('Diagnósticos digitados'),
_('Diagnósticos publicados')
)
linhas = (
@ -290,11 +463,9 @@ def busca_informacoes_camara():
lista_convenios_assinados,
lista_convenios_em_andamento,
lista_camaras_equipadas,
lista_diagnosticos_digitados,
lista_diagnosticos_publicados
)
# Unindo as duas listass para que o cabecalho da esquerda fique junto com sua
# Unindo as duas listas para que o cabecalho da esquerda fique junto com sua
# respectiva linha
lista_zip = zip(cabecalho_esquerda, linhas)
@ -307,33 +478,53 @@ def busca_informacoes_camara():
'sem_convenio': sem_convenio(),
}
def sem_convenio():
total = Orgao.objects.exclude(servico=None).filter(servico__data_desativacao=None, convenio=None).order_by('municipio__uf__sigla', 'nome').distinct('municipio__uf__sigla', 'nome')
hospedagem = Orgao.objects.exclude(servico=None).filter(servico__data_desativacao=None, servico__tipo_servico__modo='H', convenio=None).order_by('municipio__uf__sigla', 'nome').distinct('municipio__uf__sigla', 'nome')
reg_keys = set(total.values_list('pk', flat=True)).difference(set(hospedagem.values_list('pk', flat=True)))
registro = Orgao.objects.filter(pk__in=reg_keys).order_by('municipio__uf__sigla', 'nome')
total = Orgao.objects.exclude(
servico=None
).filter(
servico__data_desativacao=None, convenio=None
).order_by(
'municipio__uf__sigla', 'nome'
).distinct(
'municipio__uf__sigla', 'nome'
)
hospedagem = Orgao.objects.exclude(
servico=None
).filter(
servico__data_desativacao=None, servico__tipo_servico__modo='H',
convenio=None
).order_by(
'municipio__uf__sigla', 'nome'
).distinct(
'municipio__uf__sigla', 'nome'
)
reg_keys = set(total.values_list('pk', flat=True)).difference(
set(hospedagem.values_list('pk', flat=True))
)
registro = Orgao.objects.filter(pk__in=reg_keys).order_by(
'municipio__uf__sigla', 'nome'
)
return {
'total': total,
'hospedagem': hospedagem,
'registro': registro,
}
def grafico_convenio_projeto(convenios):
colors, highlights = color_palete()
projetos = Projeto.objects.all()
lista_projetos = [{'label': projeto.sigla,
'value': convenios.filter(projeto=projeto).count(),
'color': colors.next(),
'highlight': highlights.next()}
for projeto in projetos]
# remove projetos sem convenio
lista_projetos = [x for x in lista_projetos if x['value'] > 0]
# def grafico_convenio_projeto(convenios):
# colors, highlights = color_palete()
# projetos = Projeto.objects.all()
# lista_projetos = [{'label': projeto.sigla,
# 'value': convenios.filter(projeto=projeto).count(),
# 'color': colors.next(),
# 'highlight': highlights.next()}
# for projeto in projetos]
# # remove projetos sem convenio
# lista_projetos = [x for x in lista_projetos if x['value'] > 0]
# print lista_projetos
# total_convenios = "Total: " + str(convenios.count())
# lista_projetos.insert(0, total_convenios)
return lista_projetos
# # print lista_projetos
# # total_convenios = "Total: " + str(convenios.count())
# # lista_projetos.insert(0, total_convenios)
# return lista_projetos
def busca_informacoes_seit(mes_atual=None):
@ -341,7 +532,8 @@ def busca_informacoes_seit(mes_atual=None):
if mes_atual is None:
mes_atual = datetime.date.today().replace(day=1)
mes_anterior = mes_atual - datetime.timedelta(days=1)
proximo_mes = mes_atual + datetime.timedelta(days=calendar.monthrange(mes_atual.year, mes_atual.month)[1])
proximo_mes = mes_atual + datetime.timedelta(days=calendar.monthrange(
mes_atual.year, mes_atual.month)[1])
meses = []
mes = mes_atual
@ -374,18 +566,18 @@ def busca_informacoes_seit(mes_atual=None):
'novos_mes_anterior': tipo_servico.servico_set.filter(data_ativacao__year=mes_anterior.year, data_ativacao__month=mes_anterior.month).count(),
'novos_mes_atual': tipo_servico.servico_set.filter(data_ativacao__year=mes_atual.year, data_ativacao__month=mes_atual.month).count(),
'novos_por_mes': por_mes,
'cor': colors.next(),
'cor': next(colors),
}
)
return result
def busca_informacoes_diagnostico():
return [
{'title': _('Diagnósticos digitados'), 'count': Diagnostico.objects.count()},
{'title': _('Diagnósticos publicados'), 'count': Diagnostico.objects.filter(publicado=True).count()},
]
# def busca_informacoes_diagnostico():
# return [
# {'title': _('Diagnósticos digitados'), 'count': Diagnostico.objects.count()},
# {'title': _('Diagnósticos publicados'), 'count': Diagnostico.objects.filter(publicado=True).count()},
# ]
def color_palete():

52
sigi/apps/ocorrencias/admin.py

@ -3,7 +3,7 @@ from django.contrib.admin.views.main import ChangeList
from django.utils.translation import gettext as _
from django.utils.safestring import mark_safe
from sigi.apps.ocorrencias.filters import OcorrenciaListFilter
from sigi.apps.ocorrencias.filters import ServidorRegistroFilter
from sigi.apps.ocorrencias.models import (Ocorrencia, Comentario, Anexo,
Categoria, TipoContato)
from sigi.apps.servidores.models import Servidor
@ -18,18 +18,15 @@ class ComentarioViewInline(admin.TabularInline):
can_delete = False
verbose_name = _("Comentário anterior")
verbose_name_plural = _("Comentários anteriores")
fields = ('usuario', 'data_criacao', 'novo_status', 'encaminhar_setor',
'descricao', )
readonly_fields = ('novo_status', 'encaminhar_setor', 'descricao',
'data_criacao', 'usuario',)
fields = ('usuario', 'data_criacao', 'novo_status', 'descricao', )
readonly_fields = fields
class ComentarioInline(admin.StackedInline):
model = Comentario
extra = 1
verbose_name = _("Comentário novo")
verbose_name_plural = _("Comentários novos")
fieldsets = ((None, {'fields': (('novo_status', 'encaminhar_setor',),
'descricao', )}),)
fields = ('novo_status', 'descricao',)
def get_queryset(self, queryset):
return self.model.objects.none()
@ -39,32 +36,15 @@ class AnexosInline(admin.TabularInline):
extra = 2
readonly_fields = ['data_pub', ]
class OcorrenciaChangeList(ChangeList):
def get_queryset(self, request):
tmp_params = self.params.copy()
grupo = None
if 'grupo' in self.params:
grupo = self.params['grupo']
del self.params['grupo']
qs = super().get_queryset(request)
self.params = tmp_params.copy()
if grupo:
servidor = Servidor.objects.get(user=request.user)
if grupo == 'S': # Apenas do meu setor
qs = qs.filter(setor_responsavel=servidor.servico)
elif grupo == 'M': # Apenas criados por mim
qs = qs.filter(servidor_registro=servidor)
return qs
@admin.register(Ocorrencia)
class OcorrenciaAdmin(BaseModelAdmin):
class OcorrenciaAdmin(admin.ModelAdmin):
list_display = ('data_criacao', 'casa_legislativa', 'get_municipio',
'get_uf', 'assunto', 'prioridade', 'status',
'data_modificacao', 'setor_responsavel',)
'data_modificacao',)
list_filter = (
OcorrenciaListFilter, 'status', 'prioridade', 'categoria__nome',
'setor_responsavel__nome',
'status', 'prioridade', 'categoria__nome',
('casa_legislativa__gerentes_interlegis', GerentesInterlegisFilter),
('servidor_registro', ServidorRegistroFilter),
)
search_fields = ('casa_legislativa__search_text', 'assunto',
'servidor_registro__nome_completo', 'descricao',
@ -72,13 +52,10 @@ class OcorrenciaAdmin(BaseModelAdmin):
date_hierarchy = 'data_criacao'
fields = ('casa_legislativa', 'categoria', 'tipo_contato', 'assunto',
'status', 'prioridade', 'ticket', 'descricao',
'servidor_registro', 'setor_responsavel', 'resolucao', )
readonly_fields = ('servidor_registro', 'setor_responsavel', )
'servidor_registro', 'resolucao', )
readonly_fields = ('servidor_registro', )
inlines = (ComentarioViewInline, ComentarioInline, AnexosInline, )
raw_id_fields = ('casa_legislativa', )
def get_changelist(self, request, **kwargs):
return OcorrenciaChangeList
autocomplete_fields = ('casa_legislativa', )
def get_fieldsets(self, request, obj=None):
if obj is None:
@ -88,23 +65,20 @@ class OcorrenciaAdmin(BaseModelAdmin):
else:
self.fields = ('casa_legislativa', 'categoria', 'tipo_contato',
'assunto', 'status', 'prioridade', 'ticket',
'descricao', 'servidor_registro',
'setor_responsavel', 'resolucao', )
'descricao', 'servidor_registro', 'resolucao', )
return super().get_fieldsets(request, obj)
def save_model(self, request, obj, form, change):
if not change:
obj.servidor_registro = Servidor.objects.get(user=request.user)
obj.setor_responsavel = obj.categoria.setor_responsavel
obj.save()
def save_formset(self, request, form, formset, change):
servidor = Servidor.objects.get(user=request.user)
instances = formset.save(commit=False)
for instance in instances:
if isinstance(instance, Comentario):
instance.usuario = servidor
instance.usuario = request.user.servidor
instance.save()
super(OcorrenciaAdmin, self).save_formset(request, form, formset,
change)

14
sigi/apps/ocorrencias/filters.py

@ -1,9 +1,16 @@
from django.contrib import admin
from django.utils.translation import gettext as _
from sigi.apps.servidores.models import Servidor
class ServidorRegistroFilter(admin.filters.RelatedFieldListFilter):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
servidores = Servidor.objects.exclude(ocorrencia=None).order_by(
'nome_completo')
self.lookup_choices = [(x.id, x) for x in servidores]
class OcorrenciaListFilter(admin.SimpleListFilter):
title = _('Relacionadas a Mim')
parameter_name = 'minhas'
@ -12,16 +19,13 @@ class OcorrenciaListFilter(admin.SimpleListFilter):
if request.user.servidor is None:
return None
return (
('S', _('Atribuídos ao meu setor')),
('M', _('Registrados por mim')),
('G', _('Sobre casas que gerencio')),
)
def queryset(self, request, queryset):
servidor = request.user.servidor
if self.value() == 'S':
return queryset.filter(setor_responsavel=servidor.servico)
elif self.value() == 'M':
if self.value() == 'M':
return queryset.filter(servidor_registro=servidor)
elif self.value() == 'G':
return queryset.filter(

49
sigi/apps/ocorrencias/forms.py

@ -1,13 +1,16 @@
from django.forms import ModelForm, ModelChoiceField, HiddenInput, TextInput
from django import forms
from sigi.apps.ocorrencias.models import Ocorrencia, Comentario, Anexo
from sigi.apps.servidores.models import Servico
from django.utils.encoding import force_text
from django.utils.encoding import force_str
from django.utils.html import format_html
from django.forms.utils import flatatt
from django.urls import reverse_lazy
from django.utils.safestring import mark_safe
from material.admin.widgets import MaterialAdminTextareaWidget
from django.contrib.admin.widgets import AutocompleteSelect
from django.contrib import admin
class AjaxSelect(TextInput):
class AjaxSelect(forms.TextInput):
url = ""
def __init__(self, url, attrs=None):
super(AjaxSelect, self).__init__(attrs)
@ -20,7 +23,7 @@ class AjaxSelect(TextInput):
code_attrs = self.build_attrs(type='hidden', name=name,
id='hidden_'+name)
if value != '':
final_attrs['value'] = force_text(self._format_value(value))
final_attrs['value'] = force_str(self._format_value(value))
result = format_html('<input{0} />', flatatt(final_attrs)) + "\n"
result = result + format_html('<input{0} />', flatatt(code_attrs))
js = """
@ -38,31 +41,35 @@ class AjaxSelect(TextInput):
result = result + mark_safe(js)
return result
class AnexoForm(ModelForm):
class AnexoForm(forms.ModelForm):
class Meta:
model = Anexo
fields = ['ocorrencia', 'descricao', 'arquivo',]
widgets = {'ocorrencia': HiddenInput()}
class ComentarioForm(ModelForm):
encaminhar_setor = ModelChoiceField(
queryset=Servico.objects.all(),
cache_choices=True
)
widgets = {'ocorrencia': forms.HiddenInput()}
class ComentarioForm(forms.ModelForm):
class Meta:
model = Comentario
fields = ['ocorrencia', 'descricao', 'novo_status', 'encaminhar_setor']
widgets = {'ocorrencia': HiddenInput(),}
fields = ['ocorrencia', 'descricao', 'novo_status',]
widgets = {
'ocorrencia': forms.HiddenInput(),
'descricao': MaterialAdminTextareaWidget(),
}
class OcorrenciaForm(ModelForm):
class OcorrenciaForm(forms.ModelForm):
class Meta:
model = Ocorrencia
fields = ['casa_legislativa', 'categoria', 'tipo_contato', 'assunto',
'prioridade', 'ticket', 'descricao', 'setor_responsavel',]
'prioridade', 'ticket', 'descricao',]
widgets = {
'casa_legislativa': AjaxSelect(
url=reverse_lazy('painel-buscacasa'),
attrs={'size':100}
),
}
'casa_legislativa': AutocompleteSelect(
Ocorrencia.casa_legislativa.field,
admin.site
)
}
# widgets = {
# 'casa_legislativa': AjaxSelect(
# url=reverse_lazy('painel-buscacasa'),
# attrs={'size':100}
# ),
# }

21
sigi/apps/ocorrencias/migrations/0007_remove_comentario_encaminhar_setor_and_more.py

@ -0,0 +1,21 @@
# Generated by Django 4.0.1 on 2022-02-13 13:17
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('ocorrencias', '0006_alter_anexo_arquivo_alter_anexo_descricao_and_more'),
]
operations = [
migrations.RemoveField(
model_name='comentario',
name='encaminhar_setor',
),
migrations.RemoveField(
model_name='ocorrencia',
name='setor_responsavel',
),
]

17
sigi/apps/ocorrencias/migrations/0008_remove_categoria_setor_responsavel.py

@ -0,0 +1,17 @@
# Generated by Django 4.0.1 on 2022-02-13 13:52
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('ocorrencias', '0007_remove_comentario_encaminhar_setor_and_more'),
]
operations = [
migrations.RemoveField(
model_name='categoria',
name='setor_responsavel',
),
]

22
sigi/apps/ocorrencias/models.py

@ -8,11 +8,6 @@ from django.utils.safestring import mark_safe
class Categoria(models.Model):
nome = models.CharField(_("Categoria"), max_length=50)
descricao = models.TextField(_('descrição'), blank=True, null=True)
setor_responsavel = models.ForeignKey(
'servidores.Servico',
on_delete=models.PROTECT,
verbose_name=_("Setor responsável")
)
class Meta:
verbose_name = _('Categoria')
@ -100,11 +95,6 @@ class Ocorrencia(models.Model):
on_delete=models.PROTECT,
verbose_name=_("Servidor que registrou a ocorrência")
)
setor_responsavel = models.ForeignKey(
'servidores.Servico',
on_delete=models.PROTECT,
verbose_name=_("Setor responsável")
)
ticket = models.PositiveIntegerField(
_('Número do ticket'),
blank=True,
@ -157,20 +147,8 @@ class Comentario(models.Model):
blank=True,
null=True
)
encaminhar_setor = models.ForeignKey(
'servidores.Servico',
on_delete=models.PROTECT,
verbose_name=_('Encaminhar para setor'),
blank=True,
null=True
)
def save(self, *args, **kwargs):
if (self.encaminhar_setor
and (self.encaminhar_setor != self.ocorrencia.setor_responsavel)
):
self.ocorrencia.setor_responsavel = self.encaminhar_setor
self.ocorrencia.save()
if self.novo_status and (self.novo_status != self.ocorrencia.status):
self.ocorrencia.status = self.novo_status
self.ocorrencia.save()

198
sigi/apps/ocorrencias/templates/ocorrencias/painel-old.html

@ -0,0 +1,198 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_static %}
{% load static from staticfiles %}
{% load thumbnail %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static 'ocorrencias/css/jquery-ui.min.css' %}"/>
{% endblock %}
{% block extrahead %}
{{ block.super }}
<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.init.js' %}" ></script>
<script type="text/javascript" src="{% static 'ocorrencias/js/jquery-ui.min.js' %}" ></script>
{% endblock %}
{% block coltype %}colMS{% endblock %}
{% block content_title %}<h1>{{ panel_title }}</h1>{% endblock %}
{% block content %}
{% url 'painel-ocorrencias' as url_painel %}
<div id="content-main" class="container-fluid">
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" id="q" placeholder="{% trans 'Visitar o painel de' %}">
<span class="input-group-btn">
<button class="btn btn-default" type="button" onclick="window.location.href='{{ url_painel }}'">{% trans 'Meu painel' %}</button>
</span>
</div>
</div>
<div class="nav nav-pills">
<span class="glyphicon glyphicon-plus"></span>
<a role="button" data-toggle="collapse" href="#form_ocorrencia_panel" aria-expanded="false" aria-controls="form_ocorrencia_panel">
{% trans "Registrar nova ocorrência" %}
</a>
</div>
<div class="collapse panel panel-default" id='form_ocorrencia_panel'>
{% include 'ocorrencias/ocorrencia_form.html' %}
</div>
{% if paineis %}
<ul class="nav nav-pills">
{% for k, v in paineis.iteritems %}
<li role="presentation" class="{% if k == painel %}active{% endif %}">
<a href="{{ url_painel }}?type=servidor&id={{ servidor.id }}&painel={{ k }}">
{{ v }}</a></li>
{% endfor %}
</ul>
{% endif %}
<div class="row">
<div id="ocorrencias_display" class="col-md-12">
{% for ocorrencia in ocorrencias %}
{% include 'ocorrencias/ocorrencia_snippet.html' %}
{% empty %}
<div class="panel panel-default">
<div class="panel-body">
<p>{% trans 'Nenhuma ocorrência encontrada.' %}</p>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
<script type="text/javascript">
$( document ).ready(function() {
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!(/^(GET|HEAD|OPTIONS|TRACE)$/.test(settings.type)) && !this.crossDomain) {
var cookieValue = null, name = 'csrftoken';
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
xhr.setRequestHeader("X-CSRFToken", cookieValue);
}
}
});
$("#q").autocomplete({
source: "{% url 'painel-buscanominal' %}",
select: function(event, ui) {
window.location.replace("{{ url_painel }}?type="+ui.item.origin+"&id="+ui.item.value);
ui.item.value = ui.item.label
}
})
$('input[name^=ocorrencia-]').on('change', function() {
var $this = $(this),
data = {'id_ocorrencia': $this.attr('name').split('-')[1],
'prioridade': $this.attr('value')};
$.post('{% url "ocorrencia-mudaprioridade" %}', data, function(result) {
if (result.result == 'error') {
alert(result.message);
$this.reset();
}
});
})
function inclui_comentario( event ) {
event.preventDefault()
var $this = $(this);
$.post($this.attr('action'), $this.serialize(), function( result ) {
$('div[id=ticket_'+result.ocorrencia_id+']').html(result.ocorrencia_panel);
$('form[id^=comentar_ocorrencia_').on('submit', inclui_comentario);
});
}
function inclui_ocorrencia( event ) {
event.preventDefault()
var $this = $(this);
$.post($this.attr('action'), $this.serialize(), function( result ) {
$("#form_ocorrencia_panel").html(result.ocorrencia_form);
if (result.result == 'success') {
$("#form_ocorrencia_panel").collapse('hide');
$("#ocorrencias_display").prepend(result.ocorrencia_panel);
$('form[id^=comentar_ocorrencia_').on('submit', inclui_comentario);
}
$('#form_ocorrencia').on('submit', inclui_ocorrencia);
});
}
$('form[id^=comentar_ocorrencia_').on('submit', inclui_comentario);
$('#form_ocorrencia').on('submit', inclui_ocorrencia);
});
function remove_anexo(link) {
var $this = $(link),
url = $this.attr('href'),
div = $("div#anexos_"+$this.attr('data-ocorrencia-id')),
link = $("a#link_anexos_"+$this.attr('data-ocorrencia-id'));
$( 'body' ).append('<div id="dialog-confirm" title="{% trans "Excluir anexo?" %}"><p><span class="glyphicon glyphicon-alert" style="float:left; margin:0 7px 20px 0;"></span>{% trans "Este anexo será definitivamente excluído e não poderá ser recuperado. Você confirma a exclusão?" %}</p></div>');
var dialog = $("#dialog-confirm");
dialog.dialog({
resizable: true,
modal: true,
buttons: {
"{% trans 'Excluir' %}": function() {
$.get(url, function(result) {
if (result.result == 'error') {
alert(result.message);
}
if (result.result == 'success') {
div.html(result.anexos_panel);
link.html(result.link_label);
}
});
dialog.dialog( 'destroy' );
},
"{% trans 'Cancelar' %}": function() {
dialog.dialog( 'destroy' );
}
}
});
return false;
}
function dismissAddAnexoPopup(win, ocorrencia_id) {
var div = $("div#anexos_"+ocorrencia_id),
link = $("a#link_anexos_"+ocorrencia_id);
win.close();
$.get('{% url "ocorrencia-anexosnippet" %}?ocorrencia_id='+ocorrencia_id, function( result ) {
div.html(result);
});
}
function showAddAnexoPopup(link) {
var $this = $(link),
href = $this.attr('href'),
win = window.open(href, '', 'height=500,width=800,resizable=yes,scrollbars=yes');
win.focus();
return false;
}
</script>
{% endblock %}

399
sigi/apps/ocorrencias/templates/ocorrencias/painel.html

@ -1,198 +1,211 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_static %}
{% load static from staticfiles %}
{% load thumbnail %}
{% load i18n static admin_urls %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static 'ocorrencias/css/jquery-ui.min.css' %}"/>
{% endblock %}
{% block extrahead %}
{{ block.super }}
<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.init.js' %}" ></script>
<script type="text/javascript" src="{% static 'ocorrencias/js/jquery-ui.min.js' %}" ></script>
{{ block.super }}
<style>
#content {
display: block;
}
.user-image {
width: 64px;
height: 64px;
font-size: 64px !important;
}
commenter-image {
width: 32px;
height: 32px;
font-size: 32px !important;
}
.card-details, .user-name {
font-size: 10px;
}
.priority {
background-color: grey;
}
.priority {
background-color: antiquewhite;
margin-left: 5px;
min-width: 60px;
}
.chip>img {
float: left;
margin: 0 8px 0 -12px;
height: 32px;
width: 32px;
border-radius: 50%;
}
</style>
{% endblock %}
{% block coltype %}colMS{% endblock %}
{% block content_title %}<h1>{{ panel_title }}</h1>{% endblock %}
{% block breadcrumbs %}{% endblock %}
{% block content %}
{% url 'painel-ocorrencias' as url_painel %}
<div id="content-main" class="container-fluid">
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" id="q" placeholder="{% trans 'Visitar o painel de' %}">
<span class="input-group-btn">
<button class="btn btn-default" type="button" onclick="window.location.href='{{ url_painel }}'">{% trans 'Meu painel' %}</button>
</span>
</div>
</div>
<div class="nav nav-pills">
<span class="glyphicon glyphicon-plus"></span>
<a role="button" data-toggle="collapse" href="#form_ocorrencia_panel" aria-expanded="false" aria-controls="form_ocorrencia_panel">
{% trans "Registrar nova ocorrência" %}
</a>
</div>
<div class="collapse panel panel-default" id='form_ocorrencia_panel'>
{% include 'ocorrencias/ocorrencia_form.html' %}
</div>
{% if paineis %}
<ul class="nav nav-pills">
{% for k, v in paineis.iteritems %}
<li role="presentation" class="{% if k == painel %}active{% endif %}">
<a href="{{ url_painel }}?type=servidor&id={{ servidor.id }}&painel={{ k }}">
{{ v }}</a></li>
{% endfor %}
</ul>
{% endif %}
<div class="row">
<div id="ocorrencias_display" class="col-md-12">
{% for ocorrencia in ocorrencias %}
{% include 'ocorrencias/ocorrencia_snippet.html' %}
{% empty %}
<div class="panel panel-default">
<div class="panel-body">
<p>{% trans 'Nenhuma ocorrência encontrada.' %}</p>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
<script type="text/javascript">
$( document ).ready(function() {
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!(/^(GET|HEAD|OPTIONS|TRACE)$/.test(settings.type)) && !this.crossDomain) {
var cookieValue = null, name = 'csrftoken';
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
xhr.setRequestHeader("X-CSRFToken", cookieValue);
}
}
});
$("#q").autocomplete({
source: "{% url 'painel-buscanominal' %}",
select: function(event, ui) {
window.location.replace("{{ url_painel }}?type="+ui.item.origin+"&id="+ui.item.value);
ui.item.value = ui.item.label
}
})
$('input[name^=ocorrencia-]').on('change', function() {
var $this = $(this),
data = {'id_ocorrencia': $this.attr('name').split('-')[1],
'prioridade': $this.attr('value')};
$.post('{% url "ocorrencia-mudaprioridade" %}', data, function(result) {
if (result.result == 'error') {
alert(result.message);
$this.reset();
}
});
})
function inclui_comentario( event ) {
event.preventDefault()
var $this = $(this);
$.post($this.attr('action'), $this.serialize(), function( result ) {
$('div[id=ticket_'+result.ocorrencia_id+']').html(result.ocorrencia_panel);
$('form[id^=comentar_ocorrencia_').on('submit', inclui_comentario);
});
}
function inclui_ocorrencia( event ) {
event.preventDefault()
var $this = $(this);
$.post($this.attr('action'), $this.serialize(), function( result ) {
$("#form_ocorrencia_panel").html(result.ocorrencia_form);
if (result.result == 'success') {
$("#form_ocorrencia_panel").collapse('hide');
$("#ocorrencias_display").prepend(result.ocorrencia_panel);
$('form[id^=comentar_ocorrencia_').on('submit', inclui_comentario);
}
$('#form_ocorrencia').on('submit', inclui_ocorrencia);
});
}
$('form[id^=comentar_ocorrencia_').on('submit', inclui_comentario);
$('#form_ocorrencia').on('submit', inclui_ocorrencia);
});
function remove_anexo(link) {
var $this = $(link),
url = $this.attr('href'),
div = $("div#anexos_"+$this.attr('data-ocorrencia-id')),
link = $("a#link_anexos_"+$this.attr('data-ocorrencia-id'));
$( 'body' ).append('<div id="dialog-confirm" title="{% trans "Excluir anexo?" %}"><p><span class="glyphicon glyphicon-alert" style="float:left; margin:0 7px 20px 0;"></span>{% trans "Este anexo será definitivamente excluído e não poderá ser recuperado. Você confirma a exclusão?" %}</p></div>');
var dialog = $("#dialog-confirm");
dialog.dialog({
resizable: true,
modal: true,
buttons: {
"{% trans 'Excluir' %}": function() {
$.get(url, function(result) {
if (result.result == 'error') {
alert(result.message);
}
if (result.result == 'success') {
div.html(result.anexos_panel);
link.html(result.link_label);
}
});
dialog.dialog( 'destroy' );
},
"{% trans 'Cancelar' %}": function() {
dialog.dialog( 'destroy' );
}
}
});
return false;
}
function dismissAddAnexoPopup(win, ocorrencia_id) {
var div = $("div#anexos_"+ocorrencia_id),
link = $("a#link_anexos_"+ocorrencia_id);
win.close();
$.get('{% url "ocorrencia-anexosnippet" %}?ocorrencia_id='+ocorrencia_id, function( result ) {
div.html(result);
});
}
function showAddAnexoPopup(link) {
var $this = $(link),
href = $this.attr('href'),
win = window.open(href, '', 'height=500,width=800,resizable=yes,scrollbars=yes');
win.focus();
return false;
}
</script>
<div class="row">
<div class="col s12"><h1>{{ panel_title }}</h1></div>
</div>
<div class="row">
<div class="col s12">
{% for id, text in paineis.items %}
<a class="waves-effect waves-light btn-small{% if id != painel %} btn-flat{% endif %}" href="?painel={{ id }}">{{ text }}</a>
{% endfor %}
</div>
</div>
<div class="row">
<div class="col s12">
<button class="waves-effect waves-light btn-small btn-flat modal-trigger" href="#nova_ocorrencia">{% trans "Nova ocorrência" %}</button>
</div>
</div>
<div id="nova_ocorrencia" class="modal">
<div class="modal-content">
<h4>{% trans "Nova ocorrência" %}</h4>
{{ ocorrencia_form }}
</div>
<div class="modal-footer">
<a href="#!" class="modal-close waves-effect waves-green btn-flat">Agree</a>
</div>
</div>
{% for ocorrencia in ocorrencias %}
<div class="row">
<div class="col s12">
<div class="card hoverable">
<div class="card-content">
<span class="card-title">
<a href="{% url "admin:ocorrencias_ocorrencia_change" ocorrencia.id %}"><i class="material-icons right">edit</i></a>
{{ ocorrencia.casa_legislativa.nome }}, {{ ocorrencia.casa_legislativa.municipio.uf.sigla }}
<p class="card-details">
{% blocktrans with data_criacao=ocorrencia.data_criacao tipo_contato=ocorrencia.tipo_contato categoria=ocorrencia.categoria status=ocorrencia.get_status_display %}
Criado em {{ data_criacao }} via {{ tipo_contato }} solicitando {{ categoria }}, com status {{ status }}
{% endblocktrans %}
</p>
<p class="card-details">
<strong>{% trans "Gerentes" %}:</strong>
{% for gerente in ocorrencia.casa_legislativa.gerentes_interlegis.all %}
<div class="chip">
{% if gerente.foto %}
<img src="{{ gerente.foto.url }}">
{% endif %}
<a href="./">{{ gerente.get_apelido }}</a>
</div>
{% endfor %}
</p>
</span>
<div class="row">
<div class="col s3 m1 center-align">
<a href="./">
{% if ocorrencia.servidor_registro.foto %}
<img class="circle user-image" src="{{ MEDIA_URL }}{{ ocorrencia.servidor_registro.foto }}"/>
{% else %}
<i class="material-icons circle user-image">account_circle</i>
{% endif %}
</a>
<span class="user-name">{{ ocorrencia.servidor_registro.get_apelido }}</span>
</div>
<div class="col s9 m11">
<p>{{ ocorrencia.descricao }}</p>
<div>
{% trans "Prioridade" %}: <a class='dropdown-trigger btn-small btn-flat' href='#' data-target='prioridade-{{ ocorrencia.id }}'>{{ ocorrencia.get_prioridade_display }}</a>
<ul id='prioridade-{{ ocorrencia.id }}' class='dropdown-content'>
{% for key, name in PRIORITY_CHOICES %}
{% if key != ocorrencia.prioridade %}
<li><a href="#!">{{ name }}</a></li>
{% endif %}
{% endfor %}
</ul>
<a class="waves-effect waves-light btn-small btn-flat right modal-trigger" href="#modal{{ ocorrencia.id}}">{% blocktranslate count counter=ocorrencia.anexo_set.count %}Um anexo{% plural %}{{ counter }} anexos{% endblocktranslate %}</a>
<div id="modal{{ ocorrencia.id}}" class="modal">
<div class="modal-content">
<h4>Anexos</h4>
<ul class="collection">
{% for anexo in ocorrencia.anexo_set.all %}
<li class="collection-item">
<div>
<a href="{{ anexo.arquivo.url }}" download>{{ anexo.data_pub|date:"SHORT_DATE_FORMAT" }} | {{ anexo.descricao }}</a>
<a href="#!" class="secondary-content"><i class="material-icons">delete_forever</i></a>
</div>
</li>
{% endfor %}
</ul>
</div>
<div class="modal-footer">
<a href="#!" class="modal-close waves-effect waves-green btn-flat">Agree</a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card-content">
<ul class="collection">
<li class="collection-item avatar">
{% if usuario.foto %}
<img class="circle commenter-image" src="{{ MEDIA_URL }}{{ servidor_registro.foto }}"/>
{% else %}
<i class="material-icons circle">account_circle</i>
{% endif %}
<form class="row" id="comentar_ocorrencia_{{ ocorrencia.id|safe }}" action="#!" method="post" data-ocorrencia-id="{{ ocorrencia.id|safe }}">
{% csrf_token %}
<p>{% trans "Comentar" %}:</p>
{% for field in comentario_form %}
{% if field.name == 'ocorrencia' %}
<input type='hidden' name='ocorrencia' value='{{ ocorrencia.id|safe }}'/>
{% elif field.name == 'novo_status' %}
<div class="input-field col m4 s12">
<select name="novo_status" id="id_novo_status_{{ ocorrencia.id|safe }}" class="browser-default">
{% for value, label in field.field.widget.choices %}
{% if value == '' %}
<option value="{{ value|stringformat:'s' }}">{{ label }}</option>
{% elif value != 1 %}
{% if ocorrencia.status < 3 and value > 2 %}
<option value="{{ value|stringformat:'s' }}">{{ label }}</option>
{% endif %}
{% if ocorrencia.status > 2 and value == 2 %}
<option value="{{ value|stringformat:'s' }}">{{ label }}</option>
{% endif %}
{% endif %}
{% endfor %}
</select>
</div>
{% else %}
<div class="input-field col m8 s12">
{{ field }}
</div>
{% endif %}
{% endfor %}
<button type="submit" class="secondary-content"><i class="material-icons">send</i></button>
</form>
</li>
{% for comentario in ocorrencia.comentarios.all %}
<li class="collection-item avatar">
{% if comentario.usuario.foto %}
<img class="circle" src="{{ MEDIA_URL }}{{ comentario.usuario.foto }}"/>
{% else %}
<i class="material-icons circle ">account_circle</i>
{% endif %}
<p>{% blocktranslate with data=comentario.data_criacao nome=comentario.usuario.get_apelido %}
Em {{ data }}, {{ nome }} disse:
{% endblocktranslate %}</p>
<span class="title">{{ comentario.descricao }}</span>
{% if comentario.novo_status %}
<p>{% blocktranslate with status=comentario.get_novo_status_display|default:"-" %}
Status: {{ status }}
{% endblocktranslate %}</p>
{% endif %}
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
</div>
{% endfor %}
{% endblock %}
{% block footer %}
{{ block.super }}
<script>
$(document).ready(function(){
var elems = document.querySelectorAll('.dropdown-trigger');
var instances = M.Dropdown.init(elems, {});
var elems = document.querySelectorAll('.modal');
var instances = M.Modal.init(elems, {});
});
</script>
{% endblock %}

49
sigi/apps/ocorrencias/urls.py

@ -1,19 +1,30 @@
# coding: utf-8
from django.conf.urls import patterns, url
urlpatterns = patterns(
'sigi.apps.ocorrencias.views',
# Painel de ocorrencias
url(r'^painel/$', 'painel_ocorrencias', name='painel-ocorrencias'),
url(r'^painel/buscanominal/$', 'busca_nominal', {"origin": "tudo"}, name='painel-buscanominal'),
url(r'^painel/buscanominal/casa/$', 'busca_nominal', {"origin": "casa"}, name='painel-buscacasa'),
url(r'^painel/buscanominal/servidor/$', 'busca_nominal', {"origin": "servidor"}, name='painel-buscaservidor'),
url(r'^painel/buscanominal/servico/$', 'busca_nominal', {"origin": "servico"}, name='painel-buscaservico'),
url(r'^mudaprioridade/$', 'muda_prioridade', name='ocorrencia-mudaprioridade'),
url(r'^excluianexo/$', 'exclui_anexo', name='ocorrencia-excluianexo'),
url(r'^incluianexo/$', 'inclui_anexo', name='ocorrencia-incluianexo'),
url(r'^anexosnippet/$', 'anexo_snippet', name='ocorrencia-anexosnippet'),
url(r'^incluicomentario/$', 'inclui_comentario', name='ocorrencia-incluicomentario'),
url(r'^incluiocorrencia/$', 'inclui_ocorrencia', name='ocorrencia-incluiocorrencia'),
)
from django.urls import path
from sigi.apps.ocorrencias.views import painel_ocorrencias
urlpatterns = [
path('painel/', painel_ocorrencias, name='painel-ocorrencias'),
]
# # coding: utf-8
# from django.conf.urls import patterns, url
# urlpatterns = patterns(
# 'sigi.apps.ocorrencias.views',
# # Painel de ocorrencias
# url(r'^painel/$', 'painel_ocorrencias', name='painel-ocorrencias'),
# url(r'^painel/buscanominal/$', 'busca_nominal', {"origin": "tudo"}, name='painel-buscanominal'),
# url(r'^painel/buscanominal/casa/$', 'busca_nominal', {"origin": "casa"}, name='painel-buscacasa'),
# url(r'^painel/buscanominal/servidor/$', 'busca_nominal', {"origin": "servidor"}, name='painel-buscaservidor'),
# url(r'^painel/buscanominal/servico/$', 'busca_nominal', {"origin": "servico"}, name='painel-buscaservico'),
# url(r'^mudaprioridade/$', 'muda_prioridade', name='ocorrencia-mudaprioridade'),
# url(r'^excluianexo/$', 'exclui_anexo', name='ocorrencia-excluianexo'),
# url(r'^incluianexo/$', 'inclui_anexo', name='ocorrencia-incluianexo'),
# url(r'^anexosnippet/$', 'anexo_snippet', name='ocorrencia-anexosnippet'),
# url(r'^incluicomentario/$', 'inclui_comentario', name='ocorrencia-incluicomentario'),
# url(r'^incluiocorrencia/$', 'inclui_ocorrencia', name='ocorrencia-incluiocorrencia'),
# )

143
sigi/apps/ocorrencias/views.py

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from django.http import JsonResponse, Http404
from django.db.models import Q, Count
from django.utils.translation import ungettext, gettext as _
from django.utils.translation import ngettext, gettext as _
from django.shortcuts import get_object_or_404, render, HttpResponse
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_POST
@ -17,87 +17,92 @@ from django.utils.html import escape
@login_required
def painel_ocorrencias(request):
tipo = request.GET.get('type', None)
id = request.GET.get('id', None)
painel = request.GET.get('painel', None)
id_servidor = request.GET.get('servidor', None)
id_casa = request.GET.get('casa', None)
page = int(request.GET.get('page', '0'))
paineis = {
'gerente': _("Casas que gerencio"),
'registro': _("Ocorrências registrados por mim"),
'tudo': _("Todas as ocorrências")
}
if id_servidor is None:
servidor = request.user.servidor
else:
servidor = get_object_or_404(Servidor, id=id_servidor)
data = {}
if tipo is None or tipo == 'error':
tipo = 'servidor'
u = get_object_or_404(Servidor, user=request.user)
id = u.pk
if id is None:
raise Http404("id não definido")
if id_casa is not None:
casa = get_object_or_404(Orgao, id=id_casa)
painel = 'tudo'
panel_title = _(f"Ocorrências da {casa.nome}, {casa.municipio.uf.nome}")
else:
casa = None
if servidor:
is_gerente = servidor.casas_que_gerencia.exists()
is_registrador = (servidor.ocorrencia_set.exists() or
servidor.comentario_set.exists())
panel_title = servidor.nome_completo
else:
is_gerente = False
is_registrador = False
panel_title = _('Todas as ocorrências')
if (servidor is None) or (not is_gerente and not is_registrador):
painel = 'tudo'
elif not is_gerente and is_registrador:
painel = 'registro'
elif is_gerente:
if painel is None:
painel = 'gerente'
if tipo == 'casa':
casa = get_object_or_404(Orgao, pk=id)
ocorrencias = casa.ocorrencia_set.all()
panel_title = "{casa}, {uf}".format(
casa=casa.nome,
uf=casa.municipio.uf.sigla
if painel == 'gerente':
ocorrencias = Ocorrencia.objects.filter(
casa_legislativa__gerentes_interlegis=servidor)
elif painel == 'registro':
ocorrencias = (
Ocorrencia.objects.filter(servidor_registro=servidor) |
Ocorrencia.objects.filter(comentarios__usuario=servidor)
)
elif tipo == 'servidor':
servidor = get_object_or_404(Servidor, pk=id)
panel_title = servidor.nome_completo
paineis = {'gerente': "Minhas casas", 'servico': "Meu setor",
'timeline': "Comentados por mim"}
if painel is None:
if Orgao.objects.filter(
gerentes_interlegis=servidor).count() > 0:
painel = 'gerente'
elif Ocorrencia.objects.filter(
setor_responsavel=servidor.servico).count() > 0:
painel = 'servico'
else:
painel = 'timeline'
data.update({'paineis': paineis, 'painel': painel,
'servidor': servidor})
if painel == 'gerente':
ocorrencias = Ocorrencia.objects.filter(
casa_legislativa__gerentes_interlegis=servidor)
elif painel == 'servico':
ocorrencias = Ocorrencia.objects.filter(
setor_responsavel_id=servidor.servico_id)
else:
ocorrencias = (
Ocorrencia.objects.filter(servidor_registro=servidor) |
Ocorrencia.objects.filter(comentarios__usuario=servidor)
)
elif tipo == 'servico':
servico = get_object_or_404(Servico, pk=id)
ocorrencias = servico.ocorrencia_set.all()
panel_title = _("{sigla} - {nome}").format(
sigla=servico.sigla, nome=servico.nome)
else: # Tudo...
if casa is None: # ...de todas as Casas...
ocorrencias = Ocorrencia.objects.all()
else: # ... ou da Casa escolhida
ocorrencias = casa.ocorrencia_set.all()
ocorrencias = ocorrencias.filter(status__in=[1, 2])
ocorrencias = ocorrencias.order_by('prioridade', '-data_modificacao')
ocorrencias = ocorrencias.select_related(
'casa_legislativa', 'categoria', 'tipo_contato', 'servidor_registro',
'setor_responsavel', 'casa_legislativa__gerentes_interlegis'
'casa_legislativa', 'casa_legislativa__municipio',
'casa_legislativa__municipio__uf', 'categoria', 'tipo_contato',
'servidor_registro',
)
ocorrencias = ocorrencias.prefetch_related(
'comentarios', 'comentarios__usuario', 'comentarios__encaminhar_setor',
'casa_legislativa__municipio', 'casa_legislativa__municipio__uf',
'anexo_set'
'comentarios', 'comentarios__usuario', 'anexo_set',
'casa_legislativa__gerentes_interlegis'
)
ocorrencias = ocorrencias.annotate(total_anexos=Count('anexo'))
data.update(
{'ocorrencias': ocorrencias,
'panel_title': panel_title,
'comentario_form': ComentarioForm(),
'ocorrencia_form': OcorrenciaForm(),
'PRIORITY_CHOICES': Ocorrencia.PRIORITY_CHOICES
}
)
if page * 100 > ocorrencias.count():
ocorrencias = ocorrencias[-100]
else:
ocorrencias = ocorrencias[page * 100:page * 100 + 100]
context = {
'paineis': paineis,
'painel': painel,
'servidor': servidor,
'casa': casa,
'ocorrencias': ocorrencias,
'panel_title': panel_title,
'comentario_form': ComentarioForm(),
'ocorrencia_form': OcorrenciaForm(),
'PRIORITY_CHOICES': Ocorrencia.PRIORITY_CHOICES
}
return render(request, 'ocorrencias/painel.html', data)
return render(request, 'ocorrencias/painel.html', context)
@login_required
def busca_nominal(request, origin="tudo"):
@ -161,7 +166,7 @@ def exclui_anexo(request):
ocorrencia = anexo.ocorrencia
anexo.delete()
link_label = (ungettext('%s arquivo anexo', '%s arquivos anexos', ocorrencia.anexo_set.count()) %
link_label = (ngettext('%s arquivo anexo', '%s arquivos anexos', ocorrencia.anexo_set.count()) %
(ocorrencia.anexo_set.count(),))
painel = render_to_string('ocorrencias/anexos_snippet.html', {'ocorrencia': ocorrencia},

1
sigi/apps/parlamentares/templates/admin/parlamentares/parlamentar/change_form.html

@ -1 +0,0 @@
{% extends "change_form_with_report_and_labels.html" %}

7
sigi/apps/servidores/models.py

@ -71,6 +71,13 @@ class Servidor(models.Model):
Servidor.objects.filter(user=self.user).update(user=None)
return super(Servidor, self).save(*args, **kwargs)
def get_apelido(self):
if self.apelido:
return self.apelido
else:
nomes = self.nome_completo.split(' ')
return nomes[0]
# Soluçao alternativa para extender o usuário do django
# Acessa do servidor de um objeto user criando um profile
# baseado nos dados do LDAP

3
sigi/apps/utils/__init__.py

@ -32,7 +32,8 @@ def to_ascii(txt, codif='utf-8'):
txt = force_str(txt)
if isinstance(txt, str):
txt = txt.encode('utf-8')
return normalize('NFKD', txt.decode(codif)).encode('ASCII', 'ignore')
return normalize('NFKD', txt.decode(codif)).encode(
'ASCII', 'ignore').decode(codif)
def queryset_ascii(self, request):

7
sigi/settings/base.py

@ -69,6 +69,7 @@ TEMPLATES = [
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'django.template.context_processors.media',
],
},
},
@ -102,6 +103,12 @@ STATIC_URL = 'static/'
STATICFILES_DIRS = [BASE_DIR / "static",]
STATIC_ROOT = '/var/www/sigi/static/'
# Media files
# https://docs.djangoproject.com/en/4.0/topics/files/#managing-files
MEDIA_ROOT = BASE_DIR / '../media'
MEDIA_URL = "media/"
# Default primary key field type
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field

2
sigi/settings/menu_conf.yaml

@ -48,7 +48,7 @@ main_menu:
icon: comment
children:
- title: Painel de ocorrências
view_name:
view_name: painel-ocorrencias
- title: Registro de ocorrências
view_name: admin:ocorrencias_ocorrencia_changelist
querystr: minhas=S&status__in=1,2

37
sigi/static/css/dashboard.css

@ -0,0 +1,37 @@
table.servicos {
width: 100%;
}
table.numeros>tbody>tr>td {
text-align: right;
}
.app>.card>.card-content>.card-title {
font-size: 16px;
font-weight: bolder;
}
.full-preloader {
width: 100%;
height: 100%;
background-color: rgb(255,255,255,0.8);
position: absolute;
z-index: 2;
display: flex;
align-items: center;
justify-content: space-around;
}
.user_thumb {
width: 24px;
height: 24px;
margin-right: 1rem;
}
.gerente_selector {
width: 100%;
border: none;
}
.card-links {
padding: 0 24px;
}

BIN
sigi/static/img/ilsombra.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

72
sigi/static/js/dashboard.js

@ -0,0 +1,72 @@
$(document).ready(function () {
Chart.defaults.plugins.legend.labels.usePointStyle = true;
setlinks();
$("div[data-source]").each(function(index, container) {
var container = $(container);
var url = container.attr('data-source');
get_content(container, url);
});
$("canvas[data-source]").each(function(index, canvas) {
var canvas = $(canvas)
var url = canvas.attr("data-source");
plot_chart(canvas, url);
});
});
function setlinks() {
$('.modal').modal();
$('.dropdown-trigger').dropdown();
$('.collapsible').collapsible();
$("a[data-target]").off('click').on('click', function(e) {
e.preventDefault();
var $this = $(this);
var target = $("#"+$this.attr('data-target'));
var url = $this.attr('href');
if (target.is("canvas")) {
plot_chart(target, url);
} else if (target.is("div")) {
get_content(target, url);
}
});
}
function get_content(container, url) {
container.closest('.card').find('.full-preloader').removeClass('hide');
$.get(url, function(data) {
container.html(data);
container.closest('.card').find('.full-preloader').addClass('hide');
setlinks();
}).fail(function() {
container.closest('.card').find('.full-preloader').html("Ocorreu um erro. Tente recarregar a página");
});
}
function plot_chart(canvas, url) {
canvas.closest('.card').find('.full-preloader').removeClass('hide');
$.get(url, function(data) {
var chart_name = canvas.attr("data-chart-name");
var has_action_links = canvas.attr("data-has-action-links");
var new_canvas = $(canvas.clone()).insertBefore(canvas);
canvas.remove();
canvas = new_canvas;
canvas.removeClass("hide");
var ctx = canvas.get(0).getContext("2d");
var myChart = new Chart(ctx, data);
if (has_action_links) {
if (data.actionblock) {
$(`#${chart_name}-action-links`).html(data.actionblock).removeClass("hide");
} else {
$(`#${chart_name}-previlink`).attr('href', data.prevlink);
$(`#${chart_name}-nextlink`).attr('href', data.nextlink);
$(`#${chart_name}-action-links`).removeClass("hide");
}
}
setlinks();
canvas.closest('.card').find('.full-preloader').addClass('hide');
}).fail(function() {
canvas.closest('.card').find('.full-preloader').html("Ocorreu um erro. Tente recarregar a página");
});
}

29
sigi/templates/admin/base_site.html

@ -0,0 +1,29 @@
{% extends "admin/base_site.html" %}
{% load static i18n %}
{% block theme %}
<link rel="stylesheet" type="text/css" href="{% static 'material/admin/css/base_site-green.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'material/admin/css/base_site-theme.min.css' %}">
{% endblock %}
{% block userlinks %}
{% block welcome-msg %}{% endblock %}
{% if site_url %}
<a href="{{ site_url }}">{% trans 'Mapa' %}</a>
{% endif %}
{% if user.is_active and user.is_staff %}
{% url 'django-admindocs-docroot' as docsroot %}
{% if docsroot %}
<a href="{{ docsroot }}">{% trans 'Documentation' %}</a>
{% endif %}
{% endif %}
{% if user.has_usable_password %}
<a href="{% url 'admin:password_change' %}">
{% trans 'Change password' %}
</a>
{% endif %}
<a href="{% url 'admin:logout' %}">
{% trans 'Log out' %}
<i class="material-icons" aria-hidden="true">exit_to_app</i>
</a>
{% endblock %}

152
sigi/templates/admin/change_list.html

@ -8,16 +8,71 @@
.side-wrapper {
width: 100%;
}
</style>
<style>
#changelist {
width:100%
}
}
.float-filter {
right: 0;
left: auto;
position: fixed;
width: 300px;
top: 0;
margin: 0;
height: calc(100% + 60px);
padding-bottom: 60px;
background-color: #fff;
z-index: 999;
overflow-y: auto;
will-change: transform;
backface-visibility: hidden;
}
</style>
{% endblock extrastyle %}
{% block breadcrumbs %}{% endblock %}
{% block object-tools %}
<div class="fixed-action-btn">
<a class="btn-floating btn-large">
<i class="large material-icons">build</i>
</a>
<ul>
{% block object-tools-items %}
<li>
<a href="#" data-target="float-filter" class="btn-floating tooltipped waves-effect waves-light sidenav-trigger" data-position="left" data-tooltip="{% trans 'Filter' %}">
<i class="material-icons" aria-hidden="true">filter_list</i>
</a>
</li>
{% if has_add_permission %}
<li>
{% url cl.opts|admin_urlname:'add' as add_url %}
<a href="{% add_preserved_filters add_url is_popup to_field %}" class="btn-floating tooltipped waves-effect waves-light" data-position="left" data-tooltip="{% trans 'Add' %}">
<i class="material-icons" aria-hidden="true">add</i>
</a>
</li>
{% endif %}
{% endblock %}
</ul>
</div>
{% endblock %}
{% block side_wrapper %}
<div id="float-filter" class="float-filter hide">
<div id="side-wrapper" class="side-wrapper">
<div id="changelist-form" class="card">
{% if action_form and actions_on_top and cl.show_admin_actions %}{% admin_actions %}{% endif %}
</div>
<div class="card">
{% block search %}{% search_form cl %}{% endblock %}
</div>
<div class="card">
{% block filters %}
{{ block.super }}
{% endblock %}
</div>
</div>
</div>
{% endblock %}
{% block footer %}
{{ block.super }}
@ -25,84 +80,17 @@
$(document).ready(function(){
$('.fixed-action-btn').floatingActionButton();
M.Tooltip.init($('.tooltipped'), {});
});
</script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var elems = document.getElementById('filter');
var instances = M.Sidenav.init(elems,'');
// M.Sidenav.init($("#filter"), {edge: 'right'});
$('.float-filter').each(function() {
var id=this.id;
$(`[data-target="${id}"]`).on("click", function(e) {
e.preventDefault();
console.log('Rodou aqui também');
var targetid = $(this).attr('data-target');
$(`#${targetid}`).toggleClass('hide');
});
});
});
</script>
{% endblock footer %}
{% block content %}
<div id="content-main" class="list-content">
{% block object-tools %}
<div class="fixed-action-btn">
<a class="btn-floating btn-large">
<i class="large material-icons">build</i>
</a>
<ul>
<li>
<a href="{% add_preserved_filters add_url is_popup to_field %}" data-target="filter" class="btn-floating tooltipped waves-effect waves-light sidenav-trigger" data-position="left" data-tooltip="{% trans 'Filter' %}">
<i class="material-icons" aria-hidden="true">filter_list</i>
</a>
</li>
{% block object-tools-items %}
{% if has_add_permission %}
<li>
{% url cl.opts|admin_urlname:'add' as add_url %}
<a href="{% add_preserved_filters add_url is_popup to_field %}" class="btn-floating tooltipped waves-effect waves-light" data-position="left" data-tooltip="{% trans 'Add' %}">
<i class="material-icons" aria-hidden="true">add</i>
</a>
</li>
{% endif %}
{% endblock %}
</ul>
</div>
{% endblock %}
{% if cl.formset.errors %}
<p class="errornote">
{% if cl.formset.total_error_count == 1 %}{% trans "Please correct the error below." %}{% else %}{% trans "Please correct the errors below." %}{% endif %}
</p>
{{ cl.formset.non_form_errors }}
{% endif %}
<div class="module{% if cl.has_filters %} filtered{% endif %}" id="changelist">
{% block date_hierarchy %}{% date_hierarchy cl %}{% endblock %}
<form id="changelist-form" method="post"{% if cl.formset.is_multipart %} enctype="multipart/form-data"{% endif %} novalidate>{% csrf_token %}
{% if cl.formset %}
<div>{{ cl.formset.management_form }}</div>
{% endif %}
{% block result_list %}
{% result_list cl %}
{% if action_form and actions_on_bottom and cl.show_admin_actions %}{% admin_actions %}{% endif %}
{% endblock %}
{% block pagination %}{% pagination cl %}{% endblock %}
</form>
</div>
<ul id="filter" class="sidenav">
<div id="side-wrapper" class="side-wrapper">
<div id="changelist-form" class="card">
{% if action_form and actions_on_top and cl.show_admin_actions %}{% admin_actions %}{% endif %}
</div>
<div class="card">
{% block search %}{% search_form cl %}{% endblock %}
</div>
<div class="card">
{% block filters %}
{% if cl.has_filters %}
<div class="card-content" id="changelist-filter">
<label class="label">{% trans 'Filter' %}</label>
{% for spec in cl.filter_specs %}{% admin_list_filter cl spec %}{% endfor %}
</div>
{% endif %}
{% endblock %}
</div>
</div>
</ul>
</div>
{% endblock %}

21
sigi/templates/material/admin/index.html

@ -1,6 +1,21 @@
{% extends "admin/index.html" %}
{% load static %}
{% load static i18n %}
{% block content %}
{% include 'sigi/snippets/dashboard.html' %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static 'css/dashboard.css' %}">
{% endblock %}
{% block extrahead %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js" integrity="sha512-QSkVNOCYLtj73J4hbmVoOV6KVZuMluZlioC+trLpewV8qMjsWqlIQvkn1KGX2StWvPMdWGBqim1xlC8krl1EKQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
{{ block.super }}
{% endblock %}
{% block content %}
{% include 'sigi/snippets/dashboard.html' %}
{% endblock %}
{% block footer %}
{{ block.super }}
<script src="{% static 'js/dashboard.js' %}"></script>
{% endblock footer %}

44
sigi/templates/material/admin/side_nav.html

@ -1,31 +1,21 @@
{% load i18n material menus %}
<div class="scroll-pane">
{% if not mobile %}
<i class="material-icons minimize nav-bar" aria-hidden="true" title="{% trans 'Minimize' %}">close</i>
{% endif %}
{% if available_apps %}
<ul class="collapsible">
<li>
<div class="card">
<div class="card-image">
{% if 'profile/user_picture.html'|template_exists %}
{% include 'profile/user_picture.html' %}
{% else %}
{% include 'material/admin/user_picture.html' %}
{% endif %}
</div>
</div>
</li>
{% show_menu 'main_menu' %}
</ul>
{% else %}
<div class="app">
<div class="card">
<div class="card-content">
<p>{% trans "You don't have permission to view or edit anything." %}</>
</div>
</div>
</div>
{% endif %}
{% if not mobile %}
<i class="material-icons minimize nav-bar" aria-hidden="true" title="{% trans 'Minimize' %}">close</i>
{% endif %}
<ul class="collapsible">
<li>
<div class="card">
<div class="card-image">
{% if 'profile/user_picture.html'|template_exists %}
{% include 'profile/user_picture.html' %}
{% else %}
{% include 'material/admin/user_picture.html' %}
{% endif %}
</div>
</div>
</li>
{% show_menu 'main_menu' %}
</ul>
</div>

21
sigi/templates/material/admin/user_picture.html

@ -0,0 +1,21 @@
{% load static %}
{% block user_profile %}
{% if user.servidor.foto %}
<img class="login-logo" alt="login logo" src="{{ user.servidor.foto.url }}">
{% elif profile_picture %}
<img class="login-logo" alt="login logo" src="{{ profile_picture }}">
{% else %}
<img class="login-logo" alt="login logo" src="{% static 'material/admin/images/login-logo-'|add:current_theme|add:'.jpg' %}">
{% endif %}
{% if profile_bg %}
<img width="300" height="212" alt="profile background" src="{{ profile_bg }}">
{% else %}
<img src="{% static 'material/admin/images/login-bg-'|add:current_theme|add:'.jpg' %}" alt="profile background">
{% endif %}
<div class="card-title">
<strong>{% firstof user.get_short_name user.username|default_if_none:'' %}</strong><br>
<small>{{ user.email|default_if_none:'' }}</small>
</div>
{% endblock %}

11
sigi/templates/pdf/base_report.html

@ -41,6 +41,15 @@ tr:nth-child(even) {
.title_row {
background-color: #b2b2b2;
}
.right-align {
text-align: right;
}
ul {
list-style-type: none;
margin: 0px;
padding: 0px;
}
{% endblock extra_style %}
{% block body_content %}
@ -48,7 +57,7 @@ tr:nth-child(even) {
<p>{% trans 'SENADO FEDERAL' %}</p>
<p>{% trans 'Instituto Legislativo Brasileiro - ILB' %}</p>
<p>{% trans "INTERLEGIS" %}</p>
<p class="report_name">{{ title|upper }}</p>{% endblock header %}
<p class="report_name">{% block report_name %}{{ title|upper }}{% endblock report_name %}</p>{% endblock header %}
</header>
<footer>{% block footer %}

27
sigi/templates/sigi/snippets/base_card.html

@ -0,0 +1,27 @@
{% load i18n %}
<div class="app">
<div class="card">
<div class="full-preloader valign-wrapper">
<div class="center">
<div class="preloader-wrapper active">
<div class="spinner-layer spinner-green-only">
<div class="circle-clipper left">
<div class="circle"></div>
</div><div class="gap-patch">
<div class="circle"></div>
</div><div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
</div>
</div>
</div>
<div class="card-content">
<div class="card-title">{% block card-title %}{% translate card_title|default:"" %}{% endblock %}</div>
<div class="card-content-wrapper">
{% block card-content %}{% endblock card-content %}
</div>
</div>
</div>
</div>

18
sigi/templates/sigi/snippets/base_card_chart.html

@ -0,0 +1,18 @@
{% extends "sigi/snippets/base_card.html" %}
{% load i18n %}
{% block card-content %}
{% if has_action_links %}
{% block action-links %}
<div id="{{ chart_name }}-action-links" class="card-links hide">
<a id="{{ chart_name }}-previlink" class="waves-effect waves-light btn-small btn-flat btn-floating left" href="#" data-target="{{ chart_name }}-chart">
<i class="material-icons left">chevron_left</i>
</a>
<a id="{{ chart_name }}-nextlink" class="waves-effect waves-light btn-small btn-flat btn-floating right" href="#" data-target="{{ chart_name }}-chart">
<i class="material-icons right">chevron_right</i>
</a>
</div>
{% endblock action-links %}
{% endif %}
<canvas id="{{ chart_name }}-chart" data-source="{{ data_source }}" data-chart-name="{{ chart_name }}" data-has-action-links="{{ has_action_links }}"></canvas>
{% endblock card-content %}

8
sigi/templates/sigi/snippets/base_card_text.html

@ -0,0 +1,8 @@
{% extends "sigi/snippets/base_card.html" %}
{% load i18n %}
{% block card-content %}
<div id="card-{{ card_name }}" data-source="{% block data-source %}{{ data_source }}{% endblock %}">
<p>{% trans "Carregando conteúdo..." %}</p>
</div>
{% endblock card-content %}

57
sigi/templates/sigi/snippets/dashboard.html

@ -2,45 +2,22 @@
<div class="content-wrapper">
<div class="app-list">
{% if app_list %}
{% for app in app_list %}
<div class="app">
<div class="card">
<div class="card-content">
<div class="card-title">
{{ app.name }}
</div>
<div class="row">
{% for model in app.models %}
<div class="app-item col s6 m6 l4">
<a {% if model.admin_url %}href="{{ model.admin_url }}"{% else %}class="disabled"{% endif %}>
{% if model.count != None %}
<div class="card app-count-badge">
<div class="badge-content">
{{ model.count }}
</div>
</div>
{% endif %}
<i class="material-icons" aria-hidden="true">
{{ model.icon|default_if_none:'settings' }}
</i>
<h6 class="card-app-name">{{ model.name }}</h6>
</a>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
{% endfor %}
{% else %}
<div class="app">
<div class="card">
<div class="card-content">
<p>{% trans "You don't have permission to view or edit anything." %}</p>
</div>
</div>
</div>
{% endif %}
{% url "home_resumoseit" as source_url %}
{% include "sigi/snippets/base_card_text.html" with card_title="Serviços hospedados no Interlegis (SEIT)" data_source=source_url card_name="resumoseit" %}
{% url "home_chartseit" as source_url %}
{% include "sigi/snippets/base_card_chart.html" with card_title="Sazonalidade da hospedagem de serviços" data_source=source_url chart_name="evolucao-servicos" has_action_links="1" %}
{% url "casas-carteira" as source_url %}
{% include "sigi/snippets/base_card_text.html" with card_title="Resumo da carteira de relacionamentos" data_source=source_url|add:"?snippet=resumo&s=sim" card_name="carteira" %}
{% url "home_chartperformance" as source_url %}
{% include "sigi/snippets/base_card_chart.html" with card_title="Performance da gerência de carteiras" data_source=source_url chart_name="performance" has_action_links="1" %}
{% url "home_chartcarteira" as source_url %}
{% include "sigi/snippets/base_card_chart.html" with card_title="Distribuição de Casas por Gerente" data_source=source_url chart_name="carteira" %}
{% url "home_resumoconvenios" as source_url %}
{% include "sigi/snippets/base_card_text.html" with card_title="Resumo de informações" data_source=source_url card_name="resumo-convenios" %}
</div>
</div>

7
sigi/urls.py

@ -16,14 +16,19 @@ Including another URLconf
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/casas/', include('sigi.apps.casas.urls')),
path('admin/convenios/', include('sigi.apps.convenios.urls')),
path('admin/ocorrencias/', include('sigi.apps.ocorrencias.urls')),
path('admin/eventos/', include('sigi.apps.eventos.urls')),
path('admin/', admin.site.urls),
path('tinymce/', include('tinymce.urls')),
path('', include('sigi.apps.home.urls')),
]
if settings.DEBUG:
urlpatterns = urlpatterns + [
path('__debug__/', include('debug_toolbar.urls'))
]
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

63
sigiStatic/js/dashboard.js

@ -1,63 +0,0 @@
$(document).ready(function () {
setlinks();
$("div[data-source]").each(function(index, container) {
var container = $(container);
var url = container.attr('data-source');
get_content(container, url);
});
$("canvas[data-source]").each(function(index, canvas) {
var canvas = $(canvas)
var url = canvas.attr("data-source");
plot_chart(canvas, url);
});
});
function setlinks() {
$("a[data-target]").off('click').on('click', function(e) {
e.preventDefault();
var $this = $(this);
var target = $("#"+$this.attr('data-target'));
var url = $this.attr('href');
if (target.is("canvas")) {
plot_chart(target, url);
} else if (target.is("div")) {
get_content(target, url);
}
});
}
function get_content(container, url) {
$.get(url, function(data) {
container.html(data);
setlinks();
});
}
function plot_chart(canvas, url) {
$.get(url, function(data) {
var new_canvas = $(canvas.clone()).insertBefore(canvas);
canvas.remove();
canvas = new_canvas;
var ctx = canvas.get(0).getContext("2d");
if (data.type == 'pie') {
var myChart = new Chart(ctx).Pie(data.data, data.options);
} else if (data.type == 'line') {
var myChart = new Chart(ctx).Line(data.data, data.options);
} else if (data.type == 'bar') {
var myChart = new Chart(ctx).Bar(data.data, data.options);
}
if (canvas.is("[data-legend-id]")) {
var legend_container = $("#"+canvas.attr("data-legend-id"));
legend_container.html(myChart.generateLegend());
}
if (canvas.is("[data-prevlink-id]")) {
var prevlink = $("#"+canvas.attr("data-prevlink-id"));
prevlink.attr('href', data.prevlink);
}
if (canvas.is("[data-nextlink-id]")) {
var nextlink = $("#"+canvas.attr("data-nextlink-id"));
nextlink.attr('href', data.nextlink);
}
});
}

38
templates/snippets/modules/resumo_seit.html

@ -1,38 +0,0 @@
{% load static from staticfiles %}
{% load i18n %}
<div class="panel panel-primary flex-col">
<div class="panel-heading">{% trans 'Serviços hospedados no Interlegis (SEIT)' %}</div>
<div class="panel-body">
<table class="table table-condensed numeros servicos">
<tr>
{% for s in tabela_resumo_seit.titulos %}
<th>{{ s }}</th>
{% endfor %}
</tr>
{% for servico in tabela_resumo_seit.servicos %}
<tr>
<th class="dropdown">
<a id="ddm-{{ servico.nome }}" data-toggle="dropdown" href="#">{{ servico.nome }}</a>
<table class="table table-condensed numeros servicos dropdown-menu" role="menu" aria-labelledby="ddm-{{ servico.nome }}">
{% for mes in servico.novos_por_mes %}
<tr><th>{{ mes.mes }}</th><td>{{ mes.total }}</td></tr>
{% endfor %}
</table>
</th>
<td>{{ servico.total }}</td>
<td>{{ servico.novos_mes_anterior }}</td>
<td>{{ servico.novos_mes_atual }}</td>
</tr>
{% endfor %}
</table>
<div>
<a href="{% url "home_resumoseit" %}?ano={{ tabela_resumo_seit.mes_anterior.year|safe }}&mes={{ tabela_resumo_seit.mes_anterior.month|safe }}" aria-label="{% trans "Retroceder um mês" %}" data-target="resumoseit">
<span class="glyphicon glyphicon-chevron-left pull-left" aria-hidden="true"></span>
</a>
<a href="{% url "home_resumoseit" %}?ano={{ tabela_resumo_seit.proximo_mes.year|safe }}&mes={{ tabela_resumo_seit.proximo_mes.month|safe }}" aria-label="{% trans "Avançar um mês" %}" data-target="resumoseit">
<span class="glyphicon glyphicon-chevron-right pull-right" aria-hidden="true"></span>
</a>
</div>
</div>
</div>
Loading…
Cancel
Save