Browse Source

Merge branch 'master' of github.com:interlegis/sapl

pull/585/head
Eduardo Calil 8 years ago
parent
commit
0ee39ddc90
  1. 61
      sapl/base/forms.py
  2. 11
      sapl/base/urls.py
  3. 97
      sapl/base/views.py
  4. 19
      sapl/materia/admin.py
  5. 106
      sapl/materia/views.py
  6. 38
      sapl/templates/base/RelatorioAtas_filter.html
  7. 50
      sapl/templates/base/RelatorioPresencaSessao_filter.html
  8. 4
      sapl/templates/base/relatorios_list.html
  9. 6
      sapl/templates/sessao/pauta_sessao_list.html

61
sapl/base/forms.py

@ -10,6 +10,7 @@ from django.utils.translation import ugettext_lazy as _
from sapl.crispy_layout_mixin import form_actions, to_row
from sapl.materia.models import MateriaLegislativa
from sapl.sessao.models import SessaoPlenaria
from sapl.settings import MAX_IMAGE_UPLOAD_SIZE
from sapl.utils import (RANGE_ANOS, ImageThumbnailFileInput, autor_label,
autor_modal)
@ -37,6 +38,66 @@ class RangeWidgetOverride(forms.MultiWidget):
return ''.join(rendered_widgets)
class RelatorioAtasFilterSet(django_filters.FilterSet):
filter_overrides = {models.DateField: {
'filter_class': django_filters.DateFromToRangeFilter,
'extra': lambda f: {
'label': '%s (%s)' % (f.verbose_name, _('Inicial - Final')),
'widget': RangeWidgetOverride}
}}
class Meta:
model = SessaoPlenaria
fields = ['data_inicio']
def __init__(self, *args, **kwargs):
super(RelatorioAtasFilterSet, self).__init__(
*args, **kwargs)
self.filters['data_inicio'].label = 'Período (Inicial - Final)'
self.form.fields['data_inicio'].required = True
row1 = to_row([('data_inicio', 12)])
self.form.helper = FormHelper()
self.form.helper.form_method = 'GET'
self.form.helper.layout = Layout(
Fieldset(_('Atas das Sessões Plenárias'),
row1, form_actions(save_label='Pesquisar'))
)
class RelatorioPresencaSessaoFilterSet(django_filters.FilterSet):
filter_overrides = {models.DateField: {
'filter_class': django_filters.DateFromToRangeFilter,
'extra': lambda f: {
'label': '%s (%s)' % (f.verbose_name, _('Inicial - Final')),
'widget': RangeWidgetOverride}
}}
class Meta:
model = SessaoPlenaria
fields = ['data_inicio']
def __init__(self, *args, **kwargs):
super(RelatorioPresencaSessaoFilterSet, self).__init__(
*args, **kwargs)
self.filters['data_inicio'].label = 'Período (Inicial - Final)'
self.form.fields['data_inicio'].required = True
row1 = to_row([('data_inicio', 12)])
self.form.helper = FormHelper()
self.form.helper.form_method = 'GET'
self.form.helper.layout = Layout(
Fieldset(_('Presença dos parlamentares nas sessões plenárias'),
row1, form_actions(save_label='Pesquisar'))
)
class RelatorioHistoricoTramitacaoFilterSet(django_filters.FilterSet):
filter_overrides = {models.DateField: {

11
sapl/base/urls.py

@ -4,11 +4,12 @@ from django.views.generic.base import TemplateView
from .apps import AppConfig
from .forms import LoginForm
from .views import (CasaLegislativaCrud, HelpView,
from .views import (CasaLegislativaCrud, HelpView, RelatorioAtasView,
RelatorioHistoricoTramitacaoView,
RelatorioMateriasPorAnoAutorTipoView,
RelatorioMateriasPorAutorView,
RelatorioMateriasTramitacaoView)
RelatorioMateriasTramitacaoView,
RelatorioPresencaSessaoView)
app_name = AppConfig.name
@ -39,5 +40,11 @@ urlpatterns = [
url(r'^relatorio/historico-tramitacoes$',
RelatorioHistoricoTramitacaoView.as_view(),
name='historico_tramitacoes'),
url(r'^relatorio/presenca$',
RelatorioPresencaSessaoView.as_view(),
name='presenca_sessao'),
url(r'^relatorio/atas$',
RelatorioAtasView.as_view(),
name='atas'),
]

97
sapl/base/views.py

@ -1,5 +1,8 @@
from itertools import chain
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.core.urlresolvers import reverse
from django.db.models import Count, Q
from django.http import HttpResponseRedirect
from django.utils.translation import ugettext_lazy as _
from django.views.generic.base import TemplateView
@ -8,12 +11,17 @@ from django_filters.views import FilterView
from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView,
CrudDetailView, CrudUpdateView)
from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa
from sapl.parlamentares.models import Parlamentar
from sapl.sessao.models import (OrdemDia, PresencaOrdemDia, SessaoPlenaria,
SessaoPlenariaPresenca)
from sapl.utils import permissao_tb_aux
from .forms import (CasaLegislativaForm, RelatorioHistoricoTramitacaoFilterSet,
from .forms import (CasaLegislativaForm, RelatorioAtasFilterSet,
RelatorioHistoricoTramitacaoFilterSet,
RelatorioMateriasPorAnoAutorTipoFilterSet,
RelatorioMateriasPorAutorFilterSet,
RelatorioMateriasTramitacaoilterSet)
RelatorioMateriasTramitacaoilterSet,
RelatorioPresencaSessaoFilterSet)
from .models import CasaLegislativa
@ -21,6 +29,91 @@ def get_casalegislativa():
return CasaLegislativa.objects.first()
class RelatorioAtasView(FilterView):
model = SessaoPlenaria
filterset_class = RelatorioAtasFilterSet
template_name = 'base/RelatorioAtas_filter.html'
def get_context_data(self, **kwargs):
context = super(RelatorioAtasView,
self).get_context_data(**kwargs)
context['title'] = _('Atas das Sessões Plenárias')
# Verifica se os campos foram preenchidos
if not self.filterset.form.is_valid():
return context
context['object_list'] = context['object_list'].exclude(upload_ata='')
qr = self.request.GET.copy()
context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
return context
class RelatorioPresencaSessaoView(FilterView):
model = SessaoPlenaria
filterset_class = RelatorioPresencaSessaoFilterSet
template_name = 'base/RelatorioPresencaSessao_filter.html'
def calcular_porcentagem_presenca(self,
parlamentares,
total_sessao,
total_ordemdia):
for p in parlamentares:
p.sessao_porc = round(p.sessao_count * 100 / total_sessao, 1)
p.ordemdia_porc = round(p.ordemdia_count * 100 / total_ordemdia, 1)
return parlamentares
def get_context_data(self, **kwargs):
context = super(RelatorioPresencaSessaoView,
self).get_context_data(**kwargs)
context['title'] = _('Presença dos parlamentares nas sessões')
# Verifica se os campos foram preenchidos
if not self.filterset.form.is_valid():
return context
# =====================================================================
if 'salvar' in self.request.GET:
where = context['object_list'].query.where
_range = where.children[0].rhs
sufixo = 'sessao_plenaria__data_inicio__range'
param0 = {'%s' % sufixo: _range}
param1 = {'presencaordemdia__%s' % sufixo: _range}
param2 = {'sessaoplenariapresenca__%s' % sufixo: _range}
pls = Parlamentar.objects.filter(
Q(**param1) & Q(**param2)).annotate(
sessao_count=Count(
'sessaoplenariapresenca__sessao_plenaria__data_inicio',
distinct=True),
ordemdia_count=Count(
'presencaordemdia__sessao_plenaria',
distinct=True),
sessao_porc=Count(0),
ordemdia_porc=Count(0))
total_ordemdia = OrdemDia.objects.order_by(
'sessao_plenaria').filter(**param0).distinct(
'sessao_plenaria').count()
self.calcular_porcentagem_presenca(
pls,
context['object_list'].count(),
total_ordemdia)
context['total_ordemdia'] = total_ordemdia
context['total_sessao'] = context['object_list'].count()
context['parlamentares'] = pls
context['periodo'] = (
self.request.GET['data_inicio_0'] +
' - ' + self.request.GET['data_inicio_1'])
# =====================================================================
qr = self.request.GET.copy()
context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
return context
class RelatorioHistoricoTramitacaoView(FilterView):
model = MateriaLegislativa
filterset_class = RelatorioHistoricoTramitacaoFilterSet

19
sapl/materia/admin.py

@ -1,3 +1,22 @@
from django.contrib import admin
from sapl.materia.models import Proposicao
from sapl.settings import DEBUG
from sapl.utils import register_all_models_in_admin
register_all_models_in_admin(__name__)
if not DEBUG:
admin.site.unregister(Proposicao)
class ProposicaoAdmin(admin.ModelAdmin):
def has_add_permission(self, request, obj=None):
return False
def has_change_permission(self, request, obj=None):
return False
def has_delete_permission(self, request, obj=None):
return False
admin.site.register(Proposicao, ProposicaoAdmin)

106
sapl/materia/views.py

@ -4,6 +4,7 @@ from string import ascii_letters, digits
from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML, Button
from django.db.models import Q
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.mixins import PermissionRequiredMixin
@ -31,7 +32,7 @@ from sapl.crud.masterdetail import MasterDetailCrud
from sapl.norma.models import LegislacaoCitada
from sapl.utils import (autor_label, autor_modal, gerar_hash_arquivo,
get_base_url, permissao_tb_aux, permissoes_autor,
permissoes_materia)
permissoes_materia, permissoes_protocoloadm)
from .forms import (AcompanhamentoMateriaForm, AnexadaForm, AutorForm,
AutoriaForm, ConfirmarProposicaoForm, DespachoInicialForm,
@ -243,11 +244,12 @@ class UnidadeTramitacaoCrud(Crud):
permission_required = permissoes_materia()
class ProposicaoDevolvida(ListView):
class ProposicaoDevolvida(PermissionRequiredMixin, ListView):
template_name = 'materia/prop_devolvidas_list.html'
model = Proposicao
ordering = ['data_envio']
paginate_by = 10
permission_required = permissoes_protocoloadm()
def get_queryset(self):
return Proposicao.objects.filter(
@ -265,11 +267,12 @@ class ProposicaoDevolvida(ListView):
return context
class ProposicaoPendente(ListView):
class ProposicaoPendente(PermissionRequiredMixin, ListView):
template_name = 'materia/prop_pendentes_list.html'
model = Proposicao
ordering = ['data_envio', 'autor', 'tipo', 'descricao']
paginate_by = 10
permission_required = permissoes_protocoloadm()
def get_queryset(self):
return Proposicao.objects.filter(
@ -287,11 +290,12 @@ class ProposicaoPendente(ListView):
return context
class ProposicaoRecebida(ListView):
class ProposicaoRecebida(PermissionRequiredMixin, ListView):
template_name = 'materia/prop_recebidas_list.html'
model = Proposicao
ordering = ['data_envio']
paginate_by = 10
permission_required = permissoes_protocoloadm()
def get_queryset(self):
return Proposicao.objects.filter(
@ -309,9 +313,10 @@ class ProposicaoRecebida(ListView):
return context
class ReceberProposicao(CreateView):
class ReceberProposicao(PermissionRequiredMixin, CreateView):
template_name = "materia/receber_proposicao.html"
form_class = ReceberProposicaoForm
permission_required = permissoes_protocoloadm()
def get_context_data(self, **kwargs):
context = super(ReceberProposicao, self).get_context_data(**kwargs)
@ -341,9 +346,10 @@ class ReceberProposicao(CreateView):
return reverse('sapl.materia:receber-proposicao')
class ConfirmarProposicao(CreateView):
class ConfirmarProposicao(PermissionRequiredMixin, CreateView):
template_name = "materia/confirmar_proposicao.html"
form_class = ConfirmarProposicaoForm
permission_required = permissoes_protocoloadm()
def get_context_data(self, **kwargs):
context = super(ConfirmarProposicao, self).get_context_data(**kwargs)
@ -433,38 +439,36 @@ class ProposicaoCrud(Crud):
def has_permission(self):
perms = self.get_permission_required()
if self.request.user.has_perms(perms):
if (Proposicao.objects.filter(
id=self.kwargs['pk'],
autor__user_id=self.request.user.id).exists()):
proposicao = Proposicao.objects.get(
id=self.kwargs['pk'],
autor__user_id=self.request.user.id)
if not proposicao.data_recebimento:
return True
else:
msg = _('Essa proposição já foi recebida. ' +
'Não pode mais ser editada')
messages.add_message(self.request, messages.ERROR, msg)
return False
else:
if not self.request.user.has_perms(perms):
return False
if (Proposicao.objects.filter(
id=self.kwargs['pk'],
autor__user_id=self.request.user.id).exists()):
proposicao = Proposicao.objects.get(
id=self.kwargs['pk'],
autor__user_id=self.request.user.id)
if (not proposicao.data_recebimento or
proposicao.data_devolucao):
return True
else:
msg = _('Essa proposição já foi recebida. ' +
'Não pode mais ser editada')
messages.add_message(self.request, messages.ERROR, msg)
return False
class DetailView(PermissionRequiredMixin, CrudDetailView):
permission_required = permissoes_autor()
def has_permission(self):
perms = self.get_permission_required()
if self.request.user.has_perms(perms):
if (Proposicao.objects.filter(
id=self.kwargs['pk'],
autor__user_id=self.request.user.id).exists()):
return True
else:
return False
else:
if not self.request.user.has_perms(perms):
return False
return (Proposicao.objects.filter(
id=self.kwargs['pk'],
autor__user_id=self.request.user.id).exists())
class ListView(PermissionRequiredMixin, CrudListView):
ordering = ['-data_envio', 'descricao']
permission_required = permissoes_autor()
@ -480,35 +484,69 @@ class ProposicaoCrud(Crud):
obj.data_recebimento = 'Não recebida'
else:
obj.data_recebimento = obj.data_recebimento.strftime(
"%d/%m/%Y %H:%M")
"%d/%m/%Y %H:%M")
return [self._as_row(obj) for obj in object_list]
def get_queryset(self):
# Só tem acesso as Proposicoes criadas por ele que ainda nao foram
# recebidas ou foram devolvidas
lista = Proposicao.objects.filter(
autor__user_id=self.request.user.id)
lista = lista.filter(
Q(data_recebimento__isnull=True) |
Q(data_devolucao__isnull=False))
return lista
class DeleteView(PermissionRequiredMixin, CrudDeleteView):
permission_required = {'materia.delete_proposicao'}
def has_permission(self):
perms = self.get_permission_required()
if not self.request.user.has_perms(perms):
return False
return (Proposicao.objects.filter(
id=self.kwargs['pk'],
autor__user_id=self.request.user.id).exists())
def delete(self, request, *args, **kwargs):
proposicao = Proposicao.objects.get(id=self.kwargs['pk'])
if not proposicao.data_envio:
if not proposicao.data_envio or proposicao.data_devolucao:
proposicao.delete()
return HttpResponseRedirect(
reverse('sapl.materia:proposicao_list'))
else:
elif not proposicao.data_recebimento:
proposicao.data_envio = None
proposicao.save()
return HttpResponseRedirect(
reverse('sapl.materia:proposicao_detail',
kwargs={'pk': proposicao.pk}))
else:
msg = _('Essa proposição já foi recebida. ' +
'Não pode mais ser excluída/recuperada')
messages.add_message(self.request, messages.ERROR, msg)
return HttpResponseRedirect(
reverse('sapl.materia:proposicao_detail',
kwargs={'pk': proposicao.pk}))
class ReciboProposicaoView(TemplateView):
template_name = "materia/recibo_proposicao.html"
permission_required = permissoes_autor()
def has_permission(self):
perms = self.get_permission_required()
if not self.request.user.has_perms(perms):
return False
return (Proposicao.objects.filter(
id=self.kwargs['pk'],
autor__user_id=self.request.user.id).exists())
def get_context_data(self, **kwargs):
context = super(ReciboProposicaoView, self).get_context_data(
@ -516,8 +554,8 @@ class ReciboProposicaoView(TemplateView):
proposicao = Proposicao.objects.get(pk=self.kwargs['pk'])
context.update({'proposicao': proposicao,
'hash': gerar_hash_arquivo(
proposicao.texto_original.path,
self.kwargs['pk'])})
proposicao.texto_original.path,
self.kwargs['pk'])})
return context

38
sapl/templates/base/RelatorioAtas_filter.html

@ -0,0 +1,38 @@
{% extends "crud/list.html" %}
{% load i18n %}
{% load crispy_forms_tags staticfiles %}
{% block base_content %}
{% if not filter_url %}
{% crispy filter.form %}
{% endif %}
{% if filter_url %}
<div class="actions btn-group pull-right" role="group">
<a href="{% url 'sapl.base:atas' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a>
</div>
<br /><br /><br />
{% if object_list|length > 0 %}
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Sessão</th>
<th>Ata</th>
</tr>
</thead>
<tbody>
{% for sessao in object_list %}
<tr>
<td>{{sessao}}</td>
<td><a href="{{ sessao.upload_ata.url }}">
<img src="{% static 'img/file.png' %}">
</a></td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<font size="5"><p align="center">Nenhum sessão com ata foi encontrada!</p></font>
{% endif %}
{% endif %}
{% endblock base_content %}

50
sapl/templates/base/RelatorioPresencaSessao_filter.html

@ -0,0 +1,50 @@
{% extends "crud/list.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block base_content %}
{% if not filter_url %}
{% crispy filter.form %}
{% endif %}
{% if filter_url %}
<style type="text/css">
.presenca_table td, th{
text-align: center;
}
</style>
<div class="actions btn-group pull-right" role="group">
<a href="{% url 'sapl.base:presenca_sessao' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a>
</div>
<br /><br /><br /><br />
<b>PERÍODO: {{periodo}}</b><br />
<b>TOTAIS NO PERÍODO - SESSÕES: {{total_sessao}} - ORDENS DO DIA: {{total_ordemdia}}</b>
<table class="table table-bordered table-hover presenca_table">
<thead class="thead-default" align="center">
<tr class="active">
<th rowspan="2">Nome Parlamentar / Partido</th>
<th colspan="2">Sessão</th>
<th colspan="2">Ordem do Dia</th>
</tr>
<tr class="active">
<th>(Qtd)</th>
<th>( % )</th>
<th>(Qtd)</th>
<th>( % )</th>
</tr>
</thead>
<tbody>
{% for p in parlamentares %}
<tr>
<td><b>{{p}}</b> / {{p.filiacao_set.first.partido.sigla|default:"Sem Partido"}}</td>
<td>{{p.sessao_count}}</td>
<td>{{p.sessao_porc}}</td>
<td>{{p.ordemdia_count}}</td>
<td>{{p.ordemdia_porc}}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% endblock base_content %}

4
sapl/templates/base/relatorios_list.html

@ -25,11 +25,11 @@
<td> Totalização anual de matérias agrupadas por autor e tipo. </td>
</tr>
<tr>
<td><a href="">Presença nas sessões</a></td>
<td><a href="{% url 'sapl.base:presenca_sessao' %}">Presença nas sessões</a></td>
<td>Presença dos parlamentares nas sessões plenárias.</td>
</tr>
<tr>
<td><a href="">Atas</a></td>
<td><a href="{% url 'sapl.base:atas' %}">Atas</a></td>
<td> Atas de Sessão Plenária. </td>
</tr>
<tr>

6
sapl/templates/sessao/pauta_sessao_list.html

@ -9,7 +9,6 @@
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Data</th>
<th>Sessão</th>
<th>PDF</th>
</tr>
@ -17,9 +16,6 @@
<tbody>
{% for sessao in page_obj %}
<tr>
<td><a href="{% url 'sapl.sessao:pauta_sessao_detail' sessao.id %}">
{{sessao.data_inicio}} - {{sessao.hora_inicio}}
</a></td>
<td>{{sessao}}</td>
<td><a href="{% url 'sapl.relatorios:relatorio_sessao_plenaria' sessao.id %}">
<img src="{% static 'img/file.png' %}">
@ -29,6 +25,4 @@
</tbody>
</table>
{% endif %}
{% include "paginacao.html" %}
{% endblock %}

Loading…
Cancel
Save