From 9c3d22a44591048fa75478001a53b0869039be0c Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Wed, 28 Aug 2019 16:31:13 -0300 Subject: [PATCH 01/17] Trata URL mal formada do YouTube --- sapl/base/templatetags/common_tags.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sapl/base/templatetags/common_tags.py b/sapl/base/templatetags/common_tags.py index 12192ab6f..048778d8d 100644 --- a/sapl/base/templatetags/common_tags.py +++ b/sapl/base/templatetags/common_tags.py @@ -249,8 +249,10 @@ def facebook_url(value): def youtube_id(value): from urllib.parse import urlparse, parse_qs u_pars = urlparse(value) - quer_v = parse_qs(u_pars.query).get('v')[0] - return quer_v + quer_v = parse_qs(u_pars.query).get('v') + if quer_v: + return quer_v[0] + return '' @register.filter From 5f32c0ebd254a4b4fc85392cbc962873f2b6df85 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Wed, 28 Aug 2019 17:02:30 -0300 Subject: [PATCH 02/17] add __str__ nos resultados da api --- sapl/api/views.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sapl/api/views.py b/sapl/api/views.py index 6f4e9219a..9ddafb9ec 100644 --- a/sapl/api/views.py +++ b/sapl/api/views.py @@ -15,6 +15,7 @@ from django_filters.rest_framework.filterset import FilterSet from django_filters.utils import resolve_field from rest_framework import serializers as rest_serializers from rest_framework.decorators import action +from rest_framework.fields import SerializerMethodField from rest_framework.response import Response from rest_framework.viewsets import ModelViewSet @@ -94,10 +95,15 @@ class SaplApiViewSetConstrutor(): # Define uma classe padrão para serializer caso não tenha sido # criada a classe sapl.api.serializers.{model}Serializer class SaplSerializer(rest_serializers.ModelSerializer): + __str__ = SerializerMethodField() + class Meta: model = _model fields = '__all__' + def get___str__(self, obj): + return str(obj) + # Define uma classe padrão para filtro caso não tenha sido # criada a classe sapl.api.forms.{model}FilterSet class SaplFilterSet(SaplFilterSetMixin): From ac340918076d516f237a31d85358f2db0ee675cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Rodrigues?= Date: Thu, 29 Aug 2019 11:42:56 -0300 Subject: [PATCH 03/17] Fix #2943 (#2944) --- sapl/base/tests/test_view_base.py | 6 +++--- sapl/base/views.py | 2 +- sapl/templates/base/parlamentares_duplicados.html | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sapl/base/tests/test_view_base.py b/sapl/base/tests/test_view_base.py index 6655317b3..44d7a3632 100644 --- a/sapl/base/tests/test_view_base.py +++ b/sapl/base/tests/test_view_base.py @@ -194,13 +194,13 @@ def test_lista_parlamentares_duplicados(): sexo='M' ) - lista_dict_values_parlamentares_duplicados = parlamentares_duplicados() + lista_dict_parlamentares_duplicados = parlamentares_duplicados() parlamentar_duplicado = list( - lista_dict_values_parlamentares_duplicados[0] + lista_dict_parlamentares_duplicados[0].values() ) parlamentar_duplicado.sort(key=str) - assert len(lista_dict_values_parlamentares_duplicados) == 1 + assert len(lista_dict_parlamentares_duplicados) == 1 assert parlamentar_duplicado == [2, "Nome_Parlamentar_Teste"] diff --git a/sapl/base/views.py b/sapl/base/views.py index 8fec1a305..da9698702 100644 --- a/sapl/base/views.py +++ b/sapl/base/views.py @@ -1430,7 +1430,7 @@ class ListarParlMandatosIntersecaoView(PermissionRequiredMixin, ListView): def parlamentares_duplicados(): - return [parlamentar.values() for parlamentar in Parlamentar.objects.values( + return [parlamentar for parlamentar in Parlamentar.objects.values( 'nome_parlamentar').order_by('nome_parlamentar').annotate(count=Count( 'nome_parlamentar')).filter(count__gt=1)] diff --git a/sapl/templates/base/parlamentares_duplicados.html b/sapl/templates/base/parlamentares_duplicados.html index 0bb86e2ce..a7727f342 100644 --- a/sapl/templates/base/parlamentares_duplicados.html +++ b/sapl/templates/base/parlamentares_duplicados.html @@ -15,12 +15,12 @@ - {% for quantidade, parlamentar in parlamentares_duplicados %} + {% for parlamentar in parlamentares_duplicados %} - {{ parlamentar }} + {{ parlamentar.nome_parlamentar }} - {{ quantidade }} + {{ parlamentar.count }} {% endfor %} From 4211cff3a647cb9d717d00f6c36d34fa6673d14d Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Fri, 30 Aug 2019 14:32:34 -0300 Subject: [PATCH 04/17] HOT-FIX: mantem query_string em redirect app comp --- sapl/compilacao/views.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sapl/compilacao/views.py b/sapl/compilacao/views.py index 671e5bcf1..d27d85f1a 100644 --- a/sapl/compilacao/views.py +++ b/sapl/compilacao/views.py @@ -195,8 +195,13 @@ class IntegracaoTaView(TemplateView): return redirect(to=reverse_lazy('sapl.compilacao:ta_text_edit', kwargs={'ta_id': ta.pk})) else: - return redirect(to=reverse_lazy('sapl.compilacao:ta_text', - kwargs={'ta_id': ta.pk})) + return redirect( + to='%s?%s' % ( + reverse_lazy('sapl.compilacao:ta_text', + kwargs={'ta_id': ta.pk}), + request.META['QUERY_STRING'] + ) + ) class Meta: abstract = True From 7f819997c4329c1a7aa0935c73eb6ab3692b55dd Mon Sep 17 00:00:00 2001 From: Edward <9326037+edwardoliveira@users.noreply.github.com> Date: Fri, 30 Aug 2019 14:54:23 -0300 Subject: [PATCH 05/17] =?UTF-8?q?Adiciona=20n=C3=BAmero=20protocolo=20a=20?= =?UTF-8?q?comprovante=20de=20protocolo=20(OSTicket=20Ticket=20#730379)=20?= =?UTF-8?q?(#2950)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/protocoloadm/views.py | 7 +++++++ sapl/templates/protocoloadm/comprovante.html | 15 ++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py index a1a8b05d4..358b057ab 100755 --- a/sapl/protocoloadm/views.py +++ b/sapl/protocoloadm/views.py @@ -700,6 +700,13 @@ class ComprovanteProtocoloView(PermissionRequiredMixin, TemplateView): autenticacao = str(protocolo.tipo_processo) + \ data + str(protocolo.numero).zfill(6) + if protocolo.tipo_materia: + materia = MateriaLegislativa.objects.filter( + numero_protocolo=protocolo.numero, + ano=protocolo.ano).first() + if materia: + context['materia'] = materia.numero + context.update({"protocolo": protocolo, "barcode": barcode, "autenticacao": autenticacao}) diff --git a/sapl/templates/protocoloadm/comprovante.html b/sapl/templates/protocoloadm/comprovante.html index 2e1c3ce89..3289e2632 100644 --- a/sapl/templates/protocoloadm/comprovante.html +++ b/sapl/templates/protocoloadm/comprovante.html @@ -18,6 +18,9 @@ .hide-print { display : none; } + .downsize { + font-size: 12px; + } } @page { size: auto; /* auto is the initial value */ @@ -74,7 +77,7 @@ {% if protocolo.tipo_processo == 1 %} Ementa - {{ protocolo.assunto_ementa }} + {{ protocolo.assunto_ementa }} Autor @@ -102,10 +105,16 @@ Número Páginas - {{ protocolo.numero_paginas }} + {{ protocolo.numero_paginas|default_if_none:"0" }} + {% if materia %} - Comprovante emitido por + Número da Matéria + {{ materia }} + + {% endif %} + + Emitido por {{ request.user.username }} From 4e0a99bf5edd3a38af29c2563119adfb2b8ba63c Mon Sep 17 00:00:00 2001 From: ulyssesBML Date: Mon, 2 Sep 2019 12:16:06 -0300 Subject: [PATCH 06/17] =?UTF-8?q?HOT-FIX=20-=20Concertando=20erro=20pagina?= =?UTF-8?q?=20de=20tramita=C3=A7=C3=A3o=20em=20comissoes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/comissoes/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapl/comissoes/views.py b/sapl/comissoes/views.py index 5fa132eab..0b5ca756d 100644 --- a/sapl/comissoes/views.py +++ b/sapl/comissoes/views.py @@ -167,7 +167,7 @@ class ComissaoCrud(Crud): def lista_materias_comissao(comissao_pk): ts = Tramitacao.objects.order_by( - 'materia', '-data_tramitacao', '-id').annotate( + 'materia_id', '-data_tramitacao', '-id').annotate( comissao=F('unidade_tramitacao_destino__comissao')).distinct( 'materia').values_list('materia', 'comissao') From 5f5f8f64ed79baa6e6b0fa168bb1ae0bd13facc9 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Mon, 2 Sep 2019 17:02:45 -0300 Subject: [PATCH 07/17] HOT-FIX: autopep8 by IDE --- sapl/protocoloadm/views.py | 103 +++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 51 deletions(-) diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py index 358b057ab..71b8d4734 100755 --- a/sapl/protocoloadm/views.py +++ b/sapl/protocoloadm/views.py @@ -34,10 +34,10 @@ from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa, Unid from sapl.materia.views import gerar_pdf_impressos from sapl.parlamentares.models import Legislatura, Parlamentar from sapl.protocoloadm.models import Protocolo +from sapl.relatorios.views import relatorio_doc_administrativos from sapl.utils import (create_barcode, get_base_url, get_client_ip, get_mime_type_from_file_extension, lista_anexados, show_results_filter_set, mail_service_configured) -from sapl.relatorios.views import relatorio_doc_administrativos from .forms import (AcompanhamentoDocumentoForm, AnularProtocoloAdmForm, DocumentoAcessorioAdministrativoForm, @@ -290,7 +290,7 @@ class AcompanhamentoDocumentoView(CreateView): de mensagens e clique no link que nós enviamos para \ confirmar o acompanhamento deste documento.') messages.add_message(request, messages.SUCCESS, msg) - + # Caso esse Acompanhamento já exista # avisa ao usuário que esse documento já está sendo acompanhado else: @@ -302,7 +302,7 @@ class AcompanhamentoDocumentoView(CreateView): return self.render_to_response( {'form': form, 'documento': documento, - }) + }) return HttpResponseRedirect(self.get_success_url()) else: return self.render_to_response( @@ -917,7 +917,7 @@ class PesquisarDocumentoAdministrativoView(DocumentoAdministrativoMixin, page_obj = context['page_obj'] context['page_range'] = make_pagination( page_obj.number, paginator.num_pages) - + return context def get(self, request, *args, **kwargs): @@ -942,21 +942,22 @@ class PesquisarDocumentoAdministrativoView(DocumentoAdministrativoMixin, length = self.object_list.filter(restrito=False).count() else: length = self.object_list.count() - - is_relatorio = url!='' and request.GET.get('relatorio',None) - self.paginate_by = None if is_relatorio else self.paginate_by + + is_relatorio = url != '' and request.GET.get('relatorio', None) + self.paginate_by = None if is_relatorio else self.paginate_by context = self.get_context_data(filter=self.filterset, filter_url=url, numero_res=length ) context['show_results'] = show_results_filter_set( self.request.GET.copy()) - + if is_relatorio: - return relatorio_doc_administrativos(request,context) - else: + return relatorio_doc_administrativos(request, context) + else: return self.render_to_response(context) - + + class AnexadoCrud(MasterDetailCrud): model = Anexado parent_field = 'documento_principal' @@ -994,7 +995,7 @@ class DocumentoAnexadoEmLoteView(PermissionRequiredMixin, FilterView): def get_context_data(self, **kwargs): context = super( DocumentoAnexadoEmLoteView, self - ).get_context_data(**kwargs) + ).get_context_data(**kwargs) context['root_pk'] = self.kwargs['pk'] @@ -1004,17 +1005,17 @@ class DocumentoAnexadoEmLoteView(PermissionRequiredMixin, FilterView): # Verifica se os campos foram preenchidos if not self.request.GET.get('tipo', " "): - msg =_('Por favor, selecione um tipo de documento.') + msg = _('Por favor, selecione um tipo de documento.') messages.add_message(self.request, messages.ERROR, msg) - + if not self.request.GET.get('data_0', " ") or not self.request.GET.get('data_1', " "): - msg =_('Por favor, preencha as datas.') + msg = _('Por favor, preencha as datas.') messages.add_message(self.request, messages.ERROR, msg) return context if not self.request.GET.get('data_0', " ") or not self.request.GET.get('data_1', " "): - msg =_('Por favor, preencha as datas.') + msg = _('Por favor, preencha as datas.') messages.add_message(self.request, messages.ERROR, msg) return context @@ -1026,17 +1027,19 @@ class DocumentoAnexadoEmLoteView(PermissionRequiredMixin, FilterView): context['object_list'] = [] for obj in context['temp_object_list']: if not obj.pk == int(context['root_pk']): - documento_principal = DocumentoAdministrativo.objects.get(id=context['root_pk']) + documento_principal = DocumentoAdministrativo.objects.get( + id=context['root_pk']) documento_anexado = obj is_anexado = Anexado.objects.filter(documento_principal=documento_principal, documento_anexado=documento_anexado).exists() if not is_anexado: ciclico = False - anexados_anexado = Anexado.objects.filter(documento_principal=documento_anexado) + anexados_anexado = Anexado.objects.filter( + documento_principal=documento_anexado) while anexados_anexado and not ciclico: anexados = [] - + for anexo in anexados_anexado: if documento_principal == anexo.documento_anexado: @@ -1049,18 +1052,18 @@ class DocumentoAnexadoEmLoteView(PermissionRequiredMixin, FilterView): if not ciclico: context['object_list'].append(obj) - + context['numero_res'] = len(context['object_list']) context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' - + context['show_results'] = show_results_filter_set(qr) return context def post(self, request, *args, **kwargs): marcados = request.POST.getlist('documento_id') - + data_anexacao = datetime.strptime( request.POST['data_anexacao'], "%d/%m/%Y" ).date() @@ -1075,22 +1078,22 @@ class DocumentoAnexadoEmLoteView(PermissionRequiredMixin, FilterView): v_data_desanexacao = data_desanexacao if len(marcados) == 0: - msg =_('Nenhum documento foi selecionado') + msg = _('Nenhum documento foi selecionado') messages.add_message(request, messages.ERROR, msg) - + if data_anexacao > v_data_desanexacao: - msg=_('Data de anexação posterior à data de desanexação.') + msg = _('Data de anexação posterior à data de desanexação.') messages.add_message(request, messages.ERROR, msg) - + return self.get(request, self.kwargs) if data_anexacao > v_data_desanexacao: - msg =_('Data de anexação posterior à data de desanexação.') + msg = _('Data de anexação posterior à data de desanexação.') messages.add_message(request, messages.ERROR, msg) return self.get(request, messages.ERROR, msg) - principal = DocumentoAdministrativo.objects.get(pk = kwargs['pk']) - for documento in DocumentoAdministrativo.objects.filter(id__in = marcados): + principal = DocumentoAdministrativo.objects.get(pk=kwargs['pk']) + for documento in DocumentoAdministrativo.objects.filter(id__in=marcados): anexado = Anexado() anexado.documento_principal = principal anexado.documento_anexado = documento @@ -1101,7 +1104,8 @@ class DocumentoAnexadoEmLoteView(PermissionRequiredMixin, FilterView): msg = _('Documento(s) anexado(s).') messages.add_message(request, messages.SUCCESS, msg) - success_url = reverse('sapl.protocoloadm:anexado_list', kwargs={'pk': kwargs['pk']}) + success_url = reverse('sapl.protocoloadm:anexado_list', kwargs={ + 'pk': kwargs['pk']}) return HttpResponseRedirect(success_url) @@ -1149,7 +1153,8 @@ class TramitacaoAdmCrud(MasterDetailCrud): '-timestamp', '-id').first() - #TODO: Esta checagem foi inserida na issue #2027, mas é mesmo necessária? + # TODO: Esta checagem foi inserida na issue #2027, mas é mesmo + # necessária? if ultima_tramitacao: if ultima_tramitacao.unidade_tramitacao_destino: context['form'].fields[ @@ -1231,13 +1236,12 @@ class TramitacaoAdmCrud(MasterDetailCrud): MasterDetailCrud.DetailView): template_name = 'protocoloadm/tramitacaoadministrativo_detail.html' - + def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['user'] = self.request.user return context - class DeleteView(MasterDetailCrud.DeleteView): logger = logging.getLogger(__name__) @@ -1278,7 +1282,8 @@ class TramitacaoAdmCrud(MasterDetailCrud): if da.tramitacaoadministrativo_set.count() == 0: da.tramitacao = False da.save() - TramitacaoAdministrativo.objects.filter(id__in=tramitacoes_deletar).delete() + TramitacaoAdministrativo.objects.filter( + id__in=tramitacoes_deletar).delete() return HttpResponseRedirect(url) @@ -1471,7 +1476,6 @@ class PrimeiraTramitacaoEmLoteAdmView(PermissionRequiredMixin, FilterView): logger = logging.getLogger(__name__) - def get_context_data(self, **kwargs): context = super(PrimeiraTramitacaoEmLoteAdmView, self).get_context_data(**kwargs) @@ -1493,8 +1497,8 @@ class PrimeiraTramitacaoEmLoteAdmView(PermissionRequiredMixin, FilterView): if self.primeira_tramitacao: context['title'] = _('Primeira Tramitação em Lote') # Pega somente documentos que não possuem tramitação - context['object_list'] = [obj for obj in context['object_list'] - if obj.tramitacaoadministrativo_set.all().count() == 0] + context['object_list'] = [obj for obj in context['object_list'] + if obj.tramitacaoadministrativo_set.all().count() == 0] else: context['title'] = _('Tramitação em Lote') context['form'].fields['unidade_tramitacao_local'].initial = UnidadeTramitacao.objects.get( @@ -1516,32 +1520,33 @@ class PrimeiraTramitacaoEmLoteAdmView(PermissionRequiredMixin, FilterView): messages.add_message(request, messages.ERROR, msg) return self.get(request, self.kwargs) - form = TramitacaoEmLoteAdmForm(request.POST, - initial= {'documentos': documentos_ids, - 'user': user, 'ip':ip}) + form = TramitacaoEmLoteAdmForm(request.POST, + initial={'documentos': documentos_ids, + 'user': user, 'ip': ip}) if form.is_valid(): form.save() msg = _('Tramitação completa.') - self.logger.info('user=' + user.username + '. Tramitação completa.') + self.logger.info('user=' + user.username + + '. Tramitação completa.') messages.add_message(request, messages.SUCCESS, msg) return self.get_success_url() return self.form_invalid(form) - def get_success_url(self): return HttpResponseRedirect(reverse('sapl.protocoloadm:primeira_tramitacao_em_lote_docadm')) - def form_invalid(self, form, *args, **kwargs): for key, erros in form.errors.items(): - if not key=='__all__': - [messages.add_message(self.request, messages.ERROR, form.fields[key].label + ": " + e) for e in erros] + if not key == '__all__': + [messages.add_message( + self.request, messages.ERROR, form.fields[key].label + ": " + e) for e in erros] else: - [messages.add_message(self.request, messages.ERROR, e) for e in erros] - return self.get(self.request, kwargs, {'form':form}) + [messages.add_message(self.request, messages.ERROR, e) + for e in erros] + return self.get(self.request, kwargs, {'form': form}) class TramitacaoEmLoteAdmView(PrimeiraTramitacaoEmLoteAdmView): @@ -1569,21 +1574,18 @@ class TramitacaoEmLoteAdmView(PrimeiraTramitacaoEmLoteAdmView): return context - def pega_ultima_tramitacao(self): return TramitacaoAdministrativo.objects.values( 'documento_id').annotate(data_encaminhamento=Max( 'data_encaminhamento'), id=Max('id')).values_list('id', flat=True) - def filtra_tramitacao_status(self, status): lista = self.pega_ultima_tramitacao() return TramitacaoAdministrativo.objects.filter( id__in=lista, status=status).distinct().values_list('documento_id', flat=True) - def filtra_tramitacao_destino(self, destino): lista = self.pega_ultima_tramitacao() return TramitacaoAdministrativo.objects.filter( @@ -1591,7 +1593,6 @@ class TramitacaoEmLoteAdmView(PrimeiraTramitacaoEmLoteAdmView): unidade_tramitacao_destino=destino).distinct().values_list( 'documento_id', flat=True) - def filtra_tramitacao_destino_and_status(self, status, destino): lista = self.pega_ultima_tramitacao() return TramitacaoAdministrativo.objects.filter( From bc016c465e369b16b4359d8eef004082489976bc Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Mon, 2 Sep 2019 17:05:23 -0300 Subject: [PATCH 08/17] HOT-FIX: rem trans incor de link p texto_integral --- sapl/protocoloadm/views.py | 12 ++++++------ sapl/templates/protocoloadm/layouts.yaml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py index 71b8d4734..f8135e1bc 100755 --- a/sapl/protocoloadm/views.py +++ b/sapl/protocoloadm/views.py @@ -373,13 +373,13 @@ class DocumentoAdministrativoCrud(Crud): return redirect('/') return super(Crud.DetailView, self).get(args, kwargs) - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - self.layout_display[0]['rows'][-1][0]['text'] = ( - '' % reverse( + def urlize(self, obj, fieldname): + a = '%s' % ( + reverse( 'sapl.protocoloadm:doc_texto_integral', - kwargs={'pk': self.object.pk})) - return context + kwargs={'pk': obj.pk}), + obj.texto_integral.name.split('/')[-1]) + return obj.texto_integral.field.verbose_name, a class DeleteView(Crud.DeleteView): diff --git a/sapl/templates/protocoloadm/layouts.yaml b/sapl/templates/protocoloadm/layouts.yaml index d87a99b56..3f78f676e 100644 --- a/sapl/templates/protocoloadm/layouts.yaml +++ b/sapl/templates/protocoloadm/layouts.yaml @@ -9,7 +9,7 @@ DocumentoAdministrativo: - data protocolo - assunto - interessado tramitacao - - texto_integral + - texto_integral|urlize - documento_anexado_set__documento_principal|m2m_urlize_for_detail - documento_principal_set__documento_anexado|m2m_urlize_for_detail {% trans 'Outras Informações' %}: From f0e78b4e9006bb1b66e3be446537531b0c15cdbc Mon Sep 17 00:00:00 2001 From: Cesar Carvalho Date: Thu, 5 Sep 2019 14:11:57 -0300 Subject: [PATCH 09/17] =?UTF-8?q?HOT-FIX:=20Melhora=20HTML=20de=20Vota?= =?UTF-8?q?=C3=A7=C3=B5es=20Nominal=20e=20Simb=C3=B3lica?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/templates/sessao/votacao/nominal.html | 80 ++++++++++++---------- sapl/templates/sessao/votacao/votacao.html | 66 ++++++++++-------- 2 files changed, 78 insertions(+), 68 deletions(-) diff --git a/sapl/templates/sessao/votacao/nominal.html b/sapl/templates/sessao/votacao/nominal.html index 470b02228..540e0f3da 100644 --- a/sapl/templates/sessao/votacao/nominal.html +++ b/sapl/templates/sessao/votacao/nominal.html @@ -21,49 +21,53 @@ {% else %}
- Votos -
- {% for parlamentar in parlamentares %} -
{{parlamentar.0.nome_parlamentar}}
-
- {% if parlamentar.1 %} {% endif %} - -
- {% endfor %} -
- - Situação da Votação: - -
- -
- -
-
- {{ form.resultado_votacao|as_crispy_field }} -
-
+
+ {% for parlamentar in parlamentares %} +
{{parlamentar.0.nome_parlamentar}}
+
+ {% if parlamentar.1 %} {% endif %} + +
+ {% endfor %} +
+ + Situação da Votação: +
+ + + +
+
+ {{ form.resultado_votacao|as_crispy_field }} +
+

