Browse Source

Merge branch 'stable/2.2' of https://github.com/interlegis/sigi into new_sigi

new_sigi^2
Lude Ribeiro 3 years ago
parent
commit
2e7851b317
  1. 19
      sigi/apps/casas/admin.py
  2. 13
      sigi/apps/casas/models.py
  3. 18
      sigi/apps/convenios/admin.py
  4. 20
      sigi/apps/convenios/migrations/0017_convenio_id_contrato_gescon.py
  5. 21
      sigi/apps/convenios/migrations/0018_auto_20211208_1256.py
  6. 18
      sigi/apps/convenios/models.py
  7. 20
      sigi/apps/convenios/reports.py
  8. 9
      sigi/apps/eventos/admin.py
  9. 21
      sigi/apps/eventos/migrations/0014_auto_20211124_0736.py
  10. 29
      sigi/apps/eventos/migrations/0015_anexo.py
  11. 26
      sigi/apps/eventos/models.py
  12. 2
      sigi/apps/eventos/templates/eventos/declaracao_pdf.html
  13. 2
      sigi/apps/metas/templates/metas/openmap.html
  14. 4
      sigi/apps/metas/templatetags/mapa_tags.py
  15. 2
      sigi/apps/metas/views.py
  16. 49
      sigi/apps/servicos/admin.py
  17. 4
      sigi/apps/servicos/templates/admin/servicos/servico/change_list.html
  18. 33
      sigi/apps/servicos/templates/servico/change_list.html
  19. 100
      sigi/apps/servicos/templates/servicos/carrinho.html
  20. 4
      sigi/apps/servicos/urls.py
  21. 194
      sigi/apps/servicos/views.py
  22. 14
      sigi/apps/servidores/models.py
  23. 1
      sigi/settings/base.py
  24. 8
      templates/base_report.html

19
sigi/apps/casas/admin.py

@ -374,6 +374,23 @@ class ServicoFilter(admin.SimpleListFilter):
return queryset.distinct('municipio__uf__nome', 'nome')
class ServicoAtivoFilter(admin.SimpleListFilter):
title = _(u"Serviço ativo")
parameter_name = 'ativo'
def lookups(self, request, model_admin):
return (
('ativo', _(u"Ativo")),
('desativado', _(u"Desativado")),
)
def queryset(self, request, queryset):
if self.value() is not None:
if self.value() == 'ativo':
queryset = queryset.filter(servico__data_desativacao__isnull=True)
else:
queryset = queryset.filter(servico__data_desativacao__isnull=False)
return queryset
@admin.register(Orgao)
class OrgaoAdmin(ImageCroppingMixin, BaseModelAdmin):
form = OrgaoForm
@ -384,7 +401,7 @@ class OrgaoAdmin(ImageCroppingMixin, BaseModelAdmin):
'get_servicos')
list_display_links = ('sigla', 'nome',)
list_filter = ('tipo', ('gerentes_interlegis', GerentesInterlegisFilter),
'municipio__uf__nome', ConvenioFilter, ExcluirConvenioFilter, ServicoFilter,
'municipio__uf__nome', ConvenioFilter, ServicoAtivoFilter, ExcluirConvenioFilter, ServicoFilter,
'inclusao_digital',)
ordering = ('municipio__uf__nome', 'nome')
queryset = queryset_ascii

13
sigi/apps/casas/models.py

@ -194,6 +194,19 @@ class Orgao(models.Model):
return self.funcionario_set.get(setor='presidente')
except Funcionario.DoesNotExist:
return None
@property
def contato_interlegis(self):
""" Link para acessar diretamente o contato do presidente da casa
Util para relatorios antigos
"""
try:
if self.funcionario_set.filter(setor='contato_interlegis').count() > 1:
return self.funcionario_set.filter(setor='contato_interlegis')[0]
else:
return self.funcionario_set.get(setor='contato_interlegis')
except Funcionario.DoesNotExist:
return None
@property
def total_parlamentares(self):

18
sigi/apps/convenios/admin.py

@ -62,15 +62,15 @@ class ConvenioAdmin(BaseModelAdmin):
'data_pub_diario',)}
),
(_(u'Gescon'),
{'fields': ('atualizacao_gescon', 'observacao_gescon',)}
{'fields': ('atualizacao_gescon', 'observacao_gescon', 'link_gescon')}
),
)
readonly_fields = ('data_sigi', 'atualizacao_gescon', 'observacao_gescon',)
readonly_fields = ('data_sigi', 'atualizacao_gescon', 'observacao_gescon', 'link_gescon')
actions = ['adicionar_convenios']
inlines = (AnexosInline,)
list_display = ('num_convenio', 'casa_legislativa', 'get_uf',
list_display = ('num_convenio', 'projeto','casa_legislativa', 'get_uf',
'status_convenio', 'link_sigad', 'data_retorno_assinatura',
'data_termino_vigencia', 'projeto',)
'data_termino_vigencia',)
list_display_links = ('num_convenio', 'casa_legislativa',)
list_filter = (('casa_legislativa__gerentes_interlegis',
GerentesInterlegisFilter), 'projeto',
@ -115,6 +115,16 @@ class ConvenioAdmin(BaseModelAdmin):
link_sigad.short_description = _("Processo no Senado")
link_sigad.allow_tags = True
def link_gescon(self, obj):
if not obj.id_contrato_gescon:
return u""
return (
u"<a href='https://adm.senado.gov.br/gestao-contratos/api/"
u"contratos/buscaTexto/{id}'>https://adm.senado.gov.br/"
u"gestao-contratos/api/{id}</a>").format(id=obj.id_contrato_gescon)
link_gescon.short_description = _("Download MINUTA ASSINADA do Gescon")
link_gescon.allow_tags = True
def changelist_view(self, request, extra_context=None):
from sigi.apps.convenios.views import normaliza_data
request.GET._mutable = True

20
sigi/apps/convenios/migrations/0017_convenio_id_contrato_gescon.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('convenios', '0016_auto_20210909_0732'),
]
operations = [
migrations.AddField(
model_name='convenio',
name='id_contrato_gescon',
field=models.CharField(default=b'', verbose_name='ID do contrato no Gescon', max_length=20, editable=False, blank=True),
preserve_default=True,
),
]

21
sigi/apps/convenios/migrations/0018_auto_20211208_1256.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('convenios', '0017_convenio_id_contrato_gescon'),
]
operations = [
migrations.AlterField(
model_name='convenio',
name='projeto',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, verbose_name='Tipo de Convenio', to='convenios.Projeto'),
preserve_default=True,
),
]

18
sigi/apps/convenios/models.py

@ -57,6 +57,7 @@ class Convenio(models.Model):
projeto = models.ForeignKey(
Projeto,
on_delete=models.PROTECT,
verbose_name=_(u'Tipo de Convenio')
)
# numero designado pelo Senado Federal para o convênio
num_processo_sf = models.CharField(
@ -71,6 +72,13 @@ class Convenio(models.Model):
max_length=10,
blank=True
)
id_contrato_gescon = models.CharField(
_(u"ID do contrato no Gescon"),
max_length=20,
blank=True,
default="",
editable=False
)
data_sigi = models.DateField(
_(u"data de cadastro no SIGI"),
blank=True,
@ -504,7 +512,7 @@ class Gescon(models.Model):
self.add_message(
_(u"\tErro ao acessar {url}: {errmsg}").format(
url=url,
errmsg=str(e)
errmsg=e.message.decode("utf8")
)
)
continue
@ -734,6 +742,12 @@ class Gescon(models.Model):
'terminoVigencia'
]
convenio.data_pub_diario = contrato['publicacao']
if contrato['codTextoContrato']:
convenio.id_contrato_gescon = contrato[
'codTextoContrato'
]
else:
convenio.id_contrato_gescon = ""
try:
convenio.save()
@ -748,7 +762,7 @@ class Gescon(models.Model):
convenio._meta.model_name),
args=[convenio.id]
),
errmsg=str(e)
errmsg=e.message.decode("utf8")
)
)
erros += 1

20
sigi/apps/convenios/reports.py

@ -54,19 +54,19 @@ class ConvenioReport(ReportDefault):
),
Label(
text=_(u"Projeto"),
left=label_left[5] * cm,
left=label_left[3] * cm,
top=label_top + 0.4 * cm,
width=2 * cm,
),
Label(
text=_(u"Data do Convênio"),
left=label_left[3] * cm,
left=label_left[4] * cm,
top=label_top,
width=2 * cm,
),
Label(
text=_(u"Data de Publicação"),
left=label_left[4] * cm,
left=label_left[5] * cm,
top=label_top,
width=2 * cm,
),
@ -100,17 +100,17 @@ class ConvenioReport(ReportDefault):
),
ObjectValue(
attribute_name='projeto.sigla',
left=label_left[5] * cm
left=label_left[3] * cm
),
ObjectValue(
attribute_name='data_retorno_assinatura',
left=label_left[3] * cm,
left=label_left[4] * cm,
get_value=lambda instance:
instance.data_retorno_assinatura.strftime('%d/%m/%Y') if instance.data_retorno_assinatura is not None else '-'
),
ObjectValue(
attribute_name='data_pub_diario',
left=label_left[4] * cm,
left=label_left[5] * cm,
get_value=lambda instance:
instance.data_pub_diario.strftime('%d/%m/%Y') if instance.data_pub_diario is not None else '-'
),
@ -163,13 +163,13 @@ class ConvenioReportSemAceite(ConvenioReport):
),
Label(
text=_(u"Projeto"),
left=label_left[4] * cm,
left=label_left[3] * cm,
top=label_top,
width=2 * cm,
),
Label(
text=_(u"Data do Convênio"),
left=label_left[3] * cm,
left=label_left[4] * cm,
top=label_top,
width=2 * cm,
),
@ -200,11 +200,11 @@ class ConvenioReportSemAceite(ConvenioReport):
),
ObjectValue(
attribute_name='projeto.sigla',
left=label_left[4],
left=label_left[3],
),
ObjectValue(
attribute_name='data_retorno_assinatura',
left=label_left[3] * cm,
left=label_left[4] * cm,
get_value=lambda instance:
instance.data_retorno_assinatura.strftime('%d/%m/%Y') if instance.data_retorno_assinatura is not None else '-'
),

