Repository: interlegis/sapl

Issue:
Refatora pesquisa Protocolo django filter
A outra tela -- além de Pesquisa Matéria -- que pode se valer do django-filter e éssa de Pesquisa Protocolo. De fato, ela é até mais simples que a de Pesquisa Matéria em termos de número de campos, valores possíveis, etc.

PS: Lembrando que se existe alguma outra tela -- além dessas duas --, não foi portada para o SAPL31, que eu saiba.



Discussion:
@eduardocalil se vc quiser pegar essa issue, sinta-se a vontade, já q vc fez a outra pesquisa. Não se sinta obrigado, entretanto.


Resolving patch:
diff --git a/protocoloadm/forms.py b/protocoloadm/forms.py
--- a/protocoloadm/forms.py
+++ b/protocoloadm/forms.py
@@ -1,110 +1,112 @@
-from datetime import date
-
+import django_filters
 from crispy_forms.bootstrap import InlineRadios
 from crispy_forms.helper import FormHelper
 from crispy_forms.layout import HTML, Button, Field, Fieldset, Layout, Submit
 from django import forms
 from django.core.exceptions import ObjectDoesNotExist
+from django.db import models
 from django.forms import ModelForm
 from django.utils.translation import ugettext_lazy as _
 
 import crispy_layout_mixin
 import sapl
 from crispy_layout_mixin import form_actions
-from materia.models import Autor, TipoMateriaLegislativa
+from materia.forms import RangeWidgetOverride
+from materia.models import Autor
 from sapl.utils import RANGE_ANOS
 
 from .models import (DocumentoAcessorioAdministrativo, DocumentoAdministrativo,
                      Protocolo, TipoDocumentoAdministrativo,
                      TramitacaoAdministrativo)
 
-TIPOS_PROTOCOLO = [('0', 'Enviado'), ('1', 'Recebido')]
+TIPOS_PROTOCOLO = [('0', 'Enviado'), ('1', 'Recebido'), ('', 'Ambos')]
 
 NATUREZA_PROCESSO = [('0', 'Administrativo'),
                      ('1', 'Legislativo'),
                      ('', 'Ambos')]
 
 
-def get_range_anos():
-    return [('', 'Selecione')] \
-        + [(year, year) for year in range(date.today().year, 1960, -1)]
-
+ANO_CHOICES = [('', '---------')] + RANGE_ANOS
 
-class ProtocoloForm(forms.Form):
 
-    YEARS = get_range_anos()
+class ProtocoloFilterSet(django_filters.FilterSet):
 
-    tipo_protocolo = forms.ChoiceField(required=False,
-                                       label='Tipo de Protocolo',
-                                       choices=TIPOS_PROTOCOLO,
-                                       widget=forms.Select(
-                                           attrs={'class': 'selector'}))
+    filter_overrides = {models.DateField: {
+        'filter_class': django_filters.DateFromToRangeFilter,
+        'extra': lambda f: {
+            'label': 'Data (%s)' % (_('Inicial - Final')),
+            'widget': RangeWidgetOverride}
+    }}
 
-    numero_protocolo = forms.CharField(
-        label='Número de Protocolo', required=False)
+    ano = django_filters.ChoiceFilter(required=False,
+                                      label=u'Ano da Matéria',
+                                      choices=ANO_CHOICES)
 
-    ano = forms.ChoiceField(required=False,
-                            label='Ano',
-                            choices=YEARS,
-                            widget=forms.Select(
-                                attrs={'class': 'selector'}))
+    assunto_ementa = django_filters.CharFilter(lookup_expr='icontains')
 
-    inicial = forms.DateField(label='Data Inicial',
-                              required=False,
-                              widget=forms.TextInput(
-                                  attrs={'class': 'dateinput'}))
+    interessado = django_filters.CharFilter(lookup_expr='icontains')
 
-    final = forms.DateField(label='Data Final', required=False,
-                            widget=forms.TextInput(
-                                attrs={'class': 'dateinput'}))
+    autor = django_filters.CharFilter(widget=forms.HiddenInput())
 
-    natureza_processo = forms.ChoiceField(required=False,
-                                          label='Natureza Processo',
-                                          choices=[
-                                              ('0', 'Administrativo'),
-                                              ('1', 'Legislativo'),
-                                              ('', 'Ambos')])
+    tipo_protocolo = django_filters.ChoiceFilter(required=False,
+                                                 label='Tipo de Protocolo',
+                                                 choices=TIPOS_PROTOCOLO,
+                                                 widget=forms.Select(
+                                                  attrs={'class': 'selector'}))
 
-    tipo_documento = forms.ModelChoiceField(
-        label='Tipo de Documento',
-        required=False,
-        queryset=TipoDocumentoAdministrativo.objects.all(),
-        empty_label='Selecione',
-    )
-
-    interessado = forms.CharField(label='Interessado', required=False)
+    class Meta:
+        model = Protocolo
+        fields = ['numero',
+                  'tipo_documento',
+                  'data',
+                  'tipo_materia',
+                  ]
 
-    tipo_materia = forms.ModelChoiceField(
-        label='Tipo de Matéria',
-        required=False,
-        queryset=TipoMateriaLegislativa.objects.all(),
-        empty_label='Selecione',
-    )
+        order_by = (
+            ('', 'Selecione'),
+            ('CRE', 'Ordem Crescente'),
+            ('DEC', 'Ordem Decrescente'),
+        )
 
-    autor = forms.CharField(widget=forms.HiddenInput(), required=False)
+    order_by_mapping = {
+        '': [],
+        'CRE': ['ano', 'numero'],
+        'DEC': ['-ano', '-numero'],
+    }
 
-    assunto = forms.CharField(label='Assunto', required=False)
+    def get_order_by(self, order_value):
+        if order_value in self.order_by_mapping:
+            return self.order_by_mapping[order_value]
+        else:
+            return super(ProtocoloFilterSet,
+                         self).get_order_by(order_value)
 
     def __init__(self, *args, **kwargs):
+        super(ProtocoloFilterSet, self).__init__(*args, **kwargs)
+
+        self.filters['autor'].label = 'Tipo de Matéria'
+        self.filters['assunto_ementa'].label = 'Assunto'
 
         row1 = crispy_layout_mixin.to_row(
-            [('numero_protocolo', 6),
-             ('ano', 6)])
+            [('numero', 4),
+             ('ano', 4),
+             ('data', 4)])
 
         row2 = crispy_layout_mixin.to_row(
-            [('inicial', 6),
-             ('final', 6)])
+            [('tipo_documento', 4),
+             ('tipo_protocolo', 4),
+             ('tipo_materia', 4)])
 
         row3 = crispy_layout_mixin.to_row(
             [('tipo_documento', 4),
              ('tipo_protocolo', 4),
              ('tipo_materia', 4)])
 
-        row4 = crispy_layout_mixin.to_row(
+        row3 = crispy_layout_mixin.to_row(
             [('interessado', 6),
-             ('assunto', 6)])
+             ('assunto_ementa', 6)])
 