-
-
- Observações
- -
-
+
+
+ Observações
+ +
+


- - - - - {% endif %} +
+
+
+ + +
+
+
+ {% endif %} + + {% endblock detail_content %} {% block extra_js %} diff --git a/sapl/templates/sessao/votacao/votacao.html b/sapl/templates/sessao/votacao/votacao.html index d7320c5b1..3a74413cc 100644 --- a/sapl/templates/sessao/votacao/votacao.html +++ b/sapl/templates/sessao/votacao/votacao.html @@ -38,41 +38,47 @@
-
-
Sim*:
-
Não*:
-
Abstenções*:
-
+
+
Sim*:
+
Não*:
+
Abstenções*:
+
-
-
- A totalização inclui o voto do Presidente?* - -
+
+
+ A totalização inclui o voto do Presidente?* + +
-
- Resultado da Votação* - -
-
+
+ Resultado da Votação* + +
+
-
-
- Observações - -
-
+
+
+ Observações + +
+


- - +
+
+
+ + +
+
+
{% endblock detail_content %} From 3607486546c0a309d0f71a14bd6f376b21623446 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Fri, 6 Sep 2019 12:59:51 -0300 Subject: [PATCH 10/17] corrige crud para container_fields --- sapl/crud/base.py | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/sapl/crud/base.py b/sapl/crud/base.py index 98af2a3bb..18f3d5c29 100644 --- a/sapl/crud/base.py +++ b/sapl/crud/base.py @@ -4,13 +4,14 @@ from braces.views import FormMessagesMixin from crispy_forms.bootstrap import FieldWithButtons, StrictButton from crispy_forms.layout import Field, Layout from django import forms +from django.conf import settings from django.conf.urls import url from django.contrib import messages from django.contrib.auth.mixins import PermissionRequiredMixin from django.core.exceptions import ObjectDoesNotExist from django.core.urlresolvers import reverse from django.db import models -from django.db.models.fields.related import ForeignKey +from django.db.models.fields.related import ForeignKey, ManyToManyField from django.http.response import Http404 from django.shortcuts import redirect from django.utils.decorators import classonlymethod @@ -27,10 +28,12 @@ from sapl.crispy_layout_mixin import CrispyLayoutFormMixin, get_field_display from sapl.crispy_layout_mixin import SaplFormHelper from sapl.rules.map_rules import (RP_ADD, RP_CHANGE, RP_DELETE, RP_DETAIL, RP_LIST) -from sapl.settings import BASE_DIR from sapl.utils import normalize +logger = logging.getLogger(settings.BASE_DIR.name) + + ACTION_LIST, ACTION_CREATE, ACTION_DETAIL, ACTION_UPDATE, ACTION_DELETE = \ 'list', 'create', 'detail', 'update', 'delete' @@ -122,7 +125,6 @@ class SearchMixin(models.Model): except Exception as e: username = self.request.user.username self.logger.error("user=" + username + ". " + str(e)) - pass else: _self = self for field in fields: @@ -206,6 +208,7 @@ class PermissionRequiredContainerCrudMixin(PermissionRequiredMixin): if not self.model.objects.filter(**params).exists(): raise Http404() + elif self.container_field: container = self.container_field.split('__') @@ -230,14 +233,14 @@ class PermissionRequiredContainerCrudMixin(PermissionRequiredMixin): return super(PermissionRequiredMixin, self).dispatch( request, *args, **kwargs) - @cached_property + @property def container_field(self): if hasattr(self, 'crud') and not hasattr(self.crud, 'container_field'): self.crud.container_field = '' if hasattr(self, 'crud'): return self.crud.container_field - @cached_property + @property def container_field_set(self): if hasattr(self, 'crud') and\ not hasattr(self.crud, 'container_field_set'): @@ -245,7 +248,7 @@ class PermissionRequiredContainerCrudMixin(PermissionRequiredMixin): if hasattr(self, 'crud'): return self.crud.container_field_set - @cached_property + @property def is_contained(self): return self.container_field_set or self.container_field @@ -600,7 +603,7 @@ class CrudListView(PermissionRequiredContainerCrudMixin, ListView): # print(ordering) except Exception as e: - print(string_concat(_( + logger.error(string_concat(_( 'ERRO: construção da tupla de ordenação.'), str(e))) # print(queryset.query) @@ -1108,12 +1111,14 @@ class MasterDetailCrud(Crud): permission_required = RP_LIST, logger = logging.getLogger(__name__) + def get(self, request, *args, **kwargs): + return Crud.ListView.get(self, request, *args, **kwargs) + @classmethod def get_url_regex(cls): return r'^(?P\d+)/%s$' % cls.model._meta.model_name def get_context_data(self, **kwargs): - obj = self.crud if hasattr(self, 'crud') else self context = CrudListView.get_context_data(self, **kwargs) @@ -1133,7 +1138,12 @@ class MasterDetailCrud(Crud): else: parent_model = getattr( - self.model, obj.parent_field).field.related_model + self.model, obj.parent_field) + if isinstance(parent_model.field, ( + ForeignKey, ManyToManyField)): + parent_model = parent_model.field.related_model + else: + parent_model = parent_model.rel.related_model params = {'pk': kwargs['root_pk']} @@ -1165,6 +1175,9 @@ class MasterDetailCrud(Crud): return qs.filter(**kwargs) + def dispatch(self, request, *args, **kwargs): + return PermissionRequiredMixin.dispatch(self, request, *args, **kwargs) + class CreateView(Crud.CreateView): permission_required = RP_ADD, logger = logging.getLogger(__name__) @@ -1229,8 +1242,12 @@ class MasterDetailCrud(Crud): parent_object = getattr(parent_object, field) else: - parent_model = getattr( - parent_model, obj.parent_field).field.related_model + parent_model = getattr(self.model, obj.parent_field) + if isinstance(parent_model.field, ForeignKey): + parent_model = parent_model.field.related_model + else: + parent_model = parent_model.rel.related_model + parent_object = parent_model.objects.get(**params) context['root_pk'] = parent_object.pk From c08e0a69d388ece393c26b41e0d64aec41485005 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Sat, 14 Sep 2019 01:44:02 -0300 Subject: [PATCH 11/17] =?UTF-8?q?HOT-FIX:=20corrige=20signal=20de=20ajuste?= =?UTF-8?q?=20de=20indicador=20de=20tramita=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/base/receivers.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sapl/base/receivers.py b/sapl/base/receivers.py index b2176be14..1e402ffb0 100644 --- a/sapl/base/receivers.py +++ b/sapl/base/receivers.py @@ -1,6 +1,5 @@ from django.db.models.signals import post_delete, post_save from django.dispatch import receiver - from sapl.materia.models import Tramitacao from sapl.protocoloadm.models import TramitacaoAdministrativo from sapl.base.signals import tramitacao_signal @@ -30,7 +29,7 @@ def handle_tramitacao_signal(sender, **kwargs): @receiver(post_delete) def status_tramitacao_materia(sender, instance, **kwargs): - if isinstance(sender, TramitacaoAdministrativo): + if isinstance(sender, Tramitacao): if instance.status.indicador == 'F': materia = instance.materia materia.em_tramitacao = True From 9f29a46df487e64e0fb68ba528108fc4cd6b7bf8 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Sat, 14 Sep 2019 02:16:56 -0300 Subject: [PATCH 12/17] HOT-FIX: corrige teste de classes em post_delete --- sapl/base/receivers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sapl/base/receivers.py b/sapl/base/receivers.py index 1e402ffb0..f5f19f1f3 100644 --- a/sapl/base/receivers.py +++ b/sapl/base/receivers.py @@ -29,12 +29,12 @@ def handle_tramitacao_signal(sender, **kwargs): @receiver(post_delete) def status_tramitacao_materia(sender, instance, **kwargs): - if isinstance(sender, Tramitacao): + if sender == Tramitacao: if instance.status.indicador == 'F': materia = instance.materia materia.em_tramitacao = True materia.save() - elif isinstance(sender, TramitacaoAdministrativo): + elif sender == TramitacaoAdministrativo: if instance.status.indicador == 'F': documento = instance.documento documento.tramitacao = True From 51aefc6798c8a39abac37b88512f33359d379e80 Mon Sep 17 00:00:00 2001 From: Cesar Carvalho Date: Thu, 19 Sep 2019 09:50:39 -0300 Subject: [PATCH 13/17] Release: 3.1.160-RC1 --- docker-compose.yml | 2 +- sapl/settings.py | 2 +- sapl/templates/base.html | 2 +- setup.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 3f4eb46b3..5eb35418d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,7 +11,7 @@ sapldb: ports: - "5432:5432" sapl: - image: interlegis/sapl:3.1.160-RC0 + image: interlegis/sapl:3.1.160-RC1 restart: always environment: ADMIN_PASSWORD: interlegis diff --git a/sapl/settings.py b/sapl/settings.py index c9764545c..c97f2311a 100644 --- a/sapl/settings.py +++ b/sapl/settings.py @@ -41,7 +41,7 @@ ALLOWED_HOSTS = ['*'] LOGIN_REDIRECT_URL = '/' LOGIN_URL = '/login/?next=' -SAPL_VERSION = '3.1.160-RC0' +SAPL_VERSION = '3.1.160-RC1' if DEBUG: EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' diff --git a/sapl/templates/base.html b/sapl/templates/base.html index d9f63f74f..64d296c94 100644 --- a/sapl/templates/base.html +++ b/sapl/templates/base.html @@ -179,7 +179,7 @@ Desenvolvido pelo Interlegis em software livre e aberto. - Release: 3.1.160-RC0 + Release: 3.1.160-RC1