9
sigi/apps/eventos/admin.py

@ -23,7 +23,8 @@ from django.contrib import admin
from django.db import models
from django.http import HttpResponseRedirect
from django.utils.translation import ugettext as _
from sigi.apps.eventos.models import ModeloDeclaracao, Modulo, TipoEvento, Funcao, Evento, Equipe, Convite
from sigi.apps.eventos.models import (ModeloDeclaracao, Modulo, TipoEvento,
Funcao, Evento, Equipe, Convite, Anexo)
from sigi.apps.eventos.views import adicionar_eventos_carrinho
from sigi.apps.eventos.forms import EventoAdminForm
@ -50,6 +51,10 @@ class ConviteInline(admin.TabularInline):
class ModuloInline(admin.TabularInline):
model = Modulo
class AnexoInline(admin.TabularInline):
model = Anexo
exclude = ('data_pub',)
@admin.register(Evento)
class EventoAdmin(admin.ModelAdmin):
form = EventoAdminForm
@ -62,7 +67,7 @@ class EventoAdmin(admin.ModelAdmin):
raw_id_fields = ('casa_anfitria', 'municipio',)
search_fields = ('nome', 'tipo_evento__nome', 'casa_anfitria__search_text',
'municipio__search_text', 'solicitante')
inlines = (EquipeInline, ConviteInline, ModuloInline)
inlines = (EquipeInline, ConviteInline, ModuloInline, AnexoInline)
actions = ['adicionar_eventos', ]
def adicionar_eventos(self, request, queryset):

21
sigi/apps/eventos/migrations/0014_auto_20211124_0736.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import tinymce.models
class Migration(migrations.Migration):
dependencies = [
('eventos', '0013_modelodeclaracao'),
]
operations = [
migrations.AlterField(
model_name='modelodeclaracao',
name='texto',
field=tinymce.models.HTMLField(help_text='Use as seguintes marca\xe7\xf5es:<ul><li>{{ casa.nome }} para o nome da Casa Legislativa / \xf3rg\xe3o</li><li>{{ casa.municipio.uf.sigla }} para a sigla da UF da Casa legislativa</li><li>{{ nome }} para o nome do visitante</li><li>{{ data }} para a data de emiss\xe3o da declara\xe7\xe3o</li><li>{{ evento.data_inicio }} para a data/hora do in\xedcio da visita</li><li>{{ evento.data_termino }} para a data/hora do t\xe9rmino da visita</li><li>{{ evento.nome }} para o nome do evento</li><li>{{ evento.descricao }} para a descri\xe7\xe3o do evento</li></ul>', verbose_name='Texto da declara\xe7\xe3o'),
preserve_default=True,
),
]

29
sigi/apps/eventos/migrations/0015_anexo.py

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import datetime
class Migration(migrations.Migration):
dependencies = [
('eventos', '0014_auto_20211124_0736'),
]
operations = [
migrations.CreateModel(
name='Anexo',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('arquivo', models.FileField(max_length=500, upload_to=b'apps/eventos/anexo/arquivo')),
('descricao', models.CharField(max_length=b'70', verbose_name='descri\xe7\xe3o')),
('data_pub', models.DateTimeField(default=datetime.datetime.now, verbose_name='data da publica\xe7\xe3o do anexo')),
('evento', models.ForeignKey(verbose_name='evento', to='eventos.Evento')),
],
options={
'ordering': ('-data_pub',),
},
bases=(models.Model,),
),
]

26
sigi/apps/eventos/models.py