-        row5 = crispy_layout_mixin.to_row(
+        row4 = crispy_layout_mixin.to_row(
                  [('autor', 0),
                   (Button('pesquisar',
                           'Pesquisar Autor',
@@ -112,21 +114,20 @@ def __init__(self, *args, **kwargs):
                   (Button('limpar',
                           'Limpar Autor',
                           css_class='btn btn-primary btn-sm'), 10)])
+        row5 = crispy_layout_mixin.to_row(
+            [('o', 12)])
 
-        row6 = crispy_layout_mixin.to_row(
-            [('natureza_processo', 12)])
-
-        self.helper = FormHelper()
-        self.helper.layout = Layout(Fieldset(_('Pesquisar Protocolo'),
-                                    row1, row2,
-                                    row3, row4,
-                                    HTML(sapl.utils.autor_label),
-                                    HTML(sapl.utils.autor_modal),
-                                    row5,
-                                    row6,
-                                    form_actions(save_label='Pesquisar')))
-        super(ProtocoloForm, self).__init__(
-            *args, **kwargs)
+        self.form.helper = FormHelper()
+        self.form.helper.form_method = 'GET'
+        self.form.helper.layout = Layout(
+            Fieldset(_('Pesquisar Protocolo'),
+                     row1, row2,
+                     row3,
+                     HTML(sapl.utils.autor_label),
+                     HTML(sapl.utils.autor_modal),
+                     row4, row5,
+                     form_actions(save_label='Pesquisar'))
+            )
 
 
 class AnularProcoloAdmForm(ModelForm):
diff --git a/protocoloadm/views.py b/protocoloadm/views.py
--- a/protocoloadm/views.py
+++ b/protocoloadm/views.py
@@ -2,13 +2,14 @@
 from datetime import date, datetime
 
 from braces.views import FormValidMessageMixin
-from django.core.urlresolvers import reverse, reverse_lazy
+from django.core.urlresolvers import reverse
 from django.db.models import Q, Max
 from django.http import HttpResponse, HttpResponseRedirect
 from django.shortcuts import redirect
 from django.utils.translation import ugettext_lazy as _
 from django.views.generic import CreateView, DetailView, FormView, ListView
 from django.views.generic.base import TemplateView
+from django_filters.views import FilterView
 
 from crud.base import Crud, make_pagination
 from materia.models import Proposicao, TipoMateriaLegislativa
@@ -16,8 +17,8 @@
 
 from .forms import (AnularProcoloAdmForm, DocumentoAcessorioAdministrativoForm,
                     DocumentoAdministrativoForm, ProposicaoSimpleForm,
-                    ProtocoloDocumentForm, ProtocoloForm, ProtocoloMateriaForm,
-                    TramitacaoAdmForm)
+                    ProtocoloDocumentForm, ProtocoloFilterSet,
+                    ProtocoloMateriaForm, TramitacaoAdmForm)
 from .models import (Autor, DocumentoAcessorioAdministrativo,
                      DocumentoAdministrativo, Protocolo,
                      StatusTramitacaoAdministrativo,
@@ -37,57 +38,63 @@
 ProtocoloMateriaCrud = Crud.build(Protocolo, '')
 
 
-class ProtocoloPesquisaView(FormView):
-    template_name = 'protocoloadm/protocolo_pesquisa.html'
-    form_class = ProtocoloForm
-    context_object_name = 'protocolos'
-    success_url = reverse_lazy('protocoloadm:protocolo')
-
-    def post(self, request, *args, **kwargs):
-        form = ProtocoloForm(request.POST or None)
+class ProtocoloPesquisaView(FilterView):
+    model = Protocolo
+    filterset_class = ProtocoloFilterSet
+    paginate_by = 10
 
-        if form.is_valid():
-            kwargs = {}
+    def get_filterset_kwargs(self, filterset_class):
+        super(ProtocoloPesquisaView,
+              self).get_filterset_kwargs(filterset_class)
 
-            if request.POST['tipo_protocolo']:
-                kwargs['tipo_protocolo'] = request.POST['tipo_protocolo']
+        kwargs = {'data': self.request.GET or None}
 
-            if request.POST['numero_protocolo']:
-                kwargs['numero'] = request.POST['numero_protocolo']
+        qs = self.get_queryset()
 
-            if request.POST['ano']:
-                kwargs['ano'] = request.POST['ano']
+        qs = qs.distinct()
 
-            if request.POST['inicial']:
-                kwargs['data'] = datetime.strptime(
-                    request.POST['inicial'],
-                    '%d/%m/%Y').strftime('%Y-%m-%d')
+        kwargs.update({
+            'queryset': qs,
+        })
+        return kwargs
 
-            # if request.POST['final']:
-            #     kwargs['final'] = request.POST['final']
+    def get_context_data(self, **kwargs):
+        context = super(ProtocoloPesquisaView,
+                        self).get_context_data(**kwargs)
 
-            # if request.POST['natureza_processo']:
-            #  kwargs['natureza_processo'] = request.POST['natureza_processo']
+        paginator = context['paginator']
+        page_obj = context['page_obj']
 
-            if request.POST['tipo_documento']:
-                kwargs['tipo_documento'] = request.POST['tipo_documento']
+        context['page_range'] = make_pagination(
+            page_obj.number, paginator.num_pages)
 
-            if request.POST['interessado']:
-                kwargs['interessado__icontains'] = request.POST['interessado']
+        return context
 
-            if request.POST['tipo_materia']:
-                kwargs['tipo_materia'] = request.POST['tipo_materia']
+    def get(self, request, *args, **kwargs):
+        super(ProtocoloPesquisaView, self).get(request)
+
+        # Se a pesquisa estiver quebrando com a paginação
+        # Olhe esta função abaixo
+        # Provavelmente você criou um novo campo no Form/FilterSet
+        # Então a ordem da URL está diferente
+        data = self.filterset.data
+        if (data and data.get('numero') is not None):
+            url = "&"+str(self.request.environ['QUERY_STRING'])
+            if url.startswith("&page"):
+                ponto_comeco = url.find('numero=') - 1
+                url = url[ponto_comeco:]
+        else:
+            url = ''
 
-            if request.POST['autor']:
-                kwargs['autor'] = request.POST['autor']
+        self.filterset.form.fields['o'].label = _('Ordenação')
 
-            if request.POST['assunto']:
-                kwargs['assunto_ementa__icontains'] = request.POST['assunto']
+        context = self.get_context_data(filter=self.filterset,
+                                        object_list=self.object_list,
+                                        filter_url=url,
+                                        numero_res=len(self.object_list)
+                                        )
 
-            request.session['kwargs'] = kwargs
-            return redirect('protocoloadm:protocolo_list')
-        else:
-            return self.form_invalid(form)
+        return self.render_to_response(context)
 
 
 class ProtocoloListView(ListView):


Test patch: