Browse Source

Merge pull request #675 from interlegis/648-refatorar-crud-e-masterdetailcrud

648 refatorar crud e masterdetailcrud
pull/713/head
Leandro Roberto da Silva 8 years ago
committed by GitHub
parent
commit
1da282de38
  1. 19
      sapl/base/migrations/0019_auto_20160928_1951.py
  2. 109
      sapl/base/models.py
  3. 12
      sapl/base/templatetags/common_tags.py
  4. 5
      sapl/base/templatetags/menus.py
  5. 5
      sapl/base/urls.py
  6. 71
      sapl/base/views.py
  7. 21
      sapl/comissoes/migrations/0008_auto_20160929_1611.py
  8. 3
      sapl/comissoes/models.py
  9. 133
      sapl/comissoes/views.py
  10. 33
      sapl/crispy_layout_mixin.py
  11. 1042
      sapl/crud/base.py
  12. 81
      sapl/crud/masterdetail.py
  13. 1
      sapl/legacy/management/commands/migracao_25_31.py
  14. 6
      sapl/lexml/views.py
  15. 7
      sapl/materia/forms.py
  16. 19
      sapl/materia/migrations/0050_auto_20161003_0417.py
  17. 5
      sapl/materia/models.py
  18. 2
      sapl/materia/tests/test_materia.py
  19. 301
      sapl/materia/views.py
  20. 40
      sapl/norma/views.py
  21. 24
      sapl/parlamentares/migrations/0032_frenteproxymasterdetail.py
  22. 29
      sapl/parlamentares/migrations/0033_auto_20160930_1715.py
  23. 18
      sapl/parlamentares/migrations/0034_delete_frenteparlamentar.py
  24. 13
      sapl/parlamentares/models.py
  25. 5
      sapl/parlamentares/urls.py
  26. 475
      sapl/parlamentares/views.py
  27. 130
      sapl/protocoloadm/views.py
  28. 19
      sapl/sessao/migrations/0027_auto_20161003_0417.py
  29. 1
      sapl/sessao/models.py
  30. 12
      sapl/sessao/urls.py
  31. 224
      sapl/sessao/views.py
  32. 12
      sapl/static/styles/app.scss
  33. 4
      sapl/templates/base.html
  34. 2
      sapl/templates/crud/ajax_form.html
  35. 3
      sapl/templates/crud/confirm_delete.html
  36. 64
      sapl/templates/crud/detail.html
  37. 92
      sapl/templates/crud/detail_detail.html
  38. 2
      sapl/templates/crud/form.html
  39. 44
      sapl/templates/crud/list.html
  40. 10
      sapl/templates/parlamentares/coligacao_detail.html
  41. 4
      sapl/templates/parlamentares/composicaomesa_form.html
  42. 21
      sapl/templates/parlamentares/frentes.html
  43. 8
      sapl/templates/parlamentares/subnav.yaml
  44. 5
      sapl/templates/parlamentares/subnav_coligacao.yaml
  45. 2
      sapl/templates/sessao/mesa.html
  46. 6
      sapl/utils.py
  47. 51
      scripts/inicializa_grupos_autorizacoes.py
  48. 3
      scripts/test_inicializa_grupos_autorizacoes.py

19
sapl/base/migrations/0019_auto_20160928_1951.py

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-09-28 22:51
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('base', '0018_auto_20160919_1333'),
]
operations = [
migrations.AlterModelOptions(
name='appconfig',
options={'permissions': (('menu_sistemas', 'Renderizar Menu Sistemas'), ('view_tabelas_auxiliares', 'Visualizar Tabelas Auxiliares')), 'verbose_name': 'Configurações da Aplicação', 'verbose_name_plural': 'Configurações da Aplicação'},
),
]

109
sapl/base/models.py

@ -1,10 +1,18 @@
from builtins import LookupError
from django.apps import apps
from django.contrib.auth.management import _get_all_permissions
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.core import exceptions
from django.db import models, router
from django.db.utils import DEFAULT_DB_ALIAS
from django.utils.translation import string_concat
from django.utils.translation import ugettext_lazy as _
from sapl.utils import UF, YES_NO_CHOICES
TIPO_DOCUMENTO_ADMINISTRATIVO = (('O', _('Ostensivo')),
('R', _('Restritivo')))
@ -94,7 +102,106 @@ class AppConfig(models.Model):
class Meta:
verbose_name = _('Configurações da Aplicação')
verbose_name_plural = _('Configurações da Aplicação')
permissions = (
('menu_sistemas', _('Renderizar Menu Sistemas')),
('view_tabelas_auxiliares', _('Visualizar Tabelas Auxiliares')),
)
def __str__(self):
return _('Configurações da Aplicação - %(id)s') % {
'id': self.id}
def create_proxy_permissions(
app_config, verbosity=2, interactive=True,
using=DEFAULT_DB_ALIAS, **kwargs):
if not app_config.models_module:
return
# print(app_config)
try:
Permission = apps.get_model('auth', 'Permission')
except LookupError:
return
if not router.allow_migrate_model(using, Permission):
return
from django.contrib.contenttypes.models import ContentType
permission_name_max_length = Permission._meta.get_field('name').max_length
# This will hold the permissions we're looking for as
# (content_type, (codename, name))
searched_perms = list()
# The codenames and ctypes that should exist.
ctypes = set()
for klass in list(app_config.get_models()):
opts = klass._meta
permissions = (
("list_" + opts.model_name,
string_concat(
_('Visualizaçao da lista de'), ' ',
opts.verbose_name_plural)),
("detail_" + opts.model_name,
string_concat(
_('Visualização dos detalhes de'), ' ',
opts.verbose_name_plural)),
)
opts.permissions = tuple(
set(list(permissions) + list(opts.permissions)))
if opts.proxy:
# Force looking up the content types in the current database
# before creating foreign keys to them.
app_label, model = opts.app_label, opts.model_name
try:
ctype = ContentType.objects.db_manager(
using).get_by_natural_key(app_label, model)
except:
ctype = ContentType.objects.db_manager(
using).create(app_label=app_label, model=model)
else:
ctype = ContentType.objects.db_manager(using).get_for_model(klass)
ctypes.add(ctype)
for perm in _get_all_permissions(klass._meta, ctype):
searched_perms.append((ctype, perm))
# Find all the Permissions that have a content_type for a model we're
# looking for. We don't need to check for codenames since we already have
# a list of the ones we're going to create.
all_perms = set(Permission.objects.using(using).filter(
content_type__in=ctypes,
).values_list(
"content_type", "codename"
))
perms = [
Permission(codename=codename, name=name, content_type=ct)
for ct, (codename, name) in searched_perms
if (ct.pk, codename) not in all_perms
]
# Validate the permissions before bulk_creation to avoid cryptic database
# error when the name is longer than 255 characters
for perm in perms:
if len(perm.name) > permission_name_max_length:
raise exceptions.ValidationError(
'The permission name %s of %s.%s '
'is longer than %s characters' % (
perm.name,
perm.content_type.app_label,
perm.content_type.model,
permission_name_max_length,
)
)
Permission.objects.using(using).bulk_create(perms)
if verbosity >= 2:
for perm in perms:
print("Adding permission '%s'" % perm)
models.signals.post_migrate.connect(
receiver=create_proxy_permissions,
dispatch_uid="django.contrib.auth.management.create_permissions")

12
sapl/base/templatetags/common_tags.py

@ -126,3 +126,15 @@ def get_config_not_exists(user):
return True
else:
return False
@register.filter
def str2intabs(value):
if not isinstance(value, str):
return ''
try:
v = int(value)
v = abs(v)
return v
except:
return ''

5
sapl/base/templatetags/menus.py

@ -32,8 +32,6 @@ def subnav(context, path=None):
execução deste subnav. Inicialmente, a maneira mais prática encontrada
de isolar foi com o teste abaixo.
"""
if 'sistema' in request.path:
return
rm = request.resolver_match
app_template = rm.app_name.rsplit('.', 1)[-1]
@ -45,6 +43,9 @@ def subnav(context, path=None):
else:
yaml_path = '%s/%s' % (app_template, 'subnav.yaml')
if not yaml_path:
return
try:
"""
Por padrão, são carragados dois Loaders,

5
sapl/base/urls.py

@ -1,5 +1,6 @@
from django.conf.urls import include, url
from django.contrib.auth import views
from django.contrib.auth.decorators import permission_required
from django.views.generic.base import TemplateView
from .apps import AppConfig
@ -15,7 +16,9 @@ app_name = AppConfig.name
urlpatterns = [
url(r'^sistema/', TemplateView.as_view(template_name='sistema.html')),
url(r'^sistema/', permission_required('base.view_tabelas_auxiliares')
(TemplateView.as_view(template_name='sistema.html'))),
url(r'^ajuda/', TemplateView.as_view(template_name='ajuda.html')),
url(r'^relatorios/', TemplateView.as_view(
template_name='base/relatorios_list.html')),

71
sapl/base/views.py

@ -1,18 +1,16 @@
from django.contrib.auth.mixins import PermissionRequiredMixin
from braces.views import PermissionRequiredMixin
from django.core.urlresolvers import reverse
from django.db.models import Count, Q
from django.http import HttpResponseRedirect
from django.utils.translation import ugettext_lazy as _
from django.views.generic.base import TemplateView
from django.views.generic.edit import BaseCreateView
from django_filters.views import FilterView
from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView,
CrudDetailView, CrudUpdateView)
from sapl.crud.base import CrudAux
from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa
from sapl.parlamentares.models import Parlamentar
from sapl.sessao.models import OrdemDia, SessaoPlenaria
from sapl.utils import permissao_tb_aux
from .forms import (CasaLegislativaForm, ConfiguracoesAppForm,
RelatorioAtasFilterSet,
@ -225,24 +223,14 @@ class RelatorioMateriasPorAutorView(FilterView):
return context
class CasaLegislativaCrud(Crud):
class CasaLegislativaCrud(CrudAux):
model = CasaLegislativa
help_path = ''
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
class BaseMixin(CrudAux.BaseMixin):
list_field_names = ['codigo', 'nome', 'sigla']
def has_permission(self):
return permissao_tb_aux(self)
class CreateView(PermissionRequiredMixin, CrudCreateView):
form_class = CasaLegislativaForm
class UpdateView(PermissionRequiredMixin, CrudUpdateView):
form_class = CasaLegislativaForm
class DetailView(CrudDetailView):
form_class = CasaLegislativaForm
class DetailView(CrudAux.DetailView):
def get(self, request, *args, **kwargs):
return HttpResponseRedirect(
@ -257,28 +245,21 @@ class HelpView(PermissionRequiredMixin, TemplateView):
return ['ajuda/%s.html' % self.kwargs['topic']]
class SistemaView(PermissionRequiredMixin, TemplateView):
template_name = 'sistema.html'
permission_required = ''
def has_permission(self):
return permissao_tb_aux(self)
class AppConfigCrud(Crud):
class AppConfigCrud(CrudAux):
model = AppConfig
help_path = ''
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
list_field_names = ['documentos_administrativos',
'sequencia_numeracao',
'painel_aberto']
class BaseMixin(CrudAux.BaseMixin):
form_class = ConfiguracoesAppForm
def has_permission(self):
return permissao_tb_aux(self)
@property
def list_url(self):
return ''
class CreateView(PermissionRequiredMixin, CrudCreateView):
form_class = ConfiguracoesAppForm
@property
def create_url(self):
return ''
class CreateView(CrudAux.CreateView):
def get(self, request, *args, **kwargs):
app_config = AppConfig.objects.last()
@ -288,8 +269,20 @@ class AppConfigCrud(Crud):
kwargs={'pk': app_config.pk}))
else:
self.object = None
return super(BaseCreateView, self).get(
return super(CrudAux.CreateView, self).get(
request, *args, **kwargs)
class UpdateView(PermissionRequiredMixin, CrudUpdateView):
form_class = ConfiguracoesAppForm
class ListView(CrudAux.ListView):
def get(self, request, *args, **kwargs):
return HttpResponseRedirect(reverse('sapl.base:appconfig_create'))
class DetailView(CrudAux.DetailView):
def get(self, request, *args, **kwargs):
return HttpResponseRedirect(reverse('sapl.base:appconfig_create'))
class DeleteView(CrudAux.DeleteView):
def get(self, request, *args, **kwargs):
return HttpResponseRedirect(reverse('sapl.base:appconfig_create'))

21
sapl/comissoes/migrations/0008_auto_20160929_1611.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-09-29 19:11
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('comissoes', '0007_merge'),
]
operations = [
migrations.AlterField(
model_name='participacao',
name='composicao',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='participacao_set', to='comissoes.Composicao'),
),
]

3
sapl/comissoes/models.py

@ -1,4 +1,3 @@
import datetime
from django.db import models
from django.utils.translation import ugettext_lazy as _
@ -131,7 +130,7 @@ class Composicao(models.Model): # IGNORE
class Participacao(models.Model): # ComposicaoComissao
composicao = models.ForeignKey(Composicao)
composicao = models.ForeignKey(Composicao, related_name='participacao_set')
parlamentar = models.ForeignKey(Parlamentar)
cargo = models.ForeignKey(CargoComissao)
titular = models.BooleanField(verbose_name=_('Titular'))