@ -262,8 +262,10 @@ class ModeloDeclaracao(models.Model):
)
texto = HTMLField(
_(u"Texto da declaração"),
help_text=_(u"Use as seguintes marcações:<ul><li>{{ casa }} para o "
u"nome da Casa Legislativa / órgão</li><li>{{ nome }} "
help_text=_(u"Use as seguintes marcações:<ul><li>{{ casa.nome }} para o"
u" nome da Casa Legislativa / órgão</li>"
u"<li>{{ casa.municipio.uf.sigla }} para a sigla da UF da "
u"Casa legislativa</li><li>{{ nome }} "
u"para o nome do visitante</li><li>{{ data }} para a data "
u"de emissão da declaração</li><li>{{ evento.data_inicio }}"
u" para a data/hora do início da visita</li>"
@ -282,3 +284,23 @@ class ModeloDeclaracao(models.Model):
nome=self.nome,
formato=self.get_formato_display()
)
class Anexo(models.Model):
evento = models.ForeignKey(
Evento,
on_delete=models.CASCADE,
verbose_name=_(u'evento')
)
# caminho no sistema para o documento anexo
arquivo = models.FileField(upload_to='apps/eventos/anexo/arquivo', max_length=500)
descricao = models.CharField(_(u'descrição'), max_length='70')
data_pub = models.DateTimeField(
_(u'data da publicação do anexo'),
default=datetime.now
)
class Meta:
ordering = ('-data_pub',)
def __unicode__(self):
return unicode("%s publicado em %s" % (self.descricao, self.data_pub))

2
sigi/apps/eventos/templates/eventos/declaracao_pdf.html

@ -6,7 +6,7 @@
{% block report %}
{% for convite in evento.convite_set.all %}
{% with convite.casa.nome as casa %}
{% with convite.casa as casa %}
{% for nome in convite.nomes_participantes.splitlines %}
{% block text_body %}{% endblock %}
<pdf:nextpage />

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

@ -46,7 +46,7 @@
<a href="#" style="float: right;" id="options-toggler" type="button" data-toggle="collapse" data-target="#filterbox" aria-expanded="false" aria-controls="collapseExample">
<span class="glyphicon glyphicon-chevron-right"></span>
</a>
<div class="collapse" id="filterbox">
<div class="collapse in" id="filterbox">
<form id="searchform" class="form-inline ui-front">
<input type="text" id="search-text" class="form-control" placeholder="Procurar" aria-label="Procurar" aria-describedby="basic-addon2">
</form>

4
sigi/apps/metas/templatetags/mapa_tags.py

@ -3,7 +3,7 @@ from django import template
from django.utils.safestring import mark_safe
from sigi.apps.casas.models import Orgao
from sigi.apps.metas.views import parliament_summary
from sigi.apps.metas.views import openmap
register = template.Library()
@ -14,7 +14,7 @@ def descricao_servicos(casa):
if not isinstance(casa, Orgao):
return ""
summary = parliament_summary(casa)
summary = openmap(casa)
result = ''.join('<li>%s</li>' % info for info in summary['info'])
return mark_safe(result)
descricao_servicos.is_safe = True

2
sigi/apps/metas/views.py

@ -232,4 +232,4 @@ def openmapsearch(request):
'label': d['nome'],
'lat': d['municipio__latitude'],
'lng': d['municipio__longitude']} for d in dados]
return JsonResponse(list(dados), safe=False)
return JsonResponse(list(dados), safe=False)

49
sigi/apps/servicos/admin.py

@ -11,6 +11,7 @@ from sigi.apps.casas.admin import FuncionariosInline, GerentesInterlegisFilter
from sigi.apps.casas.models import Orgao
from sigi.apps.servicos.models import (Servico, LogServico, CasaAtendida,
TipoServico)
from sigi.apps.servicos.views import adicionar_servicos_carrinho
from sigi.apps.utils.base_admin import BaseModelAdmin
@ -111,6 +112,7 @@ class ServicoAtivoFilter(admin.SimpleListFilter):
return queryset
class ServicoAdmin(BaseModelAdmin):
change_list_template = "servico/change_list.html"
form = ServicoFormAdmin
actions = ['calcular_data_uso', ]
list_display = ('casa_legislativa', 'get_codigo_interlegis', 'get_uf', 'tipo_servico', 'hospedagem_interlegis',
@ -137,6 +139,7 @@ class ServicoAdmin(BaseModelAdmin):
'casa_legislativa__municipio__uf',
)
list_display_links = []
actions = ['adicionar_servicos']
ordering = ('casa_legislativa__municipio__uf', 'casa_legislativa', 'tipo_servico',)
inlines = (LogServicoInline,)
search_fields = ('casa_legislativa__search_text',)
@ -169,6 +172,22 @@ class ServicoAdmin(BaseModelAdmin):
get_link_erro.short_description = _(u"Erro na atualização")
get_link_erro.admin_order_field = 'erro_atualizacao'
def adicionar_servicos(self, request, queryset):
if 'carrinho_servicos' in request.session:
q1 = len(request.session['carrinho_servicos'])
else:
q1 = 0
adicionar_servicos_carrinho(request, queryset=queryset)
q2 = len(request.session['carrinho_servicos'])
quant = q2 - q1
if quant:
self.message_user(request, str(q2 - q1) + _(u" Serviços adicionados no carrinho"))
else:
self.message_user(request, _(u"Os Serviços selecionados já foram adicionadas anteriormente"))
return HttpResponseRedirect('.')
adicionar_servicos.short_description = _(u"Armazenar serviços no carrinho para exportar")
def calcular_data_uso(self, request, queryset):
for servico in queryset:
servico.atualiza_data_uso()
@ -186,7 +205,7 @@ class ServicoAdmin(BaseModelAdmin):
def lookup_allowed(self, lookup, value):
return super(ServicoAdmin, self).lookup_allowed(lookup, value) or \
lookup in ['casa_legislativa__municipio__uf__codigo_ibge__exact']
lookup in ['casa_legislativa__municipio__uf__codigo_ibge__exact', ]
def add_view(self, request, form_url='', extra_context=None):
id_casa = request.GET.get('id_casa', None)
@ -234,6 +253,34 @@ class ServicoAdmin(BaseModelAdmin):
obj.casa_legislativa = Orgao.objects.get(pk=id_casa)
return obj
def changelist_view(self, request, extra_context=None):
from sigi.apps.convenios.views import normaliza_data
request.GET._mutable = True
normaliza_data(request.GET, 'data_ativacao__gte')
normaliza_data(request.GET, 'data_ativacao__lte')
request.GET._mutable = False
return super(ServicoAdmin, self).changelist_view(
request,
extra_context={'query_str': '?' + request.META['QUERY_STRING']}
)
def adicionar_servicos(self, request, queryset):
if 'carrinho_servicos' in request.session:
q1 = len(request.session['carrinho_servicos'])
else:
q1 = 0
adicionar_servicos_carrinho(request, queryset=queryset)
q2 = len(request.session['carrinho_servicos'])
quant = q2 - q1
if quant:
self.message_user(request, str(q2 - q1) + _(u" Convênios adicionados no carrinho"))
else:
self.message_user(request, _(u"Os Convênios selecionados já foram adicionadas anteriormente"))
return HttpResponseRedirect('.')
adicionar_servicos.short_description = _(u"Armazenar Serviços no carrinho para exportar")
class ContatosInline(FuncionariosInline):

4
sigi/apps/servicos/templates/admin/servicos/servico/change_list.html

@ -1,4 +0,0 @@
{% extends "admin/change_list.html" %}
{% block object-tools-items %}
{% endblock %}

33
sigi/apps/servicos/templates/servico/change_list.html

@ -0,0 +1,33 @@
{% extends "change_list_with_cart.html" %}
{% load i18n %}
{% block extra_search %}
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Filtro de datas</a>
<p class="navbar-text">Use AAAA, AAAA-MM ou AAAA-MM-DD</p>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<form class="navbar-form navbar-left" role="extra-search" id="changelist-extrasearch" action="" method="get">
<div class="form-group">
<label for="data_ativacao__gte">{% trans 'Ativados a partir de' %}:</label>
<input type="text" class="form-control search-query" size="10" name="data_ativacao__gte" value="" id="data_ativacao__gte">
<label for="data_ativacao__lte">{% trans 'até' %}:</label>
<input type="text" class="form-control search-query" size="10" name="data_ativacao__lte" value="" id="data_ativacao__lte">
</div>
<button type="submit" class="btn btn-default navbar-btn ">
<span class="glyphicon glyphicon-search"></span>
</button>
</form>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
{% endblock %}

100
sigi/apps/servicos/templates/servicos/carrinho.html

@ -0,0 +1,100 @@
{% extends "admin/carrinho.html" %}
{% load admin_list i18n %}
{% block extrastyle %}
{{ block.super }}
{% include "admin/tabs_style.html" %}
{% endblock %}
{% block title %}{% trans 'Serviços no Carrinho | SIGI' %}{% endblock %}
{% block content_title %}<h1>{% trans 'Serviços no Carrinho' %}</h1>{% endblock %}
{% block mensagem%}
<ul class="messagelist">
{%if carIsEmpty%}
<li class="warning">{% trans 'O carrinho está vazio, sendo assim todos os Serviços entram na lista para exportação de acordo com os filtros aplicados.' %}</li>
{%else%}
<li>{{paginas.paginator.count}} {% trans 'Serviços no carrinho' %}.</li>
{%endif%}
</ul>
{% endblock %}
{% block action %}deleta_itens_carrinho{% endblock %}
{% block tabela %}
<table class="table table-striped">
<thead class="thead-dark">
<tr>
{%if not carIsEmpty%}
<th class="sorted ascending"><!-- <input type="checkbox" id="action-toggle" style="display: inline;">-->
</th>
{% endif %}
<th class="sorted ascending">{% trans 'Casa Legislativa' %}</th>
<th class="sorted ascending">{% trans 'UF' %}</th>
<th class="sorted ascending">{% trans 'Email' %}</th>
<th class="sorted ascending">{% trans 'Telefone' %}</th>
<th class="sorted ascending">{% trans 'Contato Interlegis' %}</th>
<th class="sorted ascending">{% trans 'Tipo de Serviço' %}</th>
<th class="sorted ascending">{% trans 'Data Ativação' %}</th>
</tr>
</thead>
<tbody>
{% for servico in paginas.object_list %}
<tr>
{%if not carIsEmpty%}
<th><input type="checkbox" name="_selected_action"
value="{{servico.id|safe}}" class="action-select" /></th>
{% endif %}
<td style="text-align: left;">{{servico.casa_legislativa}}</td>
<td>{{servico.casa_legislativa.municipio.uf.sigla}}</td>
<td>{{servico.casa_legislativa.email}}</td>
<td>{{servico.casa_legislativa.telefone}}</td>
<td>{{servico.casa_legislativa.contato_interlegis}}</td>
<td>{{servico.casa_legislativa.contato_interlegis.email}}</td>
<td>{{servico.tipo_servico}}</td>
<td>{{servico.data_ativacao}}</td></tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
{% block botoes %}
<ul class="nav nav-tabs" role="tablist">
<li class="active" role="presentation"><a href="#tabs-2" aria-controls="tabs-2" role="tab" data-toggle="tab">{% trans 'Arquivo CSV (Excel, Calc)' %}</a></li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="tabs-2">
<form action="../csv/{{query_str}}" method="post">{% csrf_token %}
<fieldset>
<legend>{% trans 'Escolha os atributos para exportar' %}</legend>
<ul id="sortable" class="tabs-conteudo">
<li>
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span>
<input type="checkbox" name="itens_csv_selected" value="Casa Legislativa"
class="action-select" checked="checked" />
<label>{% trans 'Casa Legislativa' %}</label>
</li>
<li>
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span>
<input type="checkbox" name="itens_csv_selected" value="Contato Interlegis"
class="action-select" checked="checked" />
<label>{% trans 'Contato Interlegis' %}</label>
</li>
<li>
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span>
<input type="checkbox" name="itens_csv_selected" value="Produto"
class="action-select" checked="checked" />
<label>{% trans 'Produto' %}</label>
</li>
<li>
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span>
<input type="checkbox" name="itens_csv_selected" value="Data de Ativação"
class="action-select" checked="checked" />
<label>{% trans 'Data de Ativação' %}</label>
</li>
</ul>
</fieldset>
<input type="submit" value="Exportar CSV" type="button" class="btn btn-primary"/>
</form>
</div>
</div>
{% endblock %}

4
sigi/apps/servicos/urls.py

