Browse Source

Merge branch 'master' into 596-quebra-css

pull/615/head
Eduardo Calil 8 years ago
parent
commit
fbfc9ab88c
  1. 25
      sapl/base/forms.py
  2. 21
      sapl/base/templatetags/common_tags.py
  3. 64
      sapl/materia/forms.py
  4. 26
      sapl/materia/migrations/0048_auto_20160927_1254.py
  5. 13
      sapl/materia/models.py
  6. 8
      sapl/materia/tests/test_materia.py
  7. 82
      sapl/materia/views.py
  8. 2
      sapl/painel/urls.py
  9. 4
      sapl/parlamentares/forms.py
  10. 21
      sapl/parlamentares/migrations/0028_legislatura_numero.py
  11. 16
      sapl/parlamentares/migrations/0029_merge.py
  12. 20
      sapl/parlamentares/migrations/0030_auto_20160928_0846.py
  13. 11
      sapl/parlamentares/models.py
  14. 25
      sapl/parlamentares/views.py
  15. 6
      sapl/protocoloadm/forms.py
  16. 8
      sapl/protocoloadm/urls.py
  17. 69
      sapl/protocoloadm/views.py
  18. 5
      sapl/relatorios/templates/pdf_pauta_sessao_gerar.py
  19. 5
      sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py
  20. 12
      sapl/relatorios/urls.py
  21. 7
      sapl/sessao/forms.py
  22. 36
      sapl/sessao/migrations/0026_auto_20160926_1445.py
  23. 7
      sapl/sessao/models.py
  24. 10
      sapl/sessao/urls.py
  25. 61
      sapl/sessao/views.py
  26. 8
      sapl/static/js/app.js
  27. 3
      sapl/static/styles/app.scss
  28. 7
      sapl/templates/base.html
  29. 49
      sapl/templates/base/appconfig_list.html
  30. 2
      sapl/templates/comissoes/composicao_detail.html
  31. 1
      sapl/templates/comissoes/layouts.yaml
  32. 2
      sapl/templates/compilacao/text_list.html
  33. 2
      sapl/templates/compilacao/textoarticulado_detail.html
  34. 2
      sapl/templates/index.html
  35. 6
      sapl/templates/materia/autor_form.html
  36. 5
      sapl/templates/materia/layouts.yaml
  37. 6
      sapl/templates/protocoloadm/documentoadministrativo_detail.html
  38. 6
      sapl/templates/protocoloadm/tramitacaoadministrativo_detail.html
  39. 30
      sapl/templates/sessao/expedientemateria_form.html
  40. 4
      sapl/templates/sessao/ordemdia_form.html
  41. 49
      sapl/templates/sessao/pauta_sessao_filter.html
  42. 62
      sapl/templates/sessao/resumo.html
  43. 3
      sapl/templates/sessao/sessaoplenaria_filter.html
  44. 24
      sapl/templates/sessao/sessaoplenaria_form.html
  45. 2
      sapl/templates/sistema.html
  46. 23
      sapl/utils.py
  47. 11
      scripts/id_numero_legislatura.py
  48. 9
      scripts/inicializa_grupos_autorizacoes.py