133
sapl/comissoes/views.py

@ -1,12 +1,9 @@
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.core.urlresolvers import reverse
from django.views.generic import ListView
from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView,
CrudDeleteView, CrudListView, CrudUpdateView)
from sapl.crud.masterdetail import MasterDetailCrud
from sapl.materia.models import MateriaLegislativa, Tramitacao
from sapl.utils import permissao_tb_aux, permissoes_comissoes
from sapl.crud.base import Crud, CrudAux, MasterDetailCrud
from sapl.materia.models import MateriaLegislativa
from .models import (CargoComissao, Comissao, Composicao, Participacao,
Periodo, TipoComissao)
@ -18,130 +15,50 @@ def pegar_url_composicao(pk):
url = reverse('sapl.comissoes:composicao_detail', kwargs={'pk': comp_pk})
return url
CargoCrud = CrudAux.build(CargoComissao, 'cargo_comissao')
PeriodoComposicaoCrud = CrudAux.build(Periodo, 'periodo_composicao_comissao')
class CargoCrud(Crud):
model = CargoComissao
help_path = 'cargo_comissao'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
list_field_names = ['nome', 'unico']
def has_permission(self):
return permissao_tb_aux(self)
class PeriodoComposicaoCrud(Crud):
model = Periodo
help_path = 'periodo_composicao_comissao'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
list_field_names = ['data_inicio', 'data_fim']
def has_permission(self):
return permissao_tb_aux(self)
class TipoComissaoCrud(Crud):
model = TipoComissao
help_path = 'tipo_comissao'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
list_field_names = ['sigla', 'nome', 'natureza',
'dispositivo_regimental']
def has_permission(self):
return permissao_tb_aux(self)
TipoComissaoCrud = CrudAux.build(
TipoComissao, 'tipo_comissao', list_field_names=[
'sigla', 'nome', 'natureza', 'dispositivo_regimental'])
class ParticipacaoCrud(MasterDetailCrud):
model = Participacao
parent_field = 'composicao'
help_path = ''
class DetailView(MasterDetailCrud.DetailView):
def get(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
context['root_pk'] = self.object.composicao.comissao.pk
return self.render_to_response(context)
class CreateView(MasterDetailCrud.CreateView):
def get_success_url(self):
return reverse(
'sapl.comissoes:composicao_detail',
kwargs={'pk': self.kwargs['pk']}
)
def cancel_url(self):
return reverse(
'sapl.comissoes:composicao_detail',
kwargs={'pk': self.kwargs['pk']}
)
class UpdateView(MasterDetailCrud.UpdateView):
parent_field = 'composicao__comissao'
def get_success_url(self):
return pegar_url_composicao(self.kwargs['pk'])
def cancel_url(self):
return pegar_url_composicao(self.kwargs['pk'])
class DeleteView(MasterDetailCrud.DeleteView):
def get_success_url(self):
return pegar_url_composicao(self.kwargs['pk'])
def cancel_url(self):
return pegar_url_composicao(self.kwargs['pk'])
class BaseMixin(PermissionRequiredMixin, MasterDetailCrud.BaseMixin):
permission_required = permissoes_comissoes()
class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['composicao', 'parlamentar', 'cargo']
class DetailView(MasterDetailCrud.DetailView):
permission_required = []
class ComposicaoCrud(MasterDetailCrud):
model = Composicao
parent_field = 'comissao'
help_path = ''
class DetailView(MasterDetailCrud.DetailView):
def get(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
composicao = Composicao.objects.get(id=self.kwargs['pk'])
context['participacoes'] = composicao.participacao_set.all()
return self.render_to_response(context)
model_set = 'participacao_set'
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
permission_required = permissoes_comissoes()
class ListView(MasterDetailCrud.ListView):
permission_required = []
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
permission_required = permissoes_comissoes()
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_comissoes()
class DetailView(MasterDetailCrud.DetailView):
permission_required = []
class ComissaoCrud(Crud):
model = Comissao
help_path = 'modulo_comissoes'
class CreateView(PermissionRequiredMixin, CrudCreateView):
permission_required = permissoes_comissoes()
class UpdateView(PermissionRequiredMixin, CrudUpdateView):
permission_required = permissoes_comissoes()
class DeleteView(PermissionRequiredMixin, CrudDeleteView):
permission_required = permissoes_comissoes()
class BaseMixin(Crud.BaseMixin):
list_field_names = ['nome', 'sigla', 'tipo', 'data_criacao', 'ativa']
ordering = '-ativa', 'sigla'
class ListView(CrudListView):
ordering = ['-ativa', 'sigla']
class ListView(Crud.ListView):
permission_required = []
class BaseMixin(CrudBaseMixin):
list_field_names = ['nome', 'sigla', 'tipo', 'data_criacao', 'ativa']
class DetailView(Crud.DetailView):
permission_required = []
class MateriasTramitacaoListView(ListView):

33
sapl/crispy_layout_mixin.py

@ -49,7 +49,12 @@ class SaplFormLayout(Layout):
def get_field_display(obj, fieldname):
field = ''
try:
field = obj._meta.get_field(fieldname)
except:
value = getattr(obj, fieldname)
return '', value
verbose_name = str(field.verbose_name)\
if hasattr(field, 'verbose_name') else ''
if hasattr(field, 'choices') and field.choices:
@ -97,10 +102,25 @@ class CrispyLayoutFormMixin:
else:
return self.model.__name__
@property
def layout_key_set(self):
if hasattr(super(CrispyLayoutFormMixin, self), 'layout_key_set'):
return super(CrispyLayoutFormMixin, self).layout_key_set
else:
obj = self.crud if hasattr(self, 'crud') else self
return getattr(obj.model,
obj.model_set).field.model.__name__
def get_layout(self):
yaml_layout = '%s/layouts.yaml' % self.model._meta.app_config.label
return read_layout_from_yaml(yaml_layout, self.layout_key)
def get_layout_set(self):
obj = self.crud if hasattr(self, 'crud') else self
yaml_layout = '%s/layouts.yaml' % getattr(
obj.model, obj.model_set).field.model._meta.app_config.label
return read_layout_from_yaml(yaml_layout, self.layout_key_set)
@property
def fields(self):
if hasattr(self, 'form_class') and self.form_class:
@ -129,9 +149,22 @@ class CrispyLayoutFormMixin:
This base implementation returns the field names
in the first fieldset of the layout.
'''
obj = self.crud if hasattr(self, 'crud') else self
if hasattr(obj, 'list_field_names') and obj.list_field_names:
return obj.list_field_names
rows = self.get_layout()[0][1:]
return [fieldname for row in rows for fieldname, __ in row]
@property
def list_field_names_set(self):
'''The list of field names to display on table
This base implementation returns the field names
in the first fieldset of the layout.
'''
rows = self.get_layout_set()[0][1:]
return [fieldname for row in rows for fieldname, __ in row]
def get_column(self, fieldname, span):
obj = self.get_object()
verbose_name, text = get_field_display(obj, fieldname)

1042
sapl/crud/base.py

File diff suppressed because it is too large

81
sapl/crud/masterdetail.py

@ -1,81 +0,0 @@
from django.utils.decorators import classonlymethod
from .base import (CREATE, LIST, Crud, CrudBaseMixin, CrudCreateView,
CrudDeleteView, CrudDetailView, CrudListView,
CrudUpdateView)
class MasterDetailCrud(Crud):
class BaseMixin(CrudBaseMixin):
@property
def list_url(self):
return self.resolve_url(LIST, args=(self.kwargs['pk'],))
@property
def create_url(self):
return self.resolve_url(CREATE, args=(self.kwargs['pk'],))
def get_context_data(self, **kwargs):
obj = getattr(self, 'object', None)
if obj:
root_pk = getattr(obj, self.crud.parent_field).pk
else:
root_pk = self.kwargs['pk'] # in list and create
kwargs.setdefault('root_pk', root_pk)
return super(MasterDetailCrud.BaseMixin,
self).get_context_data(**kwargs)
class ListView(CrudListView):
@classmethod
def get_url_regex(cls):
return r'^(?P<pk>\d+)/%s$' % cls.model._meta.model_name
def get_queryset(self):
qs = super(MasterDetailCrud.ListView, self).get_queryset()
kwargs = {self.crud.parent_field: self.kwargs['pk']}
return qs.filter(**kwargs)
class CreateView(CrudCreateView):
@classmethod
def get_url_regex(cls):
return r'^(?P<pk>\d+)/%s/create$' % cls.model._meta.model_name
def get_form(self, form_class=None):
form = super(MasterDetailCrud.CreateView,
self).get_form(self.form_class)
field = self.model._meta.get_field(self.crud.parent_field)
parent = field.related_model.objects.get(pk=self.kwargs['pk'])
setattr(form.instance, self.crud.parent_field, parent)
return form
class DetailView(CrudDetailView):
@classmethod
def get_url_regex(cls):
return r'^%s/(?P<pk>\d+)$' % cls.model._meta.model_name
class UpdateView(CrudUpdateView):
@classmethod
def get_url_regex(cls):
return r'^%s/(?P<pk>\d+)/edit$' % cls.model._meta.model_name
class DeleteView(CrudDeleteView):
@classmethod
def get_url_regex(cls):
return r'^%s/(?P<pk>\d+)/delete$' % cls.model._meta.model_name
def get_success_url(self):
pk = getattr(self.get_object(), self.crud.parent_field).pk
return self.resolve_url(LIST, args=(pk,))
@classonlymethod
def build(cls, model, parent_field, help_path):
crud = super(MasterDetailCrud, cls).build(model, help_path)
crud.parent_field = parent_field
return crud

1
sapl/legacy/management/commands/migracao_25_31.py

@ -1,4 +1,5 @@
from django.core.management.base import BaseCommand
from sapl.legacy import migration

6
sapl/lexml/views.py

@ -1,6 +1,6 @@
from sapl.crud.base import Crud
from sapl.crud.base import CrudAux
from .models import LexmlProvedor, LexmlPublicador
LexmlProvedorCrud = Crud.build(LexmlProvedor, 'lexml_provedor')
LexmlPublicadorCrud = Crud.build(LexmlPublicador, 'lexml_publicador')
LexmlProvedorCrud = CrudAux.build(LexmlProvedor, 'lexml_provedor')
LexmlPublicadorCrud = CrudAux.build(LexmlPublicador, 'lexml_publicador')

7
sapl/materia/forms.py

@ -1,6 +1,5 @@
from datetime import datetime
import django_filters
from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML, Button, Column, Fieldset, Layout
from django import forms
@ -12,6 +11,7 @@ from django.db import models, transaction
from django.db.models import Max
from django.forms import ModelForm
from django.utils.translation import ugettext_lazy as _
import django_filters
from sapl.comissoes.models import Comissao
from sapl.crispy_layout_mixin import form_actions, to_row
@ -27,6 +27,7 @@ from .models import (AcompanhamentoMateria, Anexada, Autor, Autoria,
Numeracao, Proposicao, Relatoria, TipoMateriaLegislativa,
Tramitacao, UnidadeTramitacao)
ANO_CHOICES = [('', '---------')] + RANGE_ANOS
@ -427,6 +428,10 @@ class AnexadaForm(ModelForm):
ano = forms.CharField(label='Ano', required=True)
def __init__(self, *args, **kwargs):
return super(AnexadaForm, self).__init__(*args, **kwargs)
def clean(self):
if self.errors:
return self.errors

19
sapl/materia/migrations/0050_auto_20161003_0417.py

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-10-03 07:17
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('materia', '0049_remove_autoria_partido'),
]
operations = [
migrations.AlterModelOptions(
name='tramitacao',
options={'ordering': ('data_tramitacao',), 'verbose_name': 'Tramitação', 'verbose_name_plural': 'Tramitações'},
),
]

5
sapl/materia/models.py

@ -6,8 +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,
get_settings_auth_user_model)
get_settings_auth_user_model,
restringe_tipos_de_arquivo_txt, xstr)
def grupo_autor():
@ -589,6 +589,7 @@ class Tramitacao(models.Model):
class Meta:
verbose_name = _('Tramitação')
verbose_name_plural = _('Tramitações')
ordering = 'data_tramitacao',
def __str__(self):
return _('%(materia)s | %(status)s | %(data)s') % {

2
sapl/materia/tests/test_materia.py

@ -1,8 +1,8 @@
import pytest
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,

301
sapl/materia/views.py

@ -26,25 +26,20 @@ from django_filters.views import FilterView
from sapl.base.models import CasaLegislativa
from sapl.compilacao.views import IntegracaoTaView
from sapl.crispy_layout_mixin import SaplFormLayout, form_actions, to_row
from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView,
CrudDeleteView, CrudDetailView, CrudListView,
CrudUpdateView, make_pagination)
from sapl.crud.masterdetail import MasterDetailCrud
from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud, CrudAux, CrudDetailView,
MasterDetailCrud, make_pagination)
from sapl.materia.forms import AnexadaForm
from sapl.norma.models import LegislacaoCitada
from sapl.utils import (TURNO_TRAMITACAO_CHOICES, YES_NO_CHOICES, autor_label,
autor_modal, gerar_hash_arquivo, get_base_url,
permissao_tb_aux, permissoes_autor, permissoes_materia,
permissoes_autor, permissoes_materia,
permissoes_protocoloadm)
from .forms import (AcessorioEmLoteFilterSet, AcompanhamentoMateriaForm,
AnexadaForm, AutorForm, AutoriaForm,
ConfirmarProposicaoForm, DespachoInicialForm,
DocumentoAcessorioForm, LegislacaoCitadaForm,
MateriaLegislativaFilterSet, NumeracaoForm,
AutorForm, ConfirmarProposicaoForm, DocumentoAcessorioForm,
MateriaLegislativaFilterSet,
PrimeiraTramitacaoEmLoteFilterSet, ProposicaoForm,
ReceberProposicaoForm, RelatoriaForm,
TramitacaoEmLoteFilterSet, TramitacaoForm,
TramitacaoUpdateForm, UnidadeTramitacaoForm,
ReceberProposicaoForm, TramitacaoEmLoteFilterSet,
filtra_tramitacao_destino,
filtra_tramitacao_destino_and_status,
filtra_tramitacao_status)
@ -55,8 +50,26 @@ from .models import (AcompanhamentoMateria, Anexada, Autor, Autoria,
TipoFimRelatoria, TipoMateriaLegislativa, TipoProposicao,
Tramitacao, UnidadeTramitacao)
AnexadaCrud = Crud.build(Anexada, '')
OrigemCrud = Crud.build(Origem, '')
TipoMateriaCrud = CrudAux.build(
TipoMateriaLegislativa, 'tipo_materia_legislativa')
RegimeTramitacaoCrud = CrudAux.build(
RegimeTramitacao, 'regime_tramitacao')
TipoDocumentoCrud = CrudAux.build(
TipoDocumento, 'tipo_documento')
TipoFimRelatoriaCrud = CrudAux.build(
TipoFimRelatoria, 'fim_relatoria')
TipoAutorCrud = CrudAux.build(
TipoAutor, 'regime_tramitacao')
def recuperar_materia(request):
tipo = TipoMateriaLegislativa.objects.get(pk=request.GET['tipo'])
@ -70,66 +83,6 @@ def recuperar_materia(request):
return response
class OrigemCrud(Crud):
model = Origem
help_path = 'origem'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class TipoMateriaCrud(Crud):
model = TipoMateriaLegislativa
help_path = 'tipo_materia_legislativa'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class RegimeTramitacaoCrud(Crud):
model = RegimeTramitacao
help_path = 'regime_tramitacao'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class TipoDocumentoCrud(Crud):
model = TipoDocumento
help_path = 'tipo_documento'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class TipoFimRelatoriaCrud(Crud):
model = TipoFimRelatoria
help_path = 'fim_relatoria'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class TipoAutorCrud(Crud):
model = TipoAutor
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()
@ -152,18 +105,14 @@ def montar_helper_autor(self):
' class="btn btn-inverse">Cancelar</a>')]))
class AutorCrud(Crud):
class AutorCrud(CrudAux):
model = Autor
help_path = 'autor'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
class BaseMixin(CrudAux.BaseMixin):
list_field_names = ['tipo', 'nome']
def has_permission(self):
return permissao_tb_aux(self)
class UpdateView(CrudUpdateView):
form_class = AutorForm
class UpdateView(CrudAux.UpdateView):
layout_key = 'AutorCreate'
def __init__(self, *args, **kwargs):
@ -175,7 +124,7 @@ class AutorCrud(Crud):
context['helper'] = self.helper
return context
class CreateView(CrudCreateView):
class CreateView(CrudAux.CreateView):
form_class = AutorForm
layout_key = 'AutorCreate'
@ -229,34 +178,10 @@ class ConfirmarEmailView(TemplateView):
return self.render_to_response(context)
class OrgaoCrud(Crud):
model = Orgao
help_path = 'orgao'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class TipoProposicaoCrud(Crud):
model = TipoProposicao
help_path = 'tipo_proposicao'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class StatusTramitacaoCrud(Crud):
model = StatusTramitacao
help_path = 'status_tramitacao'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
OrgaoCrud = CrudAux.build(Orgao, 'orgao')
TipoProposicaoCrud = CrudAux.build(TipoProposicao, 'tipo_proposicao')
StatusTramitacaoCrud = CrudAux.build(StatusTramitacao, 'status_tramitacao')
UnidadeTramitacaoCrud = CrudAux.build(UnidadeTramitacao, 'unidade_tramitacao')
def criar_materia_proposicao(proposicao):
@ -296,22 +221,6 @@ def criar_doc_proposicao(proposicao):
)
class UnidadeTramitacaoCrud(Crud):
model = UnidadeTramitacao
help_path = 'unidade_tramitacao'
class CreateView(PermissionRequiredMixin, CrudCreateView):
permission_required = permissoes_materia()
form_class = UnidadeTramitacaoForm
class UpdateView(PermissionRequiredMixin, CrudUpdateView):
permission_required = permissoes_materia()
form_class = UnidadeTramitacaoForm
class DeleteView(PermissionRequiredMixin, CrudDeleteView):
permission_required = permissoes_materia()
class ProposicaoDevolvida(PermissionRequiredMixin, ListView):
template_name = 'materia/prop_devolvidas_list.html'
model = Proposicao
@ -457,13 +366,12 @@ class ProposicaoCrud(Crud):
model = Proposicao
help_path = ''
class BaseMixin(CrudBaseMixin):
class BaseMixin(Crud.BaseMixin):
list_field_names = ['data_envio', 'descricao',
'tipo', 'data_recebimento']
class CreateView(PermissionRequiredMixin, CrudCreateView):
class CreateView(Crud.CreateView):
form_class = ProposicaoForm
permission_required = {'materia.add_proposicao'}
@property
def layout_key(self):
@ -489,9 +397,8 @@ class ProposicaoCrud(Crud):
else:
return {'autor': autor_id}
class UpdateView(PermissionRequiredMixin, CrudUpdateView):
class UpdateView(Crud.UpdateView):
form_class = ProposicaoForm
permission_required = permissoes_autor()
def get_initial(self):
initial = self.initial.copy()
@ -525,8 +432,7 @@ class ProposicaoCrud(Crud):
messages.add_message(self.request, messages.ERROR, msg)
return False
class DetailView(PermissionRequiredMixin, CrudDetailView):
permission_required = permissoes_autor()
class DetailView(Crud.DetailView):
def has_permission(self):
perms = self.get_permission_required()
@ -542,9 +448,8 @@ class ProposicaoCrud(Crud):
context['subnav_template_name'] = ''
return context
class ListView(PermissionRequiredMixin, CrudListView):
class ListView(Crud.ListView):
ordering = ['-data_envio', 'descricao']
permission_required = permissoes_autor()
def get_rows(self, object_list):
@ -572,8 +477,7 @@ class ProposicaoCrud(Crud):
return lista
class DeleteView(PermissionRequiredMixin, CrudDeleteView):
permission_required = {'materia.delete_proposicao'}
class DeleteView(Crud.DeleteView):
def has_permission(self):
perms = self.get_permission_required()
@ -636,10 +540,9 @@ class RelatoriaCrud(MasterDetailCrud):
model = Relatoria
parent_field = 'materia'
help_path = ''
public = [RP_LIST, RP_DETAIL]
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
permission_required = permissoes_materia()
form_class = RelatoriaForm
class CreateView(MasterDetailCrud.CreateView):
def get_initial(self):
materia = MateriaLegislativa.objects.get(id=self.kwargs['pk'])
@ -658,26 +561,20 @@ class RelatoriaCrud(MasterDetailCrud):
return {'comissao': localizacao}
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
permission_required = permissoes_materia()
form_class = RelatoriaForm
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_materia()
class TramitacaoCrud(MasterDetailCrud):
model = Tramitacao
parent_field = 'materia'
help_path = ''
public = [RP_LIST, RP_DETAIL]
class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['data_tramitacao', 'unidade_tramitacao_local',
'unidade_tramitacao_destino', 'status']
ordered_list = False
ordering = '-data_tramitacao',
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
form_class = TramitacaoForm
permission_required = permissoes_materia()
class CreateView(MasterDetailCrud.CreateView):
def get_initial(self):
local = MateriaLegislativa.objects.get(
@ -692,9 +589,7 @@ class TramitacaoCrud(MasterDetailCrud):
do_envia_email_tramitacao(request, materia)
return super(CreateView, self).post(request, *args, **kwargs)
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
form_class = TramitacaoUpdateForm
permission_required = permissoes_materia()
class UpdateView(MasterDetailCrud.UpdateView):
def post(self, request, *args, **kwargs):
materia = MateriaLegislativa.objects.get(
@ -713,8 +608,7 @@ class TramitacaoCrud(MasterDetailCrud):
kwargs = {self.crud.parent_field: self.kwargs['pk']}
return qs.filter(**kwargs).order_by('-data_tramitacao', '-id')
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_materia()
class DeleteView(MasterDetailCrud.DeleteView):
def delete(self, request, *args, **kwargs):
tramitacao = Tramitacao.objects.get(id=self.kwargs['pk'])
@ -767,78 +661,56 @@ class DocumentoAcessorioCrud(MasterDetailCrud):
model = DocumentoAcessorio
parent_field = 'materia'
help_path = ''
public = [RP_LIST, RP_DETAIL]
class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['nome', 'tipo', 'data', 'autor', 'arquivo']
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
class CreateView(MasterDetailCrud.CreateView):
form_class = DocumentoAcessorioForm
permission_required = permissoes_materia()
def __init__(self, *args, **kwargs):
def __init__(self, **kwargs):
montar_helper_documento_acessorio(self)
super(CreateView, self).__init__(*args, **kwargs)
super(MasterDetailCrud.CreateView, self).__init__(**kwargs)
def get_context_data(self, **kwargs):
context = super(CreateView, self).get_context_data(**kwargs)
context = super(
MasterDetailCrud.CreateView, self).get_context_data(**kwargs)
context['helper'] = self.helper
return context
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
class UpdateView(MasterDetailCrud.UpdateView):
form_class = DocumentoAcessorioForm
permission_required = permissoes_materia()
def __init__(self, *args, **kwargs):
def __init__(self, **kwargs):
montar_helper_documento_acessorio(self)
super(UpdateView, self).__init__(*args, **kwargs)
super(MasterDetailCrud.UpdateView, self).__init__(**kwargs)
def get_context_data(self, **kwargs):
context = super(UpdateView, self).get_context_data(**kwargs)
context['helper'] = self.helper
return context
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_materia()
class AutoriaCrud(MasterDetailCrud):
model = Autoria
parent_field = 'materia'
help_path = ''
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
form_class = AutoriaForm
permission_required = permissoes_materia()
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
form_class = AutoriaForm
permission_required = permissoes_materia()
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_materia()
public = [RP_LIST, RP_DETAIL]
class DespachoInicialCrud(MasterDetailCrud):
model = DespachoInicial
parent_field = 'materia'
help_path = ''
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
form_class = DespachoInicialForm
permission_required = permissoes_materia()
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
form_class = DespachoInicialForm
permission_required = permissoes_materia()
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_materia()
public = [RP_LIST, RP_DETAIL]
class LegislacaoCitadaCrud(MasterDetailCrud):
model = LegislacaoCitada
parent_field = 'materia'
help_path = ''
public = [RP_LIST, RP_DETAIL]
class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['norma', 'disposicoes']
@ -848,13 +720,7 @@ class LegislacaoCitadaCrud(MasterDetailCrud):
return reverse('%s:%s' % (namespace, self.url_name(suffix)),
args=args)
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
form_class = LegislacaoCitadaForm
permission_required = permissoes_materia()
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
form_class = LegislacaoCitadaForm
permission_required = permissoes_materia()
class UpdateView(MasterDetailCrud.UpdateView):
def get_initial(self):
self.initial['tipo'] = self.object.norma.tipo.id
@ -862,9 +728,6 @@ class LegislacaoCitadaCrud(MasterDetailCrud):
self.initial['ano'] = self.object.norma.ano
return self.initial
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_materia()
class DetailView(MasterDetailCrud.DetailView):
@property
@ -876,69 +739,35 @@ class NumeracaoCrud(MasterDetailCrud):
model = Numeracao
parent_field = 'materia'
help_path = ''
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
form_class = NumeracaoForm
permission_required = permissoes_materia()
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
form_class = NumeracaoForm
permission_required = permissoes_materia()
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_materia()
public = [RP_LIST, RP_DETAIL]
class AnexadaCrud(MasterDetailCrud):
model = Anexada
parent_field = 'materia_principal'
help_path = ''
public = [RP_LIST, RP_DETAIL]
class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['materia_anexada', 'data_anexacao']
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
form_class = AnexadaForm
permission_required = permissoes_materia()
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
form_class = AnexadaForm
permission_required = permissoes_materia()
def get_initial(self):
self.initial['tipo'] = self.object.materia_anexada.tipo.id
self.initial['numero'] = self.object.materia_anexada.numero
self.initial['ano'] = self.object.materia_anexada.ano
return self.initial
class DetailView(MasterDetailCrud.DetailView):
@property
def layout_key(self):
return 'AnexadaDetail'
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_materia()
class MateriaLegislativaCrud(Crud):
model = MateriaLegislativa
help_path = 'materia_legislativa'
public = [RP_LIST, RP_DETAIL]
class BaseMixin(CrudBaseMixin):
class BaseMixin(Crud.BaseMixin):
list_field_names = ['tipo', 'numero', 'ano', 'data_apresentacao']
class CreateView(PermissionRequiredMixin, CrudCreateView):
permission_required = permissoes_materia()
class UpdateView(PermissionRequiredMixin, CrudUpdateView):
permission_required = permissoes_materia()
class DeleteView(PermissionRequiredMixin, CrudDeleteView):
permission_required = permissoes_materia()
# FIXME - qual a finalidade dessa classe??
class DocumentoAcessorioView(PermissionRequiredMixin, CreateView):
template_name = "materia/documento_acessorio.html"
form_class = DocumentoAcessorioForm

40
sapl/norma/views.py

@ -1,46 +1,33 @@
from datetime import datetime
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.shortcuts import redirect
from django.views.generic import FormView, ListView
from sapl.compilacao.views import IntegracaoTaView
from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView,
CrudDeleteView, CrudUpdateView, make_pagination)
from sapl.utils import permissoes_norma
from sapl.crud.base import RP_DETAIL, RP_LIST, Crud, CrudAux, make_pagination
from .forms import NormaJuridicaForm, NormaJuridicaPesquisaForm
from .forms import NormaJuridicaPesquisaForm
from .models import (AssuntoNorma, LegislacaoCitada, NormaJuridica,
TipoNormaJuridica)
LegislacaoCitadaCrud = Crud.build(LegislacaoCitada, '')
class AssuntoNormaCrud(Crud):
model = AssuntoNorma
help_path = 'assunto_norma_juridica'
AssuntoNormaCrud = CrudAux.build(AssuntoNorma, 'assunto_norma_juridica',
list_field_names=['assunto', 'descricao'])
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
permission_required = permissoes_norma()
list_field_names = ['assunto', 'descricao']
class TipoNormaCrud(Crud):
model = TipoNormaJuridica
help_path = 'tipo_norma_juridica'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
permission_required = permissoes_norma()
list_field_names = ['equivalente_lexml', 'sigla', 'descricao']
TipoNormaCrud = CrudAux.build(
TipoNormaJuridica, 'tipo_norma_juridica',
list_field_names=['equivalente_lexml', 'sigla', 'descricao'])
class NormaCrud(Crud):
model = NormaJuridica
help_path = 'norma_juridica'
public = [RP_LIST, RP_DETAIL]
class UpdateView(PermissionRequiredMixin, CrudUpdateView):
form_class = NormaJuridicaForm
permission_required = permissoes_norma()
class UpdateView(Crud.UpdateView):
@property
def layout_key(self):
@ -54,18 +41,13 @@ class NormaCrud(Crud):
self.initial['numero_materia'] = norma.materia.numero
return self.initial.copy()
class CreateView(PermissionRequiredMixin, CrudCreateView):
form_class = NormaJuridicaForm
permission_required = permissoes_norma()
class CreateView(Crud.CreateView):
@property
def layout_key(self):
return 'NormaJuridicaCreate'
class DeleteView(PermissionRequiredMixin, CrudDeleteView):
permission_required = permissoes_norma()
class BaseMixin(CrudBaseMixin):
class BaseMixin(Crud.BaseMixin):
list_field_names = ['tipo', 'numero', 'ano', 'ementa']

24
sapl/parlamentares/migrations/0032_frenteproxymasterdetail.py

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-09-30 20:09
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('parlamentares', '0031_auto_20160929_1842'),
]
operations = [
migrations.CreateModel(
name='FrenteProxyMasterDetail',
fields=[
],
options={
'proxy': True,
},
bases=('parlamentares.frente',),
),
]

29
sapl/parlamentares/migrations/0033_auto_20160930_1715.py

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-09-30 20:15
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('parlamentares', '0032_frenteproxymasterdetail'),
]
operations = [
migrations.DeleteModel(
name='FrenteProxyMasterDetail',
),
migrations.CreateModel(
name='FrenteParlamentar',
fields=[
],
options={
'proxy': True,
'verbose_name': 'Frente',
'verbose_name_plural': 'Frentes',
},
bases=('parlamentares.frente',),
),
]

18
sapl/parlamentares/migrations/0034_delete_frenteparlamentar.py

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-09-30 21:43
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('parlamentares', '0033_auto_20160930_1715'),
]
operations = [
migrations.DeleteModel(
name='FrenteParlamentar',
),
]

13
sapl/parlamentares/models.py

@ -267,6 +267,19 @@ class Parlamentar(models.Model):
def __str__(self):
return self.nome_completo
@property
def filiacao_atual(self):
ultima_filiacao = self.filiacao_set.order_by('-data').first()
if ultima_filiacao and not ultima_filiacao.data_desfiliacao:
return ultima_filiacao.partido.sigla
else:
return _('Sem Partido')
@property
def avatar_html(self):
return '<img class="avatar-parlamentar" src='\
+ self.fotografia.url + '/>'if self.fotografia else ''
class TipoDependente(models.Model):
descricao = models.CharField(max_length=50, verbose_name=_('Descrição'))

5
sapl/parlamentares/urls.py

@ -23,12 +23,9 @@ urlpatterns = [
FiliacaoCrud.get_urls() + MandatoCrud.get_urls() +
ParticipacaoParlamentarCrud.get_urls() +
ProposicaoParlamentarCrud.get_urls() +
RelatoriaParlamentarCrud.get_urls()
RelatoriaParlamentarCrud.get_urls() + FrenteList.get_urls()
)),
url(r'^parlamentar/(?P<pk>\d+)/frente$',
FrenteList.as_view(), name="frent_list"),
url(r'^sistema/coligacao/',
include(ColigacaoCrud.get_urls() +
ComposicaoColigacaoCrud.get_urls())),

475
sapl/parlamentares/views.py

@ -1,126 +1,88 @@
from django.contrib import messages
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import reverse, reverse_lazy
from django.shortcuts import redirect
from django.utils.datastructures import MultiValueDictKeyError
from django.utils.translation import ugettext_lazy as _
from django.views.generic import FormView, ListView
from django.views.generic import FormView
from sapl.comissoes.models import Participacao
from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView,
CrudDeleteView, CrudDetailView, CrudListView,
CrudUpdateView)
from sapl.crud.masterdetail import MasterDetailCrud
from sapl.crud.base import (RP_CHANGE, RP_DETAIL, RP_LIST, Crud, CrudAux,
CrudBaseForListAndDetailExternalAppView,
MasterDetailCrud)
from sapl.materia.models import Proposicao, Relatoria
from sapl.utils import permissao_tb_aux, permissoes_parlamentares
from sapl.parlamentares.apps import AppConfig
from .forms import (ComposicaoColigacaoForm, FiliacaoForm, FrenteForm,
LegislaturaForm, ParlamentarCreateForm, ParlamentarForm)
from .forms import LegislaturaForm, ParlamentarCreateForm, ParlamentarForm
from .models import (CargoMesa, Coligacao, ComposicaoColigacao, ComposicaoMesa,
Dependente, Filiacao, Frente, Legislatura, Mandato,
NivelInstrucao, Parlamentar, Partido, SessaoLegislativa,
SituacaoMilitar, TipoAfastamento, TipoDependente)
CargoMesaCrud = CrudAux.build(CargoMesa, 'cargo_mesa')
PartidoCrud = CrudAux.build(Partido, 'partidos')
SessaoLegislativaCrud = CrudAux.build(SessaoLegislativa, 'sessao_legislativa')
TipoDependenteCrud = CrudAux.build(TipoDependente, 'tipo_dependente')
NivelInstrucaoCrud = CrudAux.build(NivelInstrucao, 'nivel_instrucao')
TipoAfastamentoCrud = CrudAux.build(TipoAfastamento, 'tipo_afastamento')
TipoMilitarCrud = CrudAux.build(SituacaoMilitar, 'tipo_situa_militar')
class FrenteList(ListView):
model = Frente
paginate_by = 10
template_name = 'parlamentares/frentes.html'
def get_queryset(self):
return Frente.objects.filter(parlamentares__in=[self.kwargs['pk']])
FrenteCrud = CrudAux.build(Frente, 'tipo_situa_militar', list_field_names=[
'nome', 'data_criacao', 'parlamentares'])
def get_context_data(self, **kwargs):
context = super(FrenteList, self).get_context_data(**kwargs)
context['root_pk'] = self.kwargs['pk']
context['object_list'] = self.get_queryset()
return context
DependenteCrud = MasterDetailCrud.build(
Dependente, 'parlamentar', 'dependente')
class FrenteCrud(Crud):
class FrenteList(MasterDetailCrud):
model = Frente
help_path = ''
class BaseMixin(CrudBaseMixin):
list_field_names = ['nome', 'data_criacao', 'parlamentares']
is_m2m = True
parent_field = 'parlamentares'
CreateView, UpdateView, DeleteView = None, None, None
def has_permission(self):
return permissao_tb_aux(self)
class BaseMixin(Crud.PublicMixin, MasterDetailCrud.BaseMixin):
list_field_names = ['nome', 'data_criacao']
class CreateView(PermissionRequiredMixin, CrudCreateView):
form_class = FrenteForm
@classmethod
def url_name(cls, suffix):
return '%s_parlamentar_%s' % (cls.model._meta.model_name, suffix)
class UpdateView(PermissionRequiredMixin, CrudUpdateView):
form_class = FrenteForm
class RelatoriaParlamentarCrud(MasterDetailCrud):
class RelatoriaParlamentarCrud(CrudBaseForListAndDetailExternalAppView):
model = Relatoria
parent_field = 'parlamentar'
help_path = ''
class ListView(MasterDetailCrud.ListView):
permission_required = permissoes_parlamentares()
help_path = 'relatoria_parlamentar'
namespace = AppConfig.name
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
permission_required = permissoes_parlamentares()
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
permission_required = permissoes_parlamentares()
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_parlamentares()
class ProposicaoParlamentarCrud(MasterDetailCrud):
class ProposicaoParlamentarCrud(CrudBaseForListAndDetailExternalAppView):
model = Proposicao
parent_field = 'autor__parlamentar'
help_path = ''
class BaseMixin(CrudBaseMixin):
list_field_names = ['tipo', 'descricao']
parent_field = 'autor__parlamentar'
namespace = AppConfig.name
class ListView(MasterDetailCrud.ListView):
permission_required = permissoes_parlamentares()
def get_context_data(self, **kwargs):
context = super(ProposicaoParlamentarCrud.ListView, self
).get_context_data(**kwargs)
context['root_pk'] = self.kwargs['pk']
return context
class ListView(CrudBaseForListAndDetailExternalAppView.ListView):
def get_queryset(self):
try:
proposicoes = Proposicao.objects.filter(
return super().get_queryset().filter(
autor__parlamentar_id=self.kwargs['pk'],
data_envio__isnull=False)
except ObjectDoesNotExist:
return []
else:
return proposicoes
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
permission_required = permissoes_parlamentares()
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
permission_required = permissoes_parlamentares()
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_parlamentares()
class ParticipacaoParlamentarCrud(MasterDetailCrud):
class ParticipacaoParlamentarCrud(CrudBaseForListAndDetailExternalAppView):
model = Participacao
parent_field = 'parlamentar'
help_path = ''
namespace = AppConfig.name
list_field_names = ['composicao__comissao__nome', 'cargo__nome', (
'composicao__periodo__data_inicio', 'composicao__periodo__data_fim')]
class ListView(MasterDetailCrud.ListView):
class ListView(CrudBaseForListAndDetailExternalAppView.ListView):
ordering = ('-composicao__periodo')
def get_rows(self, object_list):
"""
FIXME:
Este metodo não será necessário quando get_rows for refatorada
"""
comissoes = []
for p in object_list:
if p.cargo.nome != 'Relator':
@ -138,324 +100,141 @@ class ParticipacaoParlamentarCrud(MasterDetailCrud):
return comissoes
def get_headers(self):
return ['Comissão', 'Cargo', 'Período']
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
permission_required = permissoes_parlamentares()
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
permission_required = permissoes_parlamentares()
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_parlamentares()
class CargoMesaCrud(Crud):
model = CargoMesa
help_path = 'cargo_mesa'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class PartidoCrud(Crud):
model = Partido
help_path = 'partidos'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class SessaoLegislativaCrud(Crud):
model = SessaoLegislativa
help_path = 'sessao_legislativa'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class TipoDependenteCrud(Crud):
model = TipoDependente
help_path = 'nivel_instrucao'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class NivelInstrucaoCrud(Crud):
model = NivelInstrucao
help_path = 'tipo_dependente'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class TipoAfastamentoCrud(Crud):
model = TipoAfastamento
help_path = 'tipo_afastamento'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class TipoMilitarCrud(Crud):
model = SituacaoMilitar
help_path = 'tipo_situa_militar'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
return [_('Comissão'), _('Cargo'), _('Período de participação'), ]
class DependenteCrud(MasterDetailCrud):
model = Dependente
parent_field = 'parlamentar'
help_path = ''
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
permission_required = permissoes_parlamentares()
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
permission_required = permissoes_parlamentares()
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_parlamentares()
class ColigacaoCrud(CrudAux):
model = Coligacao
help_path = 'tabelas_auxiliares#coligacao'
class ListView(PermissionRequiredMixin, MasterDetailCrud.ListView):
permission_required = permissoes_parlamentares()
class ListView(CrudAux.ListView):
ordering = ('-numero_votos', 'nome')
class DetailView(PermissionRequiredMixin, MasterDetailCrud.DetailView):
permission_required = permissoes_parlamentares()
class BaseMixin(CrudAux.BaseMixin):
subnav_template_name = 'parlamentares/subnav_coligacao.yaml'
class MandatoCrud(MasterDetailCrud):
model = Mandato
parent_field = 'parlamentar'
help_path = ''
public = [RP_DETAIL, RP_LIST]
class ListView(MasterDetailCrud.ListView):
ordering = ('-legislatura__numero')
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
permission_required = permissoes_parlamentares()
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
permission_required = permissoes_parlamentares()
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_parlamentares()
class ColigacaoCrud(Crud):
model = Coligacao
help_path = 'tabelas_auxiliares#coligacao'
class ListView(CrudListView):
ordering = ('-numero_votos', 'nome')
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class ComposicaoColigacaoCrud(MasterDetailCrud):
model = ComposicaoColigacao
parent_field = 'coligacao'
help_path = ''
class CreateView(MasterDetailCrud.CreateView):
form_class = ComposicaoColigacaoForm
class BaseMixin(MasterDetailCrud.BaseMixin):
def get_initial(self):
id = self.kwargs['pk']
return {'coligacao_id': id}
class UpdateView(MasterDetailCrud.UpdateView):
form_class = ComposicaoColigacaoForm
def get_initial(self):
id = self.kwargs['pk']
return {'coligacao_id': id}
def get_context_data(self, **kwargs):
context = super().get_context_data()
context['subnav_template_name'] = \
'parlamentares/subnav_coligacao.yaml'
return context
class ListView(MasterDetailCrud.ListView):
ordering = '-partido__sigla'
class BaseMixin(PermissionRequiredMixin, MasterDetailCrud.BaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class LegislaturaCrud(Crud):
class LegislaturaCrud(CrudAux):
model = Legislatura
help_path = 'tabelas_auxiliares#legislatura'
class CreateView(CrudCreateView):
form_class = LegislaturaForm
class UpdateView(CrudUpdateView):
class BaseMixin(CrudAux.BaseMixin):
form_class = LegislaturaForm
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class FiliacaoCrud(MasterDetailCrud):
model = Filiacao
parent_field = 'parlamentar'
help_path = ''
public = [RP_LIST, RP_DETAIL]
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
form_class = FiliacaoForm
permission_required = permissoes_parlamentares()
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
form_class = FiliacaoForm
permission_required = permissoes_parlamentares()
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_parlamentares()
class ListView(MasterDetailCrud.ListView):
class BaseMixin(MasterDetailCrud.BaseMixin):
ordering = '-data'
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)
class ParlamentarCrud(Crud):
model = Parlamentar
help_path = ''
public = [RP_LIST, RP_DETAIL]
class DetailView(CrudDetailView):
def get_template_names(self):
usuario = self.request.user
lista_permissoes = get_parlamentar_permissions()
class BaseMixin(Crud.BaseMixin):
form_class = ParlamentarCreateForm
ordered_list = False
list_field_names = [
'avatar_html', 'nome_parlamentar', 'filiacao_atual', 'ativo']
if usuario.has_perms(lista_permissoes):
return ['crud/detail.html']
class DetailView(Crud.DetailView):
else:
return ['parlamentares/parlamentar_perfil_publico.html']
def get_template_names(self):
return ['crud/detail.html']\
if self.request.user.has_perm(self.permission(RP_CHANGE))\
else ['parlamentares/parlamentar_perfil_publico.html']
class UpdateView(PermissionRequiredMixin, CrudUpdateView):
class UpdateView(Crud.UpdateView):
form_class = ParlamentarForm
permission_required = permissoes_parlamentares()
class CreateView(PermissionRequiredMixin, CrudCreateView):
form_class = ParlamentarCreateForm
permission_required = permissoes_parlamentares()
class CreateView(Crud.CreateView):
@property
def layout_key(self):
return 'ParlamentarCreate'
class DeleteView(PermissionRequiredMixin, CrudDeleteView):
form_class = ParlamentarCreateForm
permission_required = permissoes_parlamentares()
def form_valid(self, form):
'''
Reimplementa form_valid devido ao save de ParlamentarCreateForm
ser específico, sendo necessário isolar padrão do crud que aciona
form.save(commit=False) para registrar dados de auditoria se
o model implementá-los, bem como de container se também implement.
'''
return super(Crud.CreateView, self).form_valid(form)
class ListView(CrudListView):
class ListView(Crud.ListView):
template_name = "parlamentares/parlamentares_list.html"
paginate_by = None
ordering = '-nome_parlamentar'
def take_legislatura_id(self):
legislaturas = Legislatura.objects.all().order_by(
'-numero')
if legislaturas:
try:
legislatura_id = int(self.request.GET['periodo'])
except MultiValueDictKeyError:
return int(self.request.GET['periodo'])
except:
for l in Legislatura.objects.all():
if l.atual():
return l.id
return legislatura_id
else:
return 0
def get_queryset(self):
if self.take_legislatura_id() != 0:
mandatos = Mandato.objects.filter(
legislatura_id=self.take_legislatura_id()).order_by(
'parlamentar__nome_parlamentar')
return mandatos
return []
queryset = super().get_queryset()
def get_rows(self, object_list):
parlamentares = []
for m in object_list:
ultima_filiacao = m.parlamentar.filiacao_set.order_by(
'-data').first()
if ultima_filiacao and not ultima_filiacao.data_desfiliacao:
partido = ultima_filiacao.partido.sigla
else:
partido = _('Sem Partido')
parlamentar = [
("<img src=" + m.parlamentar.fotografia.url + " \
height='42' width='42' />" if m.parlamentar.fotografia
else '', ''),
(m.parlamentar.nome_parlamentar, m.parlamentar.id),
(partido, None),
('Sim' if m.parlamentar.ativo else 'Não', None)
]
parlamentares.append(parlamentar)
return parlamentares
legislatura_id = self.take_legislatura_id()
if legislatura_id != 0:
queryset = queryset.filter(
mandato__legislatura_id=legislatura_id)
return queryset
def get_headers(self):
return ['', 'Parlamentar', 'Partido', 'Ativo?']
return ['', _('Parlamentar'), _('Partido'), _('Ativo?')]
def get_context_data(self, **kwargs):
context = super(ParlamentarCrud.ListView, self
).get_context_data(**kwargs)
context.setdefault('title', self.verbose_name_plural)
context = super().get_context_data(**kwargs)
# Adiciona legislatura para filtrar parlamentares
legislaturas = Legislatura.objects.all().order_by(
'-numero')
legislaturas = Legislatura.objects.all().order_by('-numero')
context['legislaturas'] = legislaturas
context['legislatura_id'] = self.take_legislatura_id()
return context
def check_permission_mesa(request):
lista_permissoes = []
cts = ContentType.objects.filter(app_label='parlamentares')
cts = cts.filter(model__icontains='mesa')
perms = list(Permission.objects.filter(content_type__in=cts))
for p in perms:
lista_permissoes.append('parlamentares.' + p.codename)
return request.user.has_perms(set(lista_permissoes))
# Tira Link do avatar_html e coloca no nome
for row in context['rows']:
row[1] = (row[1][0], row[0][1])
row[0] = (row[0][0], None)
return context
class MesaDiretoraView(FormView):
template_name = "mesa_diretora/mesa_diretora.html"
template_name = 'parlamentares/composicaomesa_form.html'
success_url = reverse_lazy('sapl.parlamentares:mesa_diretora')
# Essa função avisa quando se pode compor uma Mesa Legislativa
@ -474,18 +253,18 @@ class MesaDiretoraView(FormView):
def get(self, request, *args, **kwargs):
if (not Legislatura.objects.exists() or
not SessaoLegislativa.objects.all()):
not SessaoLegislativa.objects.exists()):
return self.validation(request)
mesa = SessaoLegislativa.objects.filter(
legislatura=Legislatura.objects.last()).first(
legislatura=Legislatura.objects.first()).first(
).composicaomesa_set.all()
cargos_ocupados = [m.cargo for m in mesa]
cargos = CargoMesa.objects.all()
cargos_vagos = list(set(cargos) - set(cargos_ocupados))
parlamentares = Legislatura.objects.last().mandato_set.all()
parlamentares = Legislatura.objects.first().mandato_set.all()
parlamentares_ocupados = [m.parlamentar for m in mesa]
parlamentares_vagos = list(
set(
@ -495,23 +274,26 @@ class MesaDiretoraView(FormView):
return self.render_to_response(
{'legislaturas': Legislatura.objects.all(
).order_by('-numero'),
'legislatura_selecionada': Legislatura.objects.last(),
'legislatura_selecionada': Legislatura.objects.first(),
'sessoes': SessaoLegislativa.objects.filter(
legislatura=Legislatura.objects.last()),
legislatura=Legislatura.objects.first()),
'sessao_selecionada': SessaoLegislativa.objects.filter(
legislatura=Legislatura.objects.last()).first(),
legislatura=Legislatura.objects.first()).first(),
'composicao_mesa': mesa,
'parlamentares': parlamentares_vagos,
'cargos_vagos': cargos_vagos
})
def post(self, request, *args, **kwargs):
if 'Incluir' in request.POST and check_permission_mesa(request):
if (not Legislatura.objects.all() or
not SessaoLegislativa.objects.all()):
if (not Legislatura.objects.exists() or
not SessaoLegislativa.objects.exists()):
return self.validation(request)
if 'Incluir' in request.POST and request.user.has_perm(
'%s.add_%s' % (
AppConfig.label, ComposicaoMesa._meta.model_name)):
composicao = ComposicaoMesa()
composicao.sessao_legislativa = SessaoLegislativa.objects.get(
id=int(request.POST['sessao']))
@ -521,13 +303,12 @@ class MesaDiretoraView(FormView):
id=int(request.POST['cargo']))
composicao.save()
return redirect('sapl.parlamentares:mesa_diretora')
messages.success(request, _(
'Parlamentar adicionado com sucesso!'))
elif 'Excluir' in request.POST and check_permission_mesa(request):
if (not Legislatura.objects.all() or
not SessaoLegislativa.objects.all()):
return self.validation(request)
elif 'Excluir' in request.POST and request.user.has_perm(
'%s.delete_%s' % (
AppConfig.label, ComposicaoMesa._meta.model_name)):
if 'composicao_mesa' in request.POST:
ids = request.POST['composicao_mesa'].split(':')
@ -537,8 +318,12 @@ class MesaDiretoraView(FormView):
cargo_id=int(ids[1])
)
composicao.delete()
return redirect('sapl.parlamentares:mesa_diretora')
messages.success(request, _(
'Parlamentar excluido com sucesso!'))
else:
messages.error(request, _(
'Selecione um parlamentar para ser excluido!'))
mesa = ComposicaoMesa.objects.filter(
sessao_legislativa=request.POST['sessao'])
@ -553,6 +338,13 @@ class MesaDiretoraView(FormView):
set(
[p.parlamentar for p in parlamentares]) - set(
parlamentares_ocupados))
sessao_selecionada = SessaoLegislativa.objects.get(
id=int(request.POST['sessao']))
if str(sessao_selecionada.legislatura_id) != int(
request.POST['legislatura']):
sessao_selecionada = SessaoLegislativa.objects.filter(
legislatura=Legislatura.objects.first()).first()
return self.render_to_response(
{'legislaturas': Legislatura.objects.all(
).order_by('-numero'),
@ -560,8 +352,7 @@ class MesaDiretoraView(FormView):
id=int(request.POST['legislatura'])),
'sessoes': SessaoLegislativa.objects.filter(
legislatura_id=int(request.POST['legislatura'])),
'sessao_selecionada': SessaoLegislativa.objects.get(
id=int(request.POST['sessao'])),
'sessao_selecionada': sessao_selecionada,
'composicao_mesa': mesa,
'parlamentares': parlamentares_vagos,
'cargos_vagos': cargos_vagos

130
sapl/protocoloadm/views.py

@ -14,12 +14,9 @@ from django.views.generic import CreateView, DetailView, FormView, ListView
from django.views.generic.base import TemplateView
from django_filters.views import FilterView
import sapl.crud.base
from sapl.base.apps import AppConfig as AppsAppConfig
from sapl.base.models import AppConfig
from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView,
CrudDeleteView, CrudDetailView, CrudListView,
CrudUpdateView, make_pagination)
from sapl.crud.masterdetail import MasterDetailCrud
from sapl.crud.base import Crud, CrudAux, MasterDetailCrud, make_pagination
from sapl.materia.models import TipoMateriaLegislativa
from sapl.utils import (create_barcode, get_client_ip, permissoes_adm,
permissoes_protocoloadm)
@ -35,79 +32,56 @@ from .models import (Autor, DocumentoAcessorioAdministrativo,
TipoDocumentoAdministrativo, TipoInstituicao,
TramitacaoAdministrativo)
TipoDocumentoAdministrativoCrud = Crud.build(TipoDocumentoAdministrativo, '')
DocumentoAcessorioAdministrativoCrud = Crud.build(
DocumentoAcessorioAdministrativo, '')
TipoDocumentoAdministrativoCrud = CrudAux.build(
TipoDocumentoAdministrativo, '')
TipoInstituicaoCrud = CrudAux.build(TipoInstituicao, '')
ProtocoloDocumentoCrud = Crud.build(Protocolo, '')
# FIXME precisa de uma chave diferente para o layout
ProtocoloMateriaCrud = Crud.build(Protocolo, '')
TipoInstituicaoCrud = Crud.build(TipoInstituicao, '')
class DocumentoAdministrativoCrud(Crud):
model = DocumentoAdministrativo
help_path = ''
class BaseMixin(sapl.crud.base.CrudBaseMixin):
list_field_names = ['tipo', 'numero', 'ano', 'data',
'numero_protocolo', 'assunto',
'interessado', 'tramitacao', 'texto_integral']
class CreateView(PermissionRequiredMixin, CrudCreateView):
permission_required = permissoes_adm()
class UpdateView(PermissionRequiredMixin, CrudUpdateView):
permission_required = permissoes_adm()
DocumentoAcessorioAdministrativoCrud = Crud.build(
DocumentoAcessorioAdministrativo, '')
class DeleteView(PermissionRequiredMixin, CrudDeleteView):
permission_required = permissoes_adm()
class ListView(PermissionRequiredMixin, CrudListView):
permission_required = permissoes_adm()
class DocumentoAdministrativoMixin:
def has_permission(self):
app_config = AppConfig.objects.last()
if app_config:
if app_config.documentos_administrativos == 'O':
if app_config and app_config.documentos_administrativos == 'O':
return True
perms = self.get_permission_required()
return self.request.user.has_perms(perms)
return self.request.user.has_module_perms(AppsAppConfig.label)
class DetailView(PermissionRequiredMixin, CrudDetailView):
permission_required = permissoes_adm()
def has_permission(self):
app_config = AppConfig.objects.last()
class DocumentoAdministrativoCrud(Crud):
model = DocumentoAdministrativo
help_path = ''
if app_config:
if app_config.documentos_administrativos == 'O':
return True
class BaseMixin(Crud.BaseMixin):
list_field_names = ['tipo', 'numero', 'ano', 'data',
'numero_protocolo', 'assunto',
'interessado', 'tramitacao', 'texto_integral']
class ListView(Crud.ListView, DocumentoAdministrativoMixin):
pass
perms = self.get_permission_required()
return self.request.user.has_perms(perms)
class DetailView(Crud.DetailView, DocumentoAdministrativoMixin):
pass
class StatusTramitacaoAdministrativoCrud(Crud):
class StatusTramitacaoAdministrativoCrud(CrudAux):
model = StatusTramitacaoAdministrativo
help_path = ''
class BaseMixin(CrudBaseMixin):
class BaseMixin(CrudAux.BaseMixin):
list_field_names = ['sigla', 'indicador', 'descricao']
class ListView(CrudListView):
class ListView(CrudAux.ListView):
ordering = 'sigla'
class CreateView(PermissionRequiredMixin, CrudCreateView):
permission_required = permissoes_adm()
class UpdateView(PermissionRequiredMixin, CrudUpdateView):
permission_required = permissoes_adm()
class DeleteView(PermissionRequiredMixin, CrudDeleteView):
permission_required = permissoes_adm()
class ProtocoloPesquisaView(PermissionRequiredMixin, FilterView):
model = Protocolo
@ -394,22 +368,13 @@ class ProtocoloMateriaView(PermissionRequiredMixin, CreateView):
class PesquisarDocumentoAdministrativoView(PermissionRequiredMixin,
FilterView):
FilterView,
DocumentoAdministrativoMixin):
model = DocumentoAdministrativo
filterset_class = DocumentoAdministrativoFilterSet
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)
@ -603,47 +568,22 @@ class TramitacaoAdmCrud(MasterDetailCrud):
list_field_names = ['data_tramitacao', 'unidade_tramitacao_local',
'unidade_tramitacao_destino', 'status']
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
class CreateView(MasterDetailCrud.CreateView):
form_class = TramitacaoAdmForm
permission_required = permissoes_adm()
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
class UpdateView(MasterDetailCrud.UpdateView):
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()
class ListView(MasterDetailCrud.ListView, DocumentoAdministrativoMixin):
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', '-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)
class DetailView(MasterDetailCrud.DetailView,
DocumentoAdministrativoMixin):
pass
def get_nome_autor(request):

19
sapl/sessao/migrations/0027_auto_20161003_0417.py

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-10-03 07:17
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('sessao', '0026_auto_20160926_1445'),
]
operations = [
migrations.AlterModelOptions(
name='bancada',
options={'ordering': ('-legislatura__numero',), 'verbose_name': 'Bancada', 'verbose_name_plural': 'Bancadas'},
),
]

1
sapl/sessao/models.py

@ -41,6 +41,7 @@ class Bancada(models.Model):
class Meta:
verbose_name = _('Bancada')
verbose_name_plural = _('Bancadas')
ordering = ('-legislatura__numero', )
def __str__(self):
return self.nome

12
sapl/sessao/urls.py

@ -39,6 +39,7 @@ urlpatterns = [
ExpedienteMateriaCrud.get_urls() +
MateriaOrdemDiaCrud.get_urls())),
url(r'^sessao/(?P<pk>\d+)/mesa$', MesaView.as_view(), name='mesa'),
url(r'^recuperar-materia/', recuperar_materia),
url(r'^recuperar-numero-sessao/', recuperar_numero_sessao),
@ -86,17 +87,16 @@ urlpatterns = [
PautaOrdemDetail.as_view(), name='pauta_ordem_detail'),
# Subnav sessão
url(r'^(?P<pk>\d+)/expediente$',
url(r'^sessao/(?P<pk>\d+)/expediente$',
ExpedienteView.as_view(), name='expediente'),
url(r'^(?P<pk>\d+)/presenca$',
url(r'^sessao/(?P<pk>\d+)/presenca$',
PresencaView.as_view(), name='presenca'),
url(r'^(?P<pk>\d+)/painel$',
url(r'^sessao/(?P<pk>\d+)/painel$',
PainelView.as_view(), name='painel'),
url(r'^(?P<pk>\d+)/presencaordemdia$',
url(r'^sessao/(?P<pk>\d+)/presencaordemdia$',
PresencaOrdemDiaView.as_view(),
name='presencaordemdia'),
url(r'^(?P<pk>\d+)/mesa$', MesaView.as_view(), name='mesa'),
url(r'^(?P<pk>\d+)/resumo$',
url(r'^sessao/(?P<pk>\d+)/resumo$',
ResumoView.as_view(), name='resumo'),
url(r'^sessao/pesquisar-sessao$',
PesquisarSessaoPlenariaView.as_view(), name='pesquisar_sessao'),

224
sapl/sessao/views.py

@ -1,41 +1,41 @@
from datetime import datetime
from re import sub
from braces.views import PermissionRequiredMixin
from django.contrib import messages
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.contrib.auth.decorators import permission_required
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.decorators import method_decorator
from django.utils.html import strip_tags
from django.utils.translation import ugettext_lazy as _
from django.views.generic import ListView, TemplateView
from django.views.generic.detail import DetailView
from django.views.generic.edit import FormMixin
from django_filters.views import FilterView
from rest_framework import generics
from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView,
CrudDeleteView, CrudDetailView, CrudListView,
CrudUpdateView, make_pagination)
from sapl.crud.masterdetail import MasterDetailCrud
from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud, CrudAux,
MasterDetailCrud, make_pagination)
from sapl.materia.forms import pega_ultima_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, SessaoLegislativa,
Legislatura)
from sapl.parlamentares.models import (Legislatura, Parlamentar,
SessaoLegislativa)
from sapl.sessao.apps import AppConfig
from sapl.sessao.serializers import SessaoPlenariaSerializer
from sapl.utils import permissao_tb_aux, permissoes_painel, permissoes_sessao
from .forms import (AdicionarVariasMateriasFilterSet, BancadaForm,
ExpedienteForm, ExpedienteMateriaForm, ListMateriaForm,
MesaForm, OradorExpedienteForm, OradorForm, OrdemDiaForm,
PautaSessaoFilterSet, PresencaForm,
SessaoPlenariaFilterSet, VotacaoEditForm, VotacaoForm,
VotacaoNominalForm)
from sapl.utils import permissoes_painel, permissoes_sessao
from .forms import (AdicionarVariasMateriasFilterSet, ExpedienteForm,
ListMateriaForm, MesaForm, PautaSessaoFilterSet,
PresencaForm, SessaoPlenariaFilterSet, VotacaoEditForm,
VotacaoForm, VotacaoNominalForm)
from .models import (Bancada, Bloco, CargoBancada, CargoMesa,
ExpedienteMateria, ExpedienteSessao, IntegranteMesa,
MateriaLegislativa, Orador, OradorExpediente, OrdemDia,
@ -46,6 +46,19 @@ from .models import (Bancada, Bloco, CargoBancada, CargoMesa,
OrdemDiaCrud = Crud.build(OrdemDia, '')
RegistroVotacaoCrud = Crud.build(RegistroVotacao, '')
TipoSessaoCrud = CrudAux.build(TipoSessaoPlenaria, 'tipo_sessao_plenaria')
TipoExpedienteCrud = CrudAux.build(TipoExpediente, 'tipo_expediente')
CargoBancadaCrud = CrudAux.build(CargoBancada, '')
TipoSessaoCrud = CrudAux.build(TipoSessaoPlenaria, 'tipo_sessao_plenaria')
TipoSessaoCrud = CrudAux.build(TipoSessaoPlenaria, 'tipo_sessao_plenaria')
BlocoCrud = CrudAux.build(
Bloco, '', list_field_names=['nome', 'data_criacao', 'partidos'])
BancadaCrud = CrudAux.build(
Bancada, '', list_field_names=['nome', 'legislatura'])
TipoResultadoVotacaoCrud = CrudAux.build(
TipoResultadoVotacao, 'tipo_resultado_votacao')
def reordernar_materias_expediente(request, pk):
expedientes = ExpedienteMateria.objects.filter(
@ -73,73 +86,6 @@ def reordernar_materias_ordem(request, pk):
reverse('sapl.sessao:ordemdia_list', kwargs={'pk': pk}))
class BlocoCrud(Crud):
model = Bloco
help_path = ''
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
list_field_names = ['nome', 'data_criacao', 'partidos']
def has_permission(self):
return permissao_tb_aux(self)
class BancadaCrud(Crud):
model = Bancada
help_path = ''
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
list_field_names = ['nome', 'legislatura']
def has_permission(self):
return permissao_tb_aux(self)
class ListView(CrudListView):
ordering = 'legislatura'
class CreateView(CrudCreateView):
form_class = BancadaForm
class UpdateView(CrudUpdateView):
form_class = BancadaForm
class TipoSessaoCrud(Crud):
model = TipoSessaoPlenaria
help_path = 'tipo_sessao_plenaria'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class TipoResultadoVotacaoCrud(Crud):
model = TipoResultadoVotacao
help_path = 'tipo_resultado_votacao'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class TipoExpedienteCrud(Crud):
model = TipoExpediente
help_path = 'tipo_expediente'
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
class CargoBancadaCrud(Crud):
model = CargoBancada
help_path = ''
class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
def abrir_votacao_expediente_view(request, pk, spk):
existe_votacao_aberta = ExpedienteMateria.objects.filter(
sessao_plenaria_id=spk, votacao_aberta=True
@ -182,14 +128,12 @@ class MateriaOrdemDiaCrud(MasterDetailCrud):
'resultado']
class CreateView(MasterDetailCrud.CreateView):
form_class = OrdemDiaForm
def get_success_url(self):
return reverse('sapl.sessao:ordemdia_list',
kwargs={'pk': self.kwargs['pk']})
class UpdateView(MasterDetailCrud.UpdateView):
form_class = OrdemDiaForm
def get_initial(self):
self.initial['tipo_materia'] = self.object.materia.tipo.id
@ -198,6 +142,7 @@ class MateriaOrdemDiaCrud(MasterDetailCrud):
return self.initial
class DetailView(MasterDetailCrud.DetailView):
@property
def layout_key(self):
return 'OrdemDiaDetail'
@ -241,7 +186,7 @@ class MateriaOrdemDiaCrud(MasterDetailCrud):
url = reverse('sapl.sessao:abrir_votacao', kwargs={
'pk': obj.pk, 'spk': obj.sessao_plenaria_id})
if self.request.user.has_perms(permissoes_sessao()):
if self.request.user.has_module_perms(AppConfig.label):
btn_abrir = '''
Matéria não votada<br />
<a href="%s"
@ -251,7 +196,7 @@ class MateriaOrdemDiaCrud(MasterDetailCrud):
else:
obj.resultado = '''Não há resultado'''
else:
if self.request.user.has_perms(permissoes_sessao()):
if self.request.user.has_module_perms(AppConfig.label):
url = ''
if obj.tipo_votacao == 1:
url = reverse('sapl.sessao:votacaosimbolicaedit',
@ -305,7 +250,7 @@ class ExpedienteMateriaCrud(MasterDetailCrud):
list_field_names = ['numero_ordem', 'materia',
'observacao', 'resultado']
class ListView(MasterDetailCrud.ListView):
class ListView(Crud.PublicMixin, MasterDetailCrud.ListView):
ordering = ['numero_ordem', 'materia', 'resultado']
def get_rows(self, object_list):
@ -345,6 +290,7 @@ class ExpedienteMateriaCrud(MasterDetailCrud):
<a href="%s"
class="btn btn-primary"
role="button">Abrir Votação</a>''' % (url)
obj.resultado = btn_abrir
else:
url = ''
@ -370,17 +316,13 @@ class ExpedienteMateriaCrud(MasterDetailCrud):
obj.resultado)
return [self._as_row(obj) for obj in object_list]
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
form_class = ExpedienteMateriaForm
permission_required = permissoes_sessao()
class CreateView(MasterDetailCrud.CreateView):
def get_success_url(self):
return reverse('sapl.sessao:expedientemateria_list',
kwargs={'pk': self.kwargs['pk']})
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
form_class = ExpedienteMateriaForm
permission_required = permissoes_sessao()
class UpdateView(MasterDetailCrud.UpdateView):
def get_initial(self):
self.initial['tipo_materia'] = self.object.materia.tipo.id
@ -388,9 +330,6 @@ class ExpedienteMateriaCrud(MasterDetailCrud):
self.initial['ano_materia'] = self.object.materia.ano
return self.initial
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_sessao()
class DetailView(MasterDetailCrud.DetailView):
@property
@ -402,57 +341,31 @@ class OradorCrud(MasterDetailCrud):
model = ''
parent_field = 'sessao_plenaria'
help_path = ''
public = [RP_LIST, RP_DETAIL]
class ListView(MasterDetailCrud.ListView):
ordering = ['numero_ordem', 'parlamentar']
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
permission_required = permissoes_sessao()
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
permission_required = permissoes_sessao()
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_sessao()
class OradorExpedienteCrud(OradorCrud):
model = OradorExpediente
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
permission_required = permissoes_sessao()
form_class = OradorExpedienteForm
class CreateView(MasterDetailCrud.CreateView):
def get_success_url(self):
return reverse('sapl.sessao:oradorexpediente_list',
kwargs={'pk': self.kwargs['pk']})
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
permission_required = permissoes_sessao()
form_class = OradorExpedienteForm
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_sessao()
class OradorCrud(OradorCrud):
model = Orador
class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
permission_required = permissoes_sessao()
form_class = OradorForm
class CreateView(MasterDetailCrud.CreateView):
def get_success_url(self):
return reverse('sapl.sessao:orador_list',
kwargs={'pk': self.kwargs['pk']})
class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
permission_required = permissoes_sessao()
form_class = OradorForm
class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
permission_required = permissoes_sessao()
def recuperar_numero_sessao(request):
try:
@ -469,22 +382,19 @@ def recuperar_numero_sessao(request):
class SessaoCrud(Crud):
model = SessaoPlenaria
help_path = 'sessao_plenaria'
public = [RP_DETAIL]
class BaseMixin(CrudBaseMixin):
class BaseMixin(Crud.BaseMixin):
list_field_names = ['data_inicio', 'legislatura', 'sessao_legislativa',
'tipo']
# FIXME!!!! corrigir referencias no codigo e remover isso!!!!!
# fazer com #230
class CrudDetailView(CrudDetailView):
class CrudDetailView(DetailView):
model = SessaoPlenaria
help_path = 'sessao_plenaria'
class ListView(CrudListView):
class ListView(Crud.ListView):
ordering = ['-data_inicio']
class CreateView(PermissionRequiredMixin, CrudCreateView):
permission_required = permissoes_sessao()
class CreateView(Crud.CreateView):
def get_initial(self):
legislatura = Legislatura.objects.order_by('-numero')[0]
@ -493,12 +403,6 @@ class SessaoCrud(Crud):
return {'legislatura': legislatura,
'sessao_legislativa': sessao_legislativa}
class UpdateView(PermissionRequiredMixin, CrudUpdateView):
permission_required = permissoes_sessao()
class DeleteView(PermissionRequiredMixin, CrudDeleteView):
permission_required = permissoes_sessao()
class PresencaMixin:
@ -531,18 +435,24 @@ class PresencaMixin:
yield (parlamentar, False)
class PresencaView(FormMixin,
PresencaMixin,
SessaoCrud.CrudDetailView):
class PresencaView(FormMixin, PresencaMixin, DetailView):
template_name = 'sessao/presenca.html'
form_class = PresencaForm
model = SessaoPlenaria
@method_decorator(permission_required((
'%s.add_%s' % (
AppConfig.label, SessaoPlenariaPresenca._meta.model_name),
'%s.change_%s' % (
AppConfig.label, SessaoPlenariaPresenca._meta.model_name),
'%s.delete_%s' % (
AppConfig.label, SessaoPlenariaPresenca._meta.model_name),
)))
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if not self.request.user.has_perms(permissoes_sessao()):
if not self.request.user.has_module_perms(AppConfig.label):
return self.form_invalid(form)
if form.is_valid():
@ -582,12 +492,16 @@ class PainelView(PermissionRequiredMixin, TemplateView):
permission_required = permissoes_painel()
class PresencaOrdemDiaView(FormMixin,
PresencaMixin,
SessaoCrud.CrudDetailView):
class PresencaOrdemDiaView(FormMixin, PresencaMixin, DetailView):
template_name = 'sessao/presenca_ordemdia.html'
form_class = PresencaForm
model = SessaoPlenaria
@method_decorator(permission_required((
'%s.add_%s' % (AppConfig.label, PresencaOrdemDia._meta.model_name),
'%s.change_%s' % (AppConfig.label, PresencaOrdemDia._meta.model_name),
'%s.delete_%s' % (AppConfig.label, PresencaOrdemDia._meta.model_name),
)))
def post(self, request, *args, **kwargs):
self.object = self.get_object()
@ -630,9 +544,10 @@ class PresencaOrdemDiaView(FormMixin,
return reverse('sapl.sessao:presencaordemdia', kwargs={'pk': pk})
class ListMateriaOrdemDiaView(FormMixin, SessaoCrud.CrudDetailView):
class ListMateriaOrdemDiaView(FormMixin, DetailView):
template_name = 'sessao/materia_ordemdia_list.html'
form_class = ListMateriaForm
model = SessaoPlenaria
def get(self, request, *args, **kwargs):
self.object = self.get_object()
@ -669,6 +584,11 @@ class ListMateriaOrdemDiaView(FormMixin, SessaoCrud.CrudDetailView):
return self.render_to_response(context)
@method_decorator(permission_required((
'%s.add_%s' % (AppConfig.label, OrdemDia._meta.model_name),
'%s.change_%s' % (AppConfig.label, OrdemDia._meta.model_name),
'%s.delete_%s' % (AppConfig.label, OrdemDia._meta.model_name),
)))
def post(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
@ -733,12 +653,13 @@ class ListMateriaOrdemDiaView(FormMixin, SessaoCrud.CrudDetailView):
return self.get(self, request, args, kwargs)
class MesaView(PermissionRequiredMixin, FormMixin, SessaoCrud.CrudDetailView):
class MesaView(FormMixin, DetailView):
template_name = 'sessao/mesa.html'
form_class = MesaForm
permission_required = permissoes_sessao()
model = SessaoPlenaria
def get(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
@ -758,6 +679,11 @@ class MesaView(PermissionRequiredMixin, FormMixin, SessaoCrud.CrudDetailView):
return self.render_to_response(context)
@method_decorator(permission_required((
'%s.add_integrantemesa' % AppConfig.label,
'%s.change_integrantemesa' % AppConfig.label,
'%s.delete_integrantemesa' % AppConfig.label,
)))
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = MesaForm(request.POST)

12
sapl/static/styles/app.scss

@ -70,6 +70,13 @@ h6, .h6 {
color: inherit;
}
.caret {
/* Por padrão caret aponta para baixo*/
&.top {
transform: rotate(180deg);
}
}
// #### CRUD DETAIL ########################################
p.control-label {
font-weight: bold;
@ -147,6 +154,11 @@ fieldset {
}
}
.avatar-parlamentar {
height: 42px;
width: 42px;
}
/* INDEX */
#conteudo {
position: relative;

4
sapl/templates/base.html

@ -103,11 +103,11 @@
<!-- <li class="nav__sub-item"><a class="nav__sub-link" href="#">Índice de Assuntos</a></li> -->
</ul>
</li>
{% if user|ver_menu_sistema_perm %}
{% if perms.base.menu_sistemas %}
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Sistema <span class="caret"></span></a>
<ul class="dropdown-menu">
<li class="nav__sub-item"><a class="nav__sub-link" href="/sistema">Tabelas Auxiliares</a></li>
{% if perms.base.view_tabelas_auxiliares %}<li class="nav__sub-item"><a class="nav__sub-link" href="/sistema">Tabelas Auxiliares</a></li>{%endif%}
<!-- <li class="nav__sub-item"><a class="nav__sub-link" href="#">Provedor LexML</a></li>
<li class="nav__sub-item"><a class="nav__sub-link" href="#">Publicador LexML</a></li>
<li class="nav__sub-item"><a class="nav__sub-link" href="#">Gerenciar Usuários</a></li>

2
sapl/templates/crud/ajax_form.html

@ -0,0 +1,2 @@
{% load i18n crispy_forms_tags %}
{% crispy form %}

3
sapl/templates/crud/confirm_delete.html

@ -3,13 +3,12 @@
{% block base_content %}
<form action="" method="post">{% csrf_token %}
<br>
<div class="panel panel-danger">
<div class="panel-heading text-center">
{% block msg %}
{% blocktrans %}
Confirma exclusão de "{{ object }}"?
{% endblocktrans %}
{% endblock msg %}
</div>
<div class="panel-body text-center">
<a href="{{ view.cancel_url }}" class="btn btn-inverse">{% trans 'Cancelar' %}</a>

64
sapl/templates/crud/detail.html

@ -1,23 +1,33 @@
{% extends "base.html" %}
{% load i18n %}
{% load common_tags %}
{% load i18n common_tags%}
{% block base_content %}
<div class="clearfix">
<div class="context-actions clearfix">
{% block actions %}
<div class="actions btn-group btn-group-sm" role="group">
{% if view.list_url %}
<a href="{{ view.list_url }}" class="btn btn-default">{% trans 'Listar' %} {{view.verbose_name_plural}}</a>
{% endif %}
{% if view.create_url %}
<a href="{{ view.create_url }}" class="btn btn-default">
{% blocktrans with verbose_name=view.verbose_name %} Adicionar {{ verbose_name }} {% endblocktrans %}
</a>
{% endif %}
</div>
{% if view.update_url or view.delete_url %}
<div class="actions btn-group pull-right" role="group">
{% if perms|get_change_perm:view %}
{% if view.update_url %}
<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>
{% if view.delete_url %}
<a href="{{ view.delete_url }}" class="btn btn-danger">{% trans 'Excluir' %}</a>
{% endif %}
</div>
{% endif %}
{% endblock actions %}
</div>
{% block extra_msg %}{% endblock extra_msg %}
{% block detail_content %}
{% for fieldset in view.layout_display %}
<h2 class="legend">{{ fieldset.legend }}</h2>
@ -28,11 +38,7 @@
<div id="div_id_{{ column.id }}" class="form-group">
<p class="control-label">{{ column.verbose_name }}</p>
<div class="controls">
{% if column.text %}
<p class="form-control-static">{{ column.text|safe }}</p>
{% else %}
<p class="form-control-static">Não informado</p>
{% endif %}
<div class="form-control-static">{{ column.text|safe }}</div>
</div>
</div>
</div>
@ -42,4 +48,36 @@
{% endfor %}
{% endblock detail_content %}
<div class="container-table">
{% if not rows %}
<p>{{ NO_ENTRIES_MSG }}</p>
{% else %}
<div class="result-count">{% blocktrans with verbose_name_plural=view.model_set_verbose_name_plural %}Total de {{ verbose_name_plural }}: <strong>{{count}}</strong>{% endblocktrans %}</div>
<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>
{% elif value != 'core.Cep.None' %}
{{ value|safe }}
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</div>
{% include "paginacao.html" %}
{% endblock base_content %}

92
sapl/templates/crud/detail_detail.html

@ -0,0 +1,92 @@
{% extends "base.html" %}
{% load i18n common_tags%}
{% block base_content %}
<div class="context-actions clearfix">
{% block actions %}
<div class="actions btn-group btn-group-sm" role="group">
{% if view.detail_list_url %}
<a href="{{ view.detail_list_url }}" class="btn btn-default">{% trans 'Listar' %} {{view.verbose_name_plural}}</a>
{% endif %}
{% if view.detail_create_url %}
<a href="{{ view.detail_create_url }}" class="btn btn-default">
{% blocktrans with verbose_name=view.verbose_name %} Adicionar {{ verbose_name }} {% endblocktrans %}
</a>
{% endif %}
</div>
{% if view.update_url or view.delete_url %}
<div class="actions btn-group pull-right " role="group">
{% if view.update_url %}
<a href="{{ view.update_url }}" class="btn btn-default">{% trans 'Editar' %}</a>
{% endif %}
{% if view.delete_url %}
<a href="{{ view.delete_url }}" class="btn btn-danger btn-excluir">{% trans 'Excluir' %}</a>
{% endif %}
</div>
{% endif %}
{% endblock actions %}
</div>
{% block detail_content %}
{% for fieldset in view.layout_display %}
<h2 class="legend">{{ fieldset.legend }}</h2>
{% for row in fieldset.rows %}
<div class="row-fluid">
{% for column in row %}
<div class="col-sm-{{ column.span }}">
<div id="div_id_{{ column.id }}" class="form-group">
<p class="control-label">{{ column.verbose_name }}</p>
<div class="controls">
<div class="form-control-static">{{ column.text|safe }}</div>
</div>
</div>
</div>
{% endfor %}
</div>
{% endfor %}
{% endfor %}
{% endblock detail_content %}
<div class="actions btn-group pull-right btn-group-lg" role="group">
{% if view.detail_set_create_url %}
<a href="{{ view.detail_set_create_url }}" class="btn btn-default">
{% blocktrans with verbose_name=view.verbose_name_set %} Adicionar {{ verbose_name }} {% endblocktrans %}
</a>
{% endif %}
{% block more_buttons %}{% endblock more_buttons %}
</div>
<div class="container-table">
{% if not rows %}
<p>{{ NO_ENTRIES_MSG }}</p>
{% else %}
<div class="result-count">{% blocktrans with verbose_name_plural=view.verbose_name_plural %}Total de Registros: <strong>{{count}}</strong>{% endblocktrans %}</div>
<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>
{% elif valu != 'core.Cep.None' %}
{{ value|safe }}
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</div>
{% include "paginacao.html" %}
{% endblock base_content %}

2
sapl/templates/crud/form.html

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

44
sapl/templates/crud/list.html

@ -1,29 +1,54 @@
{% extends "base.html" %}
{% load i18n %}
{% load common_tags %}
{% load i18n common_tags crispy_forms_tags%}
{% block base_content %}
<div class="actions btn-group pull-right" role="group">
{% if perms|get_add_perm:view %}
<div class="context-actions clearfix">
<div class="actions search pull-left">
{% if form %}
{% crispy form %}
{% endif %}
</div>
{% block actions %}
<div class="actions btn-group pull-right btn-group-lg" role="group">
{% if view.create_url %}
<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>
{% endblock actions %}
</div>
<br/><br/>
{% block extra_content %} {% endblock %}
{% if not rows %}
<p>{{ NO_ENTRIES_MSG }}</p>
{% else %}
<table class="table table-striped table-hover">
<div class="container-table">
<div class="result-count">{% blocktrans with verbose_name_plural=view.verbose_name_plural %}Total de {{ verbose_name_plural }}: <strong>{{count}}</strong>{% endblocktrans %}</div>
<table class="table table-striped table-hover table-link-ordering">
<thead>
<tr>
{% for name in headers %}
<th>{{ name }}</th>
<th>
{% if view.ordered_list %}
<a title="{% trans 'Clique para alterar a ordem a listagem'%}" href="?o={% if 'o' not in request.GET and forloop.counter == 1 or 'o' in request.GET and forloop.counter|safe == request.GET.o %}-{%endif%}{{forloop.counter}}{{ordering_url}}">
{{ name }}
{% if 'o' in request.GET or not view.ordering %}
{% if 'o' not in request.GET and forloop.counter == 1 or 'o' in request.GET and forloop.counter|safe == request.GET.o %}
<span class="caret top" title="{% trans 'Listado na Ordem Ascendente'%}"></span>
{% elif 'o' in request.GET and forloop.counter == request.GET.o|str2intabs %}
<span class="caret" title="{% trans 'Listado na Ordem Descendente'%}"></span>
{%endif%}
{%endif%}
</a>
{% else %}
{{ name }}
{% endif %}
</th>
{% endfor %}
</tr>
</thead>
@ -33,8 +58,8 @@
{% for value, href in value_list %}
<td>
{% if href %}
<a href="{{ href }}">{{ value }}</a>
{% else %}
<a href="{{ href }}">{{ value|safe }}</a>
{% elif valu != 'core.Cep.None' %}
{{ value|safe }}
{% endif %}
</td>
@ -43,6 +68,7 @@
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
{% include "paginacao.html" %}

10
sapl/templates/parlamentares/coligacao_detail.html

@ -1,10 +0,0 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% block actions %}
<div class="actions btn-group pull-right" role="group">
<a href="{% url 'sapl.parlamentares:composicaocoligacao_list' object.pk %}" class="btn btn-default">{% trans 'Ver Composição' %}</a>
<a href="{{ view.update_url }}" class="btn btn-default">{% trans 'Editar' %}</a>
<a href="{{ view.delete_url }}" class="btn btn-default">{% trans 'Excluir' %}</a>
</div>
{% endblock actions %}

4
sapl/templates/mesa_diretora/mesa_diretora.html → sapl/templates/parlamentares/composicaomesa_form.html

@ -48,13 +48,13 @@
<div class="col-md-4" align="center">
<br /><br />
{% if cargos_vagos %}
{% if perms.parlamentares.add_cargomesa or perms.parlamentares.add_composicaomesa %}
{% if perms.parlamentares.add_cargomesa %}
<input type="submit" name="Incluir" Value="Incluir" class="btn btn-primary" />
{% endif %}
{% endif %}
<br />
<br />
{% if perms.parlamentares.add_cargomesa or perms.parlamentares.add_composicaomesa %}
{% if perms.parlamentares.add_composicaomesa %}
<input type="submit" name="Excluir" Value="Excluir" class="btn btn-danger" />
{% endif %}
</div>

21
sapl/templates/parlamentares/frentes.html

@ -1,21 +0,0 @@
{% extends "crud/list.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block base_content %}
{% if object_list|length == 0 %}
<p>Nenhuma frente encontrada.</p>
{% else %}
<table class="table table-striped table-hover">
<thead>
<tr><th>Frentes</th></tr>
</thead>
<tbody>
{% for frente in object_list %}
<tr><td><a href="{% url 'sapl.parlamentares:frente_detail' frente.pk %}">{{ frente.nome }}</a></td></tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% include "paginacao.html" %}
{% endblock %}

8
sapl/templates/parlamentares/subnav.yaml

@ -8,10 +8,10 @@
- title: {% trans 'Dependentes' %}
url: dependente_list
- title: {% trans 'Comissões' %}
url: participacao_list
url: participacao_parlamentar_list
- title: {% trans 'Proposições' %}
url: proposicao_list
url: proposicao_parlamentar_list
- title: {% trans 'Relatorias' %}
url: relatoria_list
url: relatoria_parlamentar_list
- title: {% trans 'Frentes' %}
url: frent_list
url: frente_parlamentar_list

5
sapl/templates/parlamentares/subnav_coligacao.yaml

@ -0,0 +1,5 @@
{% load i18n %}
- title: {% trans 'Início' %}
url: coligacao_detail
- title: {% trans 'Composição da Coligação' %}
url: composicaocoligacao_list

2
sapl/templates/sessao/mesa.html

@ -20,10 +20,12 @@
</div>
<div class="col-md-4" align="center">
{% if perms.sessao %}
<br /><br />
{% if view.get_cargos_mesa %}<input type="submit" name="Incluir" Value="Incluir" class="btn btn-primary" />{% endif %}
<br /><br />
<input type="submit" name="Excluir" Value="Excluir" class="btn btn-danger" />
{% endif %}
</div>
{% if view.get_cargos_mesa %}
<div class="col-md-4">

6
sapl/utils.py

@ -1,6 +1,7 @@
import hashlib
from datetime import date
from functools import wraps
from unicodedata import normalize as unicodedata_normalize
import magic
from django import forms
@ -14,6 +15,11 @@ from django.utils.translation import ugettext_lazy as _
from floppyforms import ClearableFileInput
def normalize(txt):
return unicodedata_normalize(
'NFKD', txt).encode('ASCII', 'ignore').decode('ASCII')
def get_settings_auth_user_model():
return getattr(settings, 'AUTH_USER_MODEL', 'auth.User')

51
scripts/inicializa_grupos_autorizacoes.py

@ -1,25 +1,34 @@
import os
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sapl.settings")
django.setup()
if True:
from django.apps import apps
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
def cria_ou_reseta_grupo(nome):
class InicializaGruposAutorizacoes():
def cria_ou_reseta_grupo(self, nome):
grupo = Group.objects.get_or_create(name=nome)[0]
for p in list(grupo.permissions.all()):
grupo.permissions.remove(p)
return grupo
def cria_usuario(nome, grupo):
def cria_usuario(self, nome, grupo):
nome_usuario = nome
usuario = get_user_model().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)
def cria_grupos_permissoes():
def cria_grupos_permissoes(self):
nomes_apps = ['base', 'parlamentares', 'comissoes',
'materia', 'norma', 'sessao', 'painel']
@ -35,12 +44,12 @@ def cria_grupos_permissoes():
permissoes['documento_administrativo'] = list(
Permission.objects.filter(content_type__in=cts))
nome_grupo = 'Operador Administrativo'
grupo = cria_ou_reseta_grupo(nome_grupo)
grupo = self.cria_ou_reseta_grupo(nome_grupo)
for p in permissoes['documento_administrativo']:
grupo.permissions.add(p)
nome_usuario = 'operador_administrativo'
cria_usuario(nome_usuario, grupo)
self.cria_usuario(nome_usuario, grupo)
# prolocolo administrativo
cts = cts.exclude(model__icontains='tramitacao').exclude(
@ -48,12 +57,12 @@ def cria_grupos_permissoes():
permissoes['protocoloadm'] = list(
Permission.objects.filter(content_type__in=cts))
nome_grupo = 'Operador de Protocolo Administrativo'
grupo = cria_ou_reseta_grupo(nome_grupo)
grupo = self.cria_ou_reseta_grupo(nome_grupo)
for p in permissoes['protocoloadm']:
grupo.permissions.add(p)
nome_usuario = 'operador_protocoloadm'
cria_usuario(nome_usuario, grupo)
self.cria_usuario(nome_usuario, grupo)
# permissoes do base
cts = ContentType.objects.filter(app_label='base')
@ -68,7 +77,7 @@ def cria_grupos_permissoes():
# Cria Grupo
nome_grupo = 'Operador de %s' % apps.get_app_config(
nome_app).verbose_name
grupo = cria_ou_reseta_grupo(nome_grupo)
grupo = self.cria_ou_reseta_grupo(nome_grupo)
# Elimina o acesso a proposicoes pelo Operador de Matérias
if nome_app == 'materia':
@ -90,28 +99,34 @@ def cria_grupos_permissoes():
grupo.user_set.add(usuario)
# Operador Geral
grupo_geral = cria_ou_reseta_grupo('Operador Geral')
grupo_geral = self.cria_ou_reseta_grupo('Operador Geral')
for lista in permissoes.values():
for p in lista:
grupo_geral.permissions.add(p)
nome_usuario = 'operador_geral'
cria_usuario(nome_usuario, grupo_geral)
self.cria_usuario(nome_usuario, grupo_geral)
# Autor
perms_autor = []
perms_autor.append(Permission.objects.get(name='Can add Proposição'))
perms_autor.append(Permission.objects.get(name='Can change Proposição'))
perms_autor.append(Permission.objects.get(name='Can delete Proposição'))
perms_autor.append(
Permission.objects.get(name='Can change Proposição'))
perms_autor.append(
Permission.objects.get(name='Can delete Proposição'))
# Configura Permissoes Autor
grupo = cria_ou_reseta_grupo('Autor')
grupo = self.cria_ou_reseta_grupo('Autor')
for p in perms_autor:
grupo.permissions.add(p)
nome_usuario = 'operador_autor'
cria_usuario(nome_usuario, grupo)
self.cria_usuario(nome_usuario, grupo)
def __call__(self):
self.cria_grupos_permissoes()
cria_grupos_permissoes = InicializaGruposAutorizacoes()
if __name__ == '__main__':
cria_grupos_permissoes()
cria_grupos_permissoes.cria_grupos_permissoes()

3
scripts/test_inicializa_grupos_autorizacoes.py

@ -1,10 +1,11 @@
import pytest
from django.apps import apps
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
import pytest
from inicializa_grupos_autorizacoes import cria_grupos_permissoes
pytestmark = pytest.mark.django_db
apps_com_permissao_padrao = [

Loading…
Cancel
Save