@ -9,6 +9,10 @@ urlpatterns = patterns(
'sigi.apps.servicos.views',
url(r'^manifesta/$', 'casa_manifesta_view', name="casa-manifesta-view"),
url(r'^servico/carrinho/$', 'visualizar_carrinho', name='visualizar-carrinho'),
url(r'^servico/carrinho/excluir_carrinho/$', 'excluir_carrinho', name='excluir-carrinho'), # tagerror
url(r'^servico/carrinho/deleta_itens_carrinho$', 'deleta_itens_carrinho', name='deleta-itens-carrinho'), # tagerror
url(r'^servico/csv/$', 'export_csv', name='servicos-csv'),
url(r'^munatenjson/(?P<servico>\w+)/$', 'municipios_atendidos', name="municipios-atendidos"),
url(r'^mapa/(?P<servico>\w+)/$', MapaView.as_view(), name="servicos-mapa"),
# url(r'^listacasas/(?P<sigla>\w+)', 'casas_usam_servico', name="casas-usam-servico"),

194
sigi/apps/servicos/views.py

@ -1,18 +1,24 @@
# -*- coding: utf-8 -*-
import csv
import json as simplejson # XXX trocar isso por simplesmente import json e refatorar o codigo
from django import forms
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core.paginator import EmptyPage, InvalidPage, Paginator
from django.db.models import Q
from django.forms.forms import BoundField
from django.http import HttpResponse
from django.shortcuts import render_to_response, get_object_or_404
from django.http.response import HttpResponseRedirect
from django.shortcuts import render, render_to_response, get_object_or_404
from django.template.context import RequestContext
from django.utils.translation import ugettext as _
from django.views.generic.base import TemplateView
from sigi.apps.casas.models import Orgao
from sigi.apps.contatos.models import UnidadeFederativa
from sigi.apps.servicos.models import (TipoServico, CasaManifesta, CasaAtendida,
from sigi.apps.convenios.views import normaliza_data, query_ordena
from sigi.apps.servicos.models import (Servico, TipoServico, CasaManifesta, CasaAtendida,
ServicoManifesto)
@ -144,3 +150,187 @@ def casa_manifesta_view(request):
extra_context = {'uf_list': UnidadeFederativa.objects.all()}
return render_to_response('servicos/casa_manifesta.html', extra_context, context_instance=RequestContext(request))
def adicionar_servicos_carrinho(request, queryset=None, id=None):
if request.method == 'POST':
ids_selecionados = request.POST.getlist('_selected_action')
if 'carrinho_servicos' not in request.session:
request.session['carrinho_servicos'] = ids_selecionados
else:
lista = request.session['carrinho_servicos']
# Verifica se id já não está adicionado
for id in ids_selecionados:
if id not in lista:
lista.append(id)
request.session['carrinho_servicos'] = lista
def carrinhoOrGet_for_qs(request):
"""
Verifica se existe convênios na sessão se não verifica get e retorna qs correspondente.
"""
if 'carrinho_servicos' in request.session:
ids = request.session['carrinho_servicos']
qs = Servico.objects.filter(pk__in=ids)
qs = qs.order_by("casa_legislativa__municipio__uf", "casa_legislativa__municipio")
qs = get_for_qs(request.GET, qs)
else:
qs = Servico.objects.all()
if request.GET:
qs = qs.order_by("casa_legislativa__municipio__uf", "casa_legislativa__municipio")
qs = get_for_qs(request.GET, qs)
return qs
def adicionar_servicos_carrinho(request, queryset=None, id=None):
if request.method == 'POST':
ids_selecionados = request.POST.getlist('_selected_action')
if 'carrinho_servicos' not in request.session:
request.session['carrinho_servicos'] = ids_selecionados
else:
lista = request.session['carrinho_servicos']
# Verifica se id já não está adicionado
for id in ids_selecionados:
if id not in lista:
lista.append(id)
request.session['carrinho_servicos'] = lista
@login_required
def excluir_carrinho(request):
if 'carrinho_servicos' in request.session:
del request.session['carrinho_servicos']
messages.info(request, u'O carrinho foi esvaziado')
return HttpResponseRedirect('../../')
@login_required
def deleta_itens_carrinho(request):
if request.method == 'POST':
ids_selecionados = request.POST.getlist('_selected_action')
if 'carrinho_servicos' in request.session:
lista = request.session['carrinho_servicos']
for item in ids_selecionados:
lista.remove(item)
if lista:
request.session['carrinho_servicos'] = lista
else:
del lista
del request.session['carrinho_servicos']
return HttpResponseRedirect('.')
@login_required
def visualizar_carrinho(request):
qs = carrinhoOrGet_for_qs(request)
paginator = Paginator(qs, 100)
# Make sure page request is an int. If not, deliver first page.
# Esteja certo de que o `page request` é um inteiro. Se não, mostre a primeira página.
try:
page = int(request.GET.get('page', '1'))
except ValueError:
page = 1
# Se o page request (9999) está fora da lista, mostre a última página.
try:
paginas = paginator.page(page)
except (EmptyPage, InvalidPage):
paginas = paginator.page(paginator.num_pages)
carrinhoIsEmpty = not('carrinho_servicos' in request.session)
return render(
request,
'servicos/carrinho.html',
{
'carIsEmpty': carrinhoIsEmpty,
'paginas': paginas,
'query_str': '?' + request.META['QUERY_STRING']
}
)
def get_for_qs(get, qs):
kwargs = {}
ids = 0
get._mutable = True
normaliza_data(get, 'data_ativacao__gte')
normaliza_data(get, 'data_ativacao__lte')
get._mutable = False
for k, v in get.iteritems():
if k not in ['page', 'pop', 'q', '_popup']:
if not k == 'o':
if k == "ot":
qs = query_ordena(qs, get["o"], get["ot"])
else:
kwargs[str(k)] = v
if(str(k) == 'ids'):
ids = 1
break
qs = qs.filter(**kwargs)
if ids:
query = 'id IN (' + kwargs['ids'].__str__() + ')'
qs = Servico.objects.extra(where=[query])
return qs
@login_required
def export_csv(request):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=servicos.csv'
csv_writer = csv.writer(response)
servicos = carrinhoOrGet_for_qs(request)
if not servicos:
return HttpResponseRedirect('../')
atributos = [_(u"Casa Legislativa"), _(u"Contato Interlegis"), _(u"Produto"),
_(u"Data de Ativação"), ]
if request.POST:
atributos = request.POST.getlist("itens_csv_selected")
col_titles = atributos
if _(u"Casa Legislativa") in col_titles:
pos = col_titles.index(_(u"Casa Legislativa")) + 1
col_titles.insert(pos, _(u"uf"))
pos+=1
col_titles.insert(pos, _(u"email"))
pos+=1
col_titles.insert(pos, _(u"telefone"))
if _(u"Contato Interlegis") in col_titles:
pos = col_titles.index(_(u"Contato Interlegis")) + 1
col_titles.insert(pos, _(u"Email do contato"))
csv_writer.writerow([s.encode("utf-8") for s in col_titles])
for servico in servicos:
lista = []
for atributo in atributos:
if _(u"Casa Legislativa") == atributo:
lista.append(servico.casa_legislativa.nome.encode("utf-8"))
lista.append(servico.casa_legislativa.municipio.uf.sigla.encode("utf-8"))
lista.append(servico.casa_legislativa.email.encode("utf-8"))
if servico.casa_legislativa.telefone is not None:
lista.append(servico.casa_legislativa.telefone)
else:
lista.append("")
elif _(u"Contato Interlegis") == atributo:
if servico.casa_legislativa.contato_interlegis is not None:
lista.append(servico.casa_legislativa.contato_interlegis)
lista.append(servico.casa_legislativa.contato_interlegis.email.encode("utf-8"))
else:
lista.append("")
lista.append("")
elif _(u"Produto") == atributo:
lista.append(servico.tipo_servico.nome.encode("utf-8"))
elif _(u"Data de Ativação") == atributo:
data = ''
if servico.data_ativacao:
data = servico.data_ativacao.strftime("%d/%m/%Y")
lista.append(data.encode("utf-8"))
else:
pass
csv_writer.writerow(lista)
return response

14
sigi/apps/servidores/models.py

@ -2,7 +2,7 @@
from django.contrib.auth.models import User
from django.contrib.contenttypes import generic
from django.db import models
from django.db.models.signals import post_save
from django.db.models.signals import post_save, pre_save
from django.utils.translation import ugettext as _
class Servico(models.Model):
@ -89,4 +89,14 @@ def create_user_profile(sender, instance, created, **kwargs):
nome_completo="%s %s" % (instance.first_name, instance.last_name)
)
post_save.connect(create_user_profile, sender=User)
post_save.connect(create_user_profile, sender=User)
# Hack horrível para ajustar o first_name e o last_name do User criado pelo
# Django-ldap. Os campos first_name e last_name têm o tamanho máximo de
# 30 caracteres, mas o LDAP não tem esse limite, e alguns usuários podem ter
# nomes maiores que isso, o que provoca erro ao salvar o usuário.j
def ajusta_nome_usuario(sender, instance, *args, **kwargs):
instance.first_name = instance.first_name[:30]
instance.last_name = instance.last_name[:30]
pre_save.connect(ajusta_nome_usuario, sender=User)

1
sigi/settings/base.py

@ -95,6 +95,7 @@ LANGUAGE_CODE = 'pt-br'
USE_I18N = True
USE_L10N = True
USE_THOUSAND_SEPARATOR = True
TIME_ZONE = "America/Sao_Paulo"
gettext_noop = lambda s: s # for gettext discovery
LANGUAGES = (

8
templates/base_report.html

@ -15,6 +15,11 @@
font-size: 1.2em;
text-align: center;
}
.orgao_name {
margin-bottom: 0px;
margin-top: 0px;
font-weight: bold;
}
h1 {
font-size: 2em;
text-align: center;
@ -82,7 +87,8 @@
<td class="logo"><img src="{% static 'img/logo-senado.jpg' %}" /></td>
<td class="header_text">
<p><strong>{% trans 'SENADO FEDERAL' %}</strong></p>
<p><strong>{% trans 'INSTITUTO LEGISLATIVO BRASILEIRO - ILB / INTERLEGIS' %}</strong></p>
<p class="orgao_name">{% trans 'Instituto Legislativo Brasileiro' %}</p>
<p class="orgao_name">{% trans "ILB / Interlegis" %}</p>
<p>{% block subsecretaria %}{% endblock %}</p>
</td>
<td class="logo"><img src="{% static 'img/logo-interlegis.jpg' %}" /></td>

Loading…
Cancel
Save