diff --git a/sapl/base/forms.py b/sapl/base/forms.py index 5af6ee179..595814d34 100644 --- a/sapl/base/forms.py +++ b/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: { diff --git a/sapl/base/urls.py b/sapl/base/urls.py index b3dcac6ea..60804abea 100644 --- a/sapl/base/urls.py +++ b/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'), ] diff --git a/sapl/base/views.py b/sapl/base/views.py index ca5d735a3..d813d4aff 100644 --- a/sapl/base/views.py +++ b/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 @@ -136,17 +229,12 @@ class CasaLegislativaCrud(Crud): list_field_names = ['codigo', 'nome', 'sigla'] def has_permission(self): - if self.request.user.is_superuser: - return True - else: - return False + return permissao_tb_aux(self) class CreateView(PermissionRequiredMixin, CrudCreateView): - permission_required = {'base.add_casa_legislativa'} form_class = CasaLegislativaForm class UpdateView(PermissionRequiredMixin, CrudUpdateView): - permission_required = {'base.change_casalegislativa'} form_class = CasaLegislativaForm class DetailView(CrudDetailView): diff --git a/sapl/comissoes/views.py b/sapl/comissoes/views.py index d4333f63d..55b262895 100644 --- a/sapl/comissoes/views.py +++ b/sapl/comissoes/views.py @@ -3,7 +3,7 @@ from django.core.urlresolvers import reverse from django.views.generic import ListView from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView, - CrudDeleteView, CrudUpdateView) + CrudDeleteView, CrudListView, CrudUpdateView) from sapl.crud.masterdetail import MasterDetailCrud from sapl.materia.models import Tramitacao from sapl.utils import permissao_tb_aux, permissoes_comissoes @@ -137,6 +137,9 @@ class ComissaoCrud(Crud): class DeleteView(PermissionRequiredMixin, CrudDeleteView): permission_required = permissoes_comissoes() + class ListView(CrudListView): + ordering = ['-ativa', 'sigla'] + class BaseMixin(CrudBaseMixin): list_field_names = ['nome', 'sigla', 'tipo', 'data_criacao', 'ativa'] diff --git a/sapl/materia/admin.py b/sapl/materia/admin.py index 5c02ebd40..eef5d7213 100644 --- a/sapl/materia/admin.py +++ b/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) diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index a91567a7f..851dd51ba 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -216,22 +216,91 @@ class TramitacaoForm(ModelForm): 'texto'] def clean(self): + + if 'data_encaminhamento' in self.data: + data_enc_form = self.cleaned_data['data_encaminhamento'] + if 'data_fim_prazo' in self.data: + data_prazo_form = self.cleaned_data['data_fim_prazo'] + if 'data_tramitacao' in self.data: + data_tram_form = self.cleaned_data['data_tramitacao'] + if self.errors: return self.errors ultima_tramitacao = Tramitacao.objects.filter( - materia_id=self.instance.materia.id).last() + materia_id=self.instance.materia_id).exclude( + id=self.instance.id).last() + + if not self.instance.data_tramitacao: + + if ultima_tramitacao: + destino = ultima_tramitacao.unidade_tramitacao_destino + if (destino != self.cleaned_data['unidade_tramitacao_local']): + msg = _('A origem da nova tramitação deve ser igual ao ' + 'destino da última adicionada!') + raise ValidationError(msg) + + if self.cleaned_data['data_tramitacao'] > datetime.now().date(): + msg = _( + 'A data de tramitação deve ser ' + + 'menor ou igual a data de hoje!') + raise ValidationError(msg) + + if (ultima_tramitacao and + data_tram_form < ultima_tramitacao.data_tramitacao): + msg = _('A data da nova tramitação deve ser ' + + 'maior que a data da última tramitação!') + raise ValidationError(msg) + + if data_enc_form: + if data_enc_form < data_tram_form: + msg = _('A data de encaminhamento deve ser ' + + 'maior que a data de tramitação!') + raise ValidationError(msg) - if ultima_tramitacao: - destino = ultima_tramitacao.unidade_tramitacao_destino - if (destino != self.cleaned_data['unidade_tramitacao_local']): - msg = _('A origem da nova tramitação deve ser igual ao ' - 'destino da última adicionada!') + if data_prazo_form: + if data_prazo_form < data_tram_form: + msg = _('A data fim de prazo deve ser ' + + 'maior que a data de tramitação!') raise ValidationError(msg) return self.cleaned_data +class TramitacaoUpdateForm(TramitacaoForm): + unidade_tramitacao_local = forms.ModelChoiceField( + queryset=UnidadeTramitacao.objects.all(), + widget=forms.HiddenInput()) + + data_tramitacao = forms.DateField(widget=forms.HiddenInput()) + + class Meta: + model = Tramitacao + fields = ['data_tramitacao', + 'unidade_tramitacao_local', + 'status', + 'turno', + 'urgente', + 'unidade_tramitacao_destino', + 'data_encaminhamento', + 'data_fim_prazo', + 'texto', + ] + + widgets = { + 'data_encaminhamento': forms.DateInput(format='%d/%m/%Y'), + 'data_fim_prazo': forms.DateInput(format='%d/%m/%Y'), + } + + def clean(self): + local = self.instance.unidade_tramitacao_local + data_tram = self.instance.data_tramitacao + + self.cleaned_data['data_tramitacao'] = data_tram + self.cleaned_data['unidade_tramitacao_local'] = local + return super(TramitacaoUpdateForm, self).clean() + + class LegislacaoCitadaForm(ModelForm): tipo = forms.ModelChoiceField( diff --git a/sapl/materia/tests/test_materia.py b/sapl/materia/tests/test_materia.py index f400a453e..d3a9573c9 100644 --- a/sapl/materia/tests/test_materia.py +++ b/sapl/materia/tests/test_materia.py @@ -276,6 +276,8 @@ def test_tramitacao_submit(admin_client): 'urgente': True, 'status': status_tramitacao.pk, 'data_tramitacao': '2016-03-21', + 'data_fim_prazo': '2016-03-22', + 'data_encaminhamento': '2016-03-22', 'texto': 'Texto_Teste', 'salvar': 'salvar'}, follow=True) diff --git a/sapl/materia/views.py b/sapl/materia/views.py index 57a804be9..4f7966118 100644 --- a/sapl/materia/views.py +++ b/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,14 +32,15 @@ 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, DocumentoAcessorioForm, LegislacaoCitadaForm, MateriaLegislativaFilterSet, NumeracaoForm, ProposicaoForm, ReceberProposicaoForm, RelatoriaForm, TramitacaoForm, - UnidadeTramitacaoForm, filtra_tramitacao_destino, + TramitacaoUpdateForm, UnidadeTramitacaoForm, + filtra_tramitacao_destino, filtra_tramitacao_destino_and_status, filtra_tramitacao_status) from .models import (AcompanhamentoMateria, Anexada, Autor, Autoria, @@ -242,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( @@ -264,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( @@ -286,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( @@ -308,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) @@ -340,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) @@ -432,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() @@ -479,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( @@ -515,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 @@ -573,14 +612,19 @@ class TramitacaoCrud(MasterDetailCrud): return super(CreateView, self).post(request, *args, **kwargs) class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView): - form_class = TramitacaoForm + form_class = TramitacaoUpdateForm permission_required = permissoes_materia() def post(self, request, *args, **kwargs): - materia = MateriaLegislativa.objects.get(id=kwargs['pk']) + materia = MateriaLegislativa.objects.get( + tramitacao__id=kwargs['pk']) do_envia_email_tramitacao(request, materia) return super(UpdateView, self).post(request, *args, **kwargs) + @property + def layout_key(self): + return 'TramitacaoUpdate' + class ListView(MasterDetailCrud.ListView): def get_queryset(self): @@ -598,7 +642,7 @@ class TramitacaoCrud(MasterDetailCrud): kwargs={'pk': tramitacao.materia.id}) if tramitacao.pk != materia.tramitacao_set.last().pk: - msg = _('Somente a útlima tramitação pode ser deletada!') + msg = _('Somente a última tramitação pode ser deletada!') messages.add_message(request, messages.ERROR, msg) return HttpResponseRedirect(url) else: diff --git a/sapl/parlamentares/models.py b/sapl/parlamentares/models.py index d4c8d817a..1dd4db07f 100644 --- a/sapl/parlamentares/models.py +++ b/sapl/parlamentares/models.py @@ -18,11 +18,16 @@ class Legislatura(models.Model): verbose_name = _('Legislatura') verbose_name_plural = _('Legislaturas') + def atual(self): + current_year = datetime.now().year + if(self.data_inicio.year <= current_year and + self.data_fim.year >= current_year): + return True + else: + return False + def __str__(self): - # XXX Usar id mesmo? Ou criar campo para nº legislatura? - current_date = datetime.now().year - if(self.data_inicio.year <= current_date and - self.data_fim.year >= current_date): + if self.atual(): current = ' (%s)' % _('Atual') else: current = '' diff --git a/sapl/parlamentares/urls.py b/sapl/parlamentares/urls.py index 97f2a0347..09bc8bf3f 100644 --- a/sapl/parlamentares/urls.py +++ b/sapl/parlamentares/urls.py @@ -24,7 +24,7 @@ urlpatterns = [ ProposicaoParlamentarCrud.get_urls() + RelatoriaParlamentarCrud.get_urls() )), - url(r'^coligacao/', + url(r'^sistema/coligacao/', include(ColigacaoCrud.get_urls() + ComposicaoColigacaoCrud.get_urls())), diff --git a/sapl/parlamentares/views.py b/sapl/parlamentares/views.py index 0f2a8edfb..fda746e0e 100644 --- a/sapl/parlamentares/views.py +++ b/sapl/parlamentares/views.py @@ -332,6 +332,7 @@ class ParlamentarCrud(Crud): class ListView(CrudListView): template_name = "parlamentares/parlamentares_list.html" paginate_by = None + ordering = '-nome_parlamentar' def take_legislatura_id(self): legislaturas = Legislatura.objects.all().order_by( @@ -341,7 +342,9 @@ class ParlamentarCrud(Crud): try: legislatura_id = int(self.request.GET['periodo']) except MultiValueDictKeyError: - legislatura_id = legislaturas.first().id + for l in Legislatura.objects.all(): + if l.atual(): + return l.id return legislatura_id else: return 0 @@ -349,7 +352,8 @@ class ParlamentarCrud(Crud): def get_queryset(self): if self.take_legislatura_id() != 0: mandatos = Mandato.objects.filter( - legislatura_id=self.take_legislatura_id()) + legislatura_id=self.take_legislatura_id()).order_by( + 'parlamentar__nome_parlamentar') return mandatos return [] diff --git a/sapl/protocoloadm/tests/test_protocoloadm.py b/sapl/protocoloadm/tests/test_protocoloadm.py index 6f9e0ad19..e249a3312 100644 --- a/sapl/protocoloadm/tests/test_protocoloadm.py +++ b/sapl/protocoloadm/tests/test_protocoloadm.py @@ -1,4 +1,5 @@ import datetime + import pytest from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index 805609b9b..d4f06f615 100644 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -209,43 +209,54 @@ class MateriaOrdemDiaCrud(MasterDetailCrud): 'pk': obj.sessao_plenaria_id, 'oid': obj.materia_id, 'mid': obj.pk}) - - btn_registrar = ''' - Registrar Votação''' % (url) - obj.resultado = btn_registrar + if self.request.user.has_perms(permissoes_sessao()): + btn_registrar = ''' + Registrar Votação''' % ( + url) + obj.resultado = btn_registrar + else: + obj.resultado = '''Não há resultado''' else: url = reverse('sapl.sessao:abrir_votacao', kwargs={ 'pk': obj.pk, 'spk': obj.sessao_plenaria_id}) - btn_abrir = ''' - Matéria não votada
- Abrir Votação''' % (url) - obj.resultado = btn_abrir + + if self.request.user.has_perms(permissoes_sessao()): + btn_abrir = ''' + Matéria não votada
+ Abrir Votação''' % (url) + obj.resultado = btn_abrir + else: + obj.resultado = '''Não há resultado''' else: - url = '' - if obj.tipo_votacao == 1: - url = reverse('sapl.sessao:votacaosimbolicaedit', - kwargs={ - 'pk': obj.sessao_plenaria_id, - 'oid': obj.materia_id, - 'mid': obj.pk}) - elif obj.tipo_votacao == 2: - url = reverse('sapl.sessao:votacaonominaledit', - kwargs={ - 'pk': obj.sessao_plenaria_id, - 'oid': obj.materia_id, - 'mid': obj.pk}) - elif obj.tipo_votacao == 3: - url = reverse('sapl.sessao:votacaosecretaedit', - kwargs={ - 'pk': obj.sessao_plenaria_id, - 'oid': obj.materia_id, - 'mid': obj.pk}) - obj.resultado = '%s' % (url, - obj.resultado) + if self.request.user.has_perms(permissoes_sessao()): + url = '' + if obj.tipo_votacao == 1: + url = reverse('sapl.sessao:votacaosimbolicaedit', + kwargs={ + 'pk': obj.sessao_plenaria_id, + 'oid': obj.materia_id, + 'mid': obj.pk}) + elif obj.tipo_votacao == 2: + url = reverse('sapl.sessao:votacaonominaledit', + kwargs={ + 'pk': obj.sessao_plenaria_id, + 'oid': obj.materia_id, + 'mid': obj.pk}) + elif obj.tipo_votacao == 3: + url = reverse('sapl.sessao:votacaosecretaedit', + kwargs={ + 'pk': obj.sessao_plenaria_id, + 'oid': obj.materia_id, + 'mid': obj.pk}) + obj.resultado = '%s' % (url, + obj.resultado) + else: + obj.resultado = '%s' % (obj.resultado) + return [self._as_row(obj) for obj in object_list] @@ -449,19 +460,20 @@ class PresencaMixin: yield (parlamentar, False) -class PresencaView(PermissionRequiredMixin, - FormMixin, +class PresencaView(FormMixin, PresencaMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/presenca.html' form_class = PresencaForm model = SessaoPlenaria - permission_required = permissoes_sessao() def post(self, request, *args, **kwargs): self.object = self.get_object() form = self.get_form() + if not self.request.user.has_perms(permissoes_sessao()): + return self.form_invalid(form) + if form.is_valid(): # Pegar os presentes salvos no banco presentes_banco = SessaoPlenariaPresenca.objects.filter( @@ -499,13 +511,11 @@ class PainelView(PermissionRequiredMixin, TemplateView): permission_required = permissoes_painel() -class PresencaOrdemDiaView(PermissionRequiredMixin, - FormMixin, +class PresencaOrdemDiaView(FormMixin, PresencaMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/presenca_ordemdia.html' form_class = PresencaForm - permission_required = permissoes_sessao() def post(self, request, *args, **kwargs): @@ -514,6 +524,9 @@ class PresencaOrdemDiaView(PermissionRequiredMixin, pk = kwargs['pk'] + if not self.request.user.has_perms(permissoes_sessao()): + return self.form_invalid(form) + if form.is_valid(): # Pegar os presentes salvos no banco presentes_banco = PresencaOrdemDia.objects.filter( @@ -920,17 +933,18 @@ class ResumoView(SessaoCrud.CrudDetailView): return self.render_to_response(context) -class ExpedienteView(PermissionRequiredMixin, - FormMixin, +class ExpedienteView(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/expediente.html' form_class = ExpedienteForm - permission_required = permissoes_sessao() def post(self, request, *args, **kwargs): self.object = self.get_object() form = ExpedienteForm(request.POST) + if not self.request.user.has_perms(permissoes_sessao()): + return self.form_invalid(form) + if form.is_valid(): list_tipo = request.POST.getlist('tipo') list_conteudo = request.POST.getlist('conteudo') @@ -1986,7 +2000,8 @@ class PesquisarSessaoPlenariaView(FilterView): qs = self.get_queryset() - qs = qs.distinct() + qs = qs.distinct().order_by( + 'legislatura__id', 'data_inicio', 'numero') kwargs.update({ 'queryset': qs, @@ -2045,9 +2060,11 @@ def retira_materias_ja_adicionadas(id_sessao, model): return lista_id_materias -class AdicionarVariasMateriasExpediente(MateriaLegislativaPesquisaView): +class AdicionarVariasMateriasExpediente(PermissionRequiredMixin, + MateriaLegislativaPesquisaView): filterset_class = AdicionarVariasMateriasFilterSet template_name = 'sessao/adicionar_varias_materias_expediente.html' + permission_required = permissoes_sessao() def get_filterset_kwargs(self, filterset_class): super(AdicionarVariasMateriasExpediente, @@ -2123,6 +2140,7 @@ class AdicionarVariasMateriasExpediente(MateriaLegislativaPesquisaView): class AdicionarVariasMateriasOrdemDia(AdicionarVariasMateriasExpediente): filterset_class = AdicionarVariasMateriasFilterSet template_name = 'sessao/adicionar_varias_materias_ordem.html' + permission_required = permissoes_sessao() def get_filterset_kwargs(self, filterset_class): super(AdicionarVariasMateriasExpediente, diff --git a/sapl/static/js/app.js b/sapl/static/js/app.js index 4a8853cd3..127bf2b86 100644 --- a/sapl/static/js/app.js +++ b/sapl/static/js/app.js @@ -1,4 +1,4 @@ -function initTinymce(elements) { +function initTinymce(elements, readonly=false) { removeTinymce(); var config_tinymce = { force_br_newlines : false, @@ -11,6 +11,11 @@ function initTinymce(elements) { border_css: "/static/styles/style_tinymce.css", content_css: "/static/styles/style_tinymce.css", } + + if (readonly) { + config_tinymce.readonly = 1 + } + if (elements != null) { config_tinymce['elements'] = elements; config_tinymce['mode'] = "exact"; diff --git a/sapl/templates/base.html b/sapl/templates/base.html index df70b2252..363c1d7e0 100644 --- a/sapl/templates/base.html +++ b/sapl/templates/base.html @@ -42,13 +42,12 @@