Browse Source

Merge bdcddb546f into 2938835502

pull/2214/merge
Leandro Roberto da Silva 7 years ago
committed by GitHub
parent
commit
51d236798c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 0
      sapl/api/base/__init__.py
  2. 147
      sapl/api/base/forms.py
  3. 23
      sapl/api/base/serializers.py
  4. 15
      sapl/api/base/urls.py
  5. 223
      sapl/api/base/views.py
  6. 145
      sapl/api/forms.py
  7. 0
      sapl/api/materia/__init__.py
  8. 0
      sapl/api/materia/forms.py
  9. 19
      sapl/api/materia/serializers.py
  10. 13
      sapl/api/materia/urls.py
  11. 9
      sapl/api/materia/views.py
  12. 147
      sapl/api/serializers.py
  13. 0
      sapl/api/sessao/__init__.py
  14. 0
      sapl/api/sessao/forms.py
  15. 138
      sapl/api/sessao/serializers.py
  16. 15
      sapl/api/sessao/urls.py
  17. 23
      sapl/api/sessao/views.py
  18. 27
      sapl/api/urls.py
  19. 254
      sapl/api/views.py
  20. 9
      sapl/crud/base.py
  21. 10
      sapl/rules/apps.py
  22. 12
      sapl/sessao/forms.py
  23. 37
      sapl/sessao/migrations/0023_auto_20180914_1315.py
  24. 8
      sapl/sessao/models.py
  25. 16
      sapl/sessao/serializers.py
  26. 56
      sapl/sessao/views.py
  27. 2
      sapl/templates/base/relatorios_list.html
  28. 19
      sapl/templates/sessao/expedientemateria_form.html
  29. 2
      sapl/templates/sessao/layouts.yaml

0
sapl/api/base/__init__.py

147
sapl/api/base/forms.py

@ -0,0 +1,147 @@
from django.db.models import Q
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django_filters.filters import DateFilter, MethodFilter, ModelChoiceFilter
from rest_framework import serializers
from rest_framework.filters import FilterSet
from sapl.api.forms import SaplGenericRelationSearchFilterSet,\
SearchForFieldFilter
from sapl.base.models import Autor, TipoAutor
from sapl.parlamentares.models import Legislatura
class AutorChoiceFilterSet(SaplGenericRelationSearchFilterSet):
q = MethodFilter()
tipo = ModelChoiceFilter(queryset=TipoAutor.objects.all())
class Meta:
model = Autor
fields = ['q',
'tipo',
'nome', ]
def filter_q(self, queryset, value):
return SaplGenericRelationSearchFilterSet.filter_q(
self, queryset, value).distinct('nome').order_by('nome')
class AutorSearchForFieldFilterSet(AutorChoiceFilterSet):
q = SearchForFieldFilter()
class Meta(AutorChoiceFilterSet.Meta):
pass
def filter_q(self, queryset, value):
value[0] = value[0].split(',')
value[1] = value[1].split(',')
params = {}
for key, v in list(zip(value[0], value[1])):
if v in ['True', 'False']:
v = '1' if v == 'True' else '0'
params[key] = v
return queryset.filter(**params).distinct('nome').order_by('nome')
class AutoresPossiveisFilterSet(FilterSet):
data_relativa = DateFilter(method='filter_data_relativa')
tipo = MethodFilter(required=True)
class Meta:
model = Autor
fields = ['data_relativa', 'tipo', ]
def filter_data_relativa(self, queryset, name, value):
return queryset
def filter_tipo(self, queryset, value):
try:
tipo = TipoAutor.objects.get(pk=value)
except:
raise serializers.ValidationError(_('Tipo de Autor inexistente.'))
qs = queryset.filter(tipo=tipo)
return qs
@property
def qs(self):
qs = super().qs
data_relativa = self.form.cleaned_data['data_relativa'] \
if 'data_relativa' in self.form.cleaned_data else None
tipo = self.form.cleaned_data['tipo'] \
if 'tipo' in self.form.cleaned_data else None
if not tipo:
return qs
else:
tipo = TipoAutor.objects.get(pk=tipo)
if not tipo.content_type:
return qs
filter_for_model = 'filter_%s' % tipo.content_type.model
if not hasattr(self, filter_for_model):
return qs
if not data_relativa:
data_relativa = timezone.now()
return getattr(self, filter_for_model)(qs, data_relativa).distinct()
def filter_parlamentar(self, queryset, data_relativa):
# não leva em conta afastamentos
legislatura_relativa = Legislatura.objects.filter(
data_inicio__lte=data_relativa,
data_fim__gte=data_relativa).first()
q = Q(
parlamentar_set__mandato__data_inicio_mandato__lte=data_relativa,
parlamentar_set__mandato__data_fim_mandato__isnull=True) | Q(
parlamentar_set__mandato__data_inicio_mandato__lte=data_relativa,
parlamentar_set__mandato__data_fim_mandato__gte=data_relativa)
if legislatura_relativa.atual():
q = q & Q(parlamentar_set__ativo=True)
return queryset.filter(q)
def filter_comissao(self, queryset, data_relativa):
return queryset.filter(
Q(comissao_set__data_extincao__isnull=True,
comissao_set__data_fim_comissao__isnull=True) |
Q(comissao_set__data_extincao__gte=data_relativa,
comissao_set__data_fim_comissao__isnull=True) |
Q(comissao_set__data_extincao__gte=data_relativa,
comissao_set__data_fim_comissao__isnull=True) |
Q(comissao_set__data_extincao__isnull=True,
comissao_set__data_fim_comissao__gte=data_relativa) |
Q(comissao_set__data_extincao__gte=data_relativa,
comissao_set__data_fim_comissao__gte=data_relativa),
comissao_set__data_criacao__lte=data_relativa)
def filter_frente(self, queryset, data_relativa):
return queryset.filter(
Q(frente_set__data_extincao__isnull=True) |
Q(frente_set__data_extincao__gte=data_relativa),
frente_set__data_criacao__lte=data_relativa)
def filter_bancada(self, queryset, data_relativa):
return queryset.filter(
Q(bancada_set__data_extincao__isnull=True) |
Q(bancada_set__data_extincao__gte=data_relativa),
bancada_set__data_criacao__lte=data_relativa)
def filter_bloco(self, queryset, data_relativa):
return queryset.filter(
Q(bloco_set__data_extincao__isnull=True) |
Q(bloco_set__data_extincao__gte=data_relativa),
bloco_set__data_criacao__lte=data_relativa)
def filter_orgao(self, queryset, data_relativa):
# na implementação, não havia regras a implementar para orgao
return queryset

23
sapl/api/base/serializers.py

@ -0,0 +1,23 @@
from rest_framework import serializers
from sapl.api.serializers import ModelChoiceSerializer,\
ModelChoiceObjectRelatedField
from sapl.base.models import Autor
class AutorChoiceSerializer(ModelChoiceSerializer):
def get_text(self, obj):
return obj.nome
class Meta:
model = Autor
fields = ['id', 'nome']
class AutorSerializer(serializers.ModelSerializer):
autor_related = ModelChoiceObjectRelatedField(read_only=True)
class Meta:
model = Autor
fields = '__all__'

15
sapl/api/base/urls.py

@ -0,0 +1,15 @@
from django.conf.urls import url
from sapl.api.base.views import AutorListView, AutoresPossiveisListView,\
AutoresProvaveisListView
# Não adicione app_name
# app_name = AppConfig.name
urlpatterns = [
url(r'^autor/$', AutorListView.as_view(), name='autor_list'),
url(r'^autor/provaveis',
AutoresProvaveisListView.as_view(), name='autores_provaveis_list'),
url(r'^autor/possiveis',
AutoresPossiveisListView.as_view(), name='autores_possiveis_list'),
]

223
sapl/api/base/views.py

@ -0,0 +1,223 @@
from django.db.models import Q
from django.http import Http404
from django.utils.translation import ugettext_lazy as _
from rest_framework.filters import DjangoFilterBackend
from rest_framework.generics import ListAPIView
from rest_framework.permissions import (IsAuthenticated,
IsAuthenticatedOrReadOnly)
from sapl.api.base.forms import AutoresPossiveisFilterSet,\
AutorSearchForFieldFilterSet, AutorChoiceFilterSet
from sapl.api.base.serializers import AutorChoiceSerializer, AutorSerializer
from sapl.api.serializers import (ChoiceSerializer)
from sapl.base.models import Autor, TipoAutor
from sapl.utils import SaplGenericRelation, sapl_logger
class AutorListView(ListAPIView):
"""
Listagem de Autores com filtro para autores cadastrados
e/ou possíveis autores.
- tr - tipo do resultado
Prepera Lista de Autores para 3 cenários distintos
- default = 1
= 1 -> para (value, text) usados geralmente
em combobox, radiobox, checkbox, etc com pesquisa básica
de Autores feita pelo django-filter
-> processo usado nas pesquisas, o mais usado.
= 3 -> Devolve instancias da classe Autor filtradas pelo
django-filter
- tipo - chave primária do Tipo de Autor a ser filtrado
- q - busca textual no nome do Autor ou em fields_search
declarados no field SaplGenericRelation das GenericFks
A busca textual acontece via django-filter com a
variável `tr` igual 1 ou 3. Em caso contrário,
o django-filter é desativado e a busca é feita
no model do ContentType associado ao tipo.
- q_0 / q_1 - q_0 é opcional e quando usado, faz o código ignorar "q"...
q_0 -> campos lookup a serem filtrados em qualquer Model
que implemente SaplGenericRelation
q_1 -> o valor que será pesquisado no lookup de q_0
q_0 e q_1 podem ser separados por ","... isso dará a
possibilidade de filtrar mais de um campo.
http://localhost:8000
/api/autor?tr=1&q_0=parlamentar_set__ativo&q_1=False
/api/autor?tr=1&q_0=parlamentar_set__ativo&q_1=True
/api/autor?tr=3&q_0=parlamentar_set__ativo&q_1=False
/api/autor?tr=3&q_0=parlamentar_set__ativo&q_1=True
http://localhost:8000
/api/autor?tr=1
&q_0=parlamentar_set__nome_parlamentar__icontains,
parlamentar_set__ativo
&q_1=Carvalho,False
/api/autor?tr=1
&q_0=parlamentar_set__nome_parlamentar__icontains,
parlamentar_set__ativo
&q_1=Carvalho,True
/api/autor?tr=3
&q_0=parlamentar_set__nome_parlamentar__icontains,
parlamentar_set__ativo
&q_1=Carvalho,False
/api/autor?tr=3
&q_0=parlamentar_set__nome_parlamentar__icontains,
parlamentar_set__ativo
&q_1=Carvalho,True
não importa o campo que vc passe de qualquer dos Models
ligados... é possível ver que models são esses,
na ocasião do commit deste texto, executando:
In [6]: from sapl.utils import models_with_gr_for_model
In [7]: models_with_gr_for_model(Autor)
Out[7]:
[sapl.parlamentares.models.Parlamentar,
sapl.parlamentares.models.Frente,
sapl.comissoes.models.Comissao,
sapl.materia.models.Orgao,
sapl.sessao.models.Bancada,
sapl.sessao.models.Bloco]
qualquer atributo destes models podem ser passados
para busca
"""
TR_AUTOR_CHOICE_SERIALIZER = 1
TR_AUTOR_SERIALIZER = 3
permission_classes = (IsAuthenticatedOrReadOnly,)
queryset = Autor.objects.all()
model = Autor
filter_class = AutorChoiceFilterSet
filter_backends = (DjangoFilterBackend, )
serializer_class = AutorChoiceSerializer
@property
def tr(self):
try:
tr = int(self.request.GET.get
('tr', AutorListView.TR_AUTOR_CHOICE_SERIALIZER))
assert tr in (
AutorListView.TR_AUTOR_CHOICE_SERIALIZER,
AutorListView.TR_AUTOR_SERIALIZER), sapl_logger.info(
_("Tipo do Resultado a ser fornecido não existe!"))
except:
return AutorListView.TR_AUTOR_CHOICE_SERIALIZER
else:
return tr
def get(self, request, *args, **kwargs):
if self.tr == AutorListView.TR_AUTOR_SERIALIZER:
self.serializer_class = AutorSerializer
self.permission_classes = (IsAuthenticated,)
if self.filter_class and 'q_0' in request.GET:
self.filter_class = AutorSearchForFieldFilterSet
return ListAPIView.get(self, request, *args, **kwargs)
class AutoresProvaveisListView(ListAPIView):
permission_classes = (IsAuthenticatedOrReadOnly,)
queryset = Autor.objects.all()
model = Autor
filter_class = None
filter_backends = []
serializer_class = ChoiceSerializer
def get_queryset(self):
params = {'content_type__isnull': False}
tipo = ''
try:
tipo = int(self.request.GET.get('tipo', ''))
if tipo:
params['id'] = tipo
except:
pass
tipos = TipoAutor.objects.filter(**params)
if not tipos.exists() and tipo:
raise Http404()
r = []
for tipo in tipos:
q = self.request.GET.get('q', '').strip()
model_class = tipo.content_type.model_class()
fields = list(filter(
lambda field: isinstance(field, SaplGenericRelation) and
field.related_model == Autor,
model_class._meta.get_fields(include_hidden=True)))
"""
fields - é um array de SaplGenericRelation que deve possuir o
atributo fields_search. Verifique na documentação da classe
a estrutura de fields_search.
"""
assert len(fields) >= 1, (_(
'Não foi encontrado em %(model)s um atributo do tipo '
'SaplGenericRelation que use o model %(model_autor)s') % {
'model': model_class._meta.verbose_name,
'model_autor': Autor._meta.verbose_name})
qs = model_class.objects.all()
q_filter = Q()
if q:
for item in fields:
if item.related_model != Autor:
continue
q_fs = Q()
for field in item.fields_search:
q_fs = q_fs | Q(**{'%s%s' % (
field[0],
field[1]): q})
q_filter = q_filter & q_fs
qs = qs.filter(q_filter).distinct(
fields[0].fields_search[0][0]).order_by(
fields[0].fields_search[0][0])
else:
qs = qs.order_by(fields[0].fields_search[0][0])
qs = qs.values_list(
'id', fields[0].fields_search[0][0])
r += list(qs)
if tipos.count() > 1:
r.sort(key=lambda x: x[1].upper())
return r
class AutoresPossiveisListView(ListAPIView):
permission_classes = (IsAuthenticatedOrReadOnly,)
queryset = Autor.objects.all()
model = Autor
pagination_class = None
filter_class = AutoresPossiveisFilterSet
serializer_class = AutorChoiceSerializer

145
sapl/api/forms.py

@ -1,15 +1,10 @@
from django.db.models import Q
from django.forms.fields import CharField, MultiValueField
from django.forms.widgets import MultiWidget, TextInput
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django_filters.filters import DateFilter, MethodFilter, ModelChoiceFilter
from rest_framework import serializers
from django_filters.filters import MethodFilter
from rest_framework.compat import django_filters
from rest_framework.filters import FilterSet
from sapl.base.models import Autor, TipoAutor
from sapl.parlamentares.models import Legislatura
from sapl.utils import generic_relations_for_model
@ -87,141 +82,3 @@ class SearchForFieldField(MultiValueField):
class SearchForFieldFilter(django_filters.filters.MethodFilter):
field_class = SearchForFieldField
class AutorChoiceFilterSet(SaplGenericRelationSearchFilterSet):
q = MethodFilter()
tipo = ModelChoiceFilter(queryset=TipoAutor.objects.all())
class Meta:
model = Autor
fields = ['q',
'tipo',
'nome', ]
def filter_q(self, queryset, value):
return SaplGenericRelationSearchFilterSet.filter_q(
self, queryset, value).distinct('nome').order_by('nome')
class AutorSearchForFieldFilterSet(AutorChoiceFilterSet):
q = SearchForFieldFilter()
class Meta(AutorChoiceFilterSet.Meta):
pass
def filter_q(self, queryset, value):
value[0] = value[0].split(',')
value[1] = value[1].split(',')
params = {}
for key, v in list(zip(value[0], value[1])):
if v in ['True', 'False']:
v = '1' if v == 'True' else '0'
params[key] = v
return queryset.filter(**params).distinct('nome').order_by('nome')
class AutoresPossiveisFilterSet(FilterSet):
data_relativa = DateFilter(method='filter_data_relativa')
tipo = MethodFilter()
class Meta:
model = Autor
fields = ['data_relativa', 'tipo', ]
def filter_data_relativa(self, queryset, name, value):
return queryset
def filter_tipo(self, queryset, value):
try:
tipo = TipoAutor.objects.get(pk=value)
except:
raise serializers.ValidationError(_('Tipo de Autor inexistente.'))
qs = queryset.filter(tipo=tipo)
return qs
@property
def qs(self):
qs = super().qs
data_relativa = self.form.cleaned_data['data_relativa'] \
if 'data_relativa' in self.form.cleaned_data else None
tipo = self.form.cleaned_data['tipo'] \
if 'tipo' in self.form.cleaned_data else None
if not tipo and not data_relativa:
return qs
if tipo:
# não precisa de try except, já foi validado em filter_tipo
tipo = TipoAutor.objects.get(pk=tipo)
if not tipo.content_type:
return qs
filter_for_model = 'filter_%s' % tipo.content_type.model
if not hasattr(self, filter_for_model):
return qs
if not data_relativa:
data_relativa = timezone.now()
return getattr(self, filter_for_model)(qs, data_relativa).distinct()
def filter_parlamentar(self, queryset, data_relativa):
# não leva em conta afastamentos
legislatura_relativa = Legislatura.objects.filter(
data_inicio__lte=data_relativa,
data_fim__gte=data_relativa).first()
q = Q(
parlamentar_set__mandato__data_inicio_mandato__lte=data_relativa,
parlamentar_set__mandato__data_fim_mandato__isnull=True) | Q(
parlamentar_set__mandato__data_inicio_mandato__lte=data_relativa,
parlamentar_set__mandato__data_fim_mandato__gte=data_relativa)
if legislatura_relativa.atual():
q = q & Q(parlamentar_set__ativo=True)
return queryset.filter(q)
def filter_comissao(self, queryset, data_relativa):
return queryset.filter(
Q(comissao_set__data_extincao__isnull=True,
comissao_set__data_fim_comissao__isnull=True) |
Q(comissao_set__data_extincao__gte=data_relativa,
comissao_set__data_fim_comissao__isnull=True) |
Q(comissao_set__data_extincao__gte=data_relativa,
comissao_set__data_fim_comissao__isnull=True) |
Q(comissao_set__data_extincao__isnull=True,
comissao_set__data_fim_comissao__gte=data_relativa) |
Q(comissao_set__data_extincao__gte=data_relativa,
comissao_set__data_fim_comissao__gte=data_relativa),
comissao_set__data_criacao__lte=data_relativa)
def filter_frente(self, queryset, data_relativa):
return queryset.filter(
Q(frente_set__data_extincao__isnull=True) |
Q(frente_set__data_extincao__gte=data_relativa),
frente_set__data_criacao__lte=data_relativa)
def filter_bancada(self, queryset, data_relativa):
return queryset.filter(
Q(bancada_set__data_extincao__isnull=True) |
Q(bancada_set__data_extincao__gte=data_relativa),
bancada_set__data_criacao__lte=data_relativa)
def filter_bloco(self, queryset, data_relativa):
return queryset.filter(
Q(bloco_set__data_extincao__isnull=True) |
Q(bloco_set__data_extincao__gte=data_relativa),
bloco_set__data_criacao__lte=data_relativa)
def filter_orgao(self, queryset, data_relativa):
# na implementação, não havia regras a implementar para orgao
return queryset

0
sapl/api/materia/__init__.py

0
sapl/api/materia/forms.py

19
sapl/api/materia/serializers.py

@ -0,0 +1,19 @@
from rest_framework.filters import DjangoFilterBackend
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
from rest_framework.permissions import IsAuthenticated
from rest_framework.viewsets import GenericViewSet
from sapl.api.materia.views import MateriaLegislativaSerializer
from sapl.materia.models import MateriaLegislativa
class MateriaLegislativaViewSet(ListModelMixin,
RetrieveModelMixin,
GenericViewSet):
permission_classes = (IsAuthenticated,)
serializer_class = MateriaLegislativaSerializer
queryset = MateriaLegislativa.objects.all()
filter_backends = (DjangoFilterBackend,)
filter_fields = ('numero', 'ano', 'tipo', )

13
sapl/api/materia/urls.py

@ -0,0 +1,13 @@
from rest_framework.routers import DefaultRouter
from sapl.api.materia.serializers import MateriaLegislativaViewSet
# Não adicione app_name
# app_name = AppConfig.name
router = DefaultRouter()
router.register(r'materia', MateriaLegislativaViewSet)
urlpatterns = [
]

9
sapl/api/materia/views.py

@ -0,0 +1,9 @@
from rest_framework import serializers
from sapl.materia.models import MateriaLegislativa
class MateriaLegislativaSerializer(serializers.ModelSerializer):
class Meta:
model = MateriaLegislativa
fields = '__all__'

147
sapl/api/serializers.py

@ -1,9 +1,5 @@
from rest_framework import serializers
from sapl.base.models import Autor, CasaLegislativa
from sapl.materia.models import MateriaLegislativa
from sapl.sessao.models import OrdemDia, SessaoPlenaria
class ChoiceSerializer(serializers.Serializer):
value = serializers.SerializerMethodField()
@ -29,146 +25,3 @@ class ModelChoiceObjectRelatedField(serializers.RelatedField):
def to_representation(self, value):
return ModelChoiceSerializer(value).data
class AutorChoiceSerializer(ModelChoiceSerializer):
def get_text(self, obj):
return obj.nome
class Meta:
model = Autor
fields = ['id', 'nome']
class AutorSerializer(serializers.ModelSerializer):
autor_related = ModelChoiceObjectRelatedField(read_only=True)
class Meta:
model = Autor
fields = '__all__'
class MateriaLegislativaSerializer(serializers.ModelSerializer):
class Meta:
model = MateriaLegislativa
fields = '__all__'
class SessaoPlenariaSerializer(serializers.ModelSerializer):
codReuniao = serializers.SerializerMethodField('get_pk_sessao')
codReuniaoPrincipal = serializers.SerializerMethodField('get_pk_sessao')
txtTituloReuniao = serializers.SerializerMethodField('get_name')
txtSiglaOrgao = serializers.SerializerMethodField('get_sigla_orgao')
txtApelido = serializers.SerializerMethodField('get_name')
txtNomeOrgao = serializers.SerializerMethodField('get_nome_orgao')
codEstadoReuniao = serializers.SerializerMethodField(
'get_estadoSessaoPlenaria')
txtTipoReuniao = serializers.SerializerMethodField('get_tipo_sessao')
txtObjeto = serializers.SerializerMethodField('get_assunto_sessao')
txtLocal = serializers.SerializerMethodField('get_endereco_orgao')
bolReuniaoConjunta = serializers.SerializerMethodField(
'get_reuniao_conjunta')
bolHabilitarEventoInterativo = serializers.SerializerMethodField(
'get_iterativo')
idYoutube = serializers.SerializerMethodField('get_url')
codEstadoTransmissaoYoutube = serializers.SerializerMethodField(
'get_estadoTransmissaoYoutube')
datReuniaoString = serializers.SerializerMethodField('get_date')
# Constantes SessaoPlenaria (de 1-9) (apenas 3 serão usados)
SESSAO_FINALIZADA = 4
SESSAO_EM_ANDAMENTO = 3
SESSAO_CONVOCADA = 2
# Constantes EstadoTranmissaoYoutube (de 0 a 2)
TRANSMISSAO_ENCERRADA = 2
TRANSMISSAO_EM_ANDAMENTO = 1
SEM_TRANSMISSAO = 0
class Meta:
model = SessaoPlenaria
fields = (
'codReuniao',
'codReuniaoPrincipal',
'txtTituloReuniao',
'txtSiglaOrgao',
'txtApelido',
'txtNomeOrgao',
'codEstadoReuniao',
'txtTipoReuniao',
'txtObjeto',
'txtLocal',
'bolReuniaoConjunta',
'bolHabilitarEventoInterativo',
'idYoutube',
'codEstadoTransmissaoYoutube',
'datReuniaoString'
)
def __init__(self, *args, **kwargs):
super(SessaoPlenariaSerializer, self).__init__(args, kwargs)
def get_pk_sessao(self, obj):
return obj.pk
def get_name(self, obj):
return obj.__str__()
def get_estadoSessaoPlenaria(self, obj):
if obj.finalizada:
return self.SESSAO_FINALIZADA
elif obj.iniciada:
return self.SESSAO_EM_ANDAMENTO
else:
return self.SESSAO_CONVOCADA
def get_tipo_sessao(self, obj):
return obj.tipo.__str__()
def get_url(self, obj):
return obj.url_video if obj.url_video else None
def get_iterativo(self, obj):
return obj.interativa if obj.interativa else False
def get_date(self, obj):
return "{} {}{}".format(
obj.data_inicio.strftime("%d/%m/%Y"),
obj.hora_inicio,
":00"
)
def get_estadoTransmissaoYoutube(self, obj):
if obj.url_video:
if obj.finalizada:
return self.TRANSMISSAO_ENCERRADA
else:
return self.TRANSMISSAO_EM_ANDAMENTO
else:
return self.SEM_TRANSMISSAO
def get_assunto_sessao(self, obj):
pauta_sessao = ''
ordem_dia = OrdemDia.objects.filter(sessao_plenaria=obj.pk)
pauta_sessao = ', '.join([i.materia.__str__() for i in ordem_dia])
return str(pauta_sessao)
def get_endereco_orgao(self, obj):
return self.casa().endereco
def get_reuniao_conjunta(self, obj):
return False
def get_sigla_orgao(self, obj):
return self.casa().sigla
def get_nome_orgao(self, obj):
return self.casa().nome
def casa(self):
casa = CasaLegislativa.objects.first()
return casa

0
sapl/api/sessao/__init__.py

0
sapl/api/sessao/forms.py

138
sapl/api/sessao/serializers.py

@ -0,0 +1,138 @@
from rest_framework import serializers
from sapl.base.models import CasaLegislativa
from sapl.sessao.models import SessaoPlenaria, OrdemDia
class SessaoPlenariaOldSerializer(serializers.ModelSerializer):
codReuniao = serializers.SerializerMethodField('get_pk_sessao')
codReuniaoPrincipal = serializers.SerializerMethodField('get_pk_sessao')
txtTituloReuniao = serializers.SerializerMethodField('get_name')
txtSiglaOrgao = serializers.SerializerMethodField('get_sigla_orgao')
txtApelido = serializers.SerializerMethodField('get_name')
txtNomeOrgao = serializers.SerializerMethodField('get_nome_orgao')
codEstadoReuniao = serializers.SerializerMethodField(
'get_estadoSessaoPlenaria')
txtTipoReuniao = serializers.SerializerMethodField('get_tipo_sessao')
txtObjeto = serializers.SerializerMethodField('get_assunto_sessao')
txtLocal = serializers.SerializerMethodField('get_endereco_orgao')
bolReuniaoConjunta = serializers.SerializerMethodField(
'get_reuniao_conjunta')
bolHabilitarEventoInterativo = serializers.SerializerMethodField(
'get_iterativo')
idYoutube = serializers.SerializerMethodField('get_url')
codEstadoTransmissaoYoutube = serializers.SerializerMethodField(
'get_estadoTransmissaoYoutube')
datReuniaoString = serializers.SerializerMethodField('get_date')
# Constantes SessaoPlenaria (de 1-9) (apenas 3 serão usados)
SESSAO_FINALIZADA = 4
SESSAO_EM_ANDAMENTO = 3
SESSAO_CONVOCADA = 2
# Constantes EstadoTranmissaoYoutube (de 0 a 2)
TRANSMISSAO_ENCERRADA = 2
TRANSMISSAO_EM_ANDAMENTO = 1
SEM_TRANSMISSAO = 0
class Meta:
model = SessaoPlenaria
fields = (
'codReuniao',
'codReuniaoPrincipal',
'txtTituloReuniao',
'txtSiglaOrgao',
'txtApelido',
'txtNomeOrgao',
'codEstadoReuniao',
'txtTipoReuniao',
'txtObjeto',
'txtLocal',
'bolReuniaoConjunta',
'bolHabilitarEventoInterativo',
'idYoutube',
'codEstadoTransmissaoYoutube',
'datReuniaoString'
)
def __init__(self, *args, **kwargs):
super(SessaoPlenariaOldSerializer, self).__init__(args, kwargs)
def get_pk_sessao(self, obj):
return obj.pk
def get_name(self, obj):
return obj.__str__()
def get_estadoSessaoPlenaria(self, obj):
if obj.finalizada:
return self.SESSAO_FINALIZADA
elif obj.iniciada:
return self.SESSAO_EM_ANDAMENTO
else:
return self.SESSAO_CONVOCADA
def get_tipo_sessao(self, obj):
return obj.tipo.__str__()
def get_url(self, obj):
return obj.url_video if obj.url_video else None
def get_iterativo(self, obj):
return obj.interativa if obj.interativa else False
def get_date(self, obj):
return "{} {}{}".format(
obj.data_inicio.strftime("%d/%m/%Y"),
obj.hora_inicio,
":00"
)
def get_estadoTransmissaoYoutube(self, obj):
if obj.url_video:
if obj.finalizada:
return self.TRANSMISSAO_ENCERRADA
else:
return self.TRANSMISSAO_EM_ANDAMENTO
else:
return self.SEM_TRANSMISSAO
def get_assunto_sessao(self, obj):
pauta_sessao = ''
ordem_dia = OrdemDia.objects.filter(sessao_plenaria=obj.pk)
pauta_sessao = ', '.join([i.materia.__str__() for i in ordem_dia])
return str(pauta_sessao)
def get_endereco_orgao(self, obj):
return self.casa().endereco
def get_reuniao_conjunta(self, obj):
return False
def get_sigla_orgao(self, obj):
return self.casa().sigla
def get_nome_orgao(self, obj):
return self.casa().nome
def casa(self):
casa = CasaLegislativa.objects.first()
return casa
class SessaoPlenariaSerializer(serializers.ModelSerializer):
class Meta:
model = SessaoPlenaria
fields = ('tipo',
'sessao_legislativa',
'legislatura',
'data_inicio',
'hora_inicio',
'hora_fim',
'url_video',
'iniciada',
'finalizada'
)

15
sapl/api/sessao/urls.py

@ -0,0 +1,15 @@
from django.conf.urls import include, url
from rest_framework.routers import DefaultRouter
from sapl.api.sessao.views import SessaoPlenariaViewSet,\
SessaoPlenariaOldViewSet
# Não adicione app_name
# app_name = AppConfig.name
router = DefaultRouter()
router.register(r'sessao-plenaria-old', SessaoPlenariaOldViewSet,
base_name='sessao-plenaria-old')
router.register(r'sessao-plenaria', SessaoPlenariaViewSet)
urlpatterns = [
]

23
sapl/api/sessao/views.py

@ -0,0 +1,23 @@
from rest_framework.filters import DjangoFilterBackend
from rest_framework.permissions import AllowAny
from rest_framework.viewsets import ReadOnlyModelViewSet
from sapl.api.sessao.serializers import SessaoPlenariaOldSerializer,\
SessaoPlenariaSerializer
from sapl.sessao.models import SessaoPlenaria
class SessaoPlenariaOldViewSet(ReadOnlyModelViewSet):
permission_classes = (AllowAny,)
serializer_class = SessaoPlenariaOldSerializer
queryset = SessaoPlenaria.objects.all()
filter_backends = (DjangoFilterBackend,)
filter_fields = ('data_inicio', 'data_fim', 'interativa')
class SessaoPlenariaViewSet(ReadOnlyModelViewSet):
permission_classes = (AllowAny,)
serializer_class = SessaoPlenariaSerializer
queryset = SessaoPlenaria.objects.all()

27
sapl/api/urls.py

@ -2,32 +2,28 @@ from django.conf import settings
from django.conf.urls import include, url
from rest_framework.routers import DefaultRouter
from sapl.api.views import (AutoresPossiveisListView, AutoresProvaveisListView,
AutorListView, MateriaLegislativaViewSet,
ModelChoiceView, SessaoPlenariaViewSet)
import sapl.api.base.urls
import sapl.api.materia.urls
import sapl.api.sessao.urls
from sapl.api.views import ModelChoiceView, TimeRefreshDatabaseView
from .apps import AppConfig
app_name = AppConfig.name
router = DefaultRouter()
router.register(r'materia', MateriaLegislativaViewSet)
router.register(r'sessao-plenaria', SessaoPlenariaViewSet)
router.registry += sapl.api.materia.urls.router.registry + \
sapl.api.sessao.urls.router.registry
urlpatterns_router = router.urls
urlpatterns_api = [
url(r'^autor/provaveis',
AutoresProvaveisListView.as_view(), name='autores_provaveis_list'),
url(r'^autor/possiveis',
AutoresPossiveisListView.as_view(), name='autores_possiveis_list'),
url(r'^autor', AutorListView.as_view(), name='autor_list'),
url(r'^model/(?P<content_type>\d+)/(?P<pk>\d*)$',
ModelChoiceView.as_view(), name='model_list'),
url(r'time_refresh$',
TimeRefreshDatabaseView.as_view(), name="time_refresh")
]
if settings.DEBUG:
@ -35,6 +31,9 @@ if settings.DEBUG:
url(r'^docs', include('rest_framework_docs.urls')), ]
urlpatterns = [
url(r'^api/', include(sapl.api.materia.urls)),
url(r'^api/', include(sapl.api.sessao.urls)),
url(r'^api/', include(sapl.api.base.urls)),
url(r'^api/', include(urlpatterns_api)),
url(r'^api/', include(urlpatterns_router))
]

254
sapl/api/views.py

@ -1,25 +1,12 @@
from django.apps import apps
from django.contrib.contenttypes.models import ContentType
from django.db.models import Q
from django.http import Http404
from django.utils.translation import ugettext_lazy as _
from rest_framework.filters import DjangoFilterBackend
from rest_framework.generics import ListAPIView
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
from rest_framework.permissions import (AllowAny, IsAuthenticated,
IsAuthenticatedOrReadOnly)
from rest_framework.viewsets import GenericViewSet
from rest_framework.permissions import (IsAuthenticated, AllowAny)
from rest_framework.response import Response
from rest_framework.views import APIView
from sapl.api.forms import (AutorChoiceFilterSet, AutoresPossiveisFilterSet,
AutorSearchForFieldFilterSet)
from sapl.api.serializers import (AutorChoiceSerializer, AutorSerializer,
ChoiceSerializer,
MateriaLegislativaSerializer,
ModelChoiceSerializer,
SessaoPlenariaSerializer)
from sapl.base.models import Autor, TipoAutor
from sapl.materia.models import MateriaLegislativa
from sapl.sessao.models import SessaoPlenaria
from sapl.utils import SaplGenericRelation, sapl_logger
from sapl.api.serializers import ModelChoiceSerializer
from sapl.rules.apps import AppConfig
class ModelChoiceView(ListAPIView):
@ -43,232 +30,9 @@ class ModelChoiceView(ListAPIView):
return self.model.objects.all()
class AutorListView(ListAPIView):
"""
Listagem de Autores com filtro para autores cadastrados
e/ou possíveis autores.
class TimeRefreshDatabaseView(APIView):
- tr - tipo do resultado
Prepera Lista de Autores para 3 cenários distintos
- default = 1
= 1 -> para (value, text) usados geralmente
em combobox, radiobox, checkbox, etc com pesquisa básica
de Autores feita pelo django-filter
-> processo usado nas pesquisas, o mais usado.
= 3 -> Devolve instancias da classe Autor filtradas pelo
django-filter
- tipo - chave primária do Tipo de Autor a ser filtrado
- q - busca textual no nome do Autor ou em fields_search
declarados no field SaplGenericRelation das GenericFks
A busca textual acontece via django-filter com a
variável `tr` igual 1 ou 3. Em caso contrário,
o django-filter é desativado e a busca é feita
no model do ContentType associado ao tipo.
- q_0 / q_1 - q_0 é opcional e quando usado, faz o código ignorar "q"...
q_0 -> campos lookup a serem filtrados em qualquer Model
que implemente SaplGenericRelation
q_1 -> o valor que será pesquisado no lookup de q_0
q_0 e q_1 podem ser separados por ","... isso dará a
possibilidade de filtrar mais de um campo.
http://localhost:8000
/api/autor?tr=1&q_0=parlamentar_set__ativo&q_1=False
/api/autor?tr=1&q_0=parlamentar_set__ativo&q_1=True
/api/autor?tr=3&q_0=parlamentar_set__ativo&q_1=False
/api/autor?tr=3&q_0=parlamentar_set__ativo&q_1=True
http://localhost:8000
/api/autor?tr=1
&q_0=parlamentar_set__nome_parlamentar__icontains,
parlamentar_set__ativo
&q_1=Carvalho,False
/api/autor?tr=1
&q_0=parlamentar_set__nome_parlamentar__icontains,
parlamentar_set__ativo
&q_1=Carvalho,True
/api/autor?tr=3
&q_0=parlamentar_set__nome_parlamentar__icontains,
parlamentar_set__ativo
&q_1=Carvalho,False
/api/autor?tr=3
&q_0=parlamentar_set__nome_parlamentar__icontains,
parlamentar_set__ativo
&q_1=Carvalho,True
não importa o campo que vc passe de qualquer dos Models
ligados... é possível ver que models são esses,
na ocasião do commit deste texto, executando:
In [6]: from sapl.utils import models_with_gr_for_model
In [7]: models_with_gr_for_model(Autor)
Out[7]:
[sapl.parlamentares.models.Parlamentar,
sapl.parlamentares.models.Frente,
sapl.comissoes.models.Comissao,
sapl.materia.models.Orgao,
sapl.sessao.models.Bancada,
sapl.sessao.models.Bloco]
qualquer atributo destes models podem ser passados
para busca
"""
TR_AUTOR_CHOICE_SERIALIZER = 1
TR_AUTOR_SERIALIZER = 3
permission_classes = (IsAuthenticatedOrReadOnly,)
queryset = Autor.objects.all()
model = Autor
filter_class = AutorChoiceFilterSet
filter_backends = (DjangoFilterBackend, )
serializer_class = AutorChoiceSerializer
@property
def tr(self):
try:
tr = int(self.request.GET.get
('tr', AutorListView.TR_AUTOR_CHOICE_SERIALIZER))
assert tr in (
AutorListView.TR_AUTOR_CHOICE_SERIALIZER,
AutorListView.TR_AUTOR_SERIALIZER), sapl_logger.info(
_("Tipo do Resultado a ser fornecido não existe!"))
except:
return AutorListView.TR_AUTOR_CHOICE_SERIALIZER
else:
return tr
permission_classes = (AllowAny,)
def get(self, request, *args, **kwargs):
if self.tr == AutorListView.TR_AUTOR_SERIALIZER:
self.serializer_class = AutorSerializer
self.permission_classes = (IsAuthenticated,)
if self.filter_class and 'q_0' in request.GET:
self.filter_class = AutorSearchForFieldFilterSet
return ListAPIView.get(self, request, *args, **kwargs)
class AutoresProvaveisListView(ListAPIView):
permission_classes = (IsAuthenticatedOrReadOnly,)
queryset = Autor.objects.all()
model = Autor
filter_class = None
filter_backends = []
serializer_class = ChoiceSerializer
def get_queryset(self):
params = {'content_type__isnull': False}
tipo = ''
try:
tipo = int(self.request.GET.get('tipo', ''))
if tipo:
params['id'] = tipo
except:
pass
tipos = TipoAutor.objects.filter(**params)
if not tipos.exists() and tipo:
raise Http404()
r = []
for tipo in tipos:
q = self.request.GET.get('q', '').strip()
model_class = tipo.content_type.model_class()
fields = list(filter(
lambda field: isinstance(field, SaplGenericRelation) and
field.related_model == Autor,
model_class._meta.get_fields(include_hidden=True)))
"""
fields - é um array de SaplGenericRelation que deve possuir o
atributo fields_search. Verifique na documentação da classe
a estrutura de fields_search.
"""
assert len(fields) >= 1, (_(
'Não foi encontrado em %(model)s um atributo do tipo '
'SaplGenericRelation que use o model %(model_autor)s') % {
'model': model_class._meta.verbose_name,
'model_autor': Autor._meta.verbose_name})
qs = model_class.objects.all()
q_filter = Q()
if q:
for item in fields:
if item.related_model != Autor:
continue
q_fs = Q()
for field in item.fields_search:
q_fs = q_fs | Q(**{'%s%s' % (
field[0],
field[1]): q})
q_filter = q_filter & q_fs
qs = qs.filter(q_filter).distinct(
fields[0].fields_search[0][0]).order_by(
fields[0].fields_search[0][0])
else:
qs = qs.order_by(fields[0].fields_search[0][0])
qs = qs.values_list(
'id', fields[0].fields_search[0][0])
r += list(qs)
if tipos.count() > 1:
r.sort(key=lambda x: x[1].upper())
return r
class AutoresPossiveisListView(ListAPIView):
permission_classes = (IsAuthenticatedOrReadOnly,)
queryset = Autor.objects.all()
model = Autor
pagination_class = None
filter_class = AutoresPossiveisFilterSet
serializer_class = AutorChoiceSerializer
class MateriaLegislativaViewSet(ListModelMixin,
RetrieveModelMixin,
GenericViewSet):
permission_classes = (IsAuthenticated,)
serializer_class = MateriaLegislativaSerializer
queryset = MateriaLegislativa.objects.all()
filter_backends = (DjangoFilterBackend,)
filter_fields = ('numero', 'ano', 'tipo', )
class SessaoPlenariaViewSet(ListModelMixin,
RetrieveModelMixin,
GenericViewSet):
permission_classes = (AllowAny,)
serializer_class = SessaoPlenariaSerializer
queryset = SessaoPlenaria.objects.all()
filter_backends = (DjangoFilterBackend,)
filter_fields = ('data_inicio', 'data_fim', 'interativa')
return Response({'last_global_refresh_time': apps.get_app_config('rules').time_refresh})

9
sapl/crud/base.py

@ -17,8 +17,8 @@ from django.http.response import Http404
from django.shortcuts import redirect
from django.utils.decorators import classonlymethod
from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import string_concat
from django.utils.translation import ugettext_lazy as _
from django.views.generic import (CreateView, DeleteView, DetailView, ListView,
UpdateView)
from django.views.generic.base import ContextMixin
@ -30,6 +30,7 @@ from sapl.rules.map_rules import (RP_ADD, RP_CHANGE, RP_DELETE, RP_DETAIL,
from sapl.settings import BASE_DIR
from sapl.utils import normalize
logger = logging.getLogger(BASE_DIR.name)
ACTION_LIST, ACTION_CREATE, ACTION_DETAIL, ACTION_UPDATE, ACTION_DELETE = \
@ -411,9 +412,12 @@ class CrudListView(PermissionRequiredContainerCrudMixin, ListView):
m = self.model
fn = fn.split('__')
for f in fn:
if not f:
continue
f = m._meta.get_field(f)
if hasattr(f, 'related_model') and f.related_model:
m = f.related_model
if f:
s.append(force_text(f.verbose_name))
s = ' / '.join(s)
r.append(s)
@ -440,6 +444,9 @@ class CrudListView(PermissionRequiredContainerCrudMixin, ListView):
if isinstance(name, tuple):
s = ''
for j, n in enumerate(name):
if not n:
s += '<br>'
continue
m = obj
n = n.split('__')
for f in n[:-1]:

10
sapl/rules/apps.py

@ -6,7 +6,10 @@ from django.contrib.auth import get_user_model
from django.contrib.auth.management import _get_all_permissions
from django.core import exceptions
from django.db import models, router
from django.db.models.signals import post_save, post_delete
from django.db.utils import DEFAULT_DB_ALIAS
from django.dispatch.dispatcher import receiver
from django.utils import timezone
from django.utils.translation import string_concat
from django.utils.translation import ugettext_lazy as _
import reversion
@ -21,6 +24,7 @@ class AppConfig(django.apps.AppConfig):
name = 'sapl.rules'
label = 'rules'
verbose_name = _('Regras de Acesso')
time_refresh = timezone.now()
def create_proxy_permissions(
@ -254,3 +258,9 @@ models.signals.post_migrate.connect(
models.signals.pre_delete.connect(
receiver=revision_pre_delete_signal,
dispatch_uid="pre_delete_signal")
@receiver([post_save, post_delete])
def refresh_time_update_base(sender, instance, **kwargs):
rule_app = apps.get_app_config('rules')
rule_app.time_refresh = timezone.now()

12
sapl/sessao/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, Fieldset, Layout
from django import forms
@ -9,6 +8,7 @@ from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.db import transaction
from django.forms import ModelForm
from django.utils.translation import ugettext_lazy as _
import django_filters
from sapl.base.models import Autor, TipoAutor
from sapl.crispy_layout_mixin import form_actions, to_row
@ -98,7 +98,6 @@ class SessaoPlenariaForm(ModelForm):
else: # create
raise error
# Condições da verificação
abertura_entre_leg = leg.data_inicio <= abertura <= leg.data_fim
abertura_entre_sl = sl.data_inicio <= abertura <= sl.data_fim
@ -112,7 +111,8 @@ class SessaoPlenariaForm(ModelForm):
if encerramento < abertura:
raise ValidationError("A data de encerramento não pode ser "
"anterior a data de abertura.")
# Verifica se a data de abertura está entre a data de início e fim da legislatura
# Verifica se a data de abertura está entre a data de início e fim
# da legislatura
if abertura_entre_leg and encerramento_entre_leg:
if abertura_entre_sl and encerramento_entre_sl:
pass
@ -164,7 +164,6 @@ class SessaoPlenariaForm(ModelForm):
"datas de início e fim tanto Legislatura "
"quanto da Sessão Legislativa.")
# Verificações com a data de encerramento vazia
else:
if abertura_entre_leg:
@ -454,7 +453,6 @@ class SessaoPlenariaFilterSet(django_filters.FilterSet):
# pré-popula o campo do formulário com o ano corrente
self.form.fields['data_inicio__year'].initial = timezone.now().year
row1 = to_row(
[('data_inicio__year', 3),
('data_inicio__month', 3),
@ -569,7 +567,8 @@ class OradorExpedienteForm(ModelForm):
def __init__(self, *args, **kwargs):
super(OradorExpedienteForm, self).__init__(*args, **kwargs)
legislatura_vigente = SessaoPlenaria.objects.get(pk=kwargs['initial']['id_sessao']).legislatura
legislatura_vigente = SessaoPlenaria.objects.get(
pk=kwargs['initial']['id_sessao']).legislatura
if legislatura_vigente:
self.fields['parlamentar'].queryset = \
@ -597,7 +596,6 @@ class OradorExpedienteForm(ModelForm):
return self.cleaned_data
class Meta:
model = OradorExpediente
exclude = ['sessao_plenaria']

37
sapl/sessao/migrations/0023_auto_20180914_1315.py

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-09-14 16:15
from __future__ import unicode_literals
from django.db import migrations, models
def limpa_observacao_igual_ementa(apps, schema_editor):
ExpedienteMateria = apps.get_model('sessao', 'ExpedienteMateria')
OrdemDia = apps.get_model('sessao', 'OrdemDia')
q = models.Q(observacao__iexact=models.F('materia__ementa'))
ExpedienteMateria.objects.filter(q).update(observacao='')
OrdemDia.objects.filter(q).update(observacao='')
class Migration(migrations.Migration):
dependencies = [
('sessao', '0022_auto_20180618_1625'),
]
operations = [
migrations.AlterField(
model_name='expedientemateria',
name='observacao',
field=models.TextField(blank=True, verbose_name='Observação'),
),
migrations.AlterField(
model_name='ordemdia',
name='observacao',
field=models.TextField(blank=True, verbose_name='Observação'),
),
migrations.RunPython(limpa_observacao_igual_ementa),
]

8
sapl/sessao/models.py

@ -1,10 +1,10 @@
from operator import xor
import reversion
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import ugettext_lazy as _
from model_utils import Choices
import reversion
from sapl.base.models import Autor
from sapl.materia.models import MateriaLegislativa
@ -237,7 +237,7 @@ class AbstractOrdemDia(models.Model):
verbose_name=_('Matéria'))
data_ordem = models.DateField(verbose_name=_('Data da Sessão'))
observacao = models.TextField(
blank=True, verbose_name=_('Ementa'))
blank=True, verbose_name=_('Observação'))
numero_ordem = models.PositiveIntegerField(verbose_name=_('Nº Ordem'))
resultado = models.TextField(blank=True, verbose_name=_('Resultado'))
tipo_votacao = models.PositiveIntegerField(
@ -254,6 +254,10 @@ class AbstractOrdemDia(models.Model):
class Meta:
abstract = True
@property
def ementa(self):
return self.materia.ementa
def __str__(self):
return 'Ordem do Dia/Expediente: %s - %s em %s' % (
self.numero_ordem, self.materia, self.sessao_plenaria)

16
sapl/sessao/serializers.py

@ -1,19 +1,3 @@
from rest_framework import serializers
from .models import SessaoPlenaria
class SessaoPlenariaSerializer(serializers.Serializer):
class Meta:
model = SessaoPlenaria
fields = ('tipo',
'sessao_legislativa',
'legislatura',
'data_inicio',
'hora_inicio',
'hora_fim',
'url_video',
'iniciada',
'finalizada'
)

56
sapl/sessao/views.py

@ -1,5 +1,5 @@
from re import sub
from operator import itemgetter
from re import sub
from django.contrib import messages
from django.contrib.auth.decorators import permission_required
@ -49,6 +49,7 @@ from .models import (Bancada, Bloco, CargoBancada, CargoMesa,
SessaoPlenaria, SessaoPlenariaPresenca, TipoExpediente,
TipoResultadoVotacao, TipoSessaoPlenaria, VotoParlamentar)
TipoSessaoCrud = CrudAux.build(TipoSessaoPlenaria, 'tipo_sessao_plenaria')
TipoExpedienteCrud = CrudAux.build(TipoExpediente, 'tipo_expediente')
CargoBancadaCrud = CrudAux.build(CargoBancada, '')
@ -389,7 +390,8 @@ def get_presencas_generic(model, sessao, legislatura):
presentes = [p.parlamentar for p in presencas]
presentes = sorted(presentes, key=lambda x: remover_acentos(x.nome_parlamentar))
presentes = sorted(
presentes, key=lambda x: remover_acentos(x.nome_parlamentar))
mandato = Mandato.objects.filter(
legislatura=legislatura).order_by('parlamentar__nome_parlamentar')
@ -408,7 +410,8 @@ class MateriaOrdemDiaCrud(MasterDetailCrud):
public = [RP_LIST, RP_DETAIL]
class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['numero_ordem', 'materia', 'materia__ementa',
list_field_names = ['numero_ordem', 'materia',
('materia__ementa', '', 'observacao'),
'resultado']
class CreateView(MasterDetailCrud.CreateView):
@ -439,17 +442,18 @@ class MateriaOrdemDiaCrud(MasterDetailCrud):
return initial
class DetailView(MasterDetailCrud.DetailView):
layout_key = 'OrdemDiaDetail'
class ListView(MasterDetailCrud.ListView):
paginate_by = None
ordering = ['numero_ordem', 'materia', 'resultado']
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
has_permition = self.request.user.has_module_perms(AppConfig.label)
return customize_link_materia(context, self.kwargs['pk'], has_permition, False)
def recuperar_materia(request):
tipo = TipoMateriaLegislativa.objects.get(pk=request.GET['tipo_materia'])
numero = request.GET['numero_materia']
@ -476,7 +480,8 @@ class ExpedienteMateriaCrud(MasterDetailCrud):
class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['numero_ordem', 'materia',
'materia__ementa', 'resultado']
('materia__ementa', '', 'observacao'),
'resultado']
class ListView(MasterDetailCrud.ListView):
paginate_by = None
@ -544,7 +549,6 @@ class OradorExpedienteCrud(OradorCrud):
return reverse('sapl.sessao:oradorexpediente_list',
kwargs={'pk': self.kwargs['pk']})
class UpdateView(MasterDetailCrud.UpdateView):
form_class = OradorExpedienteForm
@ -778,7 +782,8 @@ class PainelView(PermissionRequiredForAppCrudMixin, TemplateView):
cronometro_discurso = AppsAppConfig.attr('cronometro_discurso')
cronometro_aparte = AppsAppConfig.attr('cronometro_aparte')
cronometro_ordem = AppsAppConfig.attr('cronometro_ordem')
cronometro_consideracoes = AppsAppConfig.attr('cronometro_consideracoes')
cronometro_consideracoes = AppsAppConfig.attr(
'cronometro_consideracoes')
if (not cronometro_discurso or not cronometro_aparte
or not cronometro_ordem or not cronometro_consideracoes):
@ -999,15 +1004,18 @@ class MesaView(FormMixin, DetailView):
cargos_vagos = list(set(cargos) - set(cargos_ocupados))
# FIX-ME: tem formas melhores de fazer isso, poupando linhas.
parlamentares = Legislatura.objects.get(id=sessao.legislatura_id).mandato_set.all()
parlamentares = Legislatura.objects.get(
id=sessao.legislatura_id).mandato_set.all()
parlamentares_ocupados = [m.parlamentar for m in mesa]
parlamentares_vagos = list(
set(
[p.parlamentar for p in parlamentares]) - set(
parlamentares_ocupados))
org_parlamentares_vagos = parlamentares_vagos
org_parlamentares_vagos.sort(key=lambda x: remover_acentos(x.nome_parlamentar))
org_parlamentares_vagos = [p for p in org_parlamentares_vagos if p.ativo]
org_parlamentares_vagos.sort(
key=lambda x: remover_acentos(x.nome_parlamentar))
org_parlamentares_vagos = [
p for p in org_parlamentares_vagos if p.ativo]
# Se todos os cargos estiverem ocupados, a listagem de parlamentares
# deve ser renderizada vazia
if not cargos_vagos:
@ -1825,7 +1833,8 @@ class VotacaoNominalAbstract(SessaoPermissionMixin):
elif self.expediente:
expediente_id = kwargs['oid']
try:
materia_votacao = ExpedienteMateria.objects.get(id=expediente_id)
materia_votacao = ExpedienteMateria.objects.get(
id=expediente_id)
except ObjectDoesNotExist:
raise Http404()
@ -1923,7 +1932,8 @@ class VotacaoNominalAbstract(SessaoPermissionMixin):
return self.form_invalid(form)
def form_invalid(self, form):
errors_tuple = [(form[e].label, form.errors[e]) for e in form.errors if e in form.fields]
errors_tuple = [(form[e].label, form.errors[e])
for e in form.errors if e in form.fields]
error_message = '''<ul>'''
for e in errors_tuple:
error_message += '''<li><b>%s</b>: %s</li>''' % (e[0], e[1][0])
@ -2000,8 +2010,10 @@ class VotacaoNominalEditAbstract(SessaoPermissionMixin):
elif self.expediente:
expediente_id = kwargs['oid']
expediente = ExpedienteMateria.objects.filter(id=expediente_id).last()
votacao = RegistroVotacao.objects.filter(expediente_id=expediente_id).last()
expediente = ExpedienteMateria.objects.filter(
id=expediente_id).last()
votacao = RegistroVotacao.objects.filter(
expediente_id=expediente_id).last()
if not expediente or not votacao:
raise Http404()
@ -2120,9 +2132,11 @@ class VotacaoNominalTransparenciaDetailView(TemplateView):
materia_votacao = self.request.GET.get('materia', None)
if materia_votacao == 'ordem':
votacao = RegistroVotacao.objects.filter(ordem=self.kwargs['oid']).last()
votacao = RegistroVotacao.objects.filter(
ordem=self.kwargs['oid']).last()
elif materia_votacao == 'expediente':
votacao = RegistroVotacao.objects.filter(expediente=self.kwargs['oid']).last()
votacao = RegistroVotacao.objects.filter(
expediente=self.kwargs['oid']).last()
else:
raise Http404()
@ -2203,9 +2217,11 @@ class VotacaoSimbolicaTransparenciaDetailView(TemplateView):
materia_votacao = self.request.GET.get('materia', None)
if materia_votacao == 'ordem':
votacao = RegistroVotacao.objects.filter(ordem=self.kwargs['oid']).last()
votacao = RegistroVotacao.objects.filter(
ordem=self.kwargs['oid']).last()
elif materia_votacao == 'expediente':
votacao = RegistroVotacao.objects.filter(expediente=self.kwargs['oid']).last()
votacao = RegistroVotacao.objects.filter(
expediente=self.kwargs['oid']).last()
else:
raise Http404()
@ -2230,6 +2246,7 @@ class VotacaoSimbolicaTransparenciaDetailView(TemplateView):
for tipo in TipoResultadoVotacao.objects.all():
yield tipo
class VotacaoExpedienteView(SessaoPermissionMixin):
"""
@ -2413,7 +2430,8 @@ class VotacaoExpedienteEditView(SessaoPermissionMixin):
expediente_id = kwargs['oid']
if int(request.POST['anular_votacao']) == 1:
RegistroVotacao.objects.filter(expediente_id=expediente_id).delete()
RegistroVotacao.objects.filter(
expediente_id=expediente_id).delete()
expediente = ExpedienteMateria.objects.get(
sessao_plenaria_id=self.object.id,

2
sapl/templates/base/relatorios_list.html

@ -42,5 +42,5 @@
</tr>
</tbody>
</table>
</fieldset
</fieldset>
{% endblock base_content %}

19
sapl/templates/sessao/expedientemateria_form.html

@ -6,7 +6,7 @@
{% block extra_js %}
<script language="Javascript">
document.getElementById("id_observacao").readOnly = true;
//document.getElementById("id_observacao").readOnly = true;
function recuperar_materia() {
var tipo_materia = $("#id_tipo_materia").val()
@ -14,11 +14,21 @@
var ano_materia = $("#id_ano_materia").val()
if (tipo_materia && numero_materia && ano_materia) {
$.get("/sessao/recuperar-materia",{tipo_materia: tipo_materia,
$.get("/sessao/recuperar-materia", {
tipo_materia: tipo_materia,
numero_materia: numero_materia,
ano_materia: ano_materia},
ano_materia: ano_materia
},
function(data, status) {
$("#id_observacao").val(data.ementa);
if ($(".ementa-materia").length === 0) {
$("#div_id_tipo_materia").closest('.row-fluid').after(
$('<div class="row-fluid"/>').append(
$('<div class="col-xs-12"/>').append(
$('<div class="alert alert-info ementa-materia"/>').html(data.ementa))))
}
else {
$('.ementa-materia').html(data.ementa)
}
});
}
}
@ -26,6 +36,7 @@
for (i = 0; i < fields.length; i++) {
$(fields[i]).change(recuperar_materia);
}
recuperar_materia()
</script>
{% endblock %}

2
sapl/templates/sessao/layouts.yaml

@ -56,12 +56,14 @@ OrdemDia:
ExpedienteMateriaDetail:
{% trans 'Matérias do Expediente' %}:
- materia
- ementa
- tipo_votacao
- observacao
OrdemDiaDetail:
{% trans 'Matérias da Ordem do Dia' %}:
- materia
- ementa
- tipo_votacao
- observacao

Loading…
Cancel
Save