25
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.materia.models import MateriaLegislativa
from sapl.sessao.models import SessaoPlenaria from sapl.sessao.models import SessaoPlenaria
from sapl.settings import MAX_IMAGE_UPLOAD_SIZE from sapl.settings import MAX_IMAGE_UPLOAD_SIZE
from sapl.utils import (RANGE_ANOS, ImageThumbnailFileInput, autor_label, from sapl.utils import (RANGE_ANOS, ImageThumbnailFileInput,
autor_modal) RangeWidgetOverride, autor_label, autor_modal)
from .models import AppConfig, CasaLegislativa 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): class RelatorioAtasFilterSet(django_filters.FilterSet):
filter_overrides = {models.DateField: { filter_overrides = {models.DateField: {
@ -287,6 +267,7 @@ class LoginForm(AuthenticationForm):
class ConfiguracoesAppForm(ModelForm): class ConfiguracoesAppForm(ModelForm):
class Meta: class Meta:
model = AppConfig model = AppConfig
fields = ['documentos_administrativos', fields = ['documentos_administrativos',

21
sapl/base/templatetags/common_tags.py

@ -1,7 +1,9 @@
from compressor.utils import get_class from compressor.utils import get_class
from django import template from django import template
from sapl.base.models import AppConfig
from sapl.parlamentares.models import Filiacao from sapl.parlamentares.models import Filiacao
from sapl.utils import permissoes_adm
register = template.Library() register = template.Library()
@ -85,6 +87,17 @@ def get_delete_perm(value, arg):
return perm.__contains__(nome_app + can_delete) 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 @register.filter
def ver_menu_sistema_perm(value): def ver_menu_sistema_perm(value):
u = value u = value
@ -105,3 +118,11 @@ def ultima_filiacao(value):
return ultima_filiacao.partido return ultima_filiacao.partido
else: else:
return None return None
@register.filter
def get_config_not_exists(user):
if not AppConfig.objects.all().exists():
return True
else:
return False

64
sapl/materia/forms.py

@ -4,6 +4,7 @@ import django_filters
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML, Button, Column, Fieldset, Layout from crispy_forms.layout import HTML, Button, Column, Fieldset, Layout
from django import forms from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group, User from django.contrib.auth.models import Group, User
from django.contrib.auth.password_validation import validate_password from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ObjectDoesNotExist, ValidationError 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, from sapl.norma.models import (LegislacaoCitada, NormaJuridica,
TipoNormaJuridica) TipoNormaJuridica)
from sapl.settings import MAX_DOC_UPLOAD_SIZE 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, from .models import (AcompanhamentoMateria, Anexada, Autor, Autoria,
DespachoInicial, DocumentoAcessorio, MateriaLegislativa, DespachoInicial, DocumentoAcessorio, MateriaLegislativa,
@ -34,6 +36,7 @@ def em_tramitacao():
class ConfirmarProposicaoForm(ModelForm): class ConfirmarProposicaoForm(ModelForm):
class Meta: class Meta:
model = Proposicao model = Proposicao
exclude = ['texto_original', 'descricao', 'tipo'] exclude = ['texto_original', 'descricao', 'tipo']
@ -445,26 +448,6 @@ class AnexadaForm(ModelForm):
fields = ['tipo', 'numero', 'ano', 'data_anexacao', 'data_desanexacao'] 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): class MateriaLegislativaFilterSet(django_filters.FilterSet):
filter_overrides = {models.DateField: { filter_overrides = {models.DateField: {
@ -678,9 +661,8 @@ class AutorForm(ModelForm):
'email', 'email',
'nome', 'nome',
'tipo', 'tipo',
'cargo', 'cargo']
'parlamentar', widgets = {'nome': forms.HiddenInput()}
'comissao']
def valida_igualdade(self, texto1, texto2, msg): def valida_igualdade(self, texto1, texto2, msg):
if texto1 != texto2: if texto1 != texto2:
@ -688,14 +670,14 @@ class AutorForm(ModelForm):
return True return True
def valida_email_existente(self): def valida_email_existente(self):
return User.objects.filter( return get_user_model().objects.filter(
email=self.cleaned_data['email']).exists() email=self.cleaned_data['email']).exists()
def usuario_existente(self):
return User.objects.filter(
username=self.cleaned_data['username']).exists()
def clean(self): def clean(self):
if 'username' not in self.cleaned_data:
raise ValidationError(_('Favor informar o username'))
if ('senha' not in self.cleaned_data or if ('senha' not in self.cleaned_data or
'senha_confirma' not in self.cleaned_data): 'senha_confirma' not in self.cleaned_data):
raise ValidationError(_('Favor informar as senhas')) raise ValidationError(_('Favor informar as senhas'))
@ -718,19 +700,29 @@ class AutorForm(ModelForm):
email_existente = self.valida_email_existente() 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: if email_existente:
msg = _('Este email já foi cadastrado.') msg = _('Este email já foi cadastrado.')
raise ValidationError(msg) raise ValidationError(msg)
if self.usuario_existente():
msg = _('Este nome de usuario já foi cadastrado.')
raise ValidationError(msg)
try: try:
validate_password(self.cleaned_data['senha']) validate_password(self.cleaned_data['senha'])
except ValidationError as error: except ValidationError as error:
raise ValidationError(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 return self.cleaned_data
@transaction.atomic @transaction.atomic
@ -738,15 +730,9 @@ class AutorForm(ModelForm):
autor = super(AutorForm, self).save(commit) autor = super(AutorForm, self).save(commit)
try:
u = User.objects.get( u = User.objects.get(
username=autor.username, username=autor.username,
email=autor.email) 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.set_password(self.cleaned_data['senha']) u.set_password(self.cleaned_data['senha'])
u.is_active = False u.is_active = False

26
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'),
),
]

13
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.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from model_utils import Choices from model_utils import Choices
@ -6,7 +6,8 @@ from model_utils import Choices
from sapl.comissoes.models import Comissao from sapl.comissoes.models import Comissao
from sapl.parlamentares.models import Parlamentar, Partido from sapl.parlamentares.models import Parlamentar, Partido
from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, 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(): def grupo_autor():
@ -208,7 +209,8 @@ class TipoAutor(models.Model):
class Autor(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) partido = models.ForeignKey(Partido, blank=True, null=True)
comissao = models.ForeignKey(Comissao, blank=True, null=True) comissao = models.ForeignKey(Comissao, blank=True, null=True)
parlamentar = models.ForeignKey(Parlamentar, blank=True, null=True) parlamentar = models.ForeignKey(Parlamentar, blank=True, null=True)
@ -243,8 +245,9 @@ class Autor(models.Model):
class Autoria(models.Model): class Autoria(models.Model):
partido = models.ForeignKey(Partido, blank=True, null=True) partido = models.ForeignKey(Partido, blank=True, null=True,
autor = models.ForeignKey(Autor) verbose_name=_('Partido'))
autor = models.ForeignKey(Autor, verbose_name=_('Autor'))
materia = models.ForeignKey(MateriaLegislativa) materia = models.ForeignKey(MateriaLegislativa)
primeiro_autor = models.BooleanField(verbose_name=_('Primeiro Autor'), primeiro_autor = models.BooleanField(verbose_name=_('Primeiro Autor'),
choices=YES_NO_CHOICES) choices=YES_NO_CHOICES)

8
sapl/materia/tests/test_materia.py

@ -1,8 +1,8 @@
import pytest from django.contrib.auth import get_user_model
from django.contrib.auth.models import User
from django.core.files.uploadedfile import SimpleUploadedFile from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from model_mommy import mommy from model_mommy import mommy
import pytest
from sapl.comissoes.models import Comissao, TipoComissao from sapl.comissoes.models import Comissao, TipoComissao
from sapl.materia.models import (Anexada, Autor, Autoria, DespachoInicial, 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) @pytest.mark.django_db(transaction=False)
def test_proposicao_submit(admin_client): def test_proposicao_submit(admin_client):
tipo_autor = mommy.make(TipoAutor, descricao='Teste Tipo_Autor') 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 = mommy.make(
Autor, Autor,
@ -469,7 +469,7 @@ def test_proposicao_submit(admin_client):
def test_form_errors_proposicao(admin_client): def test_form_errors_proposicao(admin_client):
tipo_autor = mommy.make(TipoAutor, descricao='Teste Tipo_Autor') 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 = mommy.make(
Autor, Autor,

82
sapl/materia/views.py

@ -6,8 +6,8 @@ from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML, Button from crispy_forms.layout import HTML, Button
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.contrib.auth import get_user_model
from django.contrib.auth.mixins import PermissionRequiredMixin 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.contrib.auth.tokens import default_token_generator
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
from django.core.mail import send_mail from django.core.mail import send_mail
@ -54,6 +54,7 @@ from .models import (AcompanhamentoMateria, Anexada, Autor, Autoria,
TipoFimRelatoria, TipoMateriaLegislativa, TipoProposicao, TipoFimRelatoria, TipoMateriaLegislativa, TipoProposicao,
Tramitacao, UnidadeTramitacao) Tramitacao, UnidadeTramitacao)
AnexadaCrud = Crud.build(Anexada, '') AnexadaCrud = Crud.build(Anexada, '')
@ -62,6 +63,7 @@ class OrigemCrud(Crud):
help_path = 'origem' help_path = 'origem'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self): def has_permission(self):
return permissao_tb_aux(self) return permissao_tb_aux(self)
@ -71,6 +73,7 @@ class TipoMateriaCrud(Crud):
help_path = 'tipo_materia_legislativa' help_path = 'tipo_materia_legislativa'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self): def has_permission(self):
return permissao_tb_aux(self) return permissao_tb_aux(self)
@ -80,6 +83,7 @@ class RegimeTramitacaoCrud(Crud):
help_path = 'regime_tramitacao' help_path = 'regime_tramitacao'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self): def has_permission(self):
return permissao_tb_aux(self) return permissao_tb_aux(self)
@ -89,6 +93,7 @@ class TipoDocumentoCrud(Crud):
help_path = 'tipo_documento' help_path = 'tipo_documento'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self): def has_permission(self):
return permissao_tb_aux(self) return permissao_tb_aux(self)
@ -98,6 +103,7 @@ class TipoFimRelatoriaCrud(Crud):
help_path = 'fim_relatoria' help_path = 'fim_relatoria'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self): def has_permission(self):
return permissao_tb_aux(self) return permissao_tb_aux(self)
@ -107,30 +113,75 @@ class TipoAutorCrud(Crud):
help_path = 'tipo_autor' help_path = 'tipo_autor'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self): def has_permission(self):
return permissao_tb_aux(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('<br /><br />'))
# 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('<a href="{{ view.cancel_url }}"'
' class="btn btn-inverse">Cancelar</a>')]))
class AutorCrud(Crud): class AutorCrud(Crud):
model = Autor model = Autor
help_path = 'autor' help_path = 'autor'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
list_field_names = ['tipo', 'nome', list_field_names = ['tipo', 'nome']
'username', 'cargo']
def has_permission(self): def has_permission(self):
return permissao_tb_aux(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): class CreateView(CrudCreateView):
form_class = AutorForm form_class = AutorForm
layout_key = 'AutorCreate' 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): def get_success_url(self):
pk_autor = Autor.objects.get( pk_autor = Autor.objects.get(
email=self.request.POST.get('email')).id email=self.request.POST.get('email')).id
kwargs = {} 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['token'] = default_token_generator.make_token(user)
kwargs['uidb64'] = urlsafe_base64_encode(force_bytes(user.pk)) kwargs['uidb64'] = urlsafe_base64_encode(force_bytes(user.pk))
assunto = "SAPL - Confirmação de Conta" assunto = "SAPL - Confirmação de Conta"
@ -159,7 +210,7 @@ class ConfirmarEmailView(TemplateView):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
uid = urlsafe_base64_decode(self.kwargs['uidb64']) 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.is_active = True
user.save() user.save()
context = self.get_context_data(**kwargs) context = self.get_context_data(**kwargs)
@ -181,6 +232,7 @@ class TipoProposicaoCrud(Crud):
help_path = 'tipo_proposicao' help_path = 'tipo_proposicao'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self): def has_permission(self):
return permissao_tb_aux(self) return permissao_tb_aux(self)
@ -473,6 +525,11 @@ class ProposicaoCrud(Crud):
id=self.kwargs['pk'], id=self.kwargs['pk'],
autor__user_id=self.request.user.id).exists()) 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): class ListView(PermissionRequiredMixin, CrudListView):
ordering = ['-data_envio', 'descricao'] ordering = ['-data_envio', 'descricao']
permission_required = permissoes_autor() permission_required = permissoes_autor()
@ -634,7 +691,7 @@ class TramitacaoCrud(MasterDetailCrud):
def get_queryset(self): def get_queryset(self):
qs = super(MasterDetailCrud.ListView, self).get_queryset() qs = super(MasterDetailCrud.ListView, self).get_queryset()
kwargs = {self.crud.parent_field: self.kwargs['pk']} 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): class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_materia() permission_required = permissoes_materia()
@ -654,9 +711,9 @@ class TramitacaoCrud(MasterDetailCrud):
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
def montar_row_autor(): def montar_row_autor(name):
autor_row = to_row( autor_row = to_row(
[('autor', 0), [(name, 0),
(Button('pesquisar', (Button('pesquisar',
'Pesquisar Autor', 'Pesquisar Autor',
css_class='btn btn-primary btn-sm'), 2), css_class='btn btn-primary btn-sm'), 2),
@ -668,7 +725,7 @@ def montar_row_autor():
def montar_helper_documento_acessorio(self): def montar_helper_documento_acessorio(self):
autor_row = montar_row_autor() autor_row = montar_row_autor('autor')
self.helper = FormHelper() self.helper = FormHelper()
self.helper.layout = SaplFormLayout(*self.get_layout()) self.helper.layout = SaplFormLayout(*self.get_layout())
@ -982,6 +1039,13 @@ class MateriaLegislativaPesquisaView(FilterView):
qr = self.request.GET.copy() qr = self.request.GET.copy()
if 'page' in qr: if 'page' in qr:
del qr['page'] 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 '' context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
return context return context

2
sapl/painel/urls.py

@ -8,7 +8,7 @@ from .views import (controlador_painel, cronometro_painel, get_dados_painel,
app_name = AppConfig.name app_name = AppConfig.name
urlpatterns = [ urlpatterns = [
url(r'^painel_principal/(?P<pk>\d+)$', painel_view, url(r'^painel-principal/(?P<pk>\d+)$', painel_view,
name="painel_principal"), name="painel_principal"),
url(r'^painel/(?P<pk>\d+)/dados$', get_dados_painel, name='dados_painel'), url(r'^painel/(?P<pk>\d+)/dados$', get_dados_painel, name='dados_painel'),
url(r'^painel/controlador$', url(r'^painel/controlador$',

4
sapl/parlamentares/forms.py

@ -24,6 +24,7 @@ class LegislaturaForm(ModelForm):
def clean(self): def clean(self):
cleaned_data = self.cleaned_data cleaned_data = self.cleaned_data
numero = cleaned_data['numero']
data_inicio = cleaned_data['data_inicio'] data_inicio = cleaned_data['data_inicio']
data_fim = cleaned_data['data_fim'] data_fim = cleaned_data['data_fim']
data_eleicao = cleaned_data['data_eleicao'] data_eleicao = cleaned_data['data_eleicao']
@ -32,6 +33,9 @@ class LegislaturaForm(ModelForm):
raise ValidationError(_('A data início deve ser menor que a ' + raise ValidationError(_('A data início deve ser menor que a ' +
'data fim, e a data eleição deve ser ' + 'data fim, e a data eleição deve ser ' +
'menor que a data início')) '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 return cleaned_data

21
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,
),
]

16
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 = [
]

20
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'),
),
]

11
sapl/parlamentares/models.py

@ -10,6 +10,7 @@ from sapl.utils import (INDICADOR_AFASTAMENTO, UF, YES_NO_CHOICES,
class Legislatura(models.Model): class Legislatura(models.Model):
numero = models.PositiveIntegerField(verbose_name=_('Número'))
data_inicio = models.DateField(verbose_name=_('Data Início')) data_inicio = models.DateField(verbose_name=_('Data Início'))
data_fim = models.DateField(verbose_name=_('Data Fim')) data_fim = models.DateField(verbose_name=_('Data Fim'))
data_eleicao = models.DateField(verbose_name=_('Data Eleição')) data_eleicao = models.DateField(verbose_name=_('Data Eleição'))
@ -33,8 +34,8 @@ class Legislatura(models.Model):
else: else:
current = '' current = ''
return _('%(id)sª (%(start)s - %(end)s)%(current)s') % { return _('%(numero)sª (%(start)s - %(end)s)%(current)s') % {
'id': self.id, 'numero': self.numero,
'start': self.data_inicio.year, 'start': self.data_inicio.year,
'end': self.data_fim.year, 'end': self.data_fim.year,
'current': current} 'current': current}
@ -64,8 +65,8 @@ class SessaoLegislativa(models.Model):
verbose_name_plural = _('Sessões Legislativas') verbose_name_plural = _('Sessões Legislativas')
def __str__(self): def __str__(self):
return _('%(id)sº (%(inicio)s - %(fim)s)') % { return _('%(numero)sº (%(inicio)s - %(fim)s)') % {
'id': self.id, 'numero': self.numero,
'inicio': self.data_inicio.year, 'inicio': self.data_inicio.year,
'fim': self.data_fim.year} 'fim': self.data_fim.year}
@ -267,7 +268,7 @@ class Parlamentar(models.Model):
class TipoDependente(models.Model): class TipoDependente(models.Model):
descricao = models.CharField(max_length=50) descricao = models.CharField(max_length=50, verbose_name=_('Descrição'))
class Meta: class Meta:
verbose_name = _('Tipo de Dependente') verbose_name = _('Tipo de Dependente')

25
sapl/parlamentares/views.py

@ -149,6 +149,7 @@ class CargoMesaCrud(Crud):
help_path = 'cargo_mesa' help_path = 'cargo_mesa'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self): def has_permission(self):
return permissao_tb_aux(self) return permissao_tb_aux(self)
@ -158,6 +159,7 @@ class PartidoCrud(Crud):
help_path = 'partidos' help_path = 'partidos'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self): def has_permission(self):
return permissao_tb_aux(self) return permissao_tb_aux(self)
@ -167,6 +169,7 @@ class SessaoLegislativaCrud(Crud):
help_path = 'sessao_legislativa' help_path = 'sessao_legislativa'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self): def has_permission(self):
return permissao_tb_aux(self) return permissao_tb_aux(self)
@ -176,6 +179,7 @@ class TipoDependenteCrud(Crud):
help_path = 'nivel_instrucao' help_path = 'nivel_instrucao'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self): def has_permission(self):
return permissao_tb_aux(self) return permissao_tb_aux(self)
@ -185,6 +189,7 @@ class NivelInstrucaoCrud(Crud):
help_path = 'tipo_dependente' help_path = 'tipo_dependente'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self): def has_permission(self):
return permissao_tb_aux(self) return permissao_tb_aux(self)
@ -194,6 +199,7 @@ class TipoAfastamentoCrud(Crud):
help_path = 'tipo_afastamento' help_path = 'tipo_afastamento'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self): def has_permission(self):
return permissao_tb_aux(self) return permissao_tb_aux(self)
@ -203,6 +209,7 @@ class TipoMilitarCrud(Crud):
help_path = 'tipo_situa_militar' help_path = 'tipo_situa_militar'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self): def has_permission(self):
return permissao_tb_aux(self) return permissao_tb_aux(self)
@ -234,7 +241,7 @@ class MandatoCrud(MasterDetailCrud):
help_path = '' help_path = ''
class ListView(MasterDetailCrud.ListView): class ListView(MasterDetailCrud.ListView):
ordering = ('-legislatura__data_inicio') ordering = ('-legislatura__numero')
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView): class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
permission_required = permissoes_parlamentares() permission_required = permissoes_parlamentares()
@ -251,9 +258,10 @@ class ColigacaoCrud(Crud):
help_path = 'tabelas_auxiliares#coligacao' help_path = 'tabelas_auxiliares#coligacao'
class ListView(CrudListView): class ListView(CrudListView):
ordering = ('-legislatura__data_inicio', 'nome') ordering = ('-numero_votos', 'nome')
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self): def has_permission(self):
return permissao_tb_aux(self) return permissao_tb_aux(self)
@ -281,6 +289,7 @@ class ComposicaoColigacaoCrud(MasterDetailCrud):
ordering = '-partido__sigla' ordering = '-partido__sigla'
class BaseMixin(PermissionRequiredMixin, MasterDetailCrud.BaseMixin): class BaseMixin(PermissionRequiredMixin, MasterDetailCrud.BaseMixin):
def has_permission(self): def has_permission(self):
return permissao_tb_aux(self) return permissao_tb_aux(self)
@ -296,6 +305,7 @@ class LegislaturaCrud(Crud):
form_class = LegislaturaForm form_class = LegislaturaForm
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self): def has_permission(self):
return permissao_tb_aux(self) return permissao_tb_aux(self)
@ -335,6 +345,7 @@ class ParlamentarCrud(Crud):
help_path = '' help_path = ''
class DetailView(CrudDetailView): class DetailView(CrudDetailView):
def get_template_names(self): def get_template_names(self):
usuario = self.request.user usuario = self.request.user
lista_permissoes = get_parlamentar_permissions() lista_permissoes = get_parlamentar_permissions()
@ -368,7 +379,7 @@ class ParlamentarCrud(Crud):
def take_legislatura_id(self): def take_legislatura_id(self):
legislaturas = Legislatura.objects.all().order_by( legislaturas = Legislatura.objects.all().order_by(
'-data_inicio', '-data_fim') '-numero')
if legislaturas: if legislaturas:
try: try:
@ -420,7 +431,7 @@ class ParlamentarCrud(Crud):
# Adiciona legislatura para filtrar parlamentares # Adiciona legislatura para filtrar parlamentares
legislaturas = Legislatura.objects.all().order_by( legislaturas = Legislatura.objects.all().order_by(
'-data_inicio', '-data_fim') '-numero')
context['legislaturas'] = legislaturas context['legislaturas'] = legislaturas
context['legislatura_id'] = self.take_legislatura_id() context['legislatura_id'] = self.take_legislatura_id()
return context return context
@ -450,7 +461,7 @@ class MesaDiretoraView(FormView):
return self.render_to_response( return self.render_to_response(
{'legislaturas': Legislatura.objects.all( {'legislaturas': Legislatura.objects.all(
).order_by('-data_inicio'), ).order_by('-numero'),
'legislatura_selecionada': Legislatura.objects.last(), 'legislatura_selecionada': Legislatura.objects.last(),
'cargos_vagos': CargoMesa.objects.all()}) 'cargos_vagos': CargoMesa.objects.all()})
@ -477,7 +488,7 @@ class MesaDiretoraView(FormView):
return self.render_to_response( return self.render_to_response(
{'legislaturas': Legislatura.objects.all( {'legislaturas': Legislatura.objects.all(
).order_by('-data_inicio'), ).order_by('-numero'),
'legislatura_selecionada': Legislatura.objects.last(), 'legislatura_selecionada': Legislatura.objects.last(),
'sessoes': SessaoLegislativa.objects.filter( 'sessoes': SessaoLegislativa.objects.filter(
legislatura=Legislatura.objects.last()), legislatura=Legislatura.objects.last()),
@ -538,7 +549,7 @@ class MesaDiretoraView(FormView):
parlamentares_ocupados)) parlamentares_ocupados))
return self.render_to_response( return self.render_to_response(
{'legislaturas': Legislatura.objects.all( {'legislaturas': Legislatura.objects.all(
).order_by('-data_inicio'), ).order_by('-numero'),
'legislatura_selecionada': Legislatura.objects.get( 'legislatura_selecionada': Legislatura.objects.get(
id=int(request.POST['legislatura'])), id=int(request.POST['legislatura'])),
'sessoes': SessaoLegislativa.objects.filter( 'sessoes': SessaoLegislativa.objects.filter(

6
sapl/protocoloadm/forms.py

@ -11,9 +11,9 @@ from django.forms import ModelForm
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from sapl.crispy_layout_mixin import form_actions, to_row 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.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, from .models import (DocumentoAcessorioAdministrativo, DocumentoAdministrativo,
Protocolo, TipoDocumentoAdministrativo, Protocolo, TipoDocumentoAdministrativo,
@ -43,7 +43,7 @@ class ProtocoloFilterSet(django_filters.FilterSet):
}} }}
ano = django_filters.ChoiceFilter(required=False, ano = django_filters.ChoiceFilter(required=False,
label=u'Ano da Matéria', label=u'Ano',
choices=ANO_CHOICES) choices=ANO_CHOICES)
assunto_ementa = django_filters.CharFilter(lookup_expr='icontains') assunto_ementa = django_filters.CharFilter(lookup_expr='icontains')

8
sapl/protocoloadm/urls.py

@ -43,9 +43,9 @@ urlpatterns = [
include(ProtocoloMateriaCrud.get_urls()), name='protocolomat'), include(ProtocoloMateriaCrud.get_urls()), name='protocolomat'),
url(r'^protocoloadm/protocolo$', url(r'^protocoloadm/protocolo$',
ProtocoloPesquisaView.as_view(), name='protocolo'), ProtocoloPesquisaView.as_view(), name='protocolo'),
url(r'^protocoloadm/protocolo_list$', url(r'^protocoloadm/protocolo-list$',
ProtocoloListView.as_view(), name='protocolo_list'), ProtocoloListView.as_view(), name='protocolo_list'),
url(r'^protocoloadm/(?P<pk>\d+)/(?P<ano>\d+)/protocolo_mostrar$', url(r'^protocoloadm/(?P<pk>\d+)/(?P<ano>\d+)/protocolo-mostrar$',
ProtocoloMostrarView.as_view(), name='protocolo_mostrar'), ProtocoloMostrarView.as_view(), name='protocolo_mostrar'),
url(r'^protocoloadm/anular-protocolo', url(r'^protocoloadm/anular-protocolo',
AnularProtocoloAdmView.as_view(), name='anular_protocolo'), AnularProtocoloAdmView.as_view(), name='anular_protocolo'),
@ -66,12 +66,12 @@ urlpatterns = [
url(r'^protocoloadm/(?P<pk>\d+)/(?P<ano>\d+)/comprovante$', url(r'^protocoloadm/(?P<pk>\d+)/(?P<ano>\d+)/comprovante$',
ComprovanteProtocoloView.as_view(), name='comprovante_protocolo'), ComprovanteProtocoloView.as_view(), name='comprovante_protocolo'),
url(r'^protocoloadm/(?P<pk>\d+)/(?P<ano>\d+)/criar_documento$', url(r'^protocoloadm/(?P<pk>\d+)/(?P<ano>\d+)/criar-documento$',
CriarDocumentoProtocolo.as_view(), name='criar_documento'), CriarDocumentoProtocolo.as_view(), name='criar_documento'),
# FIXME: Usado para pesquisar autor # FIXME: Usado para pesquisar autor
# Melhor forma de fazer? # Melhor forma de fazer?
# Deve mudar de app? # Deve mudar de app?
url(r'^proposicao/pesquisar_autor', url(r'^proposicao/pesquisar-autor',
pesquisa_autores, name='pesquisar_autor'), pesquisa_autores, name='pesquisar_autor'),
] ]

69
sapl/protocoloadm/views.py

@ -17,7 +17,8 @@ from django_filters.views import FilterView
import sapl.crud.base import sapl.crud.base
from sapl.base.models import AppConfig from sapl.base.models import AppConfig
from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView, from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView,
CrudDeleteView, CrudListView, CrudUpdateView, CrudDetailView, CrudDeleteView,
CrudListView, CrudUpdateView,
make_pagination) make_pagination)
from sapl.crud.masterdetail import MasterDetailCrud from sapl.crud.masterdetail import MasterDetailCrud
from sapl.materia.models import TipoMateriaLegislativa from sapl.materia.models import TipoMateriaLegislativa
@ -62,6 +63,32 @@ class DocumentoAdministrativoCrud(Crud):
class DeleteView(PermissionRequiredMixin, CrudDeleteView): class DeleteView(PermissionRequiredMixin, CrudDeleteView):
permission_required = permissoes_adm() 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): class StatusTramitacaoAdministrativoCrud(Crud):
model = StatusTramitacaoAdministrativo model = StatusTramitacaoAdministrativo
@ -95,7 +122,7 @@ class ProtocoloPesquisaView(PermissionRequiredMixin, FilterView):
kwargs = {'data': self.request.GET or None} kwargs = {'data': self.request.GET or None}
qs = self.get_queryset() qs = self.get_queryset().order_by('ano', 'numero')
qs = qs.distinct() qs = qs.distinct()
@ -373,6 +400,16 @@ class PesquisarDocumentoAdministrativoView(PermissionRequiredMixin,
paginate_by = 10 paginate_by = 10
permission_required = permissoes_adm() 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): def get_filterset_kwargs(self, filterset_class):
super(PesquisarDocumentoAdministrativoView, super(PesquisarDocumentoAdministrativoView,
self).get_filterset_kwargs(filterset_class) self).get_filterset_kwargs(filterset_class)
@ -574,13 +611,39 @@ class TramitacaoAdmCrud(MasterDetailCrud):
form_class = TramitacaoAdmEditForm form_class = TramitacaoAdmEditForm
permission_required = permissoes_adm() permission_required = permissoes_adm()
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_adm()
class ListView(PermissionRequiredMixin, MasterDetailCrud.ListView): class ListView(PermissionRequiredMixin, MasterDetailCrud.ListView):
permission_required = permissoes_adm() permission_required = permissoes_adm()
def get_queryset(self): def get_queryset(self):
qs = super(MasterDetailCrud.ListView, self).get_queryset() qs = super(MasterDetailCrud.ListView, self).get_queryset()
kwargs = {self.crud.parent_field: self.kwargs['pk']} 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): def get_nome_autor(request):

5
sapl/relatorios/templates/pdf_pauta_sessao_gerar.py

@ -21,8 +21,9 @@ def cabecalho(inf_basicas_dic, imagem):
tmp += '\t\t\t\t<setFont name="Helvetica" size="12"/>\n' tmp += '\t\t\t\t<setFont name="Helvetica" size="12"/>\n'
tmp += '\t\t\t\t<drawString x="5cm" y="26.6cm">Sistema de Apoio ao Processo Legislativo</drawString>\n' tmp += '\t\t\t\t<drawString x="5cm" y="26.6cm">Sistema de Apoio ao Processo Legislativo</drawString>\n'
tmp += '\t\t\t\t<setFont name="Helvetica-Bold" size="12"/>\n' tmp += '\t\t\t\t<setFont name="Helvetica-Bold" size="12"/>\n'
tmp += '\t\t\t\t<drawString x="2.2cm" y="24.6cm">Pauta da ' + str(inf_basicas_dic['num_sessao_plen']) + 'ª Reunião ' + str(inf_basicas_dic['nom_sessao']) + ' da ' + str( tmp += '\t\t\t\t<drawString x="4.2cm" y="25cm">Pauta 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 </drawString>\n' inf_basicas_dic['num_sessao_leg']) + 'ª Sessão Legislativa da </drawString>\n'
tmp += '\t\t\t\t<drawString x="6.7cm" y="24.5cm">' + str(inf_basicas_dic['num_legislatura']) + ' Legislatura </drawString>\n'
return tmp return tmp

5
sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py

@ -22,8 +22,9 @@ def cabecalho(inf_basicas_dic, imagem):
tmp += '\t\t\t\t<setFont name="Helvetica" size="12"/>\n' tmp += '\t\t\t\t<setFont name="Helvetica" size="12"/>\n'
tmp += '\t\t\t\t<drawString x="5cm" y="26.6cm">Sistema de Apoio ao Processo Legislativo</drawString>\n' tmp += '\t\t\t\t<drawString x="5cm" y="26.6cm">Sistema de Apoio ao Processo Legislativo</drawString>\n'
tmp += '\t\t\t\t<setFont name="Helvetica-Bold" size="12"/>\n' tmp += '\t\t\t\t<setFont name="Helvetica-Bold" size="12"/>\n'
tmp += '\t\t\t\t<drawString x="2.2cm" y="24.6cm">Resumo da ' + str(inf_basicas_dic['num_sessao_plen']) + 'ª Reunião ' + str(inf_basicas_dic['nom_sessao']) + ' da ' + str( tmp += '\t\t\t\t<drawString x="4.2cm" y="25cm">Resumo 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 </drawString>\n' inf_basicas_dic['num_sessao_leg']) + 'ª Sessão Legislativa da </drawString>\n'
tmp += '\t\t\t\t<drawString x="6.7cm" y="24.5cm">' + str(inf_basicas_dic['num_legislatura']) + ' Legislatura </drawString>\n'
return tmp return tmp

12
sapl/relatorios/urls.py

@ -11,21 +11,21 @@ app_name = AppConfig.name
urlpatterns = [ urlpatterns = [
url(r'^relatorio/materia$', relatorio_materia, name='relatorio_materia'), 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'), 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'), name='relatorio_ordem_dia'),
url(r'^relatorio/relatorio_documento_administrativo$', url(r'^relatorio/relatorio-documento-administrativo$',
relatorio_documento_administrativo, relatorio_documento_administrativo,
name='relatorio_documento_administrativo'), name='relatorio_documento_administrativo'),
url(r'^relatorio/espelho$', relatorio_espelho, url(r'^relatorio/espelho$', relatorio_espelho,
name='relatorio_espelho'), name='relatorio_espelho'),
url(r'^relatorio/(?P<pk>\d+)/sessao_plenaria$', url(r'^relatorio/(?P<pk>\d+)/sessao-plenaria$',
relatorio_sessao_plenaria, name='relatorio_sessao_plenaria'), relatorio_sessao_plenaria, name='relatorio_sessao_plenaria'),
url(r'^relatorio/protocolo$', url(r'^relatorio/protocolo$',
relatorio_protocolo, name='relatorio_protocolo'), relatorio_protocolo, name='relatorio_protocolo'),
url(r'^relatorio/(?P<nro>\d+)/(?P<ano>\d+)/etiqueta_protocolo$', url(r'^relatorio/(?P<nro>\d+)/(?P<ano>\d+)/etiqueta-protocolo$',
relatorio_etiqueta_protocolo, name='relatorio_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'), relatorio_pauta_sessao, name='relatorio_pauta_sessao'),
] ]

7
sapl/sessao/forms.py

@ -173,6 +173,7 @@ class SessaoPlenariaFilterSet(django_filters.FilterSet):
data_inicio__day = django_filters.ChoiceFilter(required=False, data_inicio__day = django_filters.ChoiceFilter(required=False,
label=u'Dia', label=u'Dia',
choices=DIA_CHOICES) choices=DIA_CHOICES)
titulo = _('Pesquisa de Sessão Plenária')
class Meta: class Meta:
model = SessaoPlenaria model = SessaoPlenaria
@ -190,7 +191,7 @@ class SessaoPlenariaFilterSet(django_filters.FilterSet):
self.form.helper = FormHelper() self.form.helper = FormHelper()
self.form.helper.form_method = 'GET' self.form.helper.form_method = 'GET'
self.form.helper.layout = Layout( self.form.helper.layout = Layout(
Fieldset(_('Pesquisa de Sessao Plenária'), Fieldset(self.titulo,
row1, row1,
form_actions(save_label='Pesquisar')) form_actions(save_label='Pesquisar'))
) )
@ -291,3 +292,7 @@ class OradorExpedienteForm(ModelForm):
class Meta: class Meta:
model = OradorExpediente model = OradorExpediente
exclude = ['sessao_plenaria'] exclude = ['sessao_plenaria']
class PautaSessaoFilterSet(SessaoPlenariaFilterSet):
titulo = _('Pesquisa de Pauta de Sessão')

36
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'),
),
]

7
sapl/sessao/models.py

@ -129,7 +129,7 @@ class SessaoPlenaria(models.Model):
'tipo_nome': self.tipo.nome, 'tipo_nome': self.tipo.nome,
'sessao_legislativa_numero': self.sessao_legislativa.numero, 'sessao_legislativa_numero': self.sessao_legislativa.numero,
# XXX check if it shouldn't be legislatura.numero # XXX check if it shouldn't be legislatura.numero
'legislatura_id': self.legislatura.id} 'legislatura_id': self.legislatura.numero}
class AbstractOrdemDia(models.Model): class AbstractOrdemDia(models.Model):
@ -140,12 +140,13 @@ class AbstractOrdemDia(models.Model):
) )
sessao_plenaria = models.ForeignKey(SessaoPlenaria) 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')) data_ordem = models.DateField(verbose_name=_('Data da Sessão'))
observacao = models.TextField( observacao = models.TextField(
blank=True, verbose_name=_('Ementa')) blank=True, verbose_name=_('Ementa'))
numero_ordem = models.PositiveIntegerField(verbose_name=_('Nº Ordem')) 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( tipo_votacao = models.PositiveIntegerField(
verbose_name=_('Tipo de votação'), choices=TIPO_VOTACAO_CHOICES) verbose_name=_('Tipo de votação'), choices=TIPO_VOTACAO_CHOICES)
votacao_aberta = models.NullBooleanField( votacao_aberta = models.NullBooleanField(

10
sapl/sessao/urls.py

@ -8,6 +8,7 @@ from sapl.sessao.views import (AdicionarVariasMateriasExpediente,
OradorExpedienteCrud, PainelView, OradorExpedienteCrud, PainelView,
PautaExpedienteDetail, PautaOrdemDetail, PautaExpedienteDetail, PautaOrdemDetail,
PautaSessaoDetailView, PautaSessaoListView, PautaSessaoDetailView, PautaSessaoListView,
PesquisarPautaSessaoView,
PesquisarSessaoPlenariaView, PesquisarSessaoPlenariaView,
PresencaOrdemDiaView, PresencaView, ResumoView, PresencaOrdemDiaView, PresencaView, ResumoView,
SessaoCrud, SessaoPlenariaView, SessaoCrud, SessaoPlenariaView,
@ -19,7 +20,8 @@ from sapl.sessao.views import (AdicionarVariasMateriasExpediente,
VotacaoNominalExpedienteView, VotacaoNominalExpedienteView,
VotacaoNominalView, VotacaoView, VotacaoNominalView, VotacaoView,
abrir_votacao_expediente_view, abrir_votacao_expediente_view,
abrir_votacao_ordem_view, abrir_votacao_ordem_view, recuperar_materia,
recuperar_numero_sessao,
reordernar_materias_expediente, reordernar_materias_expediente,
reordernar_materias_ordem) reordernar_materias_ordem)
@ -37,6 +39,10 @@ urlpatterns = [
ExpedienteMateriaCrud.get_urls() + ExpedienteMateriaCrud.get_urls() +
MateriaOrdemDiaCrud.get_urls())), MateriaOrdemDiaCrud.get_urls())),
url(r'^recuperar-materia/', recuperar_materia),
url(r'^recuperar-numero-sessao/', recuperar_numero_sessao),
url(r'^(?P<pk>\d+)/(?P<spk>\d+)/abrir-votacao-expediente$', url(r'^(?P<pk>\d+)/(?P<spk>\d+)/abrir-votacao-expediente$',
abrir_votacao_expediente_view, abrir_votacao_expediente_view,
name="abrir_votacao_exp"), name="abrir_votacao_exp"),
@ -70,6 +76,8 @@ urlpatterns = [
# PAUTA SESSÃO # PAUTA SESSÃO
url(r'^pauta-sessao$', url(r'^pauta-sessao$',
PautaSessaoListView.as_view(), name='list_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<pk>\d+)$', url(r'^pauta-sessao/(?P<pk>\d+)$',
PautaSessaoDetailView.as_view(), name='pauta_sessao_detail'), PautaSessaoDetailView.as_view(), name='pauta_sessao_detail'),
url(r'^pauta-sessao/(?P<pk>\d+)/expediente/$', url(r'^pauta-sessao/(?P<pk>\d+)/expediente/$',

61
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.exceptions import ObjectDoesNotExist, ValidationError
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.forms.utils import ErrorList from django.forms.utils import ErrorList
from django.http import JsonResponse
from django.http.response import HttpResponseRedirect from django.http.response import HttpResponseRedirect
from django.utils.datastructures import MultiValueDictKeyError from django.utils.datastructures import MultiValueDictKeyError
from django.utils.html import strip_tags from django.utils.html import strip_tags
@ -20,7 +21,8 @@ from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView,
CrudUpdateView, make_pagination) CrudUpdateView, make_pagination)
from sapl.crud.masterdetail import MasterDetailCrud from sapl.crud.masterdetail import MasterDetailCrud
from sapl.materia.forms import pega_ultima_tramitacao 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.materia.views import MateriaLegislativaPesquisaView
from sapl.norma.models import NormaJuridica from sapl.norma.models import NormaJuridica
from sapl.parlamentares.models import Parlamentar 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, from .forms import (AdicionarVariasMateriasFilterSet, BancadaForm,
ExpedienteForm, ExpedienteMateriaForm, ListMateriaForm, ExpedienteForm, ExpedienteMateriaForm, ListMateriaForm,
MesaForm, OradorExpedienteForm, OradorForm, OrdemDiaForm, MesaForm, OradorExpedienteForm, OradorForm, OrdemDiaForm,
PresencaForm, SessaoPlenariaFilterSet, VotacaoEditForm, PautaSessaoFilterSet, PresencaForm,
VotacaoForm, VotacaoNominalForm) SessaoPlenariaFilterSet, VotacaoEditForm, VotacaoForm,
VotacaoNominalForm)
from .models import (Bancada, Bloco, CargoBancada, CargoMesa, from .models import (Bancada, Bloco, CargoBancada, CargoMesa,
ExpedienteMateria, ExpedienteSessao, IntegranteMesa, ExpedienteMateria, ExpedienteSessao, IntegranteMesa,
MateriaLegislativa, Orador, OradorExpediente, OrdemDia, MateriaLegislativa, Orador, OradorExpediente, OrdemDia,
@ -275,6 +278,23 @@ class MateriaOrdemDiaCrud(MasterDetailCrud):
return [self._as_row(obj) for obj in object_list] 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): class ExpedienteMateriaCrud(MasterDetailCrud):
model = ExpedienteMateria model = ExpedienteMateria
parent_field = 'sessao_plenaria' parent_field = 'sessao_plenaria'
@ -433,6 +453,18 @@ class OradorCrud(OradorCrud):
permission_required = permissoes_sessao() 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): class SessaoCrud(Crud):
model = SessaoPlenaria model = SessaoPlenaria
help_path = 'sessao_plenaria' help_path = 'sessao_plenaria'
@ -856,18 +888,14 @@ class ResumoView(SessaoCrud.CrudDetailView):
# ===================================================================== # =====================================================================
# Expedientes # Expedientes
expediente = ExpedienteSessao.objects.filter( expediente = ExpedienteSessao.objects.filter(
sessao_plenaria_id=self.object.id) sessao_plenaria_id=self.object.id).order_by('tipo__nome')
expedientes = [] expedientes = []
for e in expediente: for e in expediente:
tipo = TipoExpediente.objects.get( tipo = TipoExpediente.objects.get(id=e.tipo_id)
id=e.tipo_id) conteudo = e.conteudo
conteudo = sub(
'&nbsp;', ' ', strip_tags(e.conteudo))
ex = {'tipo': tipo, 'conteudo': conteudo} ex = {'tipo': tipo, 'conteudo': conteudo}
expedientes.append(ex) expedientes.append(ex)
context.update({'expedientes': expedientes}) context.update({'expedientes': expedientes})
# ===================================================================== # =====================================================================
@ -1001,16 +1029,16 @@ class ExpedienteView(FormMixin,
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
self.object = self.get_object() self.object = self.get_object()
context = self.get_context_data(object=self.object) context = self.get_context_data(object=self.object)
tipos = TipoExpediente.objects.all().order_by('nome')
tipos = TipoExpediente.objects.all()
expedientes_sessao = ExpedienteSessao.objects.filter( expedientes_sessao = ExpedienteSessao.objects.filter(
sessao_plenaria_id=self.object.id) sessao_plenaria_id=self.object.id).order_by('tipo__nome')
expedientes_salvos = [] expedientes_salvos = []
for e in expedientes_sessao: for e in expedientes_sessao:
expedientes_salvos.append(e.tipo) expedientes_salvos.append(e.tipo)
tipos_null = list(set(tipos) - set(expedientes_salvos)) tipos_null = list(set(tipos) - set(expedientes_salvos))
tipos_null.sort(key=lambda x: x.nome)
expedientes = [] expedientes = []
for e, t in zip(expedientes_sessao, tipos): for e, t in zip(expedientes_sessao, tipos):
@ -2032,7 +2060,7 @@ class PesquisarSessaoPlenariaView(FilterView):
qs = self.get_queryset() qs = self.get_queryset()
qs = qs.distinct().order_by( qs = qs.distinct().order_by(
'-legislatura__id', '-data_inicio', '-numero') '-legislatura__numero', '-data_inicio', '-numero')
kwargs.update({ kwargs.update({
'queryset': qs, 'queryset': qs,
@ -2076,6 +2104,11 @@ class PesquisarSessaoPlenariaView(FilterView):
return self.render_to_response(context) return self.render_to_response(context)
class PesquisarPautaSessaoView(PesquisarSessaoPlenariaView):
filterset_class = PautaSessaoFilterSet
template_name = 'sessao/pauta_sessao_filter.html'
def filtra_tramitacao_ordem_dia(): def filtra_tramitacao_ordem_dia():
lista = pega_ultima_tramitacao() lista = pega_ultima_tramitacao()
return Tramitacao.objects.filter( return Tramitacao.objects.filter(

8
sapl/static/js/app.js

@ -13,7 +13,9 @@ function initTinymce(elements, readonly=false) {
} }
if (readonly) { if (readonly) {
config_tinymce.readonly = 1 config_tinymce.readonly = 1,
config_tinymce.menubar = false,
config_tinymce.toolbar = false
} }
if (elements != null) { if (elements != null) {
@ -88,7 +90,7 @@ function autorModal() {
$("#pesquisar").click(function() { $("#pesquisar").click(function() {
var query = $("#q").val() var query = $("#q").val()
$.get("/proposicao/pesquisar_autor?q="+ query, function( $.get("/proposicao/pesquisar-autor?q="+ query, function(
data, status){ data, status){
$("#div-resultado").children().remove(); $("#div-resultado").children().remove();
@ -140,7 +142,7 @@ function autorModal() {
if ($(fieldname).length > 0) { // se campo existir if ($(fieldname).length > 0) { // se campo existir
if ($(fieldname).val() != "") { // e não for vazio if ($(fieldname).val() != "") { // e não for vazio
var id = $(fieldname).val(); 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); $("#nome_autor").text(data.nome);
}); });
} }

3
sapl/static/styles/app.scss

@ -10,7 +10,9 @@
nav { nav {
&.navbar { &.navbar {
padding: 5px;
border-radius: 0; border-radius: 0;
font-size: 15px;
} }
} }
@ -40,7 +42,6 @@ nav {
.navbar-brand { .navbar-brand {
padding: 0px; padding: 0px;
} }
// ADJUST DRUNKEN PARROT STYLES ######################################## // ADJUST DRUNKEN PARROT STYLES ########################################
h1, .h1 { h1, .h1 {
font-size: 30px; font-size: 30px;

7
sapl/templates/base.html

@ -64,16 +64,19 @@
{# <li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'sapl.materia:proposicao' %}">Proposições</a></li> #} {# <li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'sapl.materia:proposicao' %}">Proposições</a></li> #}
</ul> </ul>
</li> </li>
{% endif %}
{% if user|get_doc_adm_template_perms %}
<li class="dropdown"> <li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Documentos Administrativos <span class="caret"></span></a> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Documentos Administrativos <span class="caret"></span></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'sapl.protocoloadm:pesq_doc_adm' %}">Pesquisar Documento Administrativo</a></li> <li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'sapl.protocoloadm:pesq_doc_adm' %}">Pesquisar Documento Administrativo</a></li>
</ul> </ul>
</li> </li>
{% endif %}
<li class="dropdown"> <li class="dropdown">
{% endif %}
<li class="dropdown"> <li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Atividade Legislativa <span class="caret"></span></a> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Atividade Legislativa <span class="caret"></span></a>
@ -83,7 +86,7 @@
{% endif %} {% endif %}
<li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'sapl.materia:pesquisar_materia' %}">Matérias Legislativas</a></li> <li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'sapl.materia:pesquisar_materia' %}">Matérias Legislativas</a></li>
<li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'sapl.sessao:pesquisar_sessao' %}">Sessões Plenárias</a></li> <li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'sapl.sessao:pesquisar_sessao' %}">Sessões Plenárias</a></li>
<li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'sapl.sessao:list_pauta_sessao' %}">Pautas das Sessões</a></li> <li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'sapl.sessao:pesquisar_pauta' %}">Pautas das Sessões</a></li>
<li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'sapl.materia:primeira_tramitacao_em_lote' %}">Tramitação em Lote</a></li> <li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'sapl.materia:primeira_tramitacao_em_lote' %}">Tramitação em Lote</a></li>
<li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'sapl.materia:acessorio_em_lote' %}">Acessório em Lote</a></li> <li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'sapl.materia:acessorio_em_lote' %}">Acessório em Lote</a></li>
<!-- <li class="nav__sub-item"><a class="nav__sub-link" href="#">Atas das Sessões</a></li> <!-- <li class="nav__sub-item"><a class="nav__sub-link" href="#">Atas das Sessões</a></li>

49
sapl/templates/base/appconfig_list.html

@ -0,0 +1,49 @@
{% extends "crud/list.html" %}
{% load i18n %}
{% load common_tags %}
<div class="actions btn-group pull-right" role="group">
{% if user|get_config_not_exists %}
<a href="{{ view.create_url }}" class="btn btn-default">
{% blocktrans with verbose_name=view.verbose_name %} Adicionar {{ verbose_name }} {% endblocktrans %}
</a>
{% endif %}
{% block more_buttons %}{% endblock more_buttons %}
</div>
<br/><br/>
{% block extra_content %} {% endblock %}
{% if not rows %}
<p>{{ NO_ENTRIES_MSG }}</p>
{% else %}
<table class="table table-striped table-hover">
<thead>
<tr>
{% for name in headers %}
<th>{{ name }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for value_list in rows %}
<tr>
{% for value, href in value_list %}
<td>
{% if href %}
<a href="{{ href }}">{{ value }}</a>
{% else %}
{{ value|safe }}
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% include "paginacao.html" %}
{% endblock %}

2
sapl/templates/comissoes/composicao_detail.html

@ -27,5 +27,7 @@
{% endfor %} {% endfor %}
</table> </table>
{% if user.is_authenticated %}
<a href="{% url 'sapl.comissoes:participacao_create' composicao.pk %}" class="btn btn-primary">Incluir Parlamentar</a> <a href="{% url 'sapl.comissoes:participacao_create' composicao.pk %}" class="btn btn-primary">Incluir Parlamentar</a>
{% endif %}
{% endblock detail_content %} {% endblock detail_content %}

1
sapl/templates/comissoes/layouts.yaml

@ -27,6 +27,7 @@ Comissao:
Composicao: Composicao:
{% trans 'Composição' %}: {% trans 'Composição' %}:
- comissao
- periodo - periodo
Participacao: Participacao:

2
sapl/templates/compilacao/text_list.html

@ -14,7 +14,9 @@
{% block actions %} {% block actions %}
<div class="clearfix"> <div class="clearfix">
<div class="actions btn-group pull-right" role="group"> <div class="actions btn-group pull-right" role="group">
{% if user.is_authenticated %}
<a href="{% url 'sapl.compilacao:ta_text_edit' object.pk %}" class="btn btn-default">{% trans 'Editar Texto' %}</a> <a href="{% url 'sapl.compilacao:ta_text_edit' object.pk %}" class="btn btn-default">{% trans 'Editar Texto' %}</a>
{% endif %}
</div> </div>
</div> </div>
{% endblock actions %} {% endblock actions %}

2
sapl/templates/compilacao/textoarticulado_detail.html

@ -25,8 +25,10 @@
{% block actions %} {% block actions %}
<div class="clearfix"> <div class="clearfix">
<div class="actions btn-group pull-right" role="group"> <div class="actions btn-group pull-right" role="group">
{% if user.is_authenticated %}
<a href="{% url 'sapl.compilacao:ta_edit' object.pk %}" class="btn btn-default">{% trans 'Editar Metadados do Texto Articulado' %}</a> <a href="{% url 'sapl.compilacao:ta_edit' object.pk %}" class="btn btn-default">{% trans 'Editar Metadados do Texto Articulado' %}</a>
<a href="{% url 'sapl.compilacao:ta_text_edit' object.pk %}" class="btn btn-default">{% trans 'Editar Texto' %}</a> <a href="{% url 'sapl.compilacao:ta_text_edit' object.pk %}" class="btn btn-default">{% trans 'Editar Texto' %}</a>
{% endif %}
</div> </div>
</div> </div>
{% endblock actions %} {% endblock actions %}

2
sapl/templates/index.html

@ -80,7 +80,7 @@
Utilizadas para se determinar quais matérias serão discutidas e votadas. A responsabilidade pela elaboração das Pautas, que incluem Expediente e Ordem do Dia, é definida no Regimento Interno que, em geral, dá poderes ao Presidente da Casa Legislativa para a sua elaboração. Também, pode ficar a cargo de um colégio de líderes dos partidos políticos. Utilizadas para se determinar quais matérias serão discutidas e votadas. A responsabilidade pela elaboração das Pautas, que incluem Expediente e Ordem do Dia, é definida no Regimento Interno que, em geral, dá poderes ao Presidente da Casa Legislativa para a sua elaboração. Também, pode ficar a cargo de um colégio de líderes dos partidos políticos.
</p> </p>
</div> </div>
<a href="{% url 'sapl.sessao:list_pauta_sessao' %}"></a> <a href="{% url 'sapl.sessao:pesquisar_pauta' %}"></a>
</div> </div>
<div class="homeBlock"> <div class="homeBlock">

6
sapl/templates/materia/autor_form.html

@ -0,0 +1,6 @@
{% extends "base.html" %}
{% load i18n crispy_forms_tags %}
{% block base_content %}
{% crispy form helper %}
{% endblock %}

5
sapl/templates/materia/layouts.yaml

@ -58,10 +58,11 @@ Autor:
AutorCreate: AutorCreate:
Autor: Autor:
- tipo:3 nome - tipo
- nome
- username:4 senha:4 senha_confirma:4 - username:4 senha:4 senha_confirma:4
- email:6 confirma_email:6 - email:6 confirma_email:6
- cargo:4 parlamentar:4 comissao:4 - cargo
Autoria: Autoria:
{% trans 'Autoria' %}: {% trans 'Autoria' %}:

6
sapl/templates/protocoloadm/documentoadministrativo_detail.html

@ -1,9 +1,15 @@
{% extends "crud/detail.html" %} {% extends "crud/detail.html" %}
{% load i18n %} {% load i18n %}
{% block actions %} {% block actions %}
{% load common_tags %}
<div class="actions btn-group pull-right" role="group"> <div class="actions btn-group pull-right" role="group">
<a href="{% url 'sapl.protocoloadm:tramitacaoadministrativo_list' object.pk %}" class="btn btn-default">{% trans 'Tramitações' %}</a> <a href="{% url 'sapl.protocoloadm:tramitacaoadministrativo_list' object.pk %}" class="btn btn-default">{% trans 'Tramitações' %}</a>
{% if perms|get_change_perm:view %}
<a href="{{ view.update_url }}" class="btn btn-default">{% trans 'Editar' %}</a> <a href="{{ view.update_url }}" class="btn btn-default">{% trans 'Editar' %}</a>
{% endif %}
{% if perms|get_delete_perm:view %}
<a href="{{ view.delete_url }}" class="btn btn-default">{% trans 'Excluir' %}</a> <a href="{{ view.delete_url }}" class="btn btn-default">{% trans 'Excluir' %}</a>
{% endif %}
</div> </div>
{% endblock actions %} {% endblock actions %}

6
sapl/templates/protocoloadm/tramitacaoadministrativo_detail.html

@ -1,9 +1,15 @@
{% extends "crud/detail.html" %} {% extends "crud/detail.html" %}
{% load i18n %} {% load i18n %}
{% block actions %} {% block actions %}
{% load common_tags %}
<div class="actions btn-group pull-right" role="group"> <div class="actions btn-group pull-right" role="group">
<a href="{% url 'protocoloadm:documentoadministrativo_detail' root_pk %}" class="btn btn-default">{% trans 'Início' %}</a> <a href="{% url 'protocoloadm:documentoadministrativo_detail' root_pk %}" class="btn btn-default">{% trans 'Início' %}</a>
{% if perms|get_change_perm:view %}
<a href="{{ view.update_url }}" class="btn btn-default">{% trans 'Editar' %}</a> <a href="{{ view.update_url }}" class="btn btn-default">{% trans 'Editar' %}</a>
{% endif %}
{% if perms|get_delete_perm:view %}
<a href="{{ view.delete_url }}" class="btn btn-default">{% trans 'Excluir' %}</a> <a href="{{ view.delete_url }}" class="btn btn-default">{% trans 'Excluir' %}</a>
{% endif %}
</div> </div>
{% endblock actions %} {% endblock actions %}

30
sapl/templates/sessao/expedientemateria_form.html

@ -0,0 +1,30 @@
{% extends "crud/form.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% load common_tags %}
{% block extra_js %}
<script language="Javascript">
function recuperar_materia() {
var tipo_materia = $("#id_tipo_materia").val()
var numero_materia = $("#id_numero_materia").val()
var ano_materia = $("#id_ano_materia").val()
if (tipo_materia && numero_materia && ano_materia) {
$.get("/recuperar-materia",{tipo_materia: tipo_materia,
numero_materia: numero_materia,
ano_materia: ano_materia},
function(data, status) {
$("#id_observacao").val(data.ementa);
});
}
}
var fields = ["#id_tipo_materia", "#id_numero_materia", "#id_ano_materia"]
for (i = 0; i < fields.length; i++) {
$(fields[i]).change(recuperar_materia);
}
</script>
{% endblock %}

4
sapl/templates/sessao/ordemdia_form.html

@ -0,0 +1,4 @@
{% extends "sessao/expedientemateria_form.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% load common_tags %}

49
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 %}
<h1><b>Pesquisar Pauta de Sessão</b></h1>
<br></br>
{% crispy filter.form %}
<p></p>
<table class="table table-striped table-hover">
<thead class="thead-default">
<tr><td><h3>Resultados</h3></td></tr>
</thead>
{% if page_obj|length %}
{% if numero_res > 1 %}
<h3>Foram encontradas {{numero_res}} pautas de sessões.</h3></br>
{% elif numero_res == 1 %}
<h3>Foi encontrada {{numero_res}} pauta de sessão.</h3></br>
{% endif %}
{% for s in page_obj %}
<tr>
<td>
<a href="{% url 'sapl.sessao:pauta_sessao_detail' s.id %}"><strong>{{s}}</strong></br></a>
</td>
<td>
<a href="{% url 'sapl.relatorios:relatorio_sessao_plenaria' s.id %}">
<img src="{% static 'img/file.png' %}">
</a>
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td>
<h3>Nenhuma Pauta de Sessão encontrada com essas especificações</h3>
</tr>
{% endif %}
</table>
{% include "paginacao.html" %}
{% endblock detail_content %}

62
sapl/templates/sessao/resumo.html

@ -49,8 +49,10 @@
{% for e in expedientes %} {% for e in expedientes %}
<tr> <tr>
<td> <td>
<b>{{e.tipo}}: </b> <br /> <b>{{e.tipo}}: </b> <br /><br />
<textarea name="ementa" class="textarea form-control" cols="40" rows="10" readonly="readonly">{{e.conteudo}}</textarea> <div contenteditable="false" style="border:0.5px solid #BAB4B1; border-radius: 10px; background-color: rgba(225, 225, 225, .8);">
<p>{{e.conteudo|safe}}</p>
</div>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
@ -61,22 +63,28 @@
<fieldset> <fieldset>
<legend>Matérias do Expediente</legend> <legend>Matérias do Expediente</legend>
<div class="row"> <table class="table table-striped table-hover">
<div class="col-md-4">Matéria</div> <thead>
<div class="col-md-4">Ementa</div> <tr>
<div class="col-md-4">Resultado da Votação</div> <th>Matéria</th>
</div> <th>Ementa</th>
<div class="row"> <th>Resultado da Votação</th>
</tr>
</thead>
<tbody>
{% for m in materia_expediente %} {% for m in materia_expediente %}
<div class="col-md-4"> <tr>
<td>
{{m.numero}} - {{m.titulo}} {{m.numero}} - {{m.titulo}}
<br /> <br />
<b>Autor{{ m.autor|length|pluralize:"es" }}</b>: {{ m.autor|join:', ' }} <b>Autor{{ m.autor|length|pluralize:"es" }}</b>: {{ m.autor|join:', ' }}
</div> </td>
<div class="col-md-4">{{m.ementa|safe}}</div> <td>{{m.ementa|safe}}</td>
<div class="col-md-4">{{m.resultado}}</div> <td>{{m.resultado}}</td>
</tr>
{% endfor %} {% endfor %}
</div> </tbody>
</table>
</fieldset> </fieldset>
<br /><br /><br /> <br /><br /><br />
@ -107,21 +115,27 @@
<fieldset> <fieldset>
<legend>Matérias da Ordem do Dia</legend> <legend>Matérias da Ordem do Dia</legend>
<div class="row"> <table class="table table-striped table-hover">
<div class="col-md-4">Matéria</div> <thead>
<div class="col-md-4">Ementa</div> <tr>
<div class="col-md-4">Resultado da Votação</div> <th>Matéria</th>
</div> <th>Ementa</th>
<div class="row"> <th>Resultado da Votação</th>
</tr>
</thead>
<tbody>
{% for m in materias_ordem %} {% for m in materias_ordem %}
<div class="col-md-4"> <tr>
<td>
{{m.numero}} - {{m.titulo}} {{m.numero}} - {{m.titulo}}
<br /> <br />
<b>Autor{{ m.autor|length|pluralize:"es" }}</b>: {{ m.autor|join:', ' }} <b>Autor{{ m.autor|length|pluralize:"es" }}</b>: {{ m.autor|join:', ' }}
</div> </td>
<div class="col-md-4">{{m.ementa|safe}}</div> <td>{{m.ementa|safe}}</td>
<div class="col-md-4">{{m.resultado}}</div> <td>{{m.resultado}}</td>
</tr>
{% endfor %} {% endfor %}
</div> </tbody>
</table>
</fieldset> </fieldset>
{% endblock detail_content %} {% endblock detail_content %}

3
sapl/templates/sessao/sessaoplenaria_filter.html

@ -1,11 +1,14 @@
{% extends "crud/detail.html" %} {% extends "crud/detail.html" %}
{% load i18n %} {% load i18n %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% load common_tags %}
{% block actions %} {% block actions %}
<div class="actions btn-group pull-right" role="group"> <div class="actions btn-group pull-right" role="group">
{% if perms|get_add_perm:view %}
<a href="{% url 'sapl.sessao:sessaoplenaria_create' %}" class="btn btn-default"> <a href="{% url 'sapl.sessao:sessaoplenaria_create' %}" class="btn btn-default">
{% blocktrans with verbose_name=view.verbose_name %} Adicionar Sessão Plenária {% endblocktrans %} {% blocktrans with verbose_name=view.verbose_name %} Adicionar Sessão Plenária {% endblocktrans %}
{% endif %}
</a> </a>
{% if filter_url %} {% if filter_url %}
<a href="{% url 'sapl.sessao:pesquisar_sessao' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a> <a href="{% url 'sapl.sessao:pesquisar_sessao' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a>

24
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 %}
<script language="Javascript">
function recuperar_numero_sessao() {
var tipo = $("#id_tipo").val()
if (tipo) {
$.get("/recuperar-numero-sessao",{tipo: tipo},
function(data, status) {
$("#id_numero").val(data.numero);
console.log(data)
});
}
}
$("#id_tipo").change(recuperar_numero_sessao);
</script>
{% endblock %}

2
sapl/templates/sistema.html

@ -16,7 +16,7 @@
<div class="col-md-6"><a href="{% url 'sapl.parlamentares:tipoafastamento_list' %}" class="btn btn-link">Tipo de Afastamento</a></div> <div class="col-md-6"><a href="{% url 'sapl.parlamentares:tipoafastamento_list' %}" class="btn btn-link">Tipo de Afastamento</a></div>
<div class="col-md-6"><a href="{% url 'sapl.parlamentares:tipodependente_list' %}" class="btn btn-link">Tipo de Dependente</a></div> <div class="col-md-6"><a href="{% url 'sapl.parlamentares:tipodependente_list' %}" class="btn btn-link">Tipo de Dependente</a></div>
<div class="col-md-6"><a href="{% url 'sapl.parlamentares:situacaomilitar_list' %}" class="btn btn-link">Tipo de Situação Militar</a></div> <div class="col-md-6"><a href="{% url 'sapl.parlamentares:situacaomilitar_list' %}" class="btn btn-link">Tipo de Situação Militar</a></div>
<div class="col-md-6"><a href="{% url 'sapl.parlamentares:nivelinstrucao_list' %}" class="btn btn-link">Nível de Intrução</a></div> <div class="col-md-6"><a href="{% url 'sapl.parlamentares:nivelinstrucao_list' %}" class="btn btn-link">Nível de Instrução</a></div>
<div class="col-md-6"><a href="{% url 'sapl.parlamentares:partido_list' %}" class="btn btn-link">Partido</a></div> <div class="col-md-6"><a href="{% url 'sapl.parlamentares:partido_list' %}" class="btn btn-link">Partido</a></div>
<div class="col-md-6"><a href="{% url 'sapl.parlamentares:coligacao_list' %}" class="btn btn-link">Coligação</a></div> <div class="col-md-6"><a href="{% url 'sapl.parlamentares:coligacao_list' %}" class="btn btn-link">Coligação</a></div>
</div> </div>

23
sapl/utils.py

@ -3,6 +3,7 @@ from datetime import date
from functools import wraps from functools import wraps
import magic import magic
from django import forms
from django.apps import apps from django.apps import apps
from django.conf import settings from django.conf import settings
from django.contrib import admin from django.contrib import admin
@ -46,6 +47,28 @@ class ImageThumbnailFileInput(ClearableFileInput):
template_name = 'floppyforms/image_thumbnail.html' 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 = '<div class="col-sm-6">%s</div><div class="col-sm-6">%s</div>'\
% tuple(rendered_widgets)
return '<div class="row">%s</div>' % html
def register_all_models_in_admin(module_name): def register_all_models_in_admin(module_name):
appname = module_name.split('.') appname = module_name.split('.')
appname = appname[1] if appname[0] == 'sapl' else appname[0] appname = appname[1] if appname[0] == 'sapl' else appname[0]

11
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()

9
scripts/inicializa_grupos_autorizacoes.py

@ -1,5 +1,6 @@
from django.apps import apps 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 from django.contrib.contenttypes.models import ContentType
@ -12,7 +13,7 @@ def cria_ou_reseta_grupo(nome):
def cria_usuario(nome, grupo): def cria_usuario(nome, grupo):
nome_usuario = nome 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.set_password('interlegis')
usuario.save() usuario.save()
grupo.user_set.add(usuario) grupo.user_set.add(usuario)
@ -82,7 +83,8 @@ def cria_grupos_permissoes():
# Cria o Usuario # Cria o Usuario
nome_usuario = 'operador_%s' % nome_app 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.set_password('interlegis')
usuario.save() usuario.save()
grupo.user_set.add(usuario) grupo.user_set.add(usuario)
@ -110,5 +112,6 @@ def cria_grupos_permissoes():
nome_usuario = 'operador_autor' nome_usuario = 'operador_autor'
cria_usuario(nome_usuario, grupo) cria_usuario(nome_usuario, grupo)
if __name__ == '__main__': if __name__ == '__main__':
cria_grupos_permissoes() cria_grupos_permissoes()

Loading…
Cancel
Save