diff --git a/setup.py b/setup.py index d15324dd6..b2fb9b1d9 100644 --- a/setup.py +++ b/setup.py @@ -43,7 +43,7 @@ install_requires = [ ] setup( name='interlegis-sapl', - version='3.1.160-RC0', + version='3.1.160-RC1', packages=find_packages(), include_package_data=True, license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007', From 8829879f74d14bd1a4abed6d4873a331b56a3652 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Wed, 25 Sep 2019 15:46:08 -0300 Subject: [PATCH 14/17] Evita que se criem autores com nomes repetidos --- sapl/base/forms.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sapl/base/forms.py b/sapl/base/forms.py index d51e0e321..e3ec2b6a9 100644 --- a/sapl/base/forms.py +++ b/sapl/base/forms.py @@ -618,6 +618,10 @@ class AutorForm(ModelForm): tipo = cd['tipo'] + if 'nome' in cd and \ + Autor.objects.filter(nome=cd['nome']).exists(): + raise ValidationError("Autor '%s' já existente!" % cd['nome']) + if not tipo.content_type: if 'nome' not in cd or not cd['nome']: self.logger.error('Nome do Autor não informado.') From 55c070b5776f6cb331a5f9be3fd9f8a2f7a575c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Rodrigues?= Date: Wed, 25 Sep 2019 15:57:30 -0300 Subject: [PATCH 15/17] =?UTF-8?q?Fix=20Ticket=20#923744=20-=20Tempo=20de?= =?UTF-8?q?=20resposta=20do=20relat=C3=B3rio=20de=20mat=C3=A9rias=20em=20t?= =?UTF-8?q?ramita=C3=A7=C3=A3o=20(#2955)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Otimiza relatório de matérias em tramitação * Refatoração * HOT-FIX: corrige erro apontado pelo travis * Adicionar nova model * Adicionar on_delete nos campos da model * Acelera pesquisa do relatório * Refatoração --- sapl/base/forms.py | 55 +++--- sapl/base/views.py | 158 +++++++++++------- .../0056_popula_materiaemtramitacao.py | 23 +++ .../migrations/0057_materiaemtramitacao.py | 25 +++ sapl/materia/models.py | 12 ++ sapl/rules/map_rules.py | 1 + ...RelatorioMateriasPorTramitacao_filter.html | 17 +- 7 files changed, 197 insertions(+), 94 deletions(-) create mode 100644 sapl/materia/migrations/0056_popula_materiaemtramitacao.py create mode 100644 sapl/materia/migrations/0057_materiaemtramitacao.py diff --git a/sapl/base/forms.py b/sapl/base/forms.py index e3ec2b6a9..d111e7f4c 100644 --- a/sapl/base/forms.py +++ b/sapl/base/forms.py @@ -18,27 +18,25 @@ from django.utils.translation import string_concat from django.utils.translation import ugettext_lazy as _ import django_filters -from sapl.audiencia.models import AudienciaPublica, TipoAudienciaPublica -from sapl.audiencia.models import AudienciaPublica, TipoAudienciaPublica +from sapl.audiencia.models import AudienciaPublica from sapl.base.models import Autor, TipoAutor -from sapl.comissoes.models import Reuniao, Comissao -from sapl.comissoes.models import Reuniao, Comissao -from sapl.crispy_layout_mixin import (SaplFormLayout, form_actions, to_column, - to_row) -from sapl.crispy_layout_mixin import SaplFormHelper -from sapl.materia.models import (MateriaLegislativa, UnidadeTramitacao, StatusTramitacao, - DocumentoAcessorio, TipoMateriaLegislativa) -from sapl.norma.models import (NormaJuridica, NormaEstatisticas) -from sapl.parlamentares.models import SessaoLegislativa, Partido +from sapl.comissoes.models import Reuniao +from sapl.crispy_layout_mixin import (form_actions, to_column, to_row, + SaplFormHelper, SaplFormLayout) +from sapl.materia.models import (DocumentoAcessorio, MateriaEmTramitacao, + MateriaLegislativa, UnidadeTramitacao, + StatusTramitacao) +from sapl.norma.models import NormaJuridica +from sapl.parlamentares.models import Partido, SessaoLegislativa from sapl.protocoloadm.models import DocumentoAdministrativo from sapl.sessao.models import SessaoPlenaria from sapl.settings import MAX_IMAGE_UPLOAD_SIZE -from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, - ChoiceWithoutValidationField, ImageThumbnailFileInput, - RangeWidgetOverride, autor_label, autor_modal, - models_with_gr_for_model, qs_override_django_filter, +from sapl.utils import (autor_label, autor_modal, ChoiceWithoutValidationField, choice_anos_com_normas, choice_anos_com_materias, - FilterOverridesMetaMixin, FileFieldCheckMixin) + FilterOverridesMetaMixin, FileFieldCheckMixin, + ImageThumbnailFileInput, models_with_gr_for_model, + qs_override_django_filter, RangeWidgetOverride, + RANGE_ANOS, YES_NO_CHOICES) from .models import AppConfig, CasaLegislativa @@ -1089,9 +1087,9 @@ class RelatorioAudienciaFilterSet(django_filters.FilterSet): ) -class RelatorioMateriasTramitacaoilterSet(django_filters.FilterSet): +class RelatorioMateriasTramitacaoFilterSet(django_filters.FilterSet): - ano = django_filters.ChoiceFilter(required=True, + materia__ano = django_filters.ChoiceFilter(required=True, label='Ano da Matéria', choices=choice_anos_com_materias) @@ -1105,22 +1103,25 @@ class RelatorioMateriasTramitacaoilterSet(django_filters.FilterSet): @property def qs(self): - parent = super(RelatorioMateriasTramitacaoilterSet, self).qs - return parent.distinct().order_by('-ano', 'tipo', '-numero') + parent = super(RelatorioMateriasTramitacaoFilterSet, self).qs + return parent.distinct().order_by( + '-materia__ano', 'materia__tipo', '-materia__numero' + ) class Meta: - model = MateriaLegislativa - fields = ['ano', 'tipo', 'tramitacao__unidade_tramitacao_destino', + model = MateriaEmTramitacao + fields = ['materia__ano', 'materia__tipo', + 'tramitacao__unidade_tramitacao_destino', 'tramitacao__status'] def __init__(self, *args, **kwargs): - super(RelatorioMateriasTramitacaoilterSet, self).__init__( + super(RelatorioMateriasTramitacaoFilterSet, self).__init__( *args, **kwargs) - self.filters['tipo'].label = 'Tipo de Matéria' + self.filters['materia__tipo'].label = 'Tipo de Matéria' - row1 = to_row([('ano', 12)]) - row2 = to_row([('tipo', 12)]) + row1 = to_row([('materia__ano', 12)]) + row2 = to_row([('materia__tipo', 12)]) row3 = to_row([('tramitacao__unidade_tramitacao_destino', 12)]) row4 = to_row([('tramitacao__status', 12)]) @@ -1576,4 +1577,4 @@ class RelatorioNormasPorAutorFilterSet(django_filters.FilterSet): HTML(autor_modal), row3, form_actions(label='Pesquisar')) - ) \ No newline at end of file + ) diff --git a/sapl/base/views.py b/sapl/base/views.py index da9698702..c54dc34cd 100644 --- a/sapl/base/views.py +++ b/sapl/base/views.py @@ -13,7 +13,8 @@ from django.core.exceptions import ObjectDoesNotExist, PermissionDenied, Validat from django.core.mail import send_mail from django.core.urlresolvers import reverse, reverse_lazy from django.db import connection -from django.db.models import Count, Q, ProtectedError +from django.db.models import Count, Q, ProtectedError, Max +from django.shortcuts import render from django.http import Http404, HttpResponseRedirect, JsonResponse from django.template import TemplateDoesNotExist from django.template.loader import get_template @@ -31,23 +32,26 @@ from haystack.query import SearchQuerySet from sapl import settings from sapl.audiencia.models import AudienciaPublica, TipoAudienciaPublica -from sapl.base.forms import AutorForm, AutorFormForAdmin, TipoAutorForm from sapl.base.models import Autor, TipoAutor -from sapl.comissoes.models import Reuniao, Comissao +from sapl.base.forms import AutorForm, AutorFormForAdmin, TipoAutorForm +from sapl.comissoes.models import Comissao, Reuniao from sapl.crud.base import CrudAux, make_pagination -from sapl.materia.models import (Autoria, MateriaLegislativa, Proposicao, Anexada, - TipoMateriaLegislativa, StatusTramitacao, UnidadeTramitacao, - DocumentoAcessorio, TipoDocumento) -from sapl.norma.models import (NormaJuridica, TipoNormaJuridica, NormaEstatisticas) -from sapl.parlamentares.models import Parlamentar, Legislatura, Mandato, Filiacao, SessaoLegislativa -from sapl.protocoloadm.models import (Protocolo, TipoDocumentoAdministrativo, - StatusTramitacaoAdministrativo, - DocumentoAdministrativo, Anexado) -from sapl.sessao.models import (PresencaOrdemDia, SessaoPlenaria, - SessaoPlenariaPresenca, Bancada, TipoSessaoPlenaria) -from sapl.utils import (parlamentares_ativos, gerar_hash_arquivo, SEPARADOR_HASH_PROPOSICAO, - show_results_filter_set, mail_service_configured, - intervalos_tem_intersecao, remover_acentos) +from sapl.materia.models import (Anexada, Autoria, DocumentoAcessorio, + MateriaEmTramitacao, MateriaLegislativa, Proposicao, + StatusTramitacao, TipoDocumento, + TipoMateriaLegislativa, UnidadeTramitacao, Tramitacao) +from sapl.norma.models import NormaJuridica, TipoNormaJuridica +from sapl.parlamentares.models import (Filiacao, Legislatura, Mandato, Parlamentar, + SessaoLegislativa) +from sapl.protocoloadm.models import (Anexado, DocumentoAdministrativo, Protocolo, + StatusTramitacaoAdministrativo, + TipoDocumentoAdministrativo) +from sapl.sessao.models import (Bancada, PresencaOrdemDia, SessaoPlenaria, + SessaoPlenariaPresenca, TipoSessaoPlenaria) +from sapl.utils import (gerar_hash_arquivo, intervalos_tem_intersecao, + mail_service_configured, parlamentares_ativos, + SEPARADOR_HASH_PROPOSICAO, show_results_filter_set) + from .forms import (AlterarSenhaForm, CasaLegislativaForm, ConfiguracoesAppForm, RelatorioAtasFilterSet, RelatorioAudienciaFilterSet, @@ -55,7 +59,7 @@ from .forms import (AlterarSenhaForm, CasaLegislativaForm, RelatorioHistoricoTramitacaoFilterSet, RelatorioMateriasPorAnoAutorTipoFilterSet, RelatorioMateriasPorAutorFilterSet, - RelatorioMateriasTramitacaoilterSet, + RelatorioMateriasTramitacaoFilterSet, RelatorioPresencaSessaoFilterSet, RelatorioReuniaoFilterSet, UsuarioCreateForm, UsuarioEditForm, RelatorioNormasMesFilterSet, @@ -67,19 +71,6 @@ from .forms import (AlterarSenhaForm, CasaLegislativaForm, from .models import AppConfig, CasaLegislativa -def filtra_url_materias_em_tramitacao(qr, qs, campo_url, local_ou_status): - id_materias = [] - filtro_url = qr[campo_url] - if local_ou_status == 'local': - id_materias = [item.id for item in qs if item.tramitacao_set.order_by( - '-id').first().unidade_tramitacao_destino_id == int(filtro_url)] - elif local_ou_status == 'status': - id_materias = [item.id for item in qs if item.tramitacao_set.order_by( - '-id').first().status_id == int(filtro_url)] - - return qs.filter(em_tramitacao=True, id__in=id_materias) - - def get_casalegislativa(): return CasaLegislativa.objects.first() @@ -703,61 +694,108 @@ class RelatorioAudienciaView(FilterView): class RelatorioMateriasTramitacaoView(FilterView): - model = MateriaLegislativa - filterset_class = RelatorioMateriasTramitacaoilterSet + model = MateriaEmTramitacao + filterset_class = RelatorioMateriasTramitacaoFilterSet template_name = 'base/RelatorioMateriasPorTramitacao_filter.html' + paginate_by = 100 + + total_resultados_tipos = {} + + def get_filterset_kwargs(self, filterset_class): + data = super().get_filterset_kwargs(filterset_class) + + if data['data']: + qs = data['queryset'] + + ano_materia = data['data']['materia__ano'] + tipo_materia = data['data']['materia__tipo'] + unidade_tramitacao_destino = data['data']['tramitacao__unidade_tramitacao_destino'] + status_tramitacao = data['data']['tramitacao__status'] + + kwargs = {} + if ano_materia: + kwargs['materia__ano'] = ano_materia + if tipo_materia: + kwargs['materia__tipo'] = tipo_materia + if unidade_tramitacao_destino: + kwargs['tramitacao__unidade_tramitacao_destino'] = unidade_tramitacao_destino + if status_tramitacao: + kwargs['tramitacao__status'] = status_tramitacao + qs = qs.filter(**kwargs) + + data['queryset'] = qs + + qtdes = { tipo:0 for tipo in TipoMateriaLegislativa.objects.all() } + for i in qs: + qtdes[i.materia.tipo] += 1 + + # remove as entradas de valor igual a zero + qtdes = {k:v for k,v in qtdes.items() if v > 0} + self.total_resultados_tipos = qtdes + + return data + + def get_queryset(self): + qs = super().get_queryset() + qs = qs.select_related('materia__tipo').filter( + materia__em_tramitacao=True + ).exclude( + tramitacao__status__indicador='F' + ).order_by('-materia__ano', '-materia__numero') + return qs + def get_context_data(self, **kwargs): - context = super(RelatorioMateriasTramitacaoView, - self).get_context_data(**kwargs) + context = super( + RelatorioMateriasTramitacaoView, self + ).get_context_data(**kwargs) context['title'] = _('Matérias em Tramitação') + if not self.filterset.form.is_valid(): return context qr = self.request.GET.copy() - qs = context['object_list'] - qs = qs.filter(em_tramitacao=True) - - if qr.get('tramitacao__unidade_tramitacao_destino'): - qs = filtra_url_materias_em_tramitacao( - qr, qs, 'tramitacao__unidade_tramitacao_destino', 'local') - if qr.get('tramitacao__status'): - qs = filtra_url_materias_em_tramitacao( - qr, qs, 'tramitacao__status', 'status') - li = [li1 for li1 in qs if li1.tramitacao_set.last() and li1.tramitacao_set.last().status.indicador != 'F'] - context['object_list'] = li + context['qtdes'] = self.total_resultados_tipos + context['ano'] = (self.request.GET['materia__ano']) - qtdes = {} - for tipo in TipoMateriaLegislativa.objects.all(): - li = context['object_list'] - qtde = sum(1 for i in li if i.tipo_id==tipo.id) - if qtde > 0: - qtdes[tipo] = qtde - context['qtdes'] = qtdes - context['ano'] = (self.request.GET['ano']) - if self.request.GET['tipo']: - tipo = self.request.GET['tipo'] + if self.request.GET['materia__tipo']: + tipo = self.request.GET['materia__tipo'] context['tipo'] = ( - str(TipoMateriaLegislativa.objects.get(id=tipo))) + str(TipoMateriaLegislativa.objects.get(id=tipo)) + ) else: context['tipo'] = '' + if self.request.GET['tramitacao__status']: tramitacao_status = self.request.GET['tramitacao__status'] context['tramitacao__status'] = ( - str(StatusTramitacao.objects.get(id=tramitacao_status))) + str(StatusTramitacao.objects.get(id=tramitacao_status)) + ) else: context['tramitacao__status'] = '' + if self.request.GET['tramitacao__unidade_tramitacao_destino']: - context['tramitacao__unidade_tramitacao_destino'] = (str(UnidadeTramitacao.objects.get( - id=self.request.GET['tramitacao__unidade_tramitacao_destino']))) + context['tramitacao__unidade_tramitacao_destino'] = ( + str(UnidadeTramitacao.objects.get( + id=self.request.GET['tramitacao__unidade_tramitacao_destino'] + )) + ) else: context['tramitacao__unidade_tramitacao_destino'] = '' + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' - context['show_results'] = show_results_filter_set(qr) + paginator = context['paginator'] + page_obj = context['page_obj'] + + context['page_range'] = make_pagination( + page_obj.number, paginator.num_pages + ) + context['NO_ENTRIES_MSG'] = 'Nenhum encontrado.' + return context diff --git a/sapl/materia/migrations/0056_popula_materiaemtramitacao.py b/sapl/materia/migrations/0056_popula_materiaemtramitacao.py new file mode 100644 index 000000000..dfa4c0175 --- /dev/null +++ b/sapl/materia/migrations/0056_popula_materiaemtramitacao.py @@ -0,0 +1,23 @@ +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0055_auto_20190816_0943'), + ] + + operations = [ + migrations.RunSQL(""" + create or replace view materia_materiaemtramitacao as + select m.id as id, + m.id as materia_id, + t.id as tramitacao_id + from materia_materialegislativa m + inner join materia_tramitacao t on (m.id = t.materia_id) + where t.id = (select max(id) from materia_tramitacao where materia_id = m.id) + order by m.id DESC + """), + ] \ No newline at end of file diff --git a/sapl/materia/migrations/0057_materiaemtramitacao.py b/sapl/materia/migrations/0057_materiaemtramitacao.py new file mode 100644 index 000000000..95953f50b --- /dev/null +++ b/sapl/materia/migrations/0057_materiaemtramitacao.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-08-27 20:13 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0056_popula_materiaemtramitacao'), + ] + + operations = [ + migrations.CreateModel( + name='MateriaEmTramitacao', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ], + options={ + 'db_table': 'materia_materiaemtramitacao', + 'managed': False, + }, + ), + ] diff --git a/sapl/materia/models.py b/sapl/materia/models.py index b641377de..77203e0e4 100644 --- a/sapl/materia/models.py +++ b/sapl/materia/models.py @@ -1084,3 +1084,15 @@ class Tramitacao(models.Model): 'materia': self.materia, 'status': self.status, 'data': self.data_tramitacao.strftime("%d/%m/%Y")} + + +class MateriaEmTramitacao(models.Model): + materia = models.ForeignKey(MateriaLegislativa, on_delete=models.DO_NOTHING) + tramitacao = models.ForeignKey(Tramitacao, on_delete=models.DO_NOTHING) + + class Meta: + managed = False + db_table = "materia_materiaemtramitacao" + + def __str__(self): + return '{}/{}'.format(self.materia, self.tramitacao) diff --git a/sapl/rules/map_rules.py b/sapl/rules/map_rules.py index 4f1b4b515..aa187477d 100644 --- a/sapl/rules/map_rules.py +++ b/sapl/rules/map_rules.py @@ -127,6 +127,7 @@ rules_group_materia = { ['can_access_impressos'], __perms_publicas__), (materia.Numeracao, __base__, __perms_publicas__), (materia.Tramitacao, __base__, __perms_publicas__), + (materia.MateriaEmTramitacao, __base__, __perms_publicas__), (norma.LegislacaoCitada, __base__, __perms_publicas__), (norma.AutoriaNorma, __base__, __perms_publicas__), (compilacao.Dispositivo, __base__ + [ diff --git a/sapl/templates/base/RelatorioMateriasPorTramitacao_filter.html b/sapl/templates/base/RelatorioMateriasPorTramitacao_filter.html index 02cad5e43..738e615b8 100644 --- a/sapl/templates/base/RelatorioMateriasPorTramitacao_filter.html +++ b/sapl/templates/base/RelatorioMateriasPorTramitacao_filter.html @@ -44,17 +44,20 @@ - {% for materia in object_list %} + {% for materia_em_tramitacao in object_list %} - - {{materia.tipo.descricao}} {{materia.numero}}/{{materia.ano}} - - {{materia.tramitacao_set.last.unidade_tramitacao_destino}} - {{materia.tramitacao_set.last.status}} + + + {{ materia_em_tramitacao.materia.tipo.descricao }} {{ materia_em_tramitacao.materia.numero }}/{{ materia_em_tramitacao.materia.ano }} + + + {{ materia_em_tramitacao.materia.tramitacao_set.last.unidade_tramitacao_destino }} + {{ materia_em_tramitacao.materia.tramitacao_set.last.status }} {% endfor %} {% endif %} - + {% include 'paginacao.html' %} +
{% endblock base_content %} From c7d5259d4d21cc739f441ab6d952ee1d8cd25469 Mon Sep 17 00:00:00 2001 From: Cesar Augusto de Carvalho Date: Wed, 25 Sep 2019 15:58:09 -0300 Subject: [PATCH 16/17] =?UTF-8?q?Fix=20#2910=20-=20Usu=C3=A1rio=20sem=20pe?= =?UTF-8?q?rmiss=C3=A3o=20acessa=20Proposi=C3=A7=C3=A3o=20pela=20url=20(#2?= =?UTF-8?q?963)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/materia/views.py | 7 +- sapl/templates/materia/proposicao_detail.html | 309 +++++++++--------- 2 files changed, 163 insertions(+), 153 deletions(-) diff --git a/sapl/materia/views.py b/sapl/materia/views.py index 2b5dc5697..94f10f539 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -772,7 +772,7 @@ class ProposicaoCrud(Crud): context['title'] = '%s (%s)' % ( self.object, self.object.autor) - + context['user'] = self.request.user context['proposicao'] = Proposicao.objects.get( pk=self.kwargs['pk'] @@ -782,7 +782,8 @@ class ProposicaoCrud(Crud): def get(self, request, *args, **kwargs): action = request.GET.get('action', '') - username = request.user.username + user = request.user + username = user.username if not action: return Crud.DetailView.get(self, request, *args, **kwargs) @@ -790,7 +791,7 @@ class ProposicaoCrud(Crud): p = Proposicao.objects.get(id=kwargs['pk']) msg_error = '' - if p: + if p and p.autor.user == user: if action == 'send': if p.data_envio and p.data_recebimento: msg_error = _('Proposição já foi enviada e recebida.') diff --git a/sapl/templates/materia/proposicao_detail.html b/sapl/templates/materia/proposicao_detail.html index b35d3de8b..487cc8600 100644 --- a/sapl/templates/materia/proposicao_detail.html +++ b/sapl/templates/materia/proposicao_detail.html @@ -3,204 +3,213 @@ {% load tz %} {% block sub_actions %} {{block.super}} -
- {% if object.texto_articulado.exists %} - {% trans "Texto Eletrônico" %} - {% endif %} - {% if object.texto_original %} - {% trans "Texto Original" %} - {% endif %} -
+ {% if user == object.autor.user %} +
+ {% if object.texto_articulado.exists %} + {% trans "Texto Eletrônico" %} + {% endif %} + {% if object.texto_original %} + {% trans "Texto Original" %} + {% endif %} +
+ {% endif %} {% endblock sub_actions%} {% block editions %} - {% if object.data_envio %} - {% if user == object.autor.user %} - {% block editions_actions_return %} + {% if user == object.autor.user %} + {% if object.data_envio %} + {% block editions_actions_return %} +
+ {% trans "Recibo de Envio" %} + {% if not object.data_recebimento %} + {% trans 'Retornar Proposição Enviada' %} + {% endif %} +
+ {% endblock %} + {% else %} + {% block editions_actions_send %}
- {% trans "Recibo de Envio" %} - {% if not object.data_recebimento %} - {% trans 'Retornar Proposição Enviada' %} - {% endif %} + {% trans 'Enviar' %} +
+ {% endblock %} {% endif %} - {% else %} - {% block editions_actions_send %} - - - {% endblock %} {% endif %} {% endblock editions %} {% block detail_content %} -

{% model_verbose_name 'sapl.materia.models.Proposicao' %}

-
-
-
-

{%field_verbose_name object 'tipo'%}

-
-
{{object.tipo}}
+ {% if user == object.autor.user %} +

{% model_verbose_name 'sapl.materia.models.Proposicao' %}

+
+
+
+

{%field_verbose_name object 'tipo'%}

+
+
{{object.tipo}}
+
-
- {% if object.data_devolucao %} -
- - {% else %} - {% if object.data_envio %} -
-
-

{%field_verbose_name object 'data_envio' %}

-
-
{{object.data_envio}}
+ {% else %} + {% if object.data_envio %} +
+
+

{%field_verbose_name object 'data_envio' %}

+
+
{{object.data_envio}}
+
-
- {% endif %} - {% if object.data_recebimento %} -
-
-

{%field_verbose_name object 'data_recebimento'%}

-
-
{{object.data_recebimento}}
+ {% endif %} + {% if object.data_recebimento %} +
+
+

{%field_verbose_name object 'data_recebimento'%}

+
+
{{object.data_recebimento}}
+
-
- {% elif object.data_envio %} -
- + {% endif %} {% endif %} - {% endif %} -
-
-
-
-

{%field_verbose_name object 'descricao'%}

-
-
{{object.descricao}}
-
-
-
- {% if object.observacao %}
-
-

{%field_verbose_name object 'observacao'%}

+
+

{%field_verbose_name object 'descricao'%}

-
{{object.observacao}}
+
{{object.descricao}}
- {% endif %} -
- {% if object.conteudo_gerado_related %} -
-

{% trans "Conteúdo Gerado" %}

-