Browse Source

Finalizando a migração

pull/159/head
Sesostris Vieira 3 years ago
parent
commit
e9bab3610e
  1. 1
      sigi/apps/casas/templates/casas/painel.html
  2. 63
      sigi/apps/casas/templates/casas/resumo_carteira_snippet.html
  3. 5
      sigi/apps/casas/urls.py
  4. 454
      sigi/apps/casas/views.py
  5. 130
      sigi/apps/convenios/templates/convenios/tabela_regiao.html
  6. 25
      sigi/apps/convenios/urls.py
  7. 225
      sigi/apps/convenios/views.py
  8. 54
      sigi/apps/eventos/templates/eventos/calendario.html
  9. 42
      sigi/apps/eventos/urls.py
  10. 825
      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. 83
      sigi/apps/home/templates/home/sem_convenio.html
  20. 22
      sigi/apps/home/templatetags/smart_pagination.py
  21. 37
      sigi/apps/home/urls.py
  22. 486
      sigi/apps/home/views.py
  23. 52
      sigi/apps/ocorrencias/admin.py
  24. 14
      sigi/apps/ocorrencias/filters.py
  25. 47
      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. 361
      sigi/apps/ocorrencias/templates/ocorrencias/painel.html
  31. 49
      sigi/apps/ocorrencias/urls.py
  32. 113
      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. 98
      sigi/templates/admin/change_list.html
  43. 17
      sigi/templates/material/admin/index.html
  44. 10
      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

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

@ -22,7 +22,6 @@
{% block extrahead %}{{ block.super }} {% block extrahead %}{{ block.super }}
<script type="text/javascript"> <script type="text/javascript">
console.log("Cheguei a executar");
$(document).ready(function(){ $(document).ready(function(){
$("select[name='servidor']").on('change', function() { $("select[name='servidor']").on('change', function() {
var form = $(this.form); var form = $(this.form);

63
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' %} {% if seletor == 'sim' %}
{% trans "Resumo da carteira de" %} <ul class="collapsible gerente_selector" style="width: 100%;">
<mark class="dropdown"> <li>
<a data-toggle="dropdown" href="">{{ gerente.nome_completo|default:_("todo o Interlegis") }}</a> <div class="collapsible-header">
<ul class="dropdown-menu"> {% if gerente %}
<li><a href="{% url "casas-carteira" %}?servidor=_all&snippet={{ snippet }}&s={{ seletor }}" data-target="resumo">{% trans "Todo o Interlegis" %}</a></li> {% 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 %} {% 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 %} {% endfor %}
</ul> </ul>
</mark>
{% else %}
{% trans "Resumo da carteira" %}
{% endif %}
</h3>
</div> </div>
<table class="table table-hover resumo"> </li>
</ul>
{% endif %}
<table class="numeros resumo-carteira">
{% for row in resumo %} {% for row in resumo %}
{% if forloop.first %}
<tr>
{% for col in row %}
<th>{{ col }}</th>
{% endfor %}
</tr>
{% else %}
<tr> <tr>
{% if row.subtitle %} {% if row.subtitle %}
<th colspan="7">{{ row.subtitle }}</th> <th colspan="7">{{ row.subtitle }}</th>
{% else %} {% else %}
{% for col in row %} {% 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 %} {% endfor %}
{% endif %} {% endif %}
</tr> </tr>
{% endif %}
{% endfor %} {% endfor %}
</table> </table>
</div> </div>

5
sigi/apps/casas/urls.py

@ -1,9 +1,10 @@
from django.urls import path, include from django.urls import path, include
from sigi.apps.casas.views import CasasSemConvenioReport from sigi.apps.casas import views
urlpatterns = [ 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'), name='casas-sem-convenio-report'),
path('carteira/', views.painel_relacionamento, name='casas-carteira'),
] ]

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

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

@ -1,109 +1,10 @@
{% load static from staticfiles %} {% extends 'pdf/base_report.html' %}
{% load i18n %} {% load static 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;
}
{% block page_size %}A4 portrait{% endblock %}
{% block report_name %}{% blocktranslate %}Relatório da Região {{ regiao }}{% endblocktranslate %}{% endblock %}
</style> {% block main_content %}
</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 %} {% for tabela in tabelas %}
<table class="tabela" repeat="1"> <table class="tabela" repeat="1">
<caption>{{ tabela.projeto }} - {{ regiao }}</caption> <caption>{{ tabela.projeto }} - {{ regiao }}</caption>
@ -116,32 +17,21 @@
</thead> </thead>
<tbody> <tbody>
{% for linha in tabela.linhas %} {% for linha in tabela.linhas %}
<tr class="conteudo"> <tr>
<th class="cabecalho_esquerda">{{linha.estado}}</th> <th>{{ linha.estado }}</th>
{% for item in linha.lista %} {% for item in linha.lista %}
<td>{{item}}</td> <td class="right-align">{{ item }}</td>
{% endfor %} {% endfor %}
</tr> </tr>
{% endfor %} {% endfor %}
<tr> <tr>
<th>Total</th> <th>Total</th>
{% for item in tabela.sumario %} {% for item in tabela.sumario %}
<th>{{item}}</th> <th class="right-align">{{item}}</th>
{% endfor %} {% endfor %}
</tr> </tr>
</tbody> </tbody>
</table> </table>
<br /> <br />
{% endfor %} {% endfor %}
</div> {% endblock main_content %}
<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>

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( # urlpatterns = patterns(
'sigi.apps.convenios.views', # 'sigi.apps.convenios.views',
url(r'^convenio/reports/$', 'report', name='convenios-report'), # url(r'^convenio/reports/$', 'report', name='convenios-report'),
url(r'^convenio/carrinho/$', 'visualizar_carrinho', name='visualizar-carrinho'), # 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/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/carrinho/deleta_itens_carrinho$', 'deleta_itens_carrinho', name='deleta-itens-carrinho'), # tagerror
url(r'^convenio/csv/$', 'export_csv', name='convenios-csv'), # 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'^importar/$', 'importar_gescon', name='importar-gescon'), # )
)

225
sigi/apps/convenios/views.py

@ -1,18 +1,16 @@
import csv import csv
import datetime import datetime
from django.contrib import messages # from django.contrib import messages
from django.http.response import HttpResponseForbidden # from django.http.response import HttpResponseForbidden
# import ho.pisa as pisa # from django.conf import settings
from django.conf import settings # from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.core.paginator import Paginator, InvalidPage, EmptyPage # from django.http import HttpResponse, HttpResponseRedirect
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_list_or_404 from django.shortcuts import render, get_list_or_404
from django.template import Context, loader from django.template import Context, loader
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
# from geraldo.generators import PDFGenerator
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django_weasyprint.views import WeasyTemplateResponse
from sigi.apps.casas.models import Orgao from sigi.apps.casas.models import Orgao
from sigi.apps.contatos.models import UnidadeFederativa from sigi.apps.contatos.models import UnidadeFederativa
from sigi.apps.convenios.models import Convenio, Gescon, Projeto from sigi.apps.convenios.models import Convenio, Gescon, Projeto
@ -23,6 +21,117 @@ from sigi.apps.convenios.models import Convenio, Gescon, Projeto
# ConvenioReportSemAceiteAL, # ConvenioReportSemAceiteAL,
# ConvenioReportSemAceiteCM) # 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): def query_ordena(qs, o, ot):
list_display = ('num_convenio', 'casa_legislativa', list_display = ('num_convenio', 'casa_legislativa',
@ -209,107 +318,7 @@ def report(request, id=None):
return response 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 @login_required
def export_csv(request): def export_csv(request):

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

@ -1,8 +1,55 @@
{% extends "admin/base_site.html" %} {% extends "admin/base_site.html" %}
{% load i18n admin_static %} {% load i18n %}
{% load static from staticfiles %} {% load static %}
{% load thumbnail %}
{% 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 %} {% block extrastyle %}
<style type="text/css"> <style type="text/css">
th { th {
@ -41,3 +88,4 @@
{% block content %} {% block content %}
{% include "eventos/calendario_snippet.html" %} {% include "eventos/calendario_snippet.html" %}
{% endblock %} {% endblock %}
{% endcomment %}

42
sigi/apps/eventos/urls.py

@ -1,22 +1,28 @@
# coding: utf-8 from django.urls import path, include
from django.conf.urls import patterns, url from sigi.apps.eventos import views
urlpatterns = [
path('calendario/', views.calendario, name='eventos-calendario'),
]
urlpatterns = patterns( # from django.conf.urls import patterns, url
'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'),
) # 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'),
# )

825
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 calendar
import datetime import datetime
import locale 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.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404, render from django.shortcuts import render
from django.utils import translation from django.utils.translation import to_locale, get_language, gettext as _
from django.utils.translation import ungettext, gettext as _
from django.http.response import JsonResponse, HttpResponse
from django.template import Template, Context
from sigi.apps.eventos.models import Evento, Equipe, Convite, Modulo from sigi.apps.eventos.models import Evento, Equipe, Convite, Modulo
from sigi.apps.eventos.forms import SelecionaModeloForm from sigi.apps.eventos.forms import SelecionaModeloForm
from sigi.apps.servidores.models import Servidor from sigi.apps.servidores.models import Servidor
from sigi.shortcuts import render_to_pdf, pdf_renderer
@login_required @login_required
def calendario(request): def calendario(request):
@ -43,388 +14,422 @@ def calendario(request):
ano_pesquisa = int(request.GET.get('ano', datetime.date.today().year)) ano_pesquisa = int(request.GET.get('ano', datetime.date.today().year))
formato = request.GET.get('fmt', 'html') formato = request.GET.get('fmt', 'html')
dia1 = datetime.date(ano_pesquisa, mes_pesquisa, 1) meses = {}
mes_anterior = dia1 - datetime.timedelta(days=1) lang = to_locale(get_language())+'.UTF-8'
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) 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 for ano, mes in Evento.objects.values_list(
def excluir_carrinho(request): 'data_inicio__year', 'data_inicio__month').order_by(
if 'carrinho_eventos' in request.session: 'data_inicio__year', 'data_inicio__month').distinct(
del request.session['carrinho_eventos'] 'data_inicio__year', 'data_inicio__month'):
messages.info(request, 'O carrinho foi esvaziado') if ano in meses:
return HttpResponseRedirect('../../') meses[ano][mes] = calendar.month_name[mes]
@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: else:
reg[mun_casa] = evento.casa_anfitria.municipio.nome.encode('utf8') meses[ano] = {mes: calendar.month_name[mes]}
reg[uf_casa] = evento.casa_anfitria.municipio.uf.sigla.\
encode('utf8') context = {
reg[reg_casa] = evento.casa_anfitria.municipio.uf.\ 'ano_pesquisa': ano_pesquisa,
get_regiao_display().encode('utf8') 'mes_pesquisa': mes_pesquisa,
'meses': meses,
idx = 1 'eventos': Evento.objects.filter(
for membro in evento.equipe_set.all(): data_inicio__year=ano_pesquisa,
reg.update( data_inicio__month=mes_pesquisa
{
"{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( return render(request, 'eventos/calendario.html', context)
request,
'eventos/seleciona_modelo.html',
{'form': form, 'evento_id': id}
)
# @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>

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

@ -1,83 +1,23 @@
{% load static from staticfiles %} {% extends 'pdf/base_report.html' %}
{% load i18n %} {% load static 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;
}
{% block page_size %}A4 portrait{% endblock %}
@page { {% block main_content %}
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>
<table repeat="1"> <table repeat="1">
<thead>
<tr> <tr>
<th>{% trans "Nome da Casa" %}</th> <th>{% trans "Nome da Casa" %}</th>
<th width=30>{% trans "UF" %}</th> <th width=30>{% trans "UF" %}</th>
<th>{% trans "Gerente de contas" %}</th> <th>{% trans "Gerente de contas" %}</th>
<th>{% trans "Serviços" %}</th> <th>{% trans "Serviços" %}</th>
</tr> </tr>
</thead>
{% for casa in casas %} {% for casa in casas %}
<tr> <tr>
<td>{{ casa.nome }}</td> <td>{{ casa.nome }}</td>
<td>{{ casa.municipio.uf.sigla }}</td> <td>{{ casa.municipio.uf.sigla }}</td>
<td>{{ casa.lista_gerentes }}</td> <td>{{ casa.lista_gerentes|safe }}</td>
<td> <td>
{% for s in casa.servico_set.all %} {% for s in casa.servico_set.all %}
{% if s.data_desativacao == None %} {% if s.data_desativacao == None %}
@ -88,11 +28,4 @@
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
{% endblock main_content %}
<div id="footer">
{%block page_foot%}
{% trans 'Página' %} <pdf:pagenumber>
{%endblock%}
</div>
</body>
</html>

22
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 from django import template
register = template.Library() register = template.Library()
@ -30,7 +10,7 @@ def smart_paginator(page_obj, querystring=None):
querystring = '?' querystring = '?'
page_range = page_obj.paginator.page_range 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:]) | 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])) set(page_range[page_obj.number-2:page_obj.number+1]))

37
sigi/apps/home/urls.py

@ -1,15 +1,28 @@
# coding: utf-8 from django.urls import path
from django.conf.urls import patterns, url 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"),
]
urlpatterns = patterns('sigi.apps.home.views', # from django.conf.urls import patterns, url
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"),
)
# 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"),
# )

486
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 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.shortcuts import render, get_object_or_404
from django.template.loader import render_to_string
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from itertools import cycle from django.views.decorators.cache import never_cache
from sigi.apps.casas.models import Orgao 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.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.servicos.models import TipoServico
from sigi.apps.servidores.models import Servidor from sigi.apps.servidores.models import Servidor
from django.views.decorators.cache import never_cache from sigi.apps.utils import to_ascii
from django.contrib.auth.decorators import login_required
from django.http.response import JsonResponse, HttpResponse # from django.shortcuts import render, get_object_or_404
from django.core.urlresolvers import reverse # from sigi.apps.casas.models import Orgao
from django.db.models import Q, Count # from sigi.apps.diagnosticos.models import Diagnostico
from sigi.shortcuts import render_to_pdf # from sigi.apps.metas.models import Meta
import csv # 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
@never_cache def openmapdata(request):
@login_required tipos_orgao = request.GET.getlist('tipo_orgao', None)
def index(request): tipos_servico = request.GET.getlist('tipo_servico', None)
context = {'gerentes': Servidor.objects.exclude(casas_que_gerencia=None)} tipos_convenio = request.GET.getlist('tipo_convenio', None)
return render(request, 'index.html', context) 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 @never_cache
@login_required @login_required
def resumo_convenios(request): def resumo_convenios(request):
context = {'tabela_resumo_camara': busca_informacoes_camara() } 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 @never_cache
@login_required @login_required
@ -66,36 +211,40 @@ def resumo_seit(request):
tabela_resumo_seit = busca_informacoes_seit() tabela_resumo_seit = busca_informacoes_seit()
context = {'tabela_resumo_seit': tabela_resumo_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 @never_cache
@login_required @login_required
def chart_seit(request): def chart_seit(request):
mes = request.GET.get('mes', None) hoje = datetime.date.today()
ano = request.GET.get('ano', None) 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) mes = datetime.date(year=int(ano), month=int(mes), day=1)
tabela_resumo_seit = busca_informacoes_seit(mes) tabela_resumo_seit = busca_informacoes_seit(mes)
except:
tabela_resumo_seit = busca_informacoes_seit()
data = { data = {
'type': 'line', 'type': 'line',
'prevlink': reverse('home_chartseit') + ('?ano=%s&mes=%s' % 'prevlink': reverse('home_chartseit') + (
(tabela_resumo_seit['mes_anterior'].year, f"?ano={tabela_resumo_seit['mes_anterior'].year}"
tabela_resumo_seit['mes_anterior'].month)), f"&mes={tabela_resumo_seit['mes_anterior'].month}"
'nextlink': reverse('home_chartseit') + ('?ano=%s&mes=%s' % ),
(tabela_resumo_seit['proximo_mes'].year, 'nextlink': reverse('home_chartseit') + (
tabela_resumo_seit['proximo_mes'].month)), f"?ano={tabela_resumo_seit['proximo_mes'].year}"
'options': {'bezierCurve': False, 'datasetFill': False, 'pointDot': False, 'responsive': True}, f"&mes={tabela_resumo_seit['proximo_mes'].month}"
),
'options': {'bezierCurve': False, 'datasetFill': False,
'pointDot': False, 'responsive': True},
'data': { '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': [ 'datasets': [
{ {
'label': servico['nome'], 'label': servico['nome'],
'strokeColor': servico['cor'], 'borderColor': servico['cor'],
'data': [mes['total'] for mes in reversed(servico['novos_por_mes'])] 'backgroundColor': servico['cor'],
'data': [mes['total']
for mes in reversed(servico['novos_por_mes'])]
} }
for servico in tabela_resumo_seit['servicos']], for servico in tabela_resumo_seit['servicos']],
} }
@ -103,37 +252,38 @@ def chart_seit(request):
return JsonResponse(data) return JsonResponse(data)
@never_cache # @never_cache
@login_required # @login_required
def chart_convenios(request): # def chart_convenios(request):
q = request.GET.get('q', 'all') # q = request.GET.get('q', 'all')
convenios = Convenio.objects.all() # convenios = Convenio.objects.all()
if q == 'assinados': # if q == 'assinados':
convenios = convenios.exclude(data_retorno_assinatura=None) # convenios = convenios.exclude(data_retorno_assinatura=None)
data = { # data = {
'type': 'pie', # 'type': 'pie',
'options': {'responsive': False, 'maintainAspectRatio': False}, # 'options': {'responsive': False, 'maintainAspectRatio': False},
'data': grafico_convenio_projeto(convenios), # 'data': grafico_convenio_projeto(convenios),
} # }
return JsonResponse(data) # return JsonResponse(data)
@never_cache @never_cache
@login_required @login_required
def chart_carteira(request): def chart_carteira(request):
colors, highlights = color_palete() colors, highlights = color_palete()
data = {'type': 'pie', gerentes = Servidor.objects.exclude(casas_que_gerencia=None).annotate(
'options': {'responsive': True}, total_casas=Count('casas_que_gerencia'))
'data': [{'value': r['total_casas'],
'color': colors.next(), data = {
'highlight': highlights.next(), 'type': 'doughnut',
'label': r['gerentes_interlegis__nome_completo'] '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]
} }
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')
]
} }
return JsonResponse(data) return JsonResponse(data)
@ -142,24 +292,42 @@ def chart_carteira(request):
@login_required @login_required
def chart_performance(request): def chart_performance(request):
servidor = request.GET.get('servidor', None) servidor = request.GET.get('servidor', None)
gerentes = Servidor.objects.exclude(casas_que_gerencia=None)
gerente = None
if servidor is None: if servidor is None:
casas = Orgao.objects.exclude(gerentes_interlegis=None) if (request.user.servidor and
request.user.servidor.casas_que_gerencia.exists()):
gerente = request.user.servidor
else: else:
servidor = '_all'
if servidor is not None and servidor != '_all':
gerente = get_object_or_404(Servidor, pk=servidor) gerente = get_object_or_404(Servidor, pk=servidor)
if gerente is None:
casas = Orgao.objects.exclude(gerentes_interlegis=None)
else:
casas = gerente.casas_que_gerencia casas = gerente.casas_que_gerencia
data = { data = {
'type': 'pie', 'type': 'doughnut',
'options': {'responsive': True}, 'data': {
'data': [ 'labels': [_("Utilizam serviços"), _("Não utilizam serviços")],
{'label': _("Utilizam serviços"), 'datasets': [
'value': casas.exclude(servico=None).count(), {
'color': '#91e8e1'}, 'label': 'SeiLaQueIsso',
{'label': _("Não utilizam serviços"), 'data': [casas.exclude(servico=None).count(),
'value': casas.filter(servico=None).count(), casas.filter(servico=None).count()],
'color': '#f7a35c'}, 'backgroundColor': ['#91e8e1', '#f7a35c']
}
] ]
},
'actionblock': render_to_string(
'home/dashboard/gerentes_snippet.html',
context={'gerentes': gerentes, 'gerente': gerente},
request=request
)
} }
return JsonResponse(data) return JsonResponse(data)
@ -187,20 +355,19 @@ def report_sem_convenio(request):
if fmt == 'csv': if fmt == 'csv':
response = HttpResponse(content_type='text/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 = csv.writer(response)
writer.writerow([titulo.encode('utf8')]) writer.writerow([titulo])
writer.writerow(['']) writer.writerow([''])
writer.writerow(['casa', 'uf', 'gerentes', writer.writerow(['casa', 'uf', 'gerentes', 'serviços'])
'serviços'.encode('utf8')])
for casa in casas: for casa in casas:
writer.writerow([ writer.writerow([
casa.nome.encode('utf8'), casa.nome,
casa.municipio.uf.sigla.encode('utf8'), casa.municipio.uf.sigla,
casa.lista_gerentes(fmt='lista').encode('utf8'), casa.lista_gerentes(fmt='lista'),
(', '.join(casa.servico_set.filter( (', '.join(casa.servico_set.filter(
data_desativacao__isnull=True).values_list( data_desativacao__isnull=True).values_list(
'tipo_servico__nome', flat=True))).encode('utf8'), 'tipo_servico__nome', flat=True))),
]) ])
return response return response
elif fmt == 'json': elif fmt == 'json':
@ -219,15 +386,17 @@ def report_sem_convenio(request):
} }
return JsonResponse(data, safe=False) return JsonResponse(data, safe=False)
else: else:
context = {'casas': casas, 'titulo': titulo} context = {'casas': casas, 'title': titulo}
return render_to_pdf('home/sem_convenio.html', context) return WeasyTemplateResponse(
filename=f'{ titulo }.pdf',
request=request,
template='home/sem_convenio.html',
context=context,
content_type='application/pdf',
)
def busca_informacoes_camara(): 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') camaras = Orgao.objects.filter(tipo__sigla='CM')
convenios = Convenio.objects.filter(casa_legislativa__tipo__sigla='CM') convenios = Convenio.objects.filter(casa_legislativa__tipo__sigla='CM')
projetos = Projeto.objects.all() projetos = Projeto.objects.all()
@ -261,15 +430,21 @@ def busca_informacoes_camara():
cabecalho_topo.append(projeto.sigla) cabecalho_topo.append(projeto.sigla)
lista_total.append(camaras.filter(convenio__projeto=projeto).count()) lista_total.append(camaras.filter(convenio__projeto=projeto).count())
lista_nao_aderidas.append(camaras.filter(convenio__in=conv_sem_adesao_proj).count()) lista_nao_aderidas.append(
lista_aderidas.append(camaras.filter(convenio__in=conv_com_adesao_proj).count()) camaras.filter(convenio__in=conv_sem_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_aderidas.append(
lista_camaras_equipadas.append(camaras.filter(convenio__in=conv_equipadas_proj).count()) camaras.filter(convenio__in=conv_com_adesao_proj).count()
)
# Monta linhas de diagnosticos lista_convenios_assinados.append(
lista_diagnosticos_digitados = ['', '', Diagnostico.objects.count(), '', '', ''] camaras.filter(convenio__in=conv_assinados_proj).count()
lista_diagnosticos_publicados = ['', '', Diagnostico.objects.filter(publicado=True).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 da esquerda na tabela
cabecalho_esquerda = ( cabecalho_esquerda = (
@ -279,8 +454,6 @@ def busca_informacoes_camara():
_('Câmaras municipais com convênios assinados'), _('Câmaras municipais com convênios assinados'),
_('Câmaras municipais convênios em andamento'), _('Câmaras municipais convênios em andamento'),
_('Câmaras municipais equipadas'), _('Câmaras municipais equipadas'),
_('Diagnósticos digitados'),
_('Diagnósticos publicados')
) )
linhas = ( linhas = (
@ -290,11 +463,9 @@ def busca_informacoes_camara():
lista_convenios_assinados, lista_convenios_assinados,
lista_convenios_em_andamento, lista_convenios_em_andamento,
lista_camaras_equipadas, 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 # respectiva linha
lista_zip = zip(cabecalho_esquerda, linhas) lista_zip = zip(cabecalho_esquerda, linhas)
@ -307,33 +478,53 @@ def busca_informacoes_camara():
'sem_convenio': sem_convenio(), 'sem_convenio': sem_convenio(),
} }
def 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') total = Orgao.objects.exclude(
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') servico=None
reg_keys = set(total.values_list('pk', flat=True)).difference(set(hospedagem.values_list('pk', flat=True))) ).filter(
registro = Orgao.objects.filter(pk__in=reg_keys).order_by('municipio__uf__sigla', 'nome') 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 { return {
'total': total, 'total': total,
'hospedagem': hospedagem, 'hospedagem': hospedagem,
'registro': registro, 'registro': registro,
} }
def grafico_convenio_projeto(convenios): # def grafico_convenio_projeto(convenios):
colors, highlights = color_palete() # colors, highlights = color_palete()
projetos = Projeto.objects.all() # projetos = Projeto.objects.all()
lista_projetos = [{'label': projeto.sigla, # lista_projetos = [{'label': projeto.sigla,
'value': convenios.filter(projeto=projeto).count(), # 'value': convenios.filter(projeto=projeto).count(),
'color': colors.next(), # 'color': colors.next(),
'highlight': highlights.next()} # 'highlight': highlights.next()}
for projeto in projetos] # for projeto in projetos]
# remove projetos sem convenio # # remove projetos sem convenio
lista_projetos = [x for x in lista_projetos if x['value'] > 0] # lista_projetos = [x for x in lista_projetos if x['value'] > 0]
# print lista_projetos # # print lista_projetos
# total_convenios = "Total: " + str(convenios.count()) # # total_convenios = "Total: " + str(convenios.count())
# lista_projetos.insert(0, total_convenios) # # lista_projetos.insert(0, total_convenios)
return lista_projetos # return lista_projetos
def busca_informacoes_seit(mes_atual=None): def busca_informacoes_seit(mes_atual=None):
@ -341,7 +532,8 @@ def busca_informacoes_seit(mes_atual=None):
if mes_atual is None: if mes_atual is None:
mes_atual = datetime.date.today().replace(day=1) mes_atual = datetime.date.today().replace(day=1)
mes_anterior = mes_atual - datetime.timedelta(days=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 = [] meses = []
mes = mes_atual 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_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_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, 'novos_por_mes': por_mes,
'cor': colors.next(), 'cor': next(colors),
} }
) )
return result return result
def busca_informacoes_diagnostico(): # def busca_informacoes_diagnostico():
return [ # return [
{'title': _('Diagnósticos digitados'), 'count': Diagnostico.objects.count()}, # {'title': _('Diagnósticos digitados'), 'count': Diagnostico.objects.count()},
{'title': _('Diagnósticos publicados'), 'count': Diagnostico.objects.filter(publicado=True).count()}, # {'title': _('Diagnósticos publicados'), 'count': Diagnostico.objects.filter(publicado=True).count()},
] # ]
def color_palete(): 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.translation import gettext as _
from django.utils.safestring import mark_safe 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, from sigi.apps.ocorrencias.models import (Ocorrencia, Comentario, Anexo,
Categoria, TipoContato) Categoria, TipoContato)
from sigi.apps.servidores.models import Servidor from sigi.apps.servidores.models import Servidor
@ -18,18 +18,15 @@ class ComentarioViewInline(admin.TabularInline):
can_delete = False can_delete = False
verbose_name = _("Comentário anterior") verbose_name = _("Comentário anterior")
verbose_name_plural = _("Comentários anteriores") verbose_name_plural = _("Comentários anteriores")
fields = ('usuario', 'data_criacao', 'novo_status', 'encaminhar_setor', fields = ('usuario', 'data_criacao', 'novo_status', 'descricao', )
'descricao', ) readonly_fields = fields
readonly_fields = ('novo_status', 'encaminhar_setor', 'descricao',
'data_criacao', 'usuario',)
class ComentarioInline(admin.StackedInline): class ComentarioInline(admin.StackedInline):
model = Comentario model = Comentario
extra = 1 extra = 1
verbose_name = _("Comentário novo") verbose_name = _("Comentário novo")
verbose_name_plural = _("Comentários novos") verbose_name_plural = _("Comentários novos")
fieldsets = ((None, {'fields': (('novo_status', 'encaminhar_setor',), fields = ('novo_status', 'descricao',)
'descricao', )}),)
def get_queryset(self, queryset): def get_queryset(self, queryset):
return self.model.objects.none() return self.model.objects.none()
@ -39,32 +36,15 @@ class AnexosInline(admin.TabularInline):
extra = 2 extra = 2
readonly_fields = ['data_pub', ] 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) @admin.register(Ocorrencia)
class OcorrenciaAdmin(BaseModelAdmin): class OcorrenciaAdmin(admin.ModelAdmin):
list_display = ('data_criacao', 'casa_legislativa', 'get_municipio', list_display = ('data_criacao', 'casa_legislativa', 'get_municipio',
'get_uf', 'assunto', 'prioridade', 'status', 'get_uf', 'assunto', 'prioridade', 'status',
'data_modificacao', 'setor_responsavel',) 'data_modificacao',)
list_filter = ( list_filter = (
OcorrenciaListFilter, 'status', 'prioridade', 'categoria__nome', 'status', 'prioridade', 'categoria__nome',
'setor_responsavel__nome',
('casa_legislativa__gerentes_interlegis', GerentesInterlegisFilter), ('casa_legislativa__gerentes_interlegis', GerentesInterlegisFilter),
('servidor_registro', ServidorRegistroFilter),
) )
search_fields = ('casa_legislativa__search_text', 'assunto', search_fields = ('casa_legislativa__search_text', 'assunto',
'servidor_registro__nome_completo', 'descricao', 'servidor_registro__nome_completo', 'descricao',
@ -72,13 +52,10 @@ class OcorrenciaAdmin(BaseModelAdmin):
date_hierarchy = 'data_criacao' date_hierarchy = 'data_criacao'
fields = ('casa_legislativa', 'categoria', 'tipo_contato', 'assunto', fields = ('casa_legislativa', 'categoria', 'tipo_contato', 'assunto',
'status', 'prioridade', 'ticket', 'descricao', 'status', 'prioridade', 'ticket', 'descricao',
'servidor_registro', 'setor_responsavel', 'resolucao', ) 'servidor_registro', 'resolucao', )
readonly_fields = ('servidor_registro', 'setor_responsavel', ) readonly_fields = ('servidor_registro', )
inlines = (ComentarioViewInline, ComentarioInline, AnexosInline, ) inlines = (ComentarioViewInline, ComentarioInline, AnexosInline, )
raw_id_fields = ('casa_legislativa', ) autocomplete_fields = ('casa_legislativa', )
def get_changelist(self, request, **kwargs):
return OcorrenciaChangeList
def get_fieldsets(self, request, obj=None): def get_fieldsets(self, request, obj=None):
if obj is None: if obj is None:
@ -88,23 +65,20 @@ class OcorrenciaAdmin(BaseModelAdmin):
else: else:
self.fields = ('casa_legislativa', 'categoria', 'tipo_contato', self.fields = ('casa_legislativa', 'categoria', 'tipo_contato',
'assunto', 'status', 'prioridade', 'ticket', 'assunto', 'status', 'prioridade', 'ticket',
'descricao', 'servidor_registro', 'descricao', 'servidor_registro', 'resolucao', )
'setor_responsavel', 'resolucao', )
return super().get_fieldsets(request, obj) return super().get_fieldsets(request, obj)
def save_model(self, request, obj, form, change): def save_model(self, request, obj, form, change):
if not change: if not change:
obj.servidor_registro = Servidor.objects.get(user=request.user) obj.servidor_registro = Servidor.objects.get(user=request.user)
obj.setor_responsavel = obj.categoria.setor_responsavel
obj.save() obj.save()
def save_formset(self, request, form, formset, change): def save_formset(self, request, form, formset, change):
servidor = Servidor.objects.get(user=request.user)
instances = formset.save(commit=False) instances = formset.save(commit=False)
for instance in instances: for instance in instances:
if isinstance(instance, Comentario): if isinstance(instance, Comentario):
instance.usuario = servidor instance.usuario = request.user.servidor
instance.save() instance.save()
super(OcorrenciaAdmin, self).save_formset(request, form, formset, super(OcorrenciaAdmin, self).save_formset(request, form, formset,
change) change)

14
sigi/apps/ocorrencias/filters.py

@ -1,9 +1,16 @@
from django.contrib import admin from django.contrib import admin
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from sigi.apps.servidores.models import Servidor 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): class OcorrenciaListFilter(admin.SimpleListFilter):
title = _('Relacionadas a Mim') title = _('Relacionadas a Mim')
parameter_name = 'minhas' parameter_name = 'minhas'
@ -12,16 +19,13 @@ class OcorrenciaListFilter(admin.SimpleListFilter):
if request.user.servidor is None: if request.user.servidor is None:
return None return None
return ( return (
('S', _('Atribuídos ao meu setor')),
('M', _('Registrados por mim')), ('M', _('Registrados por mim')),
('G', _('Sobre casas que gerencio')), ('G', _('Sobre casas que gerencio')),
) )
def queryset(self, request, queryset): def queryset(self, request, queryset):
servidor = request.user.servidor servidor = request.user.servidor
if self.value() == 'S': if self.value() == 'M':
return queryset.filter(setor_responsavel=servidor.servico)
elif self.value() == 'M':
return queryset.filter(servidor_registro=servidor) return queryset.filter(servidor_registro=servidor)
elif self.value() == 'G': elif self.value() == 'G':
return queryset.filter( return queryset.filter(

47
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.ocorrencias.models import Ocorrencia, Comentario, Anexo
from sigi.apps.servidores.models import Servico 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.utils.html import format_html
from django.forms.utils import flatatt from django.forms.utils import flatatt
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils.safestring import mark_safe 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 = "" url = ""
def __init__(self, url, attrs=None): def __init__(self, url, attrs=None):
super(AjaxSelect, self).__init__(attrs) super(AjaxSelect, self).__init__(attrs)
@ -20,7 +23,7 @@ class AjaxSelect(TextInput):
code_attrs = self.build_attrs(type='hidden', name=name, code_attrs = self.build_attrs(type='hidden', name=name,
id='hidden_'+name) id='hidden_'+name)
if value != '': 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 = format_html('<input{0} />', flatatt(final_attrs)) + "\n"
result = result + format_html('<input{0} />', flatatt(code_attrs)) result = result + format_html('<input{0} />', flatatt(code_attrs))
js = """ js = """
@ -38,31 +41,35 @@ class AjaxSelect(TextInput):
result = result + mark_safe(js) result = result + mark_safe(js)
return result return result
class AnexoForm(ModelForm): class AnexoForm(forms.ModelForm):
class Meta: class Meta:
model = Anexo model = Anexo
fields = ['ocorrencia', 'descricao', 'arquivo',] fields = ['ocorrencia', 'descricao', 'arquivo',]
widgets = {'ocorrencia': HiddenInput()} widgets = {'ocorrencia': forms.HiddenInput()}
class ComentarioForm(ModelForm):
encaminhar_setor = ModelChoiceField(
queryset=Servico.objects.all(),
cache_choices=True
)
class ComentarioForm(forms.ModelForm):
class Meta: class Meta:
model = Comentario model = Comentario
fields = ['ocorrencia', 'descricao', 'novo_status', 'encaminhar_setor'] fields = ['ocorrencia', 'descricao', 'novo_status',]
widgets = {'ocorrencia': HiddenInput(),} widgets = {
'ocorrencia': forms.HiddenInput(),
'descricao': MaterialAdminTextareaWidget(),
}
class OcorrenciaForm(ModelForm): class OcorrenciaForm(forms.ModelForm):
class Meta: class Meta:
model = Ocorrencia model = Ocorrencia
fields = ['casa_legislativa', 'categoria', 'tipo_contato', 'assunto', fields = ['casa_legislativa', 'categoria', 'tipo_contato', 'assunto',
'prioridade', 'ticket', 'descricao', 'setor_responsavel',] 'prioridade', 'ticket', 'descricao',]
widgets = { widgets = {
'casa_legislativa': AjaxSelect( 'casa_legislativa': AutocompleteSelect(
url=reverse_lazy('painel-buscacasa'), Ocorrencia.casa_legislativa.field,
attrs={'size':100} 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): class Categoria(models.Model):
nome = models.CharField(_("Categoria"), max_length=50) nome = models.CharField(_("Categoria"), max_length=50)
descricao = models.TextField(_('descrição'), blank=True, null=True) 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: class Meta:
verbose_name = _('Categoria') verbose_name = _('Categoria')
@ -100,11 +95,6 @@ class Ocorrencia(models.Model):
on_delete=models.PROTECT, on_delete=models.PROTECT,
verbose_name=_("Servidor que registrou a ocorrência") 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( ticket = models.PositiveIntegerField(
_('Número do ticket'), _('Número do ticket'),
blank=True, blank=True,
@ -157,20 +147,8 @@ class Comentario(models.Model):
blank=True, blank=True,
null=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): 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): if self.novo_status and (self.novo_status != self.ocorrencia.status):
self.ocorrencia.status = self.novo_status self.ocorrencia.status = self.novo_status
self.ocorrencia.save() 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 %}

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

@ -1,198 +1,211 @@
{% extends "admin/base_site.html" %} {% extends "admin/base_site.html" %}
{% load i18n admin_static %} {% load i18n static admin_urls %}
{% load static from staticfiles %}
{% load thumbnail %}
{% block extrastyle %} {% block extrastyle %}
{{ block.super }} {{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static 'ocorrencias/css/jquery-ui.min.css' %}"/> <style>
{% endblock %} #content {
display: block;
{% block extrahead %} }
{{ block.super }} .user-image {
<script type="text/javascript" src="{% static 'admin/js/core.js' %}" ></script> width: 64px;
<script type="text/javascript" src="{% static 'admin/js/jquery.min.js' %}" ></script> height: 64px;
<script type="text/javascript" src="{% static 'admin/js/jquery.init.js' %}" ></script> font-size: 64px !important;
<script type="text/javascript" src="{% static 'ocorrencias/js/jquery-ui.min.js' %}" ></script> }
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 %} {% endblock %}
{% block breadcrumbs %}{% endblock %}
{% block coltype %}colMS{% endblock %}
{% block content_title %}<h1>{{ panel_title }}</h1>{% endblock %}
{% block content %} {% block content %}
{% url 'painel-ocorrencias' as url_painel %} <div class="row">
<div id="content-main" class="container-fluid"> <div class="col s12"><h1>{{ panel_title }}</h1></div>
<div class="form-group"> </div>
<div class="input-group"> <div class="row">
<input type="text" class="form-control" id="q" placeholder="{% trans 'Visitar o painel de' %}"> <div class="col s12">
<span class="input-group-btn"> {% for id, text in paineis.items %}
<button class="btn btn-default" type="button" onclick="window.location.href='{{ url_painel }}'">{% trans 'Meu painel' %}</button> <a class="waves-effect waves-light btn-small{% if id != painel %} btn-flat{% endif %}" href="?painel={{ id }}">{{ text }}</a>
</span> {% endfor %}
</div> </div>
</div> </div>
<div class="row">
<div class="nav nav-pills"> <div class="col s12">
<span class="glyphicon glyphicon-plus"></span> <button class="waves-effect waves-light btn-small btn-flat modal-trigger" href="#nova_ocorrencia">{% trans "Nova ocorrência" %}</button>
<a role="button" data-toggle="collapse" href="#form_ocorrencia_panel" aria-expanded="false" aria-controls="form_ocorrencia_panel"> </div>
{% trans "Registrar nova ocorrência" %} </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> </a>
<span class="user-name">{{ ocorrencia.servidor_registro.get_apelido }}</span>
</div> </div>
<div class="col s9 m11">
<div class="collapse panel panel-default" id='form_ocorrencia_panel'> <p>{{ ocorrencia.descricao }}</p>
{% include 'ocorrencias/ocorrencia_form.html' %} <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> </div>
</li>
{% 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 %} {% endfor %}
</ul> </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 %} {% endif %}
<form class="row" id="comentar_ocorrencia_{{ ocorrencia.id|safe }}" action="#!" method="post" data-ocorrencia-id="{{ ocorrencia.id|safe }}">
<div class="row"> {% csrf_token %}
<div id="ocorrencias_display" class="col-md-12"> <p>{% trans "Comentar" %}:</p>
{% for ocorrencia in ocorrencias %} {% for field in comentario_form %}
{% include 'ocorrencias/ocorrencia_snippet.html' %} {% if field.name == 'ocorrencia' %}
{% empty %} <input type='hidden' name='ocorrencia' value='{{ ocorrencia.id|safe }}'/>
<div class="panel panel-default"> {% elif field.name == 'novo_status' %}
<div class="panel-body"> <div class="input-field col m4 s12">
<p>{% trans 'Nenhuma ocorrência encontrada.' %}</p> <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> </div>
{% else %}
<div class="input-field col m8 s12">
{{ field }}
</div> </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 %} {% endfor %}
</ul>
</div> </div>
</div> </div>
</div> </div>
</div>
{% endfor %}
{% endblock %}
<script type="text/javascript"> {% block footer %}
{{ block.super }}
<script>
$(document).ready(function(){ $(document).ready(function(){
$.ajaxSetup({ var elems = document.querySelectorAll('.dropdown-trigger');
beforeSend: function(xhr, settings) { var instances = M.Dropdown.init(elems, {});
if (!(/^(GET|HEAD|OPTIONS|TRACE)$/.test(settings.type)) && !this.crossDomain) { var elems = document.querySelectorAll('.modal');
var cookieValue = null, name = 'csrftoken'; var instances = M.Modal.init(elems, {});
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> </script>
{% endblock %} {% endblock %}

49
sigi/apps/ocorrencias/urls.py

@ -1,19 +1,30 @@
# coding: utf-8 from django.urls import path
from django.conf.urls import patterns, url from sigi.apps.ocorrencias.views import painel_ocorrencias
urlpatterns = [
urlpatterns = patterns( path('painel/', painel_ocorrencias, name='painel-ocorrencias'),
'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'), # # coding: utf-8
url(r'^mudaprioridade/$', 'muda_prioridade', name='ocorrencia-mudaprioridade'), # from django.conf.urls import patterns, url
url(r'^excluianexo/$', 'exclui_anexo', name='ocorrencia-excluianexo'),
url(r'^incluianexo/$', 'inclui_anexo', name='ocorrencia-incluianexo'),
url(r'^anexosnippet/$', 'anexo_snippet', name='ocorrencia-anexosnippet'), # urlpatterns = patterns(
url(r'^incluicomentario/$', 'inclui_comentario', name='ocorrencia-incluicomentario'), # 'sigi.apps.ocorrencias.views',
url(r'^incluiocorrencia/$', 'inclui_ocorrencia', name='ocorrencia-incluiocorrencia'), # # 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'),
# )

113
sigi/apps/ocorrencias/views.py

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.http import JsonResponse, Http404 from django.http import JsonResponse, Http404
from django.db.models import Q, Count 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.shortcuts import get_object_or_404, render, HttpResponse
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_POST from django.views.decorators.http import require_POST
@ -17,87 +17,92 @@ from django.utils.html import escape
@login_required @login_required
def painel_ocorrencias(request): def painel_ocorrencias(request):
tipo = request.GET.get('type', None)
id = request.GET.get('id', None)
painel = request.GET.get('painel', 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")
}
data = {} if id_servidor is None:
servidor = request.user.servidor
if tipo is None or tipo == 'error': else:
tipo = 'servidor' servidor = get_object_or_404(Servidor, id=id_servidor)
u = get_object_or_404(Servidor, user=request.user)
id = u.pk
if id is None:
raise Http404("id não definido")
if tipo == 'casa': if id_casa is not None:
casa = get_object_or_404(Orgao, pk=id) casa = get_object_or_404(Orgao, id=id_casa)
ocorrencias = casa.ocorrencia_set.all() painel = 'tudo'
panel_title = "{casa}, {uf}".format( panel_title = _(f"Ocorrências da {casa.nome}, {casa.municipio.uf.nome}")
casa=casa.nome, else:
uf=casa.municipio.uf.sigla casa = None
) if servidor:
elif tipo == 'servidor': is_gerente = servidor.casas_que_gerencia.exists()
servidor = get_object_or_404(Servidor, pk=id) is_registrador = (servidor.ocorrencia_set.exists() or
servidor.comentario_set.exists())
panel_title = servidor.nome_completo panel_title = servidor.nome_completo
else:
paineis = {'gerente': "Minhas casas", 'servico': "Meu setor", is_gerente = False
'timeline': "Comentados por mim"} 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: if painel is None:
if Orgao.objects.filter(
gerentes_interlegis=servidor).count() > 0:
painel = 'gerente' 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': if painel == 'gerente':
ocorrencias = Ocorrencia.objects.filter( ocorrencias = Ocorrencia.objects.filter(
casa_legislativa__gerentes_interlegis=servidor) casa_legislativa__gerentes_interlegis=servidor)
elif painel == 'servico': elif painel == 'registro':
ocorrencias = Ocorrencia.objects.filter(
setor_responsavel_id=servidor.servico_id)
else:
ocorrencias = ( ocorrencias = (
Ocorrencia.objects.filter(servidor_registro=servidor) | Ocorrencia.objects.filter(servidor_registro=servidor) |
Ocorrencia.objects.filter(comentarios__usuario=servidor) Ocorrencia.objects.filter(comentarios__usuario=servidor)
) )
elif tipo == 'servico': else: # Tudo...
servico = get_object_or_404(Servico, pk=id) if casa is None: # ...de todas as Casas...
ocorrencias = servico.ocorrencia_set.all() ocorrencias = Ocorrencia.objects.all()
panel_title = _("{sigla} - {nome}").format( else: # ... ou da Casa escolhida
sigla=servico.sigla, nome=servico.nome) ocorrencias = casa.ocorrencia_set.all()
ocorrencias = ocorrencias.filter(status__in=[1, 2]) ocorrencias = ocorrencias.filter(status__in=[1, 2])
ocorrencias = ocorrencias.order_by('prioridade', '-data_modificacao') ocorrencias = ocorrencias.order_by('prioridade', '-data_modificacao')
ocorrencias = ocorrencias.select_related( ocorrencias = ocorrencias.select_related(
'casa_legislativa', 'categoria', 'tipo_contato', 'servidor_registro', 'casa_legislativa', 'casa_legislativa__municipio',
'setor_responsavel', 'casa_legislativa__gerentes_interlegis' 'casa_legislativa__municipio__uf', 'categoria', 'tipo_contato',
'servidor_registro',
) )
ocorrencias = ocorrencias.prefetch_related( ocorrencias = ocorrencias.prefetch_related(
'comentarios', 'comentarios__usuario', 'comentarios__encaminhar_setor', 'comentarios', 'comentarios__usuario', 'anexo_set',
'casa_legislativa__municipio', 'casa_legislativa__municipio__uf', 'casa_legislativa__gerentes_interlegis'
'anexo_set'
) )
ocorrencias = ocorrencias.annotate(total_anexos=Count('anexo')) ocorrencias = ocorrencias.annotate(total_anexos=Count('anexo'))
data.update( if page * 100 > ocorrencias.count():
{'ocorrencias': ocorrencias, 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, 'panel_title': panel_title,
'comentario_form': ComentarioForm(), 'comentario_form': ComentarioForm(),
'ocorrencia_form': OcorrenciaForm(), 'ocorrencia_form': OcorrenciaForm(),
'PRIORITY_CHOICES': Ocorrencia.PRIORITY_CHOICES 'PRIORITY_CHOICES': Ocorrencia.PRIORITY_CHOICES
} }
)
return render(request, 'ocorrencias/painel.html', data) return render(request, 'ocorrencias/painel.html', context)
@login_required @login_required
def busca_nominal(request, origin="tudo"): def busca_nominal(request, origin="tudo"):
@ -161,7 +166,7 @@ def exclui_anexo(request):
ocorrencia = anexo.ocorrencia ocorrencia = anexo.ocorrencia
anexo.delete() 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(),)) (ocorrencia.anexo_set.count(),))
painel = render_to_string('ocorrencias/anexos_snippet.html', {'ocorrencia': ocorrencia}, 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) Servidor.objects.filter(user=self.user).update(user=None)
return super(Servidor, self).save(*args, **kwargs) 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 # Soluçao alternativa para extender o usuário do django
# Acessa do servidor de um objeto user criando um profile # Acessa do servidor de um objeto user criando um profile
# baseado nos dados do LDAP # 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) txt = force_str(txt)
if isinstance(txt, str): if isinstance(txt, str):
txt = txt.encode('utf-8') 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): def queryset_ascii(self, request):

7
sigi/settings/base.py

@ -69,6 +69,7 @@ TEMPLATES = [
'django.template.context_processors.request', 'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth', 'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages', 'django.contrib.messages.context_processors.messages',
'django.template.context_processors.media',
], ],
}, },
}, },
@ -102,6 +103,12 @@ STATIC_URL = 'static/'
STATICFILES_DIRS = [BASE_DIR / "static",] STATICFILES_DIRS = [BASE_DIR / "static",]
STATIC_ROOT = '/var/www/sigi/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 # Default primary key field type
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field # 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 icon: comment
children: children:
- title: Painel de ocorrências - title: Painel de ocorrências
view_name: view_name: painel-ocorrencias
- title: Registro de ocorrências - title: Registro de ocorrências
view_name: admin:ocorrencias_ocorrencia_changelist view_name: admin:ocorrencias_ocorrencia_changelist
querystr: minhas=S&status__in=1,2 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 %}

98
sigi/templates/admin/change_list.html

@ -8,48 +8,41 @@
.side-wrapper { .side-wrapper {
width: 100%; width: 100%;
} }
</style>
<style>
#changelist { #changelist {
width:100% width:100%
} }
</style>
{% endblock extrastyle %}
{% block breadcrumbs %}{% endblock %}
{% block footer %} .float-filter {
{{ block.super }} right: 0;
<script> left: auto;
$(document).ready(function(){ position: fixed;
$('.fixed-action-btn').floatingActionButton(); width: 300px;
M.Tooltip.init($('.tooltipped'), {}); top: 0;
}); margin: 0;
</script> height: calc(100% + 60px);
padding-bottom: 60px;
background-color: #fff;
z-index: 999;
overflow-y: auto;
will-change: transform;
backface-visibility: hidden;
}
<script> </style>
document.addEventListener('DOMContentLoaded', function() { {% endblock extrastyle %}
var elems = document.getElementById('filter');
var instances = M.Sidenav.init(elems,'');
});
</script>
{% endblock footer %}
{% block content %}
<div id="content-main" class="list-content">
{% block object-tools %} {% block object-tools %}
<div class="fixed-action-btn"> <div class="fixed-action-btn">
<a class="btn-floating btn-large"> <a class="btn-floating btn-large">
<i class="large material-icons">build</i> <i class="large material-icons">build</i>
</a> </a>
<ul> <ul>
{% block object-tools-items %}
<li> <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' %}"> <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> <i class="material-icons" aria-hidden="true">filter_list</i>
</a> </a>
</li> </li>
{% block object-tools-items %}
{% if has_add_permission %} {% if has_add_permission %}
<li> <li>
{% url cl.opts|admin_urlname:'add' as add_url %} {% url cl.opts|admin_urlname:'add' as add_url %}
@ -62,29 +55,9 @@
</ul> </ul>
</div> </div>
{% endblock %} {% 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 %} {% block side_wrapper %}
{% result_list cl %} <div id="float-filter" class="float-filter hide">
{% 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="side-wrapper" class="side-wrapper">
<div id="changelist-form" class="card"> <div id="changelist-form" class="card">
{% if action_form and actions_on_top and cl.show_admin_actions %}{% admin_actions %}{% endif %} {% if action_form and actions_on_top and cl.show_admin_actions %}{% admin_actions %}{% endif %}
@ -94,15 +67,30 @@
</div> </div>
<div class="card"> <div class="card">
{% block filters %} {% block filters %}
{% if cl.has_filters %} {{ block.super }}
<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 %} {% endblock %}
</div> </div>
</div> </div>
</ul>
</div> </div>
{% endblock %} {% endblock %}
{% block footer %}
{{ block.super }}
<script>
$(document).ready(function(){
$('.fixed-action-btn').floatingActionButton();
M.Tooltip.init($('.tooltipped'), {});
// 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 %}

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

@ -1,6 +1,21 @@
{% extends "admin/index.html" %} {% extends "admin/index.html" %}
{% load static %} {% load static i18n %}
{% 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 %} {% block content %}
{% include 'sigi/snippets/dashboard.html' %} {% include 'sigi/snippets/dashboard.html' %}
{% endblock %} {% endblock %}
{% block footer %}
{{ block.super }}
<script src="{% static 'js/dashboard.js' %}"></script>
{% endblock footer %}

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

@ -4,7 +4,6 @@
{% if not mobile %} {% if not mobile %}
<i class="material-icons minimize nav-bar" aria-hidden="true" title="{% trans 'Minimize' %}">close</i> <i class="material-icons minimize nav-bar" aria-hidden="true" title="{% trans 'Minimize' %}">close</i>
{% endif %} {% endif %}
{% if available_apps %}
<ul class="collapsible"> <ul class="collapsible">
<li> <li>
<div class="card"> <div class="card">
@ -19,13 +18,4 @@
</li> </li>
{% show_menu 'main_menu' %} {% show_menu 'main_menu' %}
</ul> </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 %}
</div> </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 { .title_row {
background-color: #b2b2b2; background-color: #b2b2b2;
} }
.right-align {
text-align: right;
}
ul {
list-style-type: none;
margin: 0px;
padding: 0px;
}
{% endblock extra_style %} {% endblock extra_style %}
{% block body_content %} {% block body_content %}
@ -48,7 +57,7 @@ tr:nth-child(even) {
<p>{% trans 'SENADO FEDERAL' %}</p> <p>{% trans 'SENADO FEDERAL' %}</p>
<p>{% trans 'Instituto Legislativo Brasileiro - ILB' %}</p> <p>{% trans 'Instituto Legislativo Brasileiro - ILB' %}</p>
<p>{% trans "INTERLEGIS" %}</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> </header>
<footer>{% block footer %} <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="content-wrapper">
<div class="app-list"> <div class="app-list">
{% if app_list %} {% url "home_resumoseit" as source_url %}
{% for app in app_list %} {% include "sigi/snippets/base_card_text.html" with card_title="Serviços hospedados no Interlegis (SEIT)" data_source=source_url card_name="resumoseit" %}
<div class="app">
<div class="card"> {% url "home_chartseit" as source_url %}
<div class="card-content"> {% 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" %}
<div class="card-title">
{{ app.name }} {% url "casas-carteira" as source_url %}
</div> {% 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" %}
<div class="row">
{% for model in app.models %} {% url "home_chartperformance" as source_url %}
<div class="app-item col s6 m6 l4"> {% 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" %}
<a {% if model.admin_url %}href="{{ model.admin_url }}"{% else %}class="disabled"{% endif %}>
{% if model.count != None %} {% url "home_chartcarteira" as source_url %}
<div class="card app-count-badge"> {% include "sigi/snippets/base_card_chart.html" with card_title="Distribuição de Casas por Gerente" data_source=source_url chart_name="carteira" %}
<div class="badge-content">
{{ model.count }} {% url "home_resumoconvenios" as source_url %}
</div> {% include "sigi/snippets/base_card_text.html" with card_title="Resumo de informações" data_source=source_url card_name="resumo-convenios" %}
</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 %}
</div> </div>
</div> </div>

7
sigi/urls.py

@ -16,14 +16,19 @@ Including another URLconf
from django.contrib import admin from django.contrib import admin
from django.urls import path, include from django.urls import path, include
from django.conf import settings from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [ urlpatterns = [
path('admin/casas/', include('sigi.apps.casas.urls')), 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('admin/', admin.site.urls),
path('tinymce/', include('tinymce.urls')), path('tinymce/', include('tinymce.urls')),
path('', include('sigi.apps.home.urls')),
] ]
if settings.DEBUG: if settings.DEBUG:
urlpatterns = urlpatterns + [ urlpatterns = urlpatterns + [
path('__debug__/', include('debug_toolbar.urls')) 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