diff --git a/sapl/base/forms.py b/sapl/base/forms.py index 8a28dabbe..4334f7e94 100644 --- a/sapl/base/forms.py +++ b/sapl/base/forms.py @@ -12,32 +12,12 @@ 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) +from sapl.utils import (RANGE_ANOS, ImageThumbnailFileInput, + RangeWidgetOverride, autor_label, autor_modal) from .models import AppConfig, CasaLegislativa -class RangeWidgetOverride(forms.MultiWidget): - - def __init__(self, attrs=None): - widgets = (forms.DateInput(format='%d/%m/%Y', - attrs={'class': 'dateinput', - 'placeholder': 'Inicial'}), - forms.DateInput(format='%d/%m/%Y', - attrs={'class': 'dateinput', - 'placeholder': 'Final'})) - super(RangeWidgetOverride, self).__init__(widgets, attrs) - - def decompress(self, value): - if value: - return [value.start, value.stop] - return [None, None] - - def format_output(self, rendered_widgets): - return ''.join(rendered_widgets) - - class RelatorioAtasFilterSet(django_filters.FilterSet): filter_overrides = {models.DateField: { @@ -53,7 +33,7 @@ class RelatorioAtasFilterSet(django_filters.FilterSet): def __init__(self, *args, **kwargs): super(RelatorioAtasFilterSet, self).__init__( - *args, **kwargs) + *args, **kwargs) self.filters['data_inicio'].label = 'Período (Inicial - Final)' self.form.fields['data_inicio'].required = True @@ -83,7 +63,7 @@ class RelatorioPresencaSessaoFilterSet(django_filters.FilterSet): def __init__(self, *args, **kwargs): super(RelatorioPresencaSessaoFilterSet, self).__init__( - *args, **kwargs) + *args, **kwargs) self.filters['data_inicio'].label = 'Período (Inicial - Final)' self.form.fields['data_inicio'].required = True @@ -114,7 +94,7 @@ class RelatorioHistoricoTramitacaoFilterSet(django_filters.FilterSet): def __init__(self, *args, **kwargs): super(RelatorioHistoricoTramitacaoFilterSet, self).__init__( - *args, **kwargs) + *args, **kwargs) self.filters['tipo'].label = 'Tipo de Matéria' @@ -146,7 +126,7 @@ class RelatorioMateriasTramitacaoilterSet(django_filters.FilterSet): def __init__(self, *args, **kwargs): super(RelatorioMateriasTramitacaoilterSet, self).__init__( - *args, **kwargs) + *args, **kwargs) self.filters['tipo'].label = 'Tipo de Matéria' @@ -287,6 +267,7 @@ class LoginForm(AuthenticationForm): class ConfiguracoesAppForm(ModelForm): + class Meta: model = AppConfig fields = ['documentos_administrativos', diff --git a/sapl/base/templatetags/common_tags.py b/sapl/base/templatetags/common_tags.py index 0c589e847..30db1a92f 100644 --- a/sapl/base/templatetags/common_tags.py +++ b/sapl/base/templatetags/common_tags.py @@ -1,7 +1,9 @@ from compressor.utils import get_class from django import template +from sapl.base.models import AppConfig from sapl.parlamentares.models import Filiacao +from sapl.utils import permissoes_adm register = template.Library() @@ -85,6 +87,17 @@ def get_delete_perm(value, arg): return perm.__contains__(nome_app + can_delete) +@register.filter +def get_doc_adm_template_perms(user): + app_config = AppConfig.objects.last() + + if app_config: + if app_config.documentos_administrativos == 'O': + return True + + return user.has_perms(permissoes_adm()) + + @register.filter def ver_menu_sistema_perm(value): u = value @@ -105,3 +118,11 @@ def ultima_filiacao(value): return ultima_filiacao.partido else: return None + + +@register.filter +def get_config_not_exists(user): + if not AppConfig.objects.all().exists(): + return True + else: + return False diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index bccddeb5e..e5f66a37c 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -4,6 +4,7 @@ import django_filters from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Button, Column, Fieldset, Layout from django import forms +from django.contrib.auth import get_user_model from django.contrib.auth.models import Group, User from django.contrib.auth.password_validation import validate_password from django.core.exceptions import ObjectDoesNotExist, ValidationError @@ -17,7 +18,8 @@ from sapl.crispy_layout_mixin import form_actions, to_row from sapl.norma.models import (LegislacaoCitada, NormaJuridica, TipoNormaJuridica) from sapl.settings import MAX_DOC_UPLOAD_SIZE -from sapl.utils import RANGE_ANOS, autor_label, autor_modal +from sapl.utils import (RANGE_ANOS, RangeWidgetOverride, autor_label, + autor_modal) from .models import (AcompanhamentoMateria, Anexada, Autor, Autoria, DespachoInicial, DocumentoAcessorio, MateriaLegislativa, @@ -34,6 +36,7 @@ def em_tramitacao(): class ConfirmarProposicaoForm(ModelForm): + class Meta: model = Proposicao exclude = ['texto_original', 'descricao', 'tipo'] @@ -247,7 +250,7 @@ class TramitacaoForm(ModelForm): raise ValidationError(msg) if (ultima_tramitacao and - data_tram_form < ultima_tramitacao.data_tramitacao): + 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) @@ -445,26 +448,6 @@ class AnexadaForm(ModelForm): fields = ['tipo', 'numero', 'ano', 'data_anexacao', 'data_desanexacao'] -class RangeWidgetOverride(forms.MultiWidget): - - def __init__(self, attrs=None): - widgets = (forms.DateInput(format='%d/%m/%Y', - attrs={'class': 'dateinput', - 'placeholder': 'Inicial'}), - forms.DateInput(format='%d/%m/%Y', - attrs={'class': 'dateinput', - 'placeholder': 'Final'})) - super(RangeWidgetOverride, self).__init__(widgets, attrs) - - def decompress(self, value): - if value: - return [value.start, value.stop] - return [None, None] - - def format_output(self, rendered_widgets): - return ''.join(rendered_widgets) - - class MateriaLegislativaFilterSet(django_filters.FilterSet): filter_overrides = {models.DateField: { @@ -678,9 +661,8 @@ class AutorForm(ModelForm): 'email', 'nome', 'tipo', - 'cargo', - 'parlamentar', - 'comissao'] + 'cargo'] + widgets = {'nome': forms.HiddenInput()} def valida_igualdade(self, texto1, texto2, msg): if texto1 != texto2: @@ -688,14 +670,14 @@ class AutorForm(ModelForm): return True def valida_email_existente(self): - return User.objects.filter( + return get_user_model().objects.filter( email=self.cleaned_data['email']).exists() - def usuario_existente(self): - return User.objects.filter( - username=self.cleaned_data['username']).exists() - def clean(self): + + if 'username' not in self.cleaned_data: + raise ValidationError(_('Favor informar o username')) + if ('senha' not in self.cleaned_data or 'senha_confirma' not in self.cleaned_data): raise ValidationError(_('Favor informar as senhas')) @@ -718,19 +700,29 @@ class AutorForm(ModelForm): email_existente = self.valida_email_existente() + if (Autor.objects.filter( + username=self.cleaned_data['username']).exists()): + raise ValidationError(_('Já existe um autor para este usuário')) + if email_existente: msg = _('Este email já foi cadastrado.') raise ValidationError(msg) - if self.usuario_existente(): - msg = _('Este nome de usuario já foi cadastrado.') - raise ValidationError(msg) - try: validate_password(self.cleaned_data['senha']) except ValidationError as error: raise ValidationError(error) + try: + User.objects.get( + username=self.cleaned_data['username'], + email=self.cleaned_data['email']) + except ObjectDoesNotExist: + msg = _('Este nome de usuario não está cadastrado. ' + + 'Por favor, cadastre-o no Administrador do ' + + 'Sistema antes de adicioná-lo como Autor') + raise ValidationError(msg) + return self.cleaned_data @transaction.atomic @@ -738,15 +730,9 @@ class AutorForm(ModelForm): autor = super(AutorForm, self).save(commit) - try: - u = User.objects.get( - username=autor.username, - email=autor.email) - except ObjectDoesNotExist: - msg = _('Este nome de usuario não está cadastrado. ' + - 'Por favor, cadastre-o no Administrador do ' + - 'Sistema antes de adicioná-lo como Autor') - raise ValidationError(msg) + u = User.objects.get( + username=autor.username, + email=autor.email) u.set_password(self.cleaned_data['senha']) u.is_active = False diff --git a/sapl/materia/migrations/0048_auto_20160927_1254.py b/sapl/materia/migrations/0048_auto_20160927_1254.py new file mode 100644 index 000000000..c229b854a --- /dev/null +++ b/sapl/materia/migrations/0048_auto_20160927_1254.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-27 15:54 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0047_merge'), + ] + + operations = [ + migrations.AlterField( + model_name='autoria', + name='autor', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.Autor', verbose_name='Autor'), + ), + migrations.AlterField( + model_name='autoria', + name='partido', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='parlamentares.Partido', verbose_name='Partido'), + ), + ] diff --git a/sapl/materia/models.py b/sapl/materia/models.py index ac179f714..716871980 100644 --- a/sapl/materia/models.py +++ b/sapl/materia/models.py @@ -1,4 +1,4 @@ -from django.contrib.auth.models import Group, User +from django.contrib.auth.models import Group from django.db import models from django.utils.translation import ugettext_lazy as _ from model_utils import Choices @@ -6,7 +6,8 @@ from model_utils import Choices from sapl.comissoes.models import Comissao from sapl.parlamentares.models import Parlamentar, Partido from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, - restringe_tipos_de_arquivo_txt, xstr) + restringe_tipos_de_arquivo_txt, xstr, + get_settings_auth_user_model) def grupo_autor(): @@ -208,7 +209,8 @@ class TipoAutor(models.Model): class Autor(models.Model): - user = models.ForeignKey(User, blank=True, null=True) + user = models.ForeignKey( + get_settings_auth_user_model(), blank=True, null=True) partido = models.ForeignKey(Partido, blank=True, null=True) comissao = models.ForeignKey(Comissao, blank=True, null=True) parlamentar = models.ForeignKey(Parlamentar, blank=True, null=True) @@ -243,8 +245,9 @@ class Autor(models.Model): class Autoria(models.Model): - partido = models.ForeignKey(Partido, blank=True, null=True) - autor = models.ForeignKey(Autor) + partido = models.ForeignKey(Partido, blank=True, null=True, + verbose_name=_('Partido')) + autor = models.ForeignKey(Autor, verbose_name=_('Autor')) materia = models.ForeignKey(MateriaLegislativa) primeiro_autor = models.BooleanField(verbose_name=_('Primeiro Autor'), choices=YES_NO_CHOICES) diff --git a/sapl/materia/tests/test_materia.py b/sapl/materia/tests/test_materia.py index d3a9573c9..953546c27 100644 --- a/sapl/materia/tests/test_materia.py +++ b/sapl/materia/tests/test_materia.py @@ -1,8 +1,8 @@ -import pytest -from django.contrib.auth.models import User +from django.contrib.auth import get_user_model from django.core.files.uploadedfile import SimpleUploadedFile from django.core.urlresolvers import reverse from model_mommy import mommy +import pytest from sapl.comissoes.models import Comissao, TipoComissao from sapl.materia.models import (Anexada, Autor, Autoria, DespachoInicial, @@ -434,7 +434,7 @@ def test_form_errors_relatoria(admin_client): @pytest.mark.django_db(transaction=False) def test_proposicao_submit(admin_client): tipo_autor = mommy.make(TipoAutor, descricao='Teste Tipo_Autor') - user = User.objects.filter(is_active=True)[0] + user = get_user_model().objects.filter(is_active=True)[0] autor = mommy.make( Autor, @@ -469,7 +469,7 @@ def test_proposicao_submit(admin_client): def test_form_errors_proposicao(admin_client): tipo_autor = mommy.make(TipoAutor, descricao='Teste Tipo_Autor') - user = User.objects.filter(is_active=True)[0] + user = get_user_model().objects.filter(is_active=True)[0] autor = mommy.make( Autor, @@ -484,7 +484,7 @@ def test_form_errors_proposicao(admin_client): {'autor': autor.pk, 'justificativa_devolucao': ' ', 'texto_original': texto, - 'salvar': 'salvar'}, + 'salvar': 'salvar'}, follow=True) assert (response.context_data['form'].errors['tipo'] == diff --git a/sapl/materia/views.py b/sapl/materia/views.py index ff1a849f4..2b639fafa 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -6,8 +6,8 @@ from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Button from django.conf import settings from django.contrib import messages +from django.contrib.auth import get_user_model from django.contrib.auth.mixins import PermissionRequiredMixin -from django.contrib.auth.models import User from django.contrib.auth.tokens import default_token_generator from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist from django.core.mail import send_mail @@ -54,6 +54,7 @@ from .models import (AcompanhamentoMateria, Anexada, Autor, Autoria, TipoFimRelatoria, TipoMateriaLegislativa, TipoProposicao, Tramitacao, UnidadeTramitacao) + AnexadaCrud = Crud.build(Anexada, '') @@ -62,6 +63,7 @@ class OrigemCrud(Crud): help_path = 'origem' class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): + def has_permission(self): return permissao_tb_aux(self) @@ -71,6 +73,7 @@ class TipoMateriaCrud(Crud): help_path = 'tipo_materia_legislativa' class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): + def has_permission(self): return permissao_tb_aux(self) @@ -80,6 +83,7 @@ class RegimeTramitacaoCrud(Crud): help_path = 'regime_tramitacao' class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): + def has_permission(self): return permissao_tb_aux(self) @@ -89,6 +93,7 @@ class TipoDocumentoCrud(Crud): help_path = 'tipo_documento' class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): + def has_permission(self): return permissao_tb_aux(self) @@ -98,6 +103,7 @@ class TipoFimRelatoriaCrud(Crud): help_path = 'fim_relatoria' class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): + def has_permission(self): return permissao_tb_aux(self) @@ -107,30 +113,75 @@ class TipoAutorCrud(Crud): help_path = 'tipo_autor' class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): + def has_permission(self): return permissao_tb_aux(self) +def montar_helper_autor(self): + autor_row = montar_row_autor('nome') + self.helper = FormHelper() + self.helper.layout = SaplFormLayout(*self.get_layout()) + + # Adiciona o novo campo 'autor' e mecanismo de busca + self.helper.layout[0][0].append(HTML(autor_label)) + self.helper.layout[0][0].append(HTML(autor_modal)) + self.helper.layout[0][1] = autor_row + + # Adiciona espaço entre o novo campo e os botões + # self.helper.layout[0][4][1].append(HTML('')) + + # Remove botões que estão fora do form + self.helper.layout[1].pop() + + # Adiciona novos botões dentro do form + self.helper.layout[0][4][0].insert(2, form_actions(more=[ + HTML('Cancelar')])) + + class AutorCrud(Crud): model = Autor help_path = 'autor' class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): - list_field_names = ['tipo', 'nome', - 'username', 'cargo'] + list_field_names = ['tipo', 'nome'] def has_permission(self): return permissao_tb_aux(self) + class UpdateView(CrudUpdateView): + form_class = AutorForm + layout_key = 'AutorCreate' + + def __init__(self, *args, **kwargs): + montar_helper_autor(self) + super(UpdateView, self).__init__(*args, **kwargs) + + def get_context_data(self, **kwargs): + context = super(UpdateView, self).get_context_data(**kwargs) + context['helper'] = self.helper + return context + class CreateView(CrudCreateView): form_class = AutorForm layout_key = 'AutorCreate' + def __init__(self, *args, **kwargs): + montar_helper_autor(self) + super(CreateView, self).__init__(*args, **kwargs) + + def get_context_data(self, **kwargs): + context = super(CreateView, self).get_context_data(**kwargs) + context['helper'] = self.helper + return context + def get_success_url(self): pk_autor = Autor.objects.get( email=self.request.POST.get('email')).id kwargs = {} - user = User.objects.get(email=self.request.POST.get('email')) + user = get_user_model().objects.get( + email=self.request.POST.get('email')) kwargs['token'] = default_token_generator.make_token(user) kwargs['uidb64'] = urlsafe_base64_encode(force_bytes(user.pk)) assunto = "SAPL - Confirmação de Conta" @@ -159,7 +210,7 @@ class ConfirmarEmailView(TemplateView): def get(self, request, *args, **kwargs): uid = urlsafe_base64_decode(self.kwargs['uidb64']) - user = User.objects.get(id=uid) + user = get_user_model().objects.get(id=uid) user.is_active = True user.save() context = self.get_context_data(**kwargs) @@ -181,6 +232,7 @@ class TipoProposicaoCrud(Crud): help_path = 'tipo_proposicao' class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): + def has_permission(self): return permissao_tb_aux(self) @@ -453,7 +505,7 @@ class ProposicaoCrud(Crud): id=self.kwargs['pk'], autor__user_id=self.request.user.id) if (not proposicao.data_recebimento or - proposicao.data_devolucao): + proposicao.data_devolucao): return True else: msg = _('Essa proposição já foi recebida. ' + @@ -473,6 +525,11 @@ class ProposicaoCrud(Crud): id=self.kwargs['pk'], autor__user_id=self.request.user.id).exists()) + def get_context_data(self, **kwargs): + context = CrudDetailView.get_context_data(self, **kwargs) + context['subnav_template_name'] = '' + return context + class ListView(PermissionRequiredMixin, CrudListView): ordering = ['-data_envio', 'descricao'] permission_required = permissoes_autor() @@ -544,13 +601,13 @@ class ReciboProposicaoView(TemplateView): permission_required = permissoes_autor() def has_permission(self): - perms = self.get_permission_required() - if not self.request.user.has_perms(perms): - return False + 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()) + 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( @@ -634,7 +691,7 @@ class TramitacaoCrud(MasterDetailCrud): def get_queryset(self): qs = super(MasterDetailCrud.ListView, self).get_queryset() kwargs = {self.crud.parent_field: self.kwargs['pk']} - return qs.filter(**kwargs).order_by('-data_tramitacao') + return qs.filter(**kwargs).order_by('-data_tramitacao', '-id') class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView): permission_required = permissoes_materia() @@ -654,9 +711,9 @@ class TramitacaoCrud(MasterDetailCrud): return HttpResponseRedirect(url) -def montar_row_autor(): +def montar_row_autor(name): autor_row = to_row( - [('autor', 0), + [(name, 0), (Button('pesquisar', 'Pesquisar Autor', css_class='btn btn-primary btn-sm'), 2), @@ -668,7 +725,7 @@ def montar_row_autor(): def montar_helper_documento_acessorio(self): - autor_row = montar_row_autor() + autor_row = montar_row_autor('autor') self.helper = FormHelper() self.helper.layout = SaplFormLayout(*self.get_layout()) @@ -982,6 +1039,13 @@ class MateriaLegislativaPesquisaView(FilterView): qr = self.request.GET.copy() if 'page' in qr: del qr['page'] + + paginator = context['paginator'] + page_obj = context['page_obj'] + + context['page_range'] = make_pagination( + page_obj.number, paginator.num_pages) + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' return context diff --git a/sapl/painel/urls.py b/sapl/painel/urls.py index 296b9cc8a..d6a07112f 100644 --- a/sapl/painel/urls.py +++ b/sapl/painel/urls.py @@ -8,7 +8,7 @@ from .views import (controlador_painel, cronometro_painel, get_dados_painel, app_name = AppConfig.name urlpatterns = [ - url(r'^painel_principal/(?P\d+)$', painel_view, + url(r'^painel-principal/(?P\d+)$', painel_view, name="painel_principal"), url(r'^painel/(?P\d+)/dados$', get_dados_painel, name='dados_painel'), url(r'^painel/controlador$', diff --git a/sapl/parlamentares/forms.py b/sapl/parlamentares/forms.py index 20350ef07..b09c054ec 100644 --- a/sapl/parlamentares/forms.py +++ b/sapl/parlamentares/forms.py @@ -24,6 +24,7 @@ class LegislaturaForm(ModelForm): def clean(self): cleaned_data = self.cleaned_data + numero = cleaned_data['numero'] data_inicio = cleaned_data['data_inicio'] data_fim = cleaned_data['data_fim'] data_eleicao = cleaned_data['data_eleicao'] @@ -32,6 +33,9 @@ class LegislaturaForm(ModelForm): raise ValidationError(_('A data início deve ser menor que a ' + 'data fim, e a data eleição deve ser ' + 'menor que a data início')) + if Legislatura.objects.filter(numero=numero).exists(): + raise ValidationError( + _('Já cadastrada uma legislatura com este número')) return cleaned_data diff --git a/sapl/parlamentares/migrations/0028_legislatura_numero.py b/sapl/parlamentares/migrations/0028_legislatura_numero.py new file mode 100644 index 000000000..465c1b764 --- /dev/null +++ b/sapl/parlamentares/migrations/0028_legislatura_numero.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-21 15:03 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('parlamentares', '0027_merge'), + ] + + operations = [ + migrations.AddField( + model_name='legislatura', + name='numero', + field=models.PositiveIntegerField(default=1, verbose_name='Número'), + preserve_default=False, + ), + ] diff --git a/sapl/parlamentares/migrations/0029_merge.py b/sapl/parlamentares/migrations/0029_merge.py new file mode 100644 index 000000000..034f452a4 --- /dev/null +++ b/sapl/parlamentares/migrations/0029_merge.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-22 20:52 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('parlamentares', '0028_auto_20160922_1443'), + ('parlamentares', '0028_legislatura_numero'), + ] + + operations = [ + ] diff --git a/sapl/parlamentares/migrations/0030_auto_20160928_0846.py b/sapl/parlamentares/migrations/0030_auto_20160928_0846.py new file mode 100644 index 000000000..04c88a009 --- /dev/null +++ b/sapl/parlamentares/migrations/0030_auto_20160928_0846.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-28 11:46 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('parlamentares', '0029_merge'), + ] + + operations = [ + migrations.AlterField( + model_name='tipodependente', + name='descricao', + field=models.CharField(max_length=50, verbose_name='Descrição'), + ), + ] diff --git a/sapl/parlamentares/models.py b/sapl/parlamentares/models.py index 0a4acb994..e1d414f3b 100644 --- a/sapl/parlamentares/models.py +++ b/sapl/parlamentares/models.py @@ -10,6 +10,7 @@ from sapl.utils import (INDICADOR_AFASTAMENTO, UF, YES_NO_CHOICES, class Legislatura(models.Model): + numero = models.PositiveIntegerField(verbose_name=_('Número')) data_inicio = models.DateField(verbose_name=_('Data Início')) data_fim = models.DateField(verbose_name=_('Data Fim')) data_eleicao = models.DateField(verbose_name=_('Data Eleição')) @@ -33,8 +34,8 @@ class Legislatura(models.Model): else: current = '' - return _('%(id)sª (%(start)s - %(end)s)%(current)s') % { - 'id': self.id, + return _('%(numero)sª (%(start)s - %(end)s)%(current)s') % { + 'numero': self.numero, 'start': self.data_inicio.year, 'end': self.data_fim.year, 'current': current} @@ -64,8 +65,8 @@ class SessaoLegislativa(models.Model): verbose_name_plural = _('Sessões Legislativas') def __str__(self): - return _('%(id)sº (%(inicio)s - %(fim)s)') % { - 'id': self.id, + return _('%(numero)sº (%(inicio)s - %(fim)s)') % { + 'numero': self.numero, 'inicio': self.data_inicio.year, 'fim': self.data_fim.year} @@ -267,7 +268,7 @@ class Parlamentar(models.Model): class TipoDependente(models.Model): - descricao = models.CharField(max_length=50) + descricao = models.CharField(max_length=50, verbose_name=_('Descrição')) class Meta: verbose_name = _('Tipo de Dependente') diff --git a/sapl/parlamentares/views.py b/sapl/parlamentares/views.py index 0fabc8361..796cf5223 100644 --- a/sapl/parlamentares/views.py +++ b/sapl/parlamentares/views.py @@ -120,8 +120,8 @@ class ParticipacaoParlamentarCrud(MasterDetailCrud): if p.cargo.nome != 'Relator': comissao = [ (p.composicao.comissao.nome, reverse( - 'sapl.comissoes:comissao_detail', kwargs={ - 'pk': p.composicao.comissao.pk})), + 'sapl.comissoes:comissao_detail', kwargs={ + 'pk': p.composicao.comissao.pk})), (p.cargo.nome, None), (p.composicao.periodo.data_inicio.strftime( "%d/%m/%Y") + ' a ' + @@ -149,6 +149,7 @@ class CargoMesaCrud(Crud): help_path = 'cargo_mesa' class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): + def has_permission(self): return permissao_tb_aux(self) @@ -158,6 +159,7 @@ class PartidoCrud(Crud): help_path = 'partidos' class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): + def has_permission(self): return permissao_tb_aux(self) @@ -167,6 +169,7 @@ class SessaoLegislativaCrud(Crud): help_path = 'sessao_legislativa' class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): + def has_permission(self): return permissao_tb_aux(self) @@ -176,6 +179,7 @@ class TipoDependenteCrud(Crud): help_path = 'nivel_instrucao' class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): + def has_permission(self): return permissao_tb_aux(self) @@ -185,6 +189,7 @@ class NivelInstrucaoCrud(Crud): help_path = 'tipo_dependente' class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): + def has_permission(self): return permissao_tb_aux(self) @@ -194,6 +199,7 @@ class TipoAfastamentoCrud(Crud): help_path = 'tipo_afastamento' class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): + def has_permission(self): return permissao_tb_aux(self) @@ -203,6 +209,7 @@ class TipoMilitarCrud(Crud): help_path = 'tipo_situa_militar' class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): + def has_permission(self): return permissao_tb_aux(self) @@ -234,7 +241,7 @@ class MandatoCrud(MasterDetailCrud): help_path = '' class ListView(MasterDetailCrud.ListView): - ordering = ('-legislatura__data_inicio') + ordering = ('-legislatura__numero') class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView): permission_required = permissoes_parlamentares() @@ -251,9 +258,10 @@ class ColigacaoCrud(Crud): help_path = 'tabelas_auxiliares#coligacao' class ListView(CrudListView): - ordering = ('-legislatura__data_inicio', 'nome') + ordering = ('-numero_votos', 'nome') class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): + def has_permission(self): return permissao_tb_aux(self) @@ -281,6 +289,7 @@ class ComposicaoColigacaoCrud(MasterDetailCrud): ordering = '-partido__sigla' class BaseMixin(PermissionRequiredMixin, MasterDetailCrud.BaseMixin): + def has_permission(self): return permissao_tb_aux(self) @@ -296,6 +305,7 @@ class LegislaturaCrud(Crud): form_class = LegislaturaForm class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): + def has_permission(self): return permissao_tb_aux(self) @@ -321,13 +331,13 @@ class FiliacaoCrud(MasterDetailCrud): def get_parlamentar_permissions(): - lista_permissoes = [] - cts = ContentType.objects.filter(app_label='parlamentares') - perms_parlamentares = list(Permission.objects.filter( - content_type__in=cts)) - for p in perms_parlamentares: - lista_permissoes.append('parlamentares.' + p.codename) - return set(lista_permissoes) + lista_permissoes = [] + cts = ContentType.objects.filter(app_label='parlamentares') + perms_parlamentares = list(Permission.objects.filter( + content_type__in=cts)) + for p in perms_parlamentares: + lista_permissoes.append('parlamentares.' + p.codename) + return set(lista_permissoes) class ParlamentarCrud(Crud): @@ -335,6 +345,7 @@ class ParlamentarCrud(Crud): help_path = '' class DetailView(CrudDetailView): + def get_template_names(self): usuario = self.request.user lista_permissoes = get_parlamentar_permissions() @@ -368,7 +379,7 @@ class ParlamentarCrud(Crud): def take_legislatura_id(self): legislaturas = Legislatura.objects.all().order_by( - '-data_inicio', '-data_fim') + '-numero') if legislaturas: try: @@ -420,7 +431,7 @@ class ParlamentarCrud(Crud): # Adiciona legislatura para filtrar parlamentares legislaturas = Legislatura.objects.all().order_by( - '-data_inicio', '-data_fim') + '-numero') context['legislaturas'] = legislaturas context['legislatura_id'] = self.take_legislatura_id() return context @@ -450,7 +461,7 @@ class MesaDiretoraView(FormView): return self.render_to_response( {'legislaturas': Legislatura.objects.all( - ).order_by('-data_inicio'), + ).order_by('-numero'), 'legislatura_selecionada': Legislatura.objects.last(), 'cargos_vagos': CargoMesa.objects.all()}) @@ -477,7 +488,7 @@ class MesaDiretoraView(FormView): return self.render_to_response( {'legislaturas': Legislatura.objects.all( - ).order_by('-data_inicio'), + ).order_by('-numero'), 'legislatura_selecionada': Legislatura.objects.last(), 'sessoes': SessaoLegislativa.objects.filter( legislatura=Legislatura.objects.last()), @@ -538,7 +549,7 @@ class MesaDiretoraView(FormView): parlamentares_ocupados)) return self.render_to_response( {'legislaturas': Legislatura.objects.all( - ).order_by('-data_inicio'), + ).order_by('-numero'), 'legislatura_selecionada': Legislatura.objects.get( id=int(request.POST['legislatura'])), 'sessoes': SessaoLegislativa.objects.filter( diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 4d247adfa..c1bf9f99e 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -11,9 +11,9 @@ from django.forms import ModelForm from django.utils.translation import ugettext_lazy as _ from sapl.crispy_layout_mixin import form_actions, to_row -from sapl.materia.forms import RangeWidgetOverride from sapl.materia.models import Autor, UnidadeTramitacao -from sapl.utils import RANGE_ANOS, autor_label, autor_modal +from sapl.utils import (RANGE_ANOS, RangeWidgetOverride, autor_label, + autor_modal) from .models import (DocumentoAcessorioAdministrativo, DocumentoAdministrativo, Protocolo, TipoDocumentoAdministrativo, @@ -43,7 +43,7 @@ class ProtocoloFilterSet(django_filters.FilterSet): }} ano = django_filters.ChoiceFilter(required=False, - label=u'Ano da Matéria', + label=u'Ano', choices=ANO_CHOICES) assunto_ementa = django_filters.CharFilter(lookup_expr='icontains') @@ -512,7 +512,7 @@ class TramitacaoAdmForm(ModelForm): raise ValidationError(msg) if (ultima_tramitacao and - data_tram_form < ultima_tramitacao.data_tramitacao): + 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) diff --git a/sapl/protocoloadm/urls.py b/sapl/protocoloadm/urls.py index 2c7f4f529..c98afe4c1 100644 --- a/sapl/protocoloadm/urls.py +++ b/sapl/protocoloadm/urls.py @@ -43,9 +43,9 @@ urlpatterns = [ include(ProtocoloMateriaCrud.get_urls()), name='protocolomat'), url(r'^protocoloadm/protocolo$', ProtocoloPesquisaView.as_view(), name='protocolo'), - url(r'^protocoloadm/protocolo_list$', + url(r'^protocoloadm/protocolo-list$', ProtocoloListView.as_view(), name='protocolo_list'), - url(r'^protocoloadm/(?P\d+)/(?P\d+)/protocolo_mostrar$', + url(r'^protocoloadm/(?P\d+)/(?P\d+)/protocolo-mostrar$', ProtocoloMostrarView.as_view(), name='protocolo_mostrar'), url(r'^protocoloadm/anular-protocolo', AnularProtocoloAdmView.as_view(), name='anular_protocolo'), @@ -66,12 +66,12 @@ urlpatterns = [ url(r'^protocoloadm/(?P\d+)/(?P\d+)/comprovante$', ComprovanteProtocoloView.as_view(), name='comprovante_protocolo'), - url(r'^protocoloadm/(?P\d+)/(?P\d+)/criar_documento$', + url(r'^protocoloadm/(?P\d+)/(?P\d+)/criar-documento$', CriarDocumentoProtocolo.as_view(), name='criar_documento'), # FIXME: Usado para pesquisar autor # Melhor forma de fazer? # Deve mudar de app? - url(r'^proposicao/pesquisar_autor', + url(r'^proposicao/pesquisar-autor', pesquisa_autores, name='pesquisar_autor'), ] diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py index be02f467b..1732efb9c 100644 --- a/sapl/protocoloadm/views.py +++ b/sapl/protocoloadm/views.py @@ -17,7 +17,8 @@ from django_filters.views import FilterView import sapl.crud.base from sapl.base.models import AppConfig from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView, - CrudDeleteView, CrudListView, CrudUpdateView, + CrudDetailView, CrudDeleteView, + CrudListView, CrudUpdateView, make_pagination) from sapl.crud.masterdetail import MasterDetailCrud from sapl.materia.models import TipoMateriaLegislativa @@ -62,6 +63,32 @@ class DocumentoAdministrativoCrud(Crud): class DeleteView(PermissionRequiredMixin, CrudDeleteView): permission_required = permissoes_adm() + class ListView(PermissionRequiredMixin, CrudListView): + permission_required = permissoes_adm() + + def has_permission(self): + app_config = AppConfig.objects.last() + + if app_config: + if app_config.documentos_administrativos == 'O': + return True + + perms = self.get_permission_required() + return self.request.user.has_perms(perms) + + class DetailView(PermissionRequiredMixin, CrudDetailView): + permission_required = permissoes_adm() + + def has_permission(self): + app_config = AppConfig.objects.last() + + if app_config: + if app_config.documentos_administrativos == 'O': + return True + + perms = self.get_permission_required() + return self.request.user.has_perms(perms) + class StatusTramitacaoAdministrativoCrud(Crud): model = StatusTramitacaoAdministrativo @@ -95,7 +122,7 @@ class ProtocoloPesquisaView(PermissionRequiredMixin, FilterView): kwargs = {'data': self.request.GET or None} - qs = self.get_queryset() + qs = self.get_queryset().order_by('ano', 'numero') qs = qs.distinct() @@ -373,6 +400,16 @@ class PesquisarDocumentoAdministrativoView(PermissionRequiredMixin, paginate_by = 10 permission_required = permissoes_adm() + def has_permission(self): + app_config = AppConfig.objects.last() + + if app_config: + if app_config.documentos_administrativos == 'O': + return True + + perms = self.get_permission_required() + return self.request.user.has_perms(perms) + def get_filterset_kwargs(self, filterset_class): super(PesquisarDocumentoAdministrativoView, self).get_filterset_kwargs(filterset_class) @@ -574,13 +611,39 @@ class TramitacaoAdmCrud(MasterDetailCrud): form_class = TramitacaoAdmEditForm permission_required = permissoes_adm() + class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView): + permission_required = permissoes_adm() + class ListView(PermissionRequiredMixin, MasterDetailCrud.ListView): permission_required = permissoes_adm() def get_queryset(self): qs = super(MasterDetailCrud.ListView, self).get_queryset() kwargs = {self.crud.parent_field: self.kwargs['pk']} - return qs.filter(**kwargs).order_by('-id') + return qs.filter(**kwargs).order_by('-data_tramitacao', '-id') + + def has_permission(self): + app_config = AppConfig.objects.last() + + if app_config: + if app_config.documentos_administrativos == 'O': + return True + + perms = self.get_permission_required() + return self.request.user.has_perms(perms) + + class DetailView(PermissionRequiredMixin, MasterDetailCrud.DetailView): + permission_required = permissoes_adm() + + def has_permission(self): + app_config = AppConfig.objects.last() + + if app_config: + if app_config.documentos_administrativos == 'O': + return True + + perms = self.get_permission_required() + return self.request.user.has_perms(perms) def get_nome_autor(request): diff --git a/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py b/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py index 31910156f..b35aaadb3 100755 --- a/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py +++ b/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py @@ -21,8 +21,9 @@ def cabecalho(inf_basicas_dic, imagem): tmp += '\t\t\t\t\n' tmp += '\t\t\t\tSistema de Apoio ao Processo Legislativo\n' tmp += '\t\t\t\t\n' - tmp += '\t\t\t\tPauta da ' + str(inf_basicas_dic['num_sessao_plen']) + 'ª Reunião ' + str(inf_basicas_dic['nom_sessao']) + ' da ' + str( - inf_basicas_dic['num_sessao_leg']) + 'ª Sessão Legislativa da ' + str(inf_basicas_dic['num_legislatura']) + 'ª Legislatura \n' + tmp += '\t\t\t\tPauta da ' + str(inf_basicas_dic['num_sessao_plen']) + 'ª Reunião ' + str(inf_basicas_dic['nom_sessao']) + ' da ' + str( + inf_basicas_dic['num_sessao_leg']) + 'ª Sessão Legislativa da \n' + tmp += '\t\t\t\t' + str(inf_basicas_dic['num_legislatura']) + ' Legislatura \n' return tmp diff --git a/sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py b/sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py index 3dcb87cee..251990dce 100644 --- a/sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py +++ b/sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py @@ -22,8 +22,9 @@ def cabecalho(inf_basicas_dic, imagem): tmp += '\t\t\t\t\n' tmp += '\t\t\t\tSistema de Apoio ao Processo Legislativo\n' tmp += '\t\t\t\t\n' - tmp += '\t\t\t\tResumo da ' + str(inf_basicas_dic['num_sessao_plen']) + 'ª Reunião ' + str(inf_basicas_dic['nom_sessao']) + ' da ' + str( - inf_basicas_dic['num_sessao_leg']) + 'ª Sessão Legislativa da ' + str(inf_basicas_dic['num_legislatura']) + 'ª Legislatura \n' + tmp += '\t\t\t\tResumo da ' + str(inf_basicas_dic['num_sessao_plen']) + 'ª Reunião ' + str(inf_basicas_dic['nom_sessao']) + ' da ' + str( + inf_basicas_dic['num_sessao_leg']) + 'ª Sessão Legislativa da \n' + tmp += '\t\t\t\t' + str(inf_basicas_dic['num_legislatura']) + ' Legislatura \n' return tmp diff --git a/sapl/relatorios/urls.py b/sapl/relatorios/urls.py index a2837818b..32d018e7f 100644 --- a/sapl/relatorios/urls.py +++ b/sapl/relatorios/urls.py @@ -11,21 +11,21 @@ app_name = AppConfig.name urlpatterns = [ url(r'^relatorio/materia$', relatorio_materia, name='relatorio_materia'), - url(r'^relatorio/capa_processo$', + url(r'^relatorio/capa-processo$', relatorio_capa_processo, name='relatorio_capa_processo'), - url(r'^relatorio/ordem_dia$', relatorio_ordem_dia, + url(r'^relatorio/ordem-dia$', relatorio_ordem_dia, name='relatorio_ordem_dia'), - url(r'^relatorio/relatorio_documento_administrativo$', + url(r'^relatorio/relatorio-documento-administrativo$', relatorio_documento_administrativo, name='relatorio_documento_administrativo'), url(r'^relatorio/espelho$', relatorio_espelho, name='relatorio_espelho'), - url(r'^relatorio/(?P\d+)/sessao_plenaria$', + url(r'^relatorio/(?P\d+)/sessao-plenaria$', relatorio_sessao_plenaria, name='relatorio_sessao_plenaria'), url(r'^relatorio/protocolo$', relatorio_protocolo, name='relatorio_protocolo'), - url(r'^relatorio/(?P\d+)/(?P\d+)/etiqueta_protocolo$', + url(r'^relatorio/(?P\d+)/(?P\d+)/etiqueta-protocolo$', relatorio_etiqueta_protocolo, name='relatorio_etiqueta_protocolo'), - url(r'^relatorio/pauta_sessao$', + url(r'^relatorio/pauta-sessao$', relatorio_pauta_sessao, name='relatorio_pauta_sessao'), ] diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index 0a9b7b613..9b867f943 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -173,6 +173,7 @@ class SessaoPlenariaFilterSet(django_filters.FilterSet): data_inicio__day = django_filters.ChoiceFilter(required=False, label=u'Dia', choices=DIA_CHOICES) + titulo = _('Pesquisa de Sessão Plenária') class Meta: model = SessaoPlenaria @@ -190,7 +191,7 @@ class SessaoPlenariaFilterSet(django_filters.FilterSet): self.form.helper = FormHelper() self.form.helper.form_method = 'GET' self.form.helper.layout = Layout( - Fieldset(_('Pesquisa de Sessao Plenária'), + Fieldset(self.titulo, row1, form_actions(save_label='Pesquisar')) ) @@ -291,3 +292,7 @@ class OradorExpedienteForm(ModelForm): class Meta: model = OradorExpediente exclude = ['sessao_plenaria'] + + +class PautaSessaoFilterSet(SessaoPlenariaFilterSet): + titulo = _('Pesquisa de Pauta de Sessão') diff --git a/sapl/sessao/migrations/0026_auto_20160926_1445.py b/sapl/sessao/migrations/0026_auto_20160926_1445.py new file mode 100644 index 000000000..6380bb8df --- /dev/null +++ b/sapl/sessao/migrations/0026_auto_20160926_1445.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-26 17:45 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('sessao', '0025_auto_20160919_1503'), + ] + + operations = [ + migrations.AlterField( + model_name='expedientemateria', + name='materia', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.MateriaLegislativa', verbose_name='Matéria'), + ), + migrations.AlterField( + model_name='expedientemateria', + name='resultado', + field=models.TextField(blank=True, verbose_name='Resultado'), + ), + migrations.AlterField( + model_name='ordemdia', + name='materia', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.MateriaLegislativa', verbose_name='Matéria'), + ), + migrations.AlterField( + model_name='ordemdia', + name='resultado', + field=models.TextField(blank=True, verbose_name='Resultado'), + ), + ] diff --git a/sapl/sessao/models.py b/sapl/sessao/models.py index b8b24043a..78ff6a410 100644 --- a/sapl/sessao/models.py +++ b/sapl/sessao/models.py @@ -129,7 +129,7 @@ class SessaoPlenaria(models.Model): 'tipo_nome': self.tipo.nome, 'sessao_legislativa_numero': self.sessao_legislativa.numero, # XXX check if it shouldn't be legislatura.numero - 'legislatura_id': self.legislatura.id} + 'legislatura_id': self.legislatura.numero} class AbstractOrdemDia(models.Model): @@ -140,12 +140,13 @@ class AbstractOrdemDia(models.Model): ) sessao_plenaria = models.ForeignKey(SessaoPlenaria) - materia = models.ForeignKey(MateriaLegislativa) + materia = models.ForeignKey(MateriaLegislativa, + verbose_name=_('Matéria')) data_ordem = models.DateField(verbose_name=_('Data da Sessão')) observacao = models.TextField( blank=True, verbose_name=_('Ementa')) numero_ordem = models.PositiveIntegerField(verbose_name=_('Nº Ordem')) - resultado = models.TextField(blank=True) + resultado = models.TextField(blank=True, verbose_name=_('Resultado')) tipo_votacao = models.PositiveIntegerField( verbose_name=_('Tipo de votação'), choices=TIPO_VOTACAO_CHOICES) votacao_aberta = models.NullBooleanField( diff --git a/sapl/sessao/urls.py b/sapl/sessao/urls.py index 16231d881..e23bb4113 100644 --- a/sapl/sessao/urls.py +++ b/sapl/sessao/urls.py @@ -8,6 +8,7 @@ from sapl.sessao.views import (AdicionarVariasMateriasExpediente, OradorExpedienteCrud, PainelView, PautaExpedienteDetail, PautaOrdemDetail, PautaSessaoDetailView, PautaSessaoListView, + PesquisarPautaSessaoView, PesquisarSessaoPlenariaView, PresencaOrdemDiaView, PresencaView, ResumoView, SessaoCrud, SessaoPlenariaView, @@ -19,7 +20,8 @@ from sapl.sessao.views import (AdicionarVariasMateriasExpediente, VotacaoNominalExpedienteView, VotacaoNominalView, VotacaoView, abrir_votacao_expediente_view, - abrir_votacao_ordem_view, + abrir_votacao_ordem_view, recuperar_materia, + recuperar_numero_sessao, reordernar_materias_expediente, reordernar_materias_ordem) @@ -37,6 +39,10 @@ urlpatterns = [ ExpedienteMateriaCrud.get_urls() + MateriaOrdemDiaCrud.get_urls())), + + url(r'^recuperar-materia/', recuperar_materia), + url(r'^recuperar-numero-sessao/', recuperar_numero_sessao), + url(r'^(?P\d+)/(?P\d+)/abrir-votacao-expediente$', abrir_votacao_expediente_view, name="abrir_votacao_exp"), @@ -70,6 +76,8 @@ urlpatterns = [ # PAUTA SESSÃO url(r'^pauta-sessao$', PautaSessaoListView.as_view(), name='list_pauta_sessao'), + url(r'^pauta-sessao/pesquisar-pauta$', + PesquisarPautaSessaoView.as_view(), name='pesquisar_pauta'), url(r'^pauta-sessao/(?P\d+)$', PautaSessaoDetailView.as_view(), name='pauta_sessao_detail'), url(r'^pauta-sessao/(?P\d+)/expediente/$', diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index a15c3a8e0..653e81166 100644 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -6,6 +6,7 @@ from django.contrib.auth.mixins import PermissionRequiredMixin from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.core.urlresolvers import reverse from django.forms.utils import ErrorList +from django.http import JsonResponse from django.http.response import HttpResponseRedirect from django.utils.datastructures import MultiValueDictKeyError from django.utils.html import strip_tags @@ -20,7 +21,8 @@ from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView, CrudUpdateView, make_pagination) from sapl.crud.masterdetail import MasterDetailCrud from sapl.materia.forms import pega_ultima_tramitacao -from sapl.materia.models import Autoria, DocumentoAcessorio, Tramitacao +from sapl.materia.models import (Autoria, DocumentoAcessorio, + TipoMateriaLegislativa, Tramitacao) from sapl.materia.views import MateriaLegislativaPesquisaView from sapl.norma.models import NormaJuridica from sapl.parlamentares.models import Parlamentar @@ -30,8 +32,9 @@ from sapl.utils import permissao_tb_aux, permissoes_painel, permissoes_sessao from .forms import (AdicionarVariasMateriasFilterSet, BancadaForm, ExpedienteForm, ExpedienteMateriaForm, ListMateriaForm, MesaForm, OradorExpedienteForm, OradorForm, OrdemDiaForm, - PresencaForm, SessaoPlenariaFilterSet, VotacaoEditForm, - VotacaoForm, VotacaoNominalForm) + PautaSessaoFilterSet, PresencaForm, + SessaoPlenariaFilterSet, VotacaoEditForm, VotacaoForm, + VotacaoNominalForm) from .models import (Bancada, Bloco, CargoBancada, CargoMesa, ExpedienteMateria, ExpedienteSessao, IntegranteMesa, MateriaLegislativa, Orador, OradorExpediente, OrdemDia, @@ -275,6 +278,23 @@ class MateriaOrdemDiaCrud(MasterDetailCrud): return [self._as_row(obj) for obj in object_list] +def recuperar_materia(request): + tipo = TipoMateriaLegislativa.objects.get(pk=request.GET['tipo_materia']) + numero = request.GET['numero_materia'] + ano = request.GET['ano_materia'] + + try: + materia = MateriaLegislativa.objects.get(tipo=tipo, + ano=ano, + numero=numero) + response = JsonResponse({'ementa': materia.ementa, + 'id': materia.id}) + except ObjectDoesNotExist: + response = JsonResponse({'ementa': '', 'id': 0}) + + return response + + class ExpedienteMateriaCrud(MasterDetailCrud): model = ExpedienteMateria parent_field = 'sessao_plenaria' @@ -433,6 +453,18 @@ class OradorCrud(OradorCrud): permission_required = permissoes_sessao() +def recuperar_numero_sessao(request): + try: + numero = SessaoPlenaria.objects.filter( + tipo__pk=request.GET['tipo']).last().numero + except ObjectDoesNotExist: + response = JsonResponse({'numero': 1}) + else: + response = JsonResponse({'numero': numero + 1}) + + return response + + class SessaoCrud(Crud): model = SessaoPlenaria help_path = 'sessao_plenaria' @@ -856,18 +888,14 @@ class ResumoView(SessaoCrud.CrudDetailView): # ===================================================================== # Expedientes expediente = ExpedienteSessao.objects.filter( - sessao_plenaria_id=self.object.id) + sessao_plenaria_id=self.object.id).order_by('tipo__nome') expedientes = [] for e in expediente: - tipo = TipoExpediente.objects.get( - id=e.tipo_id) - conteudo = sub( - ' ', ' ', strip_tags(e.conteudo)) - + tipo = TipoExpediente.objects.get(id=e.tipo_id) + conteudo = e.conteudo ex = {'tipo': tipo, 'conteudo': conteudo} expedientes.append(ex) - context.update({'expedientes': expedientes}) # ===================================================================== @@ -1001,16 +1029,16 @@ class ExpedienteView(FormMixin, def get(self, request, *args, **kwargs): self.object = self.get_object() context = self.get_context_data(object=self.object) - - tipos = TipoExpediente.objects.all() + tipos = TipoExpediente.objects.all().order_by('nome') expedientes_sessao = ExpedienteSessao.objects.filter( - sessao_plenaria_id=self.object.id) + sessao_plenaria_id=self.object.id).order_by('tipo__nome') expedientes_salvos = [] for e in expedientes_sessao: expedientes_salvos.append(e.tipo) tipos_null = list(set(tipos) - set(expedientes_salvos)) + tipos_null.sort(key=lambda x: x.nome) expedientes = [] for e, t in zip(expedientes_sessao, tipos): @@ -2032,7 +2060,7 @@ class PesquisarSessaoPlenariaView(FilterView): qs = self.get_queryset() qs = qs.distinct().order_by( - '-legislatura__id', '-data_inicio', '-numero') + '-legislatura__numero', '-data_inicio', '-numero') kwargs.update({ 'queryset': qs, @@ -2076,6 +2104,11 @@ class PesquisarSessaoPlenariaView(FilterView): return self.render_to_response(context) +class PesquisarPautaSessaoView(PesquisarSessaoPlenariaView): + filterset_class = PautaSessaoFilterSet + template_name = 'sessao/pauta_sessao_filter.html' + + def filtra_tramitacao_ordem_dia(): lista = pega_ultima_tramitacao() return Tramitacao.objects.filter( diff --git a/sapl/static/js/app.js b/sapl/static/js/app.js index 127bf2b86..84ceb0e8a 100644 --- a/sapl/static/js/app.js +++ b/sapl/static/js/app.js @@ -13,7 +13,9 @@ function initTinymce(elements, readonly=false) { } if (readonly) { - config_tinymce.readonly = 1 + config_tinymce.readonly = 1, + config_tinymce.menubar = false, + config_tinymce.toolbar = false } if (elements != null) { @@ -88,7 +90,7 @@ function autorModal() { $("#pesquisar").click(function() { var query = $("#q").val() - $.get("/proposicao/pesquisar_autor?q="+ query, function( + $.get("/proposicao/pesquisar-autor?q="+ query, function( data, status){ $("#div-resultado").children().remove(); @@ -140,7 +142,7 @@ function autorModal() { if ($(fieldname).length > 0) { // se campo existir if ($(fieldname).val() != "") { // e não for vazio var id = $(fieldname).val(); - $.get("/proposicao/get_nome_autor?id=" + id, function(data, status){ + $.get("/proposicao/get-nome-autor?id=" + id, function(data, status){ $("#nome_autor").text(data.nome); }); } diff --git a/sapl/static/styles/app.scss b/sapl/static/styles/app.scss index 27830c7e1..114d4052d 100644 --- a/sapl/static/styles/app.scss +++ b/sapl/static/styles/app.scss @@ -10,7 +10,9 @@ nav { &.navbar { + padding: 5px; border-radius: 0; + font-size: 15px; } } @@ -40,7 +42,6 @@ nav { .navbar-brand { padding: 0px; } - // ADJUST DRUNKEN PARROT STYLES ######################################## h1, .h1 { font-size: 30px; diff --git a/sapl/templates/base.html b/sapl/templates/base.html index 83f6414a3..4170b58b4 100644 --- a/sapl/templates/base.html +++ b/sapl/templates/base.html @@ -64,16 +64,19 @@ {# Proposições #} + {% endif %} + {% if user|get_doc_adm_template_perms %} Documentos Administrativos Pesquisar Documento Administrativo + {% endif %} - {% endif %} + Atividade Legislativa @@ -83,7 +86,7 @@ {% endif %} Matérias Legislativas Sessões Plenárias - Pautas das Sessões + Pautas das Sessões Tramitação em Lote Acessório em Lote + {% block extra_js %} {% if perms|get_add_perm:view %} + +{% endblock %} diff --git a/sapl/templates/sessao/ordemdia_form.html b/sapl/templates/sessao/ordemdia_form.html new file mode 100644 index 000000000..dbb2739c8 --- /dev/null +++ b/sapl/templates/sessao/ordemdia_form.html @@ -0,0 +1,4 @@ +{% extends "sessao/expedientemateria_form.html" %} +{% load i18n %} +{% load crispy_forms_tags %} +{% load common_tags %} diff --git a/sapl/templates/sessao/pauta_sessao_filter.html b/sapl/templates/sessao/pauta_sessao_filter.html new file mode 100644 index 000000000..efacee554 --- /dev/null +++ b/sapl/templates/sessao/pauta_sessao_filter.html @@ -0,0 +1,49 @@ +{% extends "crud/detail.html" %} +{% load i18n %} +{% load crispy_forms_tags %} +{% load i18n staticfiles %} + +{% block sections_nav %} {% endblock %} + +{% block detail_content %} + Pesquisar Pauta de Sessão + + + {% crispy filter.form %} + + + + Resultados + + {% if page_obj|length %} + {% if numero_res > 1 %} + Foram encontradas {{numero_res}} pautas de sessões. + {% elif numero_res == 1 %} + Foi encontrada {{numero_res}} pauta de sessão. + {% endif %} + + {% for s in page_obj %} + + + {{s}} + + + + + + + + {% endfor %} + {% else %} + + + Nenhuma Pauta de Sessão encontrada com essas especificações + + {% endif %} + + + +{% include "paginacao.html" %} + +{% endblock detail_content %} + diff --git a/sapl/templates/sessao/resumo.html b/sapl/templates/sessao/resumo.html index bc1fe4b96..607064358 100644 --- a/sapl/templates/sessao/resumo.html +++ b/sapl/templates/sessao/resumo.html @@ -49,8 +49,10 @@ {% for e in expedientes %} - {{e.tipo}}: - {{e.conteudo}} + {{e.tipo}}: + + {{e.conteudo|safe}} + {% endfor %} @@ -61,22 +63,28 @@ Matérias do Expediente - - Matéria - Ementa - Resultado da Votação - - - {% for m in materia_expediente %} - - {{m.numero}} - {{m.titulo}} - - Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }} - - {{m.ementa|safe}} - {{m.resultado}} - {% endfor %} - + + + + Matéria + Ementa + Resultado da Votação + + + + {% for m in materia_expediente %} + + + {{m.numero}} - {{m.titulo}} + + Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }} + + {{m.ementa|safe}} + {{m.resultado}} + + {% endfor %} + + @@ -107,21 +115,27 @@ Matérias da Ordem do Dia - - Matéria - Ementa - Resultado da Votação - - - {% for m in materias_ordem %} - - {{m.numero}} - {{m.titulo}} - - Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }} - - {{m.ementa|safe}} - {{m.resultado}} - {% endfor %} - + + + + Matéria + Ementa + Resultado da Votação + + + + {% for m in materias_ordem %} + + + {{m.numero}} - {{m.titulo}} + + Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }} + + {{m.ementa|safe}} + {{m.resultado}} + + {% endfor %} + + {% endblock detail_content %} diff --git a/sapl/templates/sessao/sessaoplenaria_filter.html b/sapl/templates/sessao/sessaoplenaria_filter.html index a1fe89169..aa35489b8 100644 --- a/sapl/templates/sessao/sessaoplenaria_filter.html +++ b/sapl/templates/sessao/sessaoplenaria_filter.html @@ -1,11 +1,14 @@ {% extends "crud/detail.html" %} {% load i18n %} {% load crispy_forms_tags %} +{% load common_tags %} {% block actions %} - - {% blocktrans with verbose_name=view.verbose_name %} Adicionar Sessão Plenária {% endblocktrans %} + {% if perms|get_add_perm:view %} + + {% blocktrans with verbose_name=view.verbose_name %} Adicionar Sessão Plenária {% endblocktrans %} + {% endif %} {% if filter_url %} {% trans 'Fazer nova pesquisa' %} diff --git a/sapl/templates/sessao/sessaoplenaria_form.html b/sapl/templates/sessao/sessaoplenaria_form.html new file mode 100644 index 000000000..5e9281eba --- /dev/null +++ b/sapl/templates/sessao/sessaoplenaria_form.html @@ -0,0 +1,24 @@ +{% extends "crud/form.html" %} +{% load i18n %} +{% load crispy_forms_tags %} +{% load common_tags %} + +{% block extra_js %} + + + +{% endblock %} diff --git a/sapl/templates/sistema.html b/sapl/templates/sistema.html index 88da240e3..659e4706d 100644 --- a/sapl/templates/sistema.html +++ b/sapl/templates/sistema.html @@ -16,7 +16,7 @@ Tipo de Afastamento Tipo de Dependente Tipo de Situação Militar - Nível de Intrução + Nível de Instrução Partido Coligação diff --git a/sapl/utils.py b/sapl/utils.py index b59b4f5b3..df4a895d1 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -3,6 +3,7 @@ from datetime import date from functools import wraps import magic +from django import forms from django.apps import apps from django.conf import settings from django.contrib import admin @@ -46,6 +47,28 @@ class ImageThumbnailFileInput(ClearableFileInput): template_name = 'floppyforms/image_thumbnail.html' +class RangeWidgetOverride(forms.MultiWidget): + + def __init__(self, attrs=None): + widgets = (forms.DateInput(format='%d/%m/%Y', + attrs={'class': 'dateinput', + 'placeholder': 'Inicial'}), + forms.DateInput(format='%d/%m/%Y', + attrs={'class': 'dateinput', + 'placeholder': 'Final'})) + super(RangeWidgetOverride, self).__init__(widgets, attrs) + + def decompress(self, value): + if value: + return [value.start, value.stop] + return [None, None] + + def format_output(self, rendered_widgets): + html = '%s%s'\ + % tuple(rendered_widgets) + return '%s' % html + + def register_all_models_in_admin(module_name): appname = module_name.split('.') appname = appname[1] if appname[0] == 'sapl' else appname[0] diff --git a/scripts/id_numero_legislatura.py b/scripts/id_numero_legislatura.py new file mode 100644 index 000000000..5552050cf --- /dev/null +++ b/scripts/id_numero_legislatura.py @@ -0,0 +1,11 @@ +from sapl.parlamentares.models import Legislatura + + +def popula_numero_legislatura_id(): + for l in Legislatura.objects.all(): + l.numero = l.id + l.save() + + +if __name__ == '__main__': + popula_numero_legislatura_id() diff --git a/scripts/inicializa_grupos_autorizacoes.py b/scripts/inicializa_grupos_autorizacoes.py index f0fe713ca..1377d66e6 100644 --- a/scripts/inicializa_grupos_autorizacoes.py +++ b/scripts/inicializa_grupos_autorizacoes.py @@ -1,5 +1,6 @@ from django.apps import apps -from django.contrib.auth.models import Group, Permission, User +from django.contrib.auth import get_user_model +from django.contrib.auth.models import Group, Permission from django.contrib.contenttypes.models import ContentType @@ -12,7 +13,7 @@ def cria_ou_reseta_grupo(nome): def cria_usuario(nome, grupo): nome_usuario = nome - usuario = User.objects.get_or_create(username=nome_usuario)[0] + usuario = get_user_model().objects.get_or_create(username=nome_usuario)[0] usuario.set_password('interlegis') usuario.save() grupo.user_set.add(usuario) @@ -82,7 +83,8 @@ def cria_grupos_permissoes(): # Cria o Usuario nome_usuario = 'operador_%s' % nome_app - usuario = User.objects.get_or_create(username=nome_usuario)[0] + usuario = get_user_model().objects.get_or_create( + username=nome_usuario)[0] usuario.set_password('interlegis') usuario.save() grupo.user_set.add(usuario) @@ -110,5 +112,6 @@ def cria_grupos_permissoes(): nome_usuario = 'operador_autor' cria_usuario(nome_usuario, grupo) + if __name__ == '__main__': cria_grupos_permissoes()
{{e.conteudo|safe}}