Repository: interlegis/sapl

Issue:
Frente Parlamentar
Todos os Parlamentares ficam disponíveis para serem marcados na composição da frente, penso que uma solução seria a mesma encontrada pelo cristian-longhi para presenças nas sessões
Inclusão de autoria de matéria legislativa: Filtrar nomes por tipo de autor
No 2.5, ao incluir o autor de uma matéria, o sistema apresenta os campos Tipo e Nome, com o segundo oferendo opões de acordo com o Tipo. O 3.1 está apresentando, no campo Nome, todos os possíveis, independentemente de tipo.
![captura de tela de 2017-07-10 16 02 12](https://user-images.githubusercontent.com/19169882/28035192-16e57dee-658a-11e7-8f91-375dff2fab77.png)
![captura de tela de 2017-07-10 16 07 08](https://user-images.githubusercontent.com/19169882/28035195-1c79172a-658a-11e7-9299-6e4e6bdfae72.png)




Discussion:
@DtiLegBG, pode especificar melhor o problema? (se tiver imagens melhor ainda)
Claro, todos os parlamentares ficam disponíveis para serem incluídos na frente, inclusive os inativos. O cristian fez uma solução para esse mesmo problema onde todos os parlamentares ficaram disponíveis para inclusão na sessão ordinária. Ele colocou essa caixa...

![image](https://user-images.githubusercontent.com/13314947/27395850-97f36520-5687-11e7-8954-01369df3c711.png)



Resolving patch:
diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py
--- a/sapl/materia/forms.py
+++ b/sapl/materia/forms.py
@@ -723,8 +723,16 @@ def clean(self):
             materia=self.instance.materia,
             autor=self.cleaned_data['autor'],
         ).exists():
-            msg = _('Esse Autor já foi cadastrado.')
-            raise ValidationError(msg)
+            if not self.instance.pk:
+                msg = _('Esse Autor já foi cadastrado.')
+                raise ValidationError(msg)
+            else:
+                autoria = Autoria.objects.get(
+                    materia=self.instance.materia,
+                    autor=self.cleaned_data['autor'])
+                if autoria != self.instance:
+                    msg = _('Esse Autor já foi cadastrado.')
+                    raise ValidationError(msg)
 
         return self.cleaned_data
 
diff --git a/sapl/materia/urls.py b/sapl/materia/urls.py
--- a/sapl/materia/urls.py
+++ b/sapl/materia/urls.py
@@ -21,6 +21,7 @@
                                 TipoFimRelatoriaCrud, TipoMateriaCrud,
                                 TipoProposicaoCrud, TramitacaoCrud,
                                 TramitacaoEmLoteView, UnidadeTramitacaoCrud,
+                                atualizar_autores,
                                 proposicao_texto, recuperar_materia)
 
 from .apps import AppConfig
@@ -41,6 +42,10 @@
                               RelatoriaCrud.get_urls() +
                               DocumentoAcessorioCrud.get_urls())),
 
+    url(r'^materia/autoria/atualizar-autores$',
+            atualizar_autores,
+            name='atualizar_autores'),
+
     url(r'^materia/(?P<pk>[0-9]+)/create_simplificado$',
         CriarProtocoloMateriaView.as_view(),
         name='materia_create_simplificado'),
diff --git a/sapl/materia/views.py b/sapl/materia/views.py
--- a/sapl/materia/views.py
+++ b/sapl/materia/views.py
@@ -40,7 +40,7 @@
 from django.views.generic.edit import FormView
 from django_filters.views import FilterView
 import sapl
-from sapl.base.models import Autor, CasaLegislativa
+from sapl.base.models import Autor, CasaLegislativa, TipoAutor
 from sapl.comissoes.models import Comissao
 from sapl.comissoes.models import Comissao, Participacao
 from sapl.compilacao.models import (STATUS_TA_IMMUTABLE_RESTRICT,
@@ -57,8 +57,9 @@
                                 TramitacaoUpdateForm)
 from sapl.materia.models import Autor
 from sapl.norma.models import LegislacaoCitada
-from sapl.parlamentares.models import Parlamentar
+from sapl.parlamentares.models import Frente, Mandato, Parlamentar
 from sapl.protocoloadm.models import Protocolo
+from sapl.sessao.models import Bancada, Bloco
 from sapl.utils import (TURNO_TRAMITACAO_CHOICES, YES_NO_CHOICES, autor_label,
                         autor_modal, gerar_hash_arquivo, get_base_url,
                         montar_row_autor)
@@ -1080,6 +1081,151 @@ def get_context_data(self, **kwargs):
             return context
 
 
+def filtra_ativos(content_type, materia):
+    if content_type.model_class() == Parlamentar:
+        mandatos_ativos = Mandato.objects.filter(Q(
+            data_inicio_mandato__lte=materia.data_apresentacao,
+            data_fim_mandato__isnull=True) | Q(
+            data_inicio_mandato__lte=materia.data_apresentacao,
+            data_fim_mandato__gte=materia.data_apresentacao)
+        ).values_list('parlamentar_id', flat=True).distinct('parlamentar_id')
+
+        return Autor.objects.filter(
+            content_type=content_type,
+            object_id__in=mandatos_ativos)
+
+    elif content_type.model_class() == Comissao:
+        comissoes = Comissao.objects.filter(
+            data_criacao__lte=materia.data_apresentacao)
+        comissoes_id = comissoes.filter(Q(
+            data_extincao__isnull=True,
+            data_fim_comissao__isnull=True) | Q(
+            data_extincao__gte=materia.data_apresentacao,
+            data_fim_comissao__isnull=True) | Q(
+            data_extincao__gte=materia.data_apresentacao,
+            data_fim_comissao__isnull=True) | Q(
+            data_extincao__isnull=True,
+            data_fim_comissao__gte=materia.data_apresentacao) | Q(
+            data_extincao__gte=materia.data_apresentacao,
+            data_fim_comissao__gte=materia.data_apresentacao)).values_list(
+            'id', flat=True).distinct()
+
+        return Autor.objects.filter(
+            content_type=content_type,
+            object_id__in=comissoes_id)
+
+    elif content_type.model_class() == Frente:
+        frentes = Frente.objects.filter(
+            data_criacao__lte=materia.data_apresentacao)
+        frentes_id = frentes.filter(Q(
+            data_extincao__isnull=True) | Q(
+            data_extincao__gte=materia.data_apresentacao)).values_list(
+            'id', flat=True).distinct()
+
+        return Autor.objects.filter(
+            content_type=content_type,
+            object_id__in=frentes_id)
+
+    elif content_type.model_class() == Bancada:
+        bancadas = Bancada.objects.filter(
+            data_criacao__lte=materia.data_apresentacao)
+        bancadas_id = bancadas.filter(Q(
+            data_extincao__isnull=True) | Q(
+            data_extincao__gte=materia.data_apresentacao)).values_list(
+            'id', flat=True).distinct()
+
+        return Autor.objects.filter(
+            content_type=content_type,
+            object_id__in=bancadas_id)
+
+    elif content_type.model_class() == Bloco:
+        blocos = Bloco.objects.filter(
+            data_criacao__lte=materia.data_apresentacao)
+        blocos_id = blocos.filter(Q(
+            data_extincao__isnull=True) | Q(
+            data_extincao__gte=materia.data_apresentacao)).values_list(
+            'id', flat=True).distinct()
+
+        return Autor.objects.filter(
+            content_type=content_type,
+            object_id__in=blocos_id)
+
+    elif content_type.model_class() == Orgao:
+        orgaos_id = Orgao.objects.values_list('id', flat=True)
+
+        return Autor.objects.filter(
+            content_type=content_type,
+            object_id__in=orgaos_id)
+
+
+def autores_ativos(materia, tipo=None):
+    """
+    :param materia: é a matéria para na qual a Autoria será inserida
+    :param tipo: é o tipo de autor que foi selecionado
+    :return: Lista dos autores ativos disponíveis para serem inseridos
+    na matéria em questão.
+    Primeiramente são inseridos em uma lista uma tupla relacionando
+    cada TipoAutor ao seu ContentType. Posteriormente, para cada elemento
+    dessa lista são filtrados os autores ativos para aquele ContentType e,
+    por convêniencia, inseridos em um dicionário no qual a chave é o id
+    do TipoAutor. Após isso, com a chave 'others' são inseridos os Autores
+    os quais seu TipoAutor não possui ContentType.
+    """
+
+    content_types_list = []
+    for ta in TipoAutor.objects.all():
+        if ta.content_type:
+            content_types_list.append((ta.content_type, ta))
+
+    autores_by_ct = {}
+    for ct, ta in content_types_list:
+        autores_by_ct[str(ta.id)] = filtra_ativos(ct, materia)
+
+    ct_list = [c[0] for c in content_types_list]
+    autores_by_ct['others'] = Autor.objects.exclude(
+        content_type__in=ct_list).order_by(
+        'nome'
+    )
+
+    if not tipo:
+        autor_qs = Autor.objects.none()
+        for key in autores_by_ct:
+            autor_qs = autor_qs | autores_by_ct[key]
+
+        return (autor_qs | autores_by_ct['others']).order_by('nome')
+
+    else:
+        if not tipo in autores_by_ct:
+            return autores_by_ct['others'].filter(
+                tipo_id=tipo).order_by('nome')
+
+        return autores_by_ct[tipo].order_by('nome')
+
+
+def atualizar_autores(request):
+    if 'materia_id' in request.GET and request.GET['materia_id']:
+        materia_id = int(request.GET['materia_id'])
+
+        try:
+            materia = MateriaLegislativa.objects.get(id=materia_id)
+        except ObjectDoesNotExist:
+            pass
+        else:
+            if 'tipo_autor' in request.GET and request.GET['tipo_autor']:
+                tipo_autor = request.GET['tipo_autor']
+                autores = autores_ativos(materia, tipo=tipo_autor)
+
+            else:
+                autores = autores_ativos(materia)
+
+            empty_option = [('', '---------')]
+            autores_list = [(a.id, a.__str__()) for a in autores]
+
+            return JsonResponse({'lista_autores': empty_option + autores_list})
+
+    return JsonResponse({})
+
+
 class AutoriaCrud(MasterDetailCrud):
     model = Autoria
     parent_field = 'materia'
@@ -1095,24 +1241,67 @@ def layout_key(self):
 
         def get_context_data(self, **kwargs):
             context = super(CreateView, self).get_context_data(**kwargs)
-            autores_ativos = self.autores_ativos()
+
+            materia = MateriaLegislativa.objects.get(
+                id=int(kwargs['root_pk']))
+
+            if context['form']['tipo_autor'].data:
+                autores_ativos_list = autores_ativos(
+                    materia,
+                    context['form']['tipo_autor'].data
+                )
+            else:
+                autores_ativos_list = autores_ativos(materia)
 
             autores = []
+            for a in autores_ativos_list:
+                autores.append([a.id, a.__str__()])
 
-            context['form'].fields['autor'].choices = autores
+            empty_option = [('', '---------')]
+            context['form'].fields['autor'].choices = empty_option + autores
             return context
 
-        def autores_ativos(self):
-            lista_parlamentares = Parlamentar.objects.filter(ativo=True).values_list('id', flat=True)
-            model_parlamentar = ContentType.objects.get_for_model(Parlamentar)
-            autor_parlamentar = Autor.objects.filter(content_type=model_parlamentar, object_id__in=lista_parlamentares)
-
-            lista_comissoes = Comissao.objects.filter(Q(data_extincao__isnull=True)|Q(data_extincao__gt=date.today())).values_list('id', flat=True)
-            model_comissao = ContentType.objects.get_for_model(Comissao)
-            autor_comissoes = Autor.objects.filter(content_type=model_comissao, object_id__in=lista_comissoes)
-            autores_outros = Autor.objects.exclude(content_type__in=[model_parlamentar, model_comissao])
-            q = autor_parlamentar | autor_comissoes | autores_outros
-            return q
+    class UpdateView(MasterDetailCrud.UpdateView):
+        form_class = AutoriaForm
+
+        @property
+        def layout_key(self):
+            return 'AutoriaUpdate'
+
+        def get_initial(self):
+            return {
+                'tipo_autor': self.object.autor.tipo.id,
+                'autor': self.object.autor.id,
+                'primeiro_autor': self.object.primeiro_autor
+            }
+
+        def get_context_data(self, **kwargs):
+            context = super(UpdateView, self).get_context_data(**kwargs)
+
+            materia = MateriaLegislativa.objects.get(
+                id=int(kwargs['root_pk']))
+
+            if context['form']['tipo_autor'].data is None:
+                autores_ativos_list = autores_ativos(
+                    materia,
+                    str(context['object'].autor.tipo.id))
+            else:
+                if context['form']['tipo_autor'].data == '':
+                    autores_ativos_list = autores_ativos(
+                        materia)
+                else:
+                    autores_ativos_list = autores_ativos(
+                        materia,
+                        context['form']['tipo_autor'].data)
+
+            autores = []
+            for a in autores_ativos_list:
+                autores.append([a.id, a.__str__()])
+
+            empty_option = [('', '---------')]
+            context['form'].fields['autor'].choices = empty_option + autores
+
+            return context
 
     class ListView(MasterDetailCrud.ListView):
 


Test patch: