From c7db9779e0c3cb6194385740123cad465a70360a Mon Sep 17 00:00:00 2001 From: Victor Fabre Date: Thu, 20 Dec 2018 08:54:17 -0200 Subject: [PATCH 01/41] HOT-FIX coloca filter_override no novo formato --- sapl/base/forms.py | 14 ++++++-------- sapl/templates/base/relatorios_list.html | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/sapl/base/forms.py b/sapl/base/forms.py index fecba4a52..a82dcab53 100644 --- a/sapl/base/forms.py +++ b/sapl/base/forms.py @@ -694,15 +694,13 @@ class RelatorioNormasMesFilterSet(django_filters.FilterSet): label='Ano da Norma', choices=RANGE_ANOS) - filter_overrides = {models.DateField: { - 'filter_class': django_filters.DateFromToRangeFilter, - 'extra': lambda f: { - 'label': '%s (%s)' % (f.verbose_name, _('Ano')), - 'widget': RangeWidgetOverride} - }} - - class Meta: + filter_overrides = {models.DateField: { + 'filter_class': django_filters.DateFromToRangeFilter, + 'extra': lambda f: { + 'label': '%s (%s)' % (f.verbose_name, _('Ano')), + 'widget': RangeWidgetOverride} + }} model = NormaJuridica fields = ['ano'] diff --git a/sapl/templates/base/relatorios_list.html b/sapl/templates/base/relatorios_list.html index 87f8933be..012064096 100644 --- a/sapl/templates/base/relatorios_list.html +++ b/sapl/templates/base/relatorios_list.html @@ -58,7 +58,7 @@ {% if estatisticas_acesso_normas %} - Estatísticas de acesso de Normas. + Estatísticas de acesso de Normas Normas por acesso. {% endif %} From 9bf8cc4afe40d169ebed6dade9a239ec82a419e0 Mon Sep 17 00:00:00 2001 From: Cesar Augusto de Carvalho Date: Thu, 20 Dec 2018 14:02:05 -0200 Subject: [PATCH 02/41] fix #2432 (#2434) --- sapl/materia/views.py | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/sapl/materia/views.py b/sapl/materia/views.py index ebce51a5d..578357721 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -2039,24 +2039,41 @@ class PrimeiraTramitacaoEmLoteView(PermissionRequiredMixin, FilterView): if not request.POST['data_encaminhamento']: data_encaminhamento = None else: - data_encaminhamento = tz.localize(datetime.strptime( - request.POST['data_encaminhamento'], "%d/%m/%Y")) + try: + data_encaminhamento = tz.localize(datetime.strptime( + request.POST['data_encaminhamento'], "%d/%m/%Y")) + except ValueError: + msg = _('Formato da data de encaminhamento incorreto.') + messages.add_message(request, messages.ERROR, msg) + return self.get(request, self.kwargs) if request.POST['data_fim_prazo'] == '': data_fim_prazo = None else: - data_fim_prazo = tz.localize(datetime.strptime( - request.POST['data_fim_prazo'], "%d/%m/%Y")) + try: + data_fim_prazo = tz.localize(datetime.strptime( + request.POST['data_fim_prazo'], "%d/%m/%Y")) + except ValueError: + msg = _('Formato da data fim do prazo incorreto.') + messages.add_message(request, messages.ERROR, msg) + return self.get(request, self.kwargs) # issue https://github.com/interlegis/sapl/issues/1123 # TODO: usar Form urgente = request.POST['urgente'] == 'True' flag_error = False for materia_id in marcadas: + try: + data_tramitacao = tz.localize(datetime.strptime( + request.POST['data_tramitacao'], "%d/%m/%Y")) + except ValueError: + msg = _('Formato da data da tramitação incorreto.') + messages.add_message(request, messages.ERROR, msg) + return self.get(request, self.kwargs) + t = Tramitacao( materia_id=materia_id, - data_tramitacao=tz.localize(datetime.strptime( - request.POST['data_tramitacao'], "%d/%m/%Y")), + data_tramitacao=data_tramitacao, data_encaminhamento=data_encaminhamento, data_fim_prazo=data_fim_prazo, unidade_tramitacao_local_id=request.POST[ From 0c464b685930aa28476c134d003e138c0c9434a3 Mon Sep 17 00:00:00 2001 From: Victor Fabre Date: Thu, 20 Dec 2018 14:04:13 -0200 Subject: [PATCH 03/41] Fix #2435 (#2436) --- sapl/base/views.py | 7 ++++++- sapl/templates/base/RelatorioPresencaSessao_filter.html | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/sapl/base/views.py b/sapl/base/views.py index 599d6b05f..8d5acce7b 100644 --- a/sapl/base/views.py +++ b/sapl/base/views.py @@ -10,7 +10,7 @@ from django.contrib.auth.tokens import default_token_generator from django.core.exceptions import ObjectDoesNotExist, PermissionDenied from django.core.mail import send_mail from django.core.urlresolvers import reverse -from django.db.models import Count +from django.db.models import Count, Q from django.http import Http404, HttpResponseRedirect from django.template import TemplateDoesNotExist from django.template.loader import get_template @@ -373,8 +373,13 @@ class RelatorioPresencaSessaoView(FilterView): # Completa o dicionario as informacoes parlamentar/sessao/ordem parlamentares_presencas = [] for i, p in enumerate(parlamentares_qs): + m = p.mandato_set.filter(Q(data_inicio_mandato__lte=_range[0], data_fim_mandato__gte=_range[1]) | + Q(data_inicio_mandato__lte=_range[0], data_fim_mandato__isnull=True) | + Q(data_inicio_mandato__gte=_range[0], data_fim_mandato__lte=_range[1])) + m = m.last() parlamentares_presencas.append({ 'parlamentar': p, + 'titular': m.titular, 'sessao_porc': 0, 'ordemdia_porc': 0 }) diff --git a/sapl/templates/base/RelatorioPresencaSessao_filter.html b/sapl/templates/base/RelatorioPresencaSessao_filter.html index e3e447f8d..9836235ca 100644 --- a/sapl/templates/base/RelatorioPresencaSessao_filter.html +++ b/sapl/templates/base/RelatorioPresencaSessao_filter.html @@ -25,6 +25,7 @@ Nome Parlamentar / Partido + Titular Sessão Ordem do Dia @@ -39,6 +40,7 @@ {% for p in parlamentares %} {{p.parlamentar}} / {{p.parlamentar|filiacao_intervalo_filter:date_range|default:"Sem Partido"}} + {%if p.titular %} Sim {% else %} Não {% endif %} {{p.sessao_count}} {{p.sessao_porc}} {{p.ordemdia_count}} From 90dec5fd76c33df51828a58802b5e1e6e1df76db Mon Sep 17 00:00:00 2001 From: Edward Date: Thu, 20 Dec 2018 14:13:24 -0200 Subject: [PATCH 04/41] Fixes #2055 - Busca Textual (#2179) Fixes #2055 - Busca Textual --- Dockerfile | 5 +- sapl/base/search_indexes.py | 72 +- sapl/materia/views.py | 2 + sapl/norma/views.py | 2 + sapl/settings.py | 21 +- .../materia/materialegislativa_filter.html | 10 +- .../templates/norma/normajuridica_filter.html | 10 +- solr/docker-compose.yml | 61 + .../sapl_configset/conf/lang/stopwords_en.txt | 54 + .../sapl_configset/conf/lang/stopwords_pt.txt | 253 +++ solr/sapl_configset/conf/managed-schema | 573 +++++++ solr/sapl_configset/conf/params.json | 20 + solr/sapl_configset/conf/protwords.txt | 21 + solr/sapl_configset/conf/saplconfigset.zip | Bin 0 -> 30297 bytes solr/sapl_configset/conf/schema.xml | 165 ++ solr/sapl_configset/conf/solrconfig.xml | 1367 +++++++++++++++++ solr/sapl_configset/conf/stopwords.txt | 14 + solr/sapl_configset/conf/synonyms.txt | 29 + solr_api.py | 155 ++ start.sh | 18 +- 20 files changed, 2797 insertions(+), 55 deletions(-) create mode 100644 solr/docker-compose.yml create mode 100644 solr/sapl_configset/conf/lang/stopwords_en.txt create mode 100644 solr/sapl_configset/conf/lang/stopwords_pt.txt create mode 100644 solr/sapl_configset/conf/managed-schema create mode 100644 solr/sapl_configset/conf/params.json create mode 100644 solr/sapl_configset/conf/protwords.txt create mode 100644 solr/sapl_configset/conf/saplconfigset.zip create mode 100644 solr/sapl_configset/conf/schema.xml create mode 100644 solr/sapl_configset/conf/solrconfig.xml create mode 100644 solr/sapl_configset/conf/stopwords.txt create mode 100644 solr/sapl_configset/conf/synonyms.txt create mode 100755 solr_api.py diff --git a/Dockerfile b/Dockerfile index 3f3adc78e..ffb812d6b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,9 @@ FROM alpine:3.8 ENV BUILD_PACKAGES postgresql-dev graphviz-dev graphviz build-base git pkgconfig \ - python3-dev libxml2-dev jpeg-dev libressl-dev libffi-dev libxslt-dev \ - nodejs npm py3-lxml py3-magic postgresql-client poppler-utils antiword vim openssh-client + python3-dev libxml2-dev jpeg-dev libressl-dev libffi-dev libxslt-dev \ + nodejs npm py3-lxml py3-magic postgresql-client poppler-utils antiword \ + curl jq openssh-client vim openssh-client RUN apk update --update-cache && apk upgrade diff --git a/sapl/base/search_indexes.py b/sapl/base/search_indexes.py index f1ec87ddd..0e0283ba8 100644 --- a/sapl/base/search_indexes.py +++ b/sapl/base/search_indexes.py @@ -1,6 +1,4 @@ import os.path -import re -import string import textract import logging @@ -8,6 +6,7 @@ from django.db.models import F, Q, Value from django.db.models.fields import TextField from django.db.models.functions import Concat from django.template import loader +from haystack import connections from haystack.constants import Indexable from haystack.fields import CharField from haystack.indexes import SearchIndex @@ -24,6 +23,7 @@ from sapl.utils import RemoveTag class TextExtractField(CharField): + backend = None logger = logging.getLogger(__name__) def __init__(self, **kwargs): @@ -34,24 +34,20 @@ class TextExtractField(CharField): self.model_attr = (self.model_attr, ) def solr_extraction(self, arquivo): - extracted_data = self._get_backend(None).extract_file_contents( - arquivo)['contents'] - # Remove as tags xml - self.logger.debug("Removendo as tags xml.") - extracted_data = re.sub('<[^>]*>', '', extracted_data) - # Remove tags \t e \n - self.logger.debug("Removendo as \t e \n.") - extracted_data = extracted_data.replace( - '\n', ' ').replace('\t', ' ') - # Remove sinais de pontuação - self.logger.debug("Removendo sinais de pontuação.") - extracted_data = re.sub('[' + string.punctuation + ']', - ' ', extracted_data) - # Remove espaços múltiplos - self.logger.debugger("Removendo espaços múltiplos.") - extracted_data = " ".join(extracted_data.split()) - - return extracted_data + if not self.backend: + self.backend = connections['default'].get_backend() + try: + with open(arquivo.path, 'rb') as f: + content = self.backend.extract_file_contents(f) + if not content or not content['contents']: + return '' + data = content['contents'] + except Exception as e: + print('erro processando arquivo: ' % arquivo.path) + self.logger.error(arquivo.path) + self.logger.error('erro processando arquivo: ' % arquivo.path) + data = '' + return data def whoosh_extraction(self, arquivo): @@ -66,11 +62,11 @@ class TextExtractField(CharField): language='pt-br').decode('utf-8').replace('\n', ' ').replace( '\t', ' ') - def print_error(self, arquivo): - self.logger.error("Erro inesperado processando arquivo: {}".format(arquivo.path)) - msg = 'Erro inesperado processando arquivo: %s' % ( - arquivo.path) - print(msg) + def print_error(self, arquivo, error): + msg = 'Erro inesperado processando arquivo %s erro: %s' % ( + arquivo.path, error) + print(msg, error) + self.logger.error(msg, error) def file_extractor(self, arquivo): if not os.path.exists(arquivo.path) or \ @@ -81,9 +77,9 @@ class TextExtractField(CharField): if SOLR_URL: try: return self.solr_extraction(arquivo) - except Exception as e: - self.logger.error("Erro no arquivo {}. ".format(arquivo.path) + str(e)) - self.print_error(arquivo) + except Exception as err: + print(str(err)) + self.print_error(arquivo, err) # Em ambiente de DEV utiliza-se o Whoosh # Como ele não possui extração, faz-se uso do textract @@ -91,13 +87,13 @@ class TextExtractField(CharField): try: self.logger.debug("Tentando whoosh_extraction no arquivo {}".format(arquivo.path)) return self.whoosh_extraction(arquivo) - except ExtensionNotSupported as e: - self.logger.error("Erro no arquivo {}".format(arquivo.path) + str(e)) - print(str(e)) - except Exception as e2: - self.logger.error(str(e)) - print(str(e2)) self.print_error(arquivo) + except ExtensionNotSupported as err: + print(str(err)) + self.logger.error(str(err)) + except Exception as err: + print(str(err)) + self.print_error(arquivo, str(err)) return '' def ta_extractor(self, value): @@ -133,7 +129,9 @@ class TextExtractField(CharField): value = getattr(obj, attr) if not value: continue - data += getattr(self, func)(value) + data += getattr(self, func)(value) + ' ' + + data = data.replace('\n', ' ') return data @@ -159,6 +157,10 @@ class DocumentoAcessorioIndex(SearchIndex, Indexable): ) ) + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.text.search_index = self + def get_model(self): return self.model diff --git a/sapl/materia/views.py b/sapl/materia/views.py index 578357721..8af8a19e2 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -1810,6 +1810,8 @@ class MateriaLegislativaPesquisaView(FilterView): context['show_results'] = show_results_filter_set(qr) + context['USE_SOLR'] = settings.USE_SOLR if hasattr(settings, 'USE_SOLR') else False + return context diff --git a/sapl/norma/views.py b/sapl/norma/views.py index f7800c42f..0e0ed23e4 100644 --- a/sapl/norma/views.py +++ b/sapl/norma/views.py @@ -15,6 +15,7 @@ from django.views.generic import TemplateView, UpdateView from django.views.generic.base import RedirectView from django.views.generic.edit import FormView from django_filters.views import FilterView +from sapl import settings from sapl.base.models import AppConfig from sapl.compilacao.views import IntegracaoTaView from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud, CrudAux, @@ -107,6 +108,7 @@ class NormaPesquisaView(FilterView): context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' context['show_results'] = show_results_filter_set(qr) + context['USE_SOLR'] = settings.USE_SOLR if hasattr(settings, 'USE_SOLR') else False return context diff --git a/sapl/settings.py b/sapl/settings.py index d30b4df3c..0d6a452bc 100755 --- a/sapl/settings.py +++ b/sapl/settings.py @@ -100,23 +100,28 @@ INSTALLED_APPS = ( # FTS = Full Text Search # Desabilita a indexação textual até encontramos uma solução para a issue # https://github.com/interlegis/sapl/issues/2055 -#HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor' -HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.BaseSignalProcessor' +#HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.BaseSignalProcessor' # Disable auto index +HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor' SEARCH_BACKEND = 'haystack.backends.whoosh_backend.WhooshEngine' SEARCH_URL = ('PATH', PROJECT_DIR.child('whoosh')) -SOLR_URL = config('SOLR_URL', cast=str, default='') -if SOLR_URL: +# SOLR +USE_SOLR = config('USE_SOLR', cast=bool, default=False) +SOLR_URL = config('SOLR_URL', cast=str, default='http://localhost:8983') +SOLR_COLLECTION = config('SOLR_COLLECTION', cast=str, default='sapl') + +if USE_SOLR: SEARCH_BACKEND = 'haystack.backends.solr_backend.SolrEngine' - SEARCH_URL = ('URL', config('SOLR_URL', cast=str)) - # ...or for multicore... - # 'URL': 'http://127.0.0.1:8983/solr/mysite', + SEARCH_URL = ('URL', '{}/solr/{}'.format(SOLR_URL, SOLR_COLLECTION)) +# BATCH_SIZE: default is 1000 if omitted, avoid Too Large Entity Body errors HAYSTACK_CONNECTIONS = { 'default': { 'ENGINE': SEARCH_BACKEND, - SEARCH_URL[0]: SEARCH_URL[1] + SEARCH_URL[0]: SEARCH_URL[1], + 'BATCH_SIZE': 500, + 'TIMEOUT': 60, }, } diff --git a/sapl/templates/materia/materialegislativa_filter.html b/sapl/templates/materia/materialegislativa_filter.html index cdd408af3..5ff3eaee0 100644 --- a/sapl/templates/materia/materialegislativa_filter.html +++ b/sapl/templates/materia/materialegislativa_filter.html @@ -3,11 +3,13 @@ {% load crispy_forms_tags %} {% block actions %} +
- + {% if USE_SOLR %} + + Pesquisa Textual + + {% endif %} {% if perms.materia.add_materialegislativa %} diff --git a/sapl/templates/norma/normajuridica_filter.html b/sapl/templates/norma/normajuridica_filter.html index ef668cf36..0c7547661 100644 --- a/sapl/templates/norma/normajuridica_filter.html +++ b/sapl/templates/norma/normajuridica_filter.html @@ -4,11 +4,11 @@ {% block actions %}
- + {% if USE_SOLR %} + + Pesquisa Textual + + {% endif %} {% if perms.norma.add_normajuridica %} diff --git a/solr/docker-compose.yml b/solr/docker-compose.yml new file mode 100644 index 000000000..2f97a7e10 --- /dev/null +++ b/solr/docker-compose.yml @@ -0,0 +1,61 @@ +version: '2' +services: + sapldb: + image: postgres:10.5-alpine + restart: always + environment: + POSTGRES_PASSWORD: sapl + POSTGRES_USER: sapl + POSTGRES_DB: sapl + PGDATA : /var/lib/postgresql/data/ + volumes: + - sapldb_data:/var/lib/postgresql/data/ + ports: + - "5432:5432" + + saplsolr: + image: solr:7.4-alpine + restart: always + command: bin/solr start -c -f + volumes: + - solr_data:/opt/solr/server/solr + - solr_configsets:/opt/solr/server/solr/configsets + ports: + - "8983:8983" + + sapl: + image: interlegis/sapl:3.1.138 + # build: . + restart: always + environment: + ADMIN_PASSWORD: interlegis + ADMIN_EMAIL: email@dominio.net + DEBUG: 'False' + USE_TLS: 'False' + EMAIL_PORT: 587 + EMAIL_HOST: smtp.dominio.net + EMAIL_HOST_USER: usuariosmtp + EMAIL_HOST_PASSWORD: senhasmtp + USE_SOLR: 'True' + #SOLR_COLLECTION: sapl + #SOLR_HOST: saplsolr + SOLR_URL: http://saplsolr:8983/solr/sapl + TZ: America/Sao_Paulo + volumes: + - sapl_data:/var/interlegis/sapl/data + - sapl_media:/var/interlegis/sapl/media + - sapl_root:/var/interlegis/sapl + volumes_from: + - saplsolr + depends_on: + - sapldb + - saplsolr + ports: + - "80:80" +volumes: + sapldb_data: + sapl_data: + sapl_media: + sapl_root: + solr_data: + solr_configsets: diff --git a/solr/sapl_configset/conf/lang/stopwords_en.txt b/solr/sapl_configset/conf/lang/stopwords_en.txt new file mode 100644 index 000000000..2c164c0b2 --- /dev/null +++ b/solr/sapl_configset/conf/lang/stopwords_en.txt @@ -0,0 +1,54 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# a couple of test stopwords to test that the words are really being +# configured from this file: +stopworda +stopwordb + +# Standard english stop words taken from Lucene's StopAnalyzer +a +an +and +are +as +at +be +but +by +for +if +in +into +is +it +no +not +of +on +or +such +that +the +their +then +there +these +they +this +to +was +will +with diff --git a/solr/sapl_configset/conf/lang/stopwords_pt.txt b/solr/sapl_configset/conf/lang/stopwords_pt.txt new file mode 100644 index 000000000..acfeb01af --- /dev/null +++ b/solr/sapl_configset/conf/lang/stopwords_pt.txt @@ -0,0 +1,253 @@ + | From svn.tartarus.org/snowball/trunk/website/algorithms/portuguese/stop.txt + | This file is distributed under the BSD License. + | See http://snowball.tartarus.org/license.php + | Also see http://www.opensource.org/licenses/bsd-license.html + | - Encoding was converted to UTF-8. + | - This notice was added. + | + | NOTE: To use this file with StopFilterFactory, you must specify format="snowball" + + | A Portuguese stop word list. Comments begin with vertical bar. Each stop + | word is at the start of a line. + + + | The following is a ranked list (commonest to rarest) of stopwords + | deriving from a large sample of text. + + | Extra words have been added at the end. + +de | of, from +a | the; to, at; her +o | the; him +que | who, that +e | and +do | de + o +da | de + a +em | in +um | a +para | for + | é from SER +com | with +não | not, no +uma | a +os | the; them +no | em + o +se | himself etc +na | em + a +por | for +mais | more +as | the; them +dos | de + os +como | as, like +mas | but + | foi from SER +ao | a + o +ele | he +das | de + as + | tem from TER +à | a + a +seu | his +sua | her +ou | or + | ser from SER +quando | when +muito | much + | há from HAV +nos | em + os; us +já | already, now + | está from EST +eu | I +também | also +só | only, just +pelo | per + o +pela | per + a +até | up to +isso | that +ela | he +entre | between + | era from SER +depois | after +sem | without +mesmo | same +aos | a + os + | ter from TER +seus | his +quem | whom +nas | em + as +me | me +esse | that +eles | they + | estão from EST +você | you + | tinha from TER + | foram from SER +essa | that +num | em + um +nem | nor +suas | her +meu | my +às | a + as +minha | my + | têm from TER +numa | em + uma +pelos | per + os +elas | they + | havia from HAV + | seja from SER +qual | which + | será from SER +nós | we + | tenho from TER +lhe | to him, her +deles | of them +essas | those +esses | those +pelas | per + as +este | this + | fosse from SER +dele | of him + + | other words. There are many contractions such as naquele = em+aquele, + | mo = me+o, but they are rare. + | Indefinite article plural forms are also rare. + +tu | thou +te | thee +vocês | you (plural) +vos | you +lhes | to them +meus | my +minhas +teu | thy +tua +teus +tuas +nosso | our +nossa +nossos +nossas + +dela | of her +delas | of them + +esta | this +estes | these +estas | these +aquele | that +aquela | that +aqueles | those +aquelas | those +isto | this +aquilo | that + + | forms of estar, to be (not including the infinitive): +estou +está +estamos +estão +estive +esteve +estivemos +estiveram +estava +estávamos +estavam +estivera +estivéramos +esteja +estejamos +estejam +estivesse +estivéssemos +estivessem +estiver +estivermos +estiverem + + | forms of haver, to have (not including the infinitive): +hei +há +havemos +hão +houve +houvemos +houveram +houvera +houvéramos +haja +hajamos +hajam +houvesse +houvéssemos +houvessem +houver +houvermos +houverem +houverei +houverá +houveremos +houverão +houveria +houveríamos +houveriam + + | forms of ser, to be (not including the infinitive): +sou +somos +são +era +éramos +eram +fui +foi +fomos +foram +fora +fôramos +seja +sejamos +sejam +fosse +fôssemos +fossem +for +formos +forem +serei +será +seremos +serão +seria +seríamos +seriam + + | forms of ter, to have (not including the infinitive): +tenho +tem +temos +tém +tinha +tínhamos +tinham +tive +teve +tivemos +tiveram +tivera +tivéramos +tenha +tenhamos +tenham +tivesse +tivéssemos +tivessem +tiver +tivermos +tiverem +terei +terá +teremos +terão +teria +teríamos +teriam diff --git a/solr/sapl_configset/conf/managed-schema b/solr/sapl_configset/conf/managed-schema new file mode 100644 index 000000000..0cba1950a --- /dev/null +++ b/solr/sapl_configset/conf/managed-schema @@ -0,0 +1,573 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/solr/sapl_configset/conf/params.json b/solr/sapl_configset/conf/params.json new file mode 100644 index 000000000..06114ef25 --- /dev/null +++ b/solr/sapl_configset/conf/params.json @@ -0,0 +1,20 @@ +{"params":{ + "query":{ + "defType":"edismax", + "q.alt":"*:*", + "rows":"10", + "fl":"*,score", + "":{"v":0} + }, + "facets":{ + "facet":"on", + "facet.mincount": "1", + "":{"v":0} + }, + "velocity":{ + "wt": "velocity", + "v.template":"browse", + "v.layout": "layout", + "":{"v":0} + } +}} \ No newline at end of file diff --git a/solr/sapl_configset/conf/protwords.txt b/solr/sapl_configset/conf/protwords.txt new file mode 100644 index 000000000..1dfc0abec --- /dev/null +++ b/solr/sapl_configset/conf/protwords.txt @@ -0,0 +1,21 @@ +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#----------------------------------------------------------------------- +# Use a protected word file to protect against the stemmer reducing two +# unrelated words to the same base word. + +# Some non-words that normally won't be encountered, +# just to test that they won't be stemmed. +dontstems +zwhacky + diff --git a/solr/sapl_configset/conf/saplconfigset.zip b/solr/sapl_configset/conf/saplconfigset.zip new file mode 100644 index 0000000000000000000000000000000000000000..13a7a41ce84f6f9fe4af1f73fd10906b37291d7e GIT binary patch literal 30297 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 z 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 a_5VbK`rFR@4`moUK=kkT9?bbauKpJT4iLEj literal 0 HcmV?d00001 diff --git a/solr/sapl_configset/conf/schema.xml b/solr/sapl_configset/conf/schema.xml new file mode 100644 index 000000000..597033929 --- /dev/null +++ b/solr/sapl_configset/conf/schema.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id + + + text + + + + diff --git a/solr/sapl_configset/conf/solrconfig.xml b/solr/sapl_configset/conf/solrconfig.xml new file mode 100644 index 000000000..9a9f29196 --- /dev/null +++ b/solr/sapl_configset/conf/solrconfig.xml @@ -0,0 +1,1367 @@ + + + + + + + + + 7.3.1 + + + + + + + + + + + + + + + + + + + + ${solr.data.dir:} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${solr.lock.type:native} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${solr.ulog.dir:} + ${solr.ulog.numVersionBuckets:65536} + + + + + 300000 + false + + + + + + 30000 + + + + + + + + + + + + + + 1024 + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + 20 + + + 200 + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + explicit + 10 + text + edismax + + + + + + + + + + + + + + + + explicit + json + true + + + + + + + + explicit + + + + + + _text_ + + + + + + + true + ignored_ + _text_ + + + + + + + + + text_general + + + + + + default + _text_ + solr.DirectSolrSpellChecker + + internal + + 0.5 + + 2 + + 1 + + 5 + + 4 + + 0.01 + + + + + + + + + + + + default + on + true + 10 + 5 + 5 + true + true + 10 + 5 + + + spellcheck + + + + + + + + + + true + + + tvComponent + + + + + + + + + + + + true + false + + + terms + + + + + + + + string + + + + + + explicit + + + elevator + + + + + + + + + + + 100 + + + + + + + + 70 + + 0.5 + + [-\w ,/\n\"']{20,200} + + + + + + + ]]> + ]]> + + + + + + + + + + + + + + + + + + + + + + + + ,, + ,, + ,, + ,, + ,]]> + ]]> + + + + + + 10 + .,!? + + + + + + + WORD + + + en + US + + + + + + + + + + + + [^\w-\.] + _ + + + + + + + yyyy-MM-dd'T'HH:mm:ss.SSSZ + yyyy-MM-dd'T'HH:mm:ss,SSSZ + yyyy-MM-dd'T'HH:mm:ss.SSS + yyyy-MM-dd'T'HH:mm:ss,SSS + yyyy-MM-dd'T'HH:mm:ssZ + yyyy-MM-dd'T'HH:mm:ss + yyyy-MM-dd'T'HH:mmZ + yyyy-MM-dd'T'HH:mm + yyyy-MM-dd HH:mm:ss.SSSZ + yyyy-MM-dd HH:mm:ss,SSSZ + yyyy-MM-dd HH:mm:ss.SSS + yyyy-MM-dd HH:mm:ss,SSS + yyyy-MM-dd HH:mm:ssZ + yyyy-MM-dd HH:mm:ss + yyyy-MM-dd HH:mmZ + yyyy-MM-dd HH:mm + yyyy-MM-dd + + + + + java.lang.String + text_general + + *_str + 256 + + + true + + + java.lang.Boolean + booleans + + + java.util.Date + pdates + + + java.lang.Long + java.lang.Integer + plongs + + + java.lang.Number + pdoubles + + + + + + + + + + + + + + + + + + + + + + + + + + text/plain; charset=UTF-8 + + + + + ${velocity.template.base.dir:} + ${velocity.solr.resource.loader.enabled:true} + ${velocity.params.resource.loader.enabled:false} + + + + + 5 + + + + + + + + + + + + + + diff --git a/solr/sapl_configset/conf/stopwords.txt b/solr/sapl_configset/conf/stopwords.txt new file mode 100644 index 000000000..ae1e83eeb --- /dev/null +++ b/solr/sapl_configset/conf/stopwords.txt @@ -0,0 +1,14 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/solr/sapl_configset/conf/synonyms.txt b/solr/sapl_configset/conf/synonyms.txt new file mode 100644 index 000000000..eab4ee875 --- /dev/null +++ b/solr/sapl_configset/conf/synonyms.txt @@ -0,0 +1,29 @@ +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#----------------------------------------------------------------------- +#some test synonym mappings unlikely to appear in real input text +aaafoo => aaabar +bbbfoo => bbbfoo bbbbar +cccfoo => cccbar cccbaz +fooaaa,baraaa,bazaaa + +# Some synonym groups specific to this example +GB,gib,gigabyte,gigabytes +MB,mib,megabyte,megabytes +Television, Televisions, TV, TVs +#notice we use "gib" instead of "GiB" so any WordDelimiterGraphFilter coming +#after us won't split it into two words. + +# Synonym mappings can be used for spelling correction too +pixima => pixma + diff --git a/solr_api.py b/solr_api.py new file mode 100755 index 000000000..9bec45daa --- /dev/null +++ b/solr_api.py @@ -0,0 +1,155 @@ + +import requests +import subprocess +import sys +import argparse + + +class SolrClient: + + LIST_CONFIGSETS = "{}/solr/admin/configs?action=LIST&omitHeader=true&wt=json" + UPLOAD_CONFIGSET = "{}/solr/admin/configs?action=UPLOAD&name={}&wt=json" + LIST_COLLECTIONS = "{}/solr/admin/collections?action=LIST&wt=json" + STATUS_COLLECTION = "{}/solr/admin/collections?action=CLUSTERSTATUS&collection={}&wt=json" + STATUS_CORE = "{}/admin/cores?action=STATUS&name={}" + EXISTS_COLLECTION = "{}/solr/{}/admin/ping?wt=json" + OPTIMIZE_COLLECTION = "{}/solr/{}/update?optimize=true&wt=json" + CREATE_COLLECTION = "{}/solr/admin/collections?action=CREATE&name={}&collection.configName={}&numShards={}&replicationFactor={}&maxShardsPerNode={}&wt=json" + DELETE_COLLECTION = "{}/solr/admin/collections?action=DELETE&name={}&wt=json" + DELETE_DATA = "{}/solr/{}/update?commitWithin=1000&overwrite=true&wt=json" + QUERY_DATA = "{}/solr/{}/select?q=*:*" + + CONFIGSET_NAME = "sapl_configset" + + def __init__(self, url): + self.url = url + + def get_num_docs(self, collection_name): + final_url = self.QUERY_DATA.format(self.url, collection_name) + res = requests.get(final_url) + dic = res.json() + num_docs = dic["response"]["numFound"] + return num_docs + + def list_collections(self): + req_url = self.LIST_COLLECTIONS.format(self.url) + res = requests.get(req_url) + dic = res.json() + return dic['collections'] + + def exists_collection(self, collection_name): + collections = self.list_collections() + return True if collection_name in collections else False + + def maybe_upload_configset(self, force=False): + req_url = self.LIST_CONFIGSETS.format(self.url) + res = requests.get(req_url) + dic = res.json() + configsets = dic['configSets'] + # UPLOAD configset + if not self.CONFIGSET_NAME in configsets or force: + files = {'file': ('saplconfigset.zip', + open('./solr/sapl_configset/conf/saplconfigset.zip', + 'rb'), + 'application/octet-stream', + {'Expires': '0'})} + + req_url = self.UPLOAD_CONFIGSET.format(self.url, self.CONFIGSET_NAME) + + resp = requests.post(req_url, files=files) + print(resp.content) + else: + print('O %s já presente no servidor, NÃO enviando.' % self.CONFIGSET_NAME) + + def create_collection(self, collection_name, shards=1, replication_factor=1, max_shards_per_node=1): + self.maybe_upload_configset() + req_url = self.CREATE_COLLECTION.format(self.url, + collection_name, + self.CONFIGSET_NAME, + shards, + replication_factor, + max_shards_per_node) + res = requests.post(req_url) + if res.ok: + print("Collection '%s' created succesfully" % collection_name) + else: + print("Error creating collection '%s'" % collection_name) + as_json = res.json() + print("Error %s: %s" % (res.status_code, as_json['error']['msg'])) + return False + return True + + def delete_collection(self, collection_name): + if collection_name == '*': + collections = self.list_collections() + else: + collections = [collection_name] + + for c in collections: + req_url = self.DELETE_COLLECTION.format(self.url, c) + res = requests.post(req_url) + if not res.ok: + print("Error deleting collection '%s'", c) + print("Code {}: {}".format(res.status_code, res.text)) + else: + print("Collection '%s' deleted successfully!" % c) + + def delete_index_data(self, collection_name): + req_url = self.DELETE_DATA.format(self.url, collection_name) + res = requests.post(req_url, + data='*:*', + headers={'Content-Type': 'application/xml'}) + if not res.ok: + print("Error deleting index for collection '%s'", collection_name) + print("Code {}: {}".format(res.status_code, res.text)) + else: + print("Collection '%s' data deleted successfully!" % collection_name) + + num_docs = self.get_num_docs(collection_name) + print("Num docs: %s" % num_docs) + + +if __name__ == '__main__': + + parser = argparse.ArgumentParser(description='Cria uma collection no Solr') + + # required arguments + parser.add_argument('-u', type=str, metavar='URL', nargs=1, dest='url', + required=True, help='Endereço do servidor Solr na forma http(s)://
[:port]') + parser.add_argument('-c', type=str, metavar='COLLECTION', dest='collection', nargs=1, + required=True, help='Collection Solr a ser criada') + + # optional arguments + parser.add_argument('-s', type=int, dest='shards', nargs='?', + help='Number of shards (default=1)', default=1) + parser.add_argument('-rf', type=int, dest='replication_factor', nargs='?', + help='Replication factor (default=1)', default=1) + parser.add_argument('-ms', type=int, dest='max_shards_per_node', nargs='?', + help='Max shards per node (default=1)', default=1) + + try: + args = parser.parse_args() + except IOError as msg: + parser.error(str(msg)) + sys.exit(-1) + + url = args.url.pop() + collection = args.collection.pop() + + client = SolrClient(url=url) + + if not client.exists_collection(collection): + print("Collection '%s' doesn't exists. Creating a new one..." % collection) + created = client.create_collection(collection, + shards=args.shards, + replication_factor=args.replication_factor, + max_shards_per_node=args.max_shards_per_node) + if not created: + sys.exit(-1) + else: + print("Collection '%s' exists." % collection) + + num_docs = client.get_num_docs(collection) + if num_docs == 0: + print("Performing a full reindex of '%s' collection..." % collection) + p = subprocess.call(["python3", "manage.py", "rebuild_index", "--noinput"]) diff --git a/start.sh b/start.sh index 9695572ef..865c37079 100755 --- a/start.sh +++ b/start.sh @@ -36,6 +36,10 @@ create_env() { echo "EMAIL_SEND_USER = ""${EMAIL_HOST_USER-''}" >> $FILENAME echo "DEFAULT_FROM_EMAIL = ""${EMAIL_HOST_USER-''}" >> $FILENAME echo "SERVER_EMAIL = ""${EMAIL_HOST_USER-''}" >> $FILENAME + echo "USE_SOLR = ""${USER_SOLR-True}" >> $FILENAME + echo "SOLR_COLLECTION = ""${SOLR_COLLECTION-'sapl'}" >> $FILENAME + echo "SOLR_URL = ""${SOLR_URL-'http://saplsolr:8983'}" >> $FILENAME + echo "[ENV FILE] done." } @@ -46,10 +50,22 @@ create_env /bin/sh busy-wait.sh $DATABASE_URL +## SOLR + +NUM_SHARDS=""${NUM_SHARDS-1}" +RF=""${RF-1}" +MAX_SHARDS_PER_NODE=""${NUM_SHARDS-1}" + +# Verifica se a variável USE_SOLR foi definida e é igual a True +if [[ ! -z "$USE_SOLR" ]] && [[ "$USE_SOLR" = "True" ]]; then + python3 solr_api.py -u $SOLR_URL -c $SOLR_COLLECTION -s $NUM_SHARDS -rf $RF -ms $MAX_SHARDS_PER_NODE & + # python3 manage.py rebuild_index --noinput & +fi + # manage.py migrate --noinput nao funcionava yes yes | python3 manage.py migrate #python3 manage.py collectstatic --no-input -# python3 manage.py rebuild_index --noinput & + echo "Criando usuário admin..." From 66038ec6adb78c0766c5038f5325e5efba3c4420 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Thu, 20 Dec 2018 14:57:31 -0200 Subject: [PATCH 05/41] Release: 3.1.139 --- docker-compose.yml | 2 +- sapl/templates/base.html | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 3691de798..45a2d206c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,7 +11,7 @@ sapldb: ports: - "5432:5432" sapl: - image: interlegis/sapl:3.1.138 + image: interlegis/sapl:3.1.139 restart: always environment: ADMIN_PASSWORD: interlegis diff --git a/sapl/templates/base.html b/sapl/templates/base.html index 0291ef7ba..b5a4d1098 100644 --- a/sapl/templates/base.html +++ b/sapl/templates/base.html @@ -184,7 +184,7 @@ Desenvolvido pelo Interlegis em software livre e aberto. - Release: 3.1.138 + Release: 3.1.139

diff --git a/setup.py b/setup.py index fd2490fbf..29e5d94f8 100644 --- a/setup.py +++ b/setup.py @@ -52,7 +52,7 @@ install_requires = [ ] setup( name='interlegis-sapl', - version='3.1.138', + version='3.1.139', packages=find_packages(), include_package_data=True, license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007', From 984a9cedef0d102c66d1131b6d87576656140138 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Thu, 20 Dec 2018 15:37:50 -0200 Subject: [PATCH 06/41] HOT-FIX: conserta --- start.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/start.sh b/start.sh index 865c37079..ab37fb86e 100755 --- a/start.sh +++ b/start.sh @@ -54,7 +54,7 @@ create_env NUM_SHARDS=""${NUM_SHARDS-1}" RF=""${RF-1}" -MAX_SHARDS_PER_NODE=""${NUM_SHARDS-1}" +MAX_SHARDS_PER_NODE=""${MAX_SHARDS_PER_NODE-1}" # Verifica se a variável USE_SOLR foi definida e é igual a True if [[ ! -z "$USE_SOLR" ]] && [[ "$USE_SOLR" = "True" ]]; then From 0c87632ffe8308e7a74aa57a60450cf834dd041f Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Thu, 20 Dec 2018 15:54:36 -0200 Subject: [PATCH 07/41] =?UTF-8?q?HOT-FIX:=20adiciona=20permiss=C3=A3o=20de?= =?UTF-8?q?=20acesso=20a=20vota=C3=A7=C3=A3o=20em=20bloco?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/sessao/views.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index b705e302f..0b18ccbcf 100755 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -3280,7 +3280,7 @@ class JustificativaAusenciaCrud(MasterDetailCrud): pass -class VotacaoEmBlocoExpediente(ListView): +class VotacaoEmBlocoExpediente(PermissionRequiredForAppCrudMixin, ListView): model = ExpedienteMateria template_name = 'sessao/votacao/votacao_bloco_expediente.html' @@ -3303,7 +3303,7 @@ class VotacaoEmBlocoExpediente(ListView): return context -class VotacaoEmBlocoOrdemDia(ListView): +class VotacaoEmBlocoOrdemDia(PermissionRequiredForAppCrudMixin, ListView): model = OrdemDia template_name = 'sessao/votacao/votacao_bloco_ordem.html' app_label = AppConfig.label @@ -3325,7 +3325,7 @@ class VotacaoEmBlocoOrdemDia(ListView): return context -class VotacaoEmBlocoSimbolicaView(TemplateView): +class VotacaoEmBlocoSimbolicaView(PermissionRequiredForAppCrudMixin, TemplateView): """ Votação Simbólica @@ -3502,7 +3502,7 @@ class VotacaoEmBlocoSimbolicaView(TemplateView): return self.render_to_response(context) -class VotacaoEmBlocoNominalView(TemplateView): +class VotacaoEmBlocoNominalView(PermissionRequiredForAppCrudMixin, TemplateView): """ Votação Nominal """ From b4b6d735fbe10d0c334a6aa4daa5cc29be9a0ee0 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Fri, 21 Dec 2018 16:54:58 -0200 Subject: [PATCH 08/41] HOT-FIX: fix docker entrypoint script --- sapl/settings.py | 2 +- start.sh | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/sapl/settings.py b/sapl/settings.py index 0d6a452bc..dba421f72 100755 --- a/sapl/settings.py +++ b/sapl/settings.py @@ -120,7 +120,7 @@ HAYSTACK_CONNECTIONS = { 'default': { 'ENGINE': SEARCH_BACKEND, SEARCH_URL[0]: SEARCH_URL[1], - 'BATCH_SIZE': 500, + 'BATCH_SIZE': 1000, 'TIMEOUT': 60, }, } diff --git a/start.sh b/start.sh index ab37fb86e..c3049adc3 100755 --- a/start.sh +++ b/start.sh @@ -36,7 +36,7 @@ create_env() { echo "EMAIL_SEND_USER = ""${EMAIL_HOST_USER-''}" >> $FILENAME echo "DEFAULT_FROM_EMAIL = ""${EMAIL_HOST_USER-''}" >> $FILENAME echo "SERVER_EMAIL = ""${EMAIL_HOST_USER-''}" >> $FILENAME - echo "USE_SOLR = ""${USER_SOLR-True}" >> $FILENAME + echo "USE_SOLR = ""${USE_SOLR-False}" >> $FILENAME echo "SOLR_COLLECTION = ""${SOLR_COLLECTION-'sapl'}" >> $FILENAME echo "SOLR_URL = ""${SOLR_URL-'http://saplsolr:8983'}" >> $FILENAME @@ -52,19 +52,18 @@ create_env ## SOLR -NUM_SHARDS=""${NUM_SHARDS-1}" -RF=""${RF-1}" -MAX_SHARDS_PER_NODE=""${MAX_SHARDS_PER_NODE-1}" +NUM_SHARDS=${NUM_SHARDS:=1} +RF=${RF:=1} +MAX_SHARDS_PER_NODE=${MAX_SHARDS_PER_NODE:=1} -# Verifica se a variável USE_SOLR foi definida e é igual a True -if [[ ! -z "$USE_SOLR" ]] && [[ "$USE_SOLR" = "True" ]]; then +if [ "${USE_SOLR-False}" == "True" ]; then python3 solr_api.py -u $SOLR_URL -c $SOLR_COLLECTION -s $NUM_SHARDS -rf $RF -ms $MAX_SHARDS_PER_NODE & # python3 manage.py rebuild_index --noinput & fi # manage.py migrate --noinput nao funcionava yes yes | python3 manage.py migrate -#python3 manage.py collectstatic --no-input +# python3 manage.py collectstatic --no-input echo "Criando usuário admin..." From fecf9ca04813fe4a8ed5470f2de625421660f4ac Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Fri, 21 Dec 2018 17:15:26 -0200 Subject: [PATCH 09/41] HOT-FIX: muda interpreter para BASH --- Dockerfile | 2 +- start.sh | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index ffb812d6b..f4953de84 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ FROM alpine:3.8 ENV BUILD_PACKAGES postgresql-dev graphviz-dev graphviz build-base git pkgconfig \ python3-dev libxml2-dev jpeg-dev libressl-dev libffi-dev libxslt-dev \ nodejs npm py3-lxml py3-magic postgresql-client poppler-utils antiword \ - curl jq openssh-client vim openssh-client + curl jq openssh-client vim openssh-client bash RUN apk update --update-cache && apk upgrade diff --git a/start.sh b/start.sh index c3049adc3..cdb3b6868 100755 --- a/start.sh +++ b/start.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash create_env() { echo "[ENV FILE] creating .env file..." @@ -48,17 +48,32 @@ create_env #python3 manage.py bower install -/bin/sh busy-wait.sh $DATABASE_URL +/bin/bash busy-wait.sh $DATABASE_URL ## SOLR +USE_SOLR="${USE_SOLR:=False}" +SOLR_URL="${SOLR_URL:='http://saplsolr:8983'}" +SOLR_COLLECTION="${SOLR_COLLECTION:='sapl_$RANDOM'}" NUM_SHARDS=${NUM_SHARDS:=1} RF=${RF:=1} MAX_SHARDS_PER_NODE=${MAX_SHARDS_PER_NODE:=1} if [ "${USE_SOLR-False}" == "True" ]; then + + echo "SOLR configurations" + echo "===================" + echo "URL: $SOLR_URL" + echo "COLLECTION: $SOLR_COLLECTION" + echo "NUM_SHARDS: $NUM_SHARDS" + echo "REPLICATION FACTOR: $RF" + echo "MAX SHARDS PER NODE: $MAX_SHARDS_PER_NODE" + echo "=========================================" + python3 solr_api.py -u $SOLR_URL -c $SOLR_COLLECTION -s $NUM_SHARDS -rf $RF -ms $MAX_SHARDS_PER_NODE & # python3 manage.py rebuild_index --noinput & +else + echo "Suporte a SOLR não inicializado." fi # manage.py migrate --noinput nao funcionava From bd24e8454a36b74777a26dc569ae5a82802acf25 Mon Sep 17 00:00:00 2001 From: Edward Date: Sat, 22 Dec 2018 10:21:13 -0200 Subject: [PATCH 10/41] =?UTF-8?q?Gerando=20nome=20de=20collection=20aleat?= =?UTF-8?q?=C3=B3rio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- start.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/start.sh b/start.sh index cdb3b6868..d3aa17c09 100755 --- a/start.sh +++ b/start.sh @@ -37,7 +37,7 @@ create_env() { echo "DEFAULT_FROM_EMAIL = ""${EMAIL_HOST_USER-''}" >> $FILENAME echo "SERVER_EMAIL = ""${EMAIL_HOST_USER-''}" >> $FILENAME echo "USE_SOLR = ""${USE_SOLR-False}" >> $FILENAME - echo "SOLR_COLLECTION = ""${SOLR_COLLECTION-'sapl'}" >> $FILENAME + echo "SOLR_COLLECTION = ""${SOLR_COLLECTION-'sapl_$RANDOM'}" >> $FILENAME echo "SOLR_URL = ""${SOLR_URL-'http://saplsolr:8983'}" >> $FILENAME From 53ce5bc5170af368f730476067c4b74d0bb480d4 Mon Sep 17 00:00:00 2001 From: Edward Date: Sat, 22 Dec 2018 10:50:07 -0200 Subject: [PATCH 11/41] =?UTF-8?q?Espera=20at=C3=A9=20que=20Solr=20esteja?= =?UTF-8?q?=20pronto=20para=20requests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- check_solr.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 check_solr.sh diff --git a/check_solr.sh b/check_solr.sh new file mode 100644 index 000000000..17ce5fe65 --- /dev/null +++ b/check_solr.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +echo "Waiting for solr connection at $SOLR_URL ..." +while true; do + echo "$SOLR_URL/solr/admin/collections?action=LIST" + RESULT=$(curl -s -o /dev/null -I "$SOLR_URL/solr/admin/collections?action=LIST" -w '%{http_code}') + echo $RESULT + if [ "$RESULT" -eq '200' ]; then + echo "Solr server is up!" + break + else + sleep 3 + fi +done From 2f23f2c8481941153ec7495130a83d7ddcc23c2a Mon Sep 17 00:00:00 2001 From: Edward Date: Sat, 22 Dec 2018 10:52:53 -0200 Subject: [PATCH 12/41] =?UTF-8?q?Espera=20at=C3=A9=20servidor=20Solr=20est?= =?UTF-8?q?ar=20pronto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- start.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/start.sh b/start.sh index d3aa17c09..a94cea7a5 100755 --- a/start.sh +++ b/start.sh @@ -69,6 +69,8 @@ if [ "${USE_SOLR-False}" == "True" ]; then echo "REPLICATION FACTOR: $RF" echo "MAX SHARDS PER NODE: $MAX_SHARDS_PER_NODE" echo "=========================================" + + /bin/bash check_solr.sh python3 solr_api.py -u $SOLR_URL -c $SOLR_COLLECTION -s $NUM_SHARDS -rf $RF -ms $MAX_SHARDS_PER_NODE & # python3 manage.py rebuild_index --noinput & From fefab6d94ea39ff4f790188cdb51f261ac441bae Mon Sep 17 00:00:00 2001 From: Victor Fabre Date: Fri, 28 Dec 2018 07:47:48 -0200 Subject: [PATCH 13/41] fix #2438 (#2439) * fix #2438 * tira ipdb --- sapl/sessao/forms.py | 4 ++-- sapl/sessao/views.py | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index 5a3cde342..87f7b9c47 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -540,10 +540,10 @@ class VotacaoForm(forms.Form): qtde_votos = votos_sim + votos_nao + abstencoes voto_presidente = cleaned_data['voto_presidente'] - if not voto_presidente: + if qtde_presentes and not voto_presidente: qtde_presentes -= 1 - if qtde_votos != qtde_presentes: + if qtde_presentes and qtde_votos != qtde_presentes: raise ValidationError('O total de votos não corresponde com a quantidade de presentes!') return cleaned_data diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index 0b18ccbcf..b4665429b 100755 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -1902,7 +1902,8 @@ class VotacaoView(SessaoPermissionMixin): qtde_presentes -= 1 if (qtde_votos > qtde_presentes or qtde_votos < qtde_presentes): - form._errors["total_votos"] = ErrorList([u""]) + msg = _('O total de votos não corresponde com a quantidade de presentes!') + messages.add_message(request, messages.ERROR, msg) return self.render_to_response(context) elif (qtde_presentes == qtde_votos): try: @@ -3330,7 +3331,7 @@ class VotacaoEmBlocoSimbolicaView(PermissionRequiredForAppCrudMixin, TemplateVie """ Votação Simbólica """ - + app_label = AppConfig.label template_name = 'sessao/votacao/votacao_simbolica_bloco.html' logger = logging.getLogger(__name__) @@ -3506,6 +3507,7 @@ class VotacaoEmBlocoNominalView(PermissionRequiredForAppCrudMixin, TemplateView) """ Votação Nominal """ + app_label = AppConfig.label template_name = 'sessao/votacao/votacao_nominal_bloco.html' logger = logging.getLogger(__name__) From 143b8c9e309a42d6360ad2beb5c3328f6eb8e4c1 Mon Sep 17 00:00:00 2001 From: Victor Fabre Date: Fri, 28 Dec 2018 08:07:56 -0200 Subject: [PATCH 14/41] Release: 3.1.140 --- docker-compose.yml | 2 +- sapl/templates/base.html | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 45a2d206c..e3980a639 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,7 +11,7 @@ sapldb: ports: - "5432:5432" sapl: - image: interlegis/sapl:3.1.139 + image: interlegis/sapl:3.1.140 restart: always environment: ADMIN_PASSWORD: interlegis diff --git a/sapl/templates/base.html b/sapl/templates/base.html index b5a4d1098..59f9919f1 100644 --- a/sapl/templates/base.html +++ b/sapl/templates/base.html @@ -184,7 +184,7 @@ Desenvolvido pelo Interlegis em software livre e aberto. - Release: 3.1.139 + Release: 3.1.140

diff --git a/setup.py b/setup.py index 29e5d94f8..aa79dc5b8 100644 --- a/setup.py +++ b/setup.py @@ -52,7 +52,7 @@ install_requires = [ ] setup( name='interlegis-sapl', - version='3.1.139', + version='3.1.140', packages=find_packages(), include_package_data=True, license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007', From 0008b1c2775f966e91499d0fc289305a89066cdd Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Fri, 28 Dec 2018 11:30:22 -0200 Subject: [PATCH 15/41] Reposiciona Solr para depois do migrate --- start.sh | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/start.sh b/start.sh index a94cea7a5..e55739436 100755 --- a/start.sh +++ b/start.sh @@ -38,7 +38,7 @@ create_env() { echo "SERVER_EMAIL = ""${EMAIL_HOST_USER-''}" >> $FILENAME echo "USE_SOLR = ""${USE_SOLR-False}" >> $FILENAME echo "SOLR_COLLECTION = ""${SOLR_COLLECTION-'sapl_$RANDOM'}" >> $FILENAME - echo "SOLR_URL = ""${SOLR_URL-'http://saplsolr:8983'}" >> $FILENAME + echo "SOLR_URL = ""${SOLR_URL-'http://localhost:8983'}" >> $FILENAME echo "[ENV FILE] done." @@ -50,9 +50,15 @@ create_env /bin/bash busy-wait.sh $DATABASE_URL + +# manage.py migrate --noinput nao funcionava +yes yes | python3 manage.py migrate +# python3 manage.py collectstatic --no-input + + ## SOLR USE_SOLR="${USE_SOLR:=False}" -SOLR_URL="${SOLR_URL:='http://saplsolr:8983'}" +SOLR_URL="${SOLR_URL:='http://localhost:8983'}" SOLR_COLLECTION="${SOLR_COLLECTION:='sapl_$RANDOM'}" NUM_SHARDS=${NUM_SHARDS:=1} @@ -78,11 +84,6 @@ else echo "Suporte a SOLR não inicializado." fi -# manage.py migrate --noinput nao funcionava -yes yes | python3 manage.py migrate -# python3 manage.py collectstatic --no-input - - echo "Criando usuário admin..." user_created=$(python3 create_admin.py 2>&1) From 91548dd61662ede9cf09760ed9b304c4cbbb61f1 Mon Sep 17 00:00:00 2001 From: Edward Date: Tue, 1 Jan 2019 14:13:49 -0200 Subject: [PATCH 16/41] Pass Solr URL as parameter to shell script --- check_solr.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/check_solr.sh b/check_solr.sh index 17ce5fe65..b3c4760c4 100644 --- a/check_solr.sh +++ b/check_solr.sh @@ -1,5 +1,9 @@ #!/bin/bash +# Pass the base SOLR URL as parameter, i.e., bash check_solr http://localhost:8983 + +SOLR_URL=$1 + echo "Waiting for solr connection at $SOLR_URL ..." while true; do echo "$SOLR_URL/solr/admin/collections?action=LIST" From 0208c832ca429615b47209dc5817efa5798a08e0 Mon Sep 17 00:00:00 2001 From: Edward Date: Tue, 1 Jan 2019 14:14:48 -0200 Subject: [PATCH 17/41] Pass Solr URL as param to check_solr script --- start.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/start.sh b/start.sh index e55739436..1c87a6d1b 100755 --- a/start.sh +++ b/start.sh @@ -76,7 +76,7 @@ if [ "${USE_SOLR-False}" == "True" ]; then echo "MAX SHARDS PER NODE: $MAX_SHARDS_PER_NODE" echo "=========================================" - /bin/bash check_solr.sh + /bin/bash check_solr.sh $SOLR_URL python3 solr_api.py -u $SOLR_URL -c $SOLR_COLLECTION -s $NUM_SHARDS -rf $RF -ms $MAX_SHARDS_PER_NODE & # python3 manage.py rebuild_index --noinput & From cb82810a51beed926b687dfa299c4a8716fb3794 Mon Sep 17 00:00:00 2001 From: Edward Date: Tue, 1 Jan 2019 15:02:36 -0200 Subject: [PATCH 18/41] =?UTF-8?q?Customiza=20par=C3=A2metros=20do=20Solr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- start.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/start.sh b/start.sh index 1c87a6d1b..fb9a7bddd 100755 --- a/start.sh +++ b/start.sh @@ -37,8 +37,8 @@ create_env() { echo "DEFAULT_FROM_EMAIL = ""${EMAIL_HOST_USER-''}" >> $FILENAME echo "SERVER_EMAIL = ""${EMAIL_HOST_USER-''}" >> $FILENAME echo "USE_SOLR = ""${USE_SOLR-False}" >> $FILENAME - echo "SOLR_COLLECTION = ""${SOLR_COLLECTION-'sapl_$RANDOM'}" >> $FILENAME - echo "SOLR_URL = ""${SOLR_URL-'http://localhost:8983'}" >> $FILENAME + echo "SOLR_COLLECTION = ""${SOLR_COLLECTION-sapl}" >> $FILENAME + echo "SOLR_URL = ""${SOLR_URL-http://localhost:8983}" >> $FILENAME echo "[ENV FILE] done." @@ -58,8 +58,8 @@ yes yes | python3 manage.py migrate ## SOLR USE_SOLR="${USE_SOLR:=False}" -SOLR_URL="${SOLR_URL:='http://localhost:8983'}" -SOLR_COLLECTION="${SOLR_COLLECTION:='sapl_$RANDOM'}" +SOLR_URL="${SOLR_URL:=http://localhost:8983}" +SOLR_COLLECTION="${SOLR_COLLECTION:=sapl}" NUM_SHARDS=${NUM_SHARDS:=1} RF=${RF:=1} From 512147014b8a997207750b29cbf6feb131171b6e Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Tue, 1 Jan 2019 16:20:59 -0200 Subject: [PATCH 19/41] HOT-FIX: ajusta o ano para 2019 --- .../migrations/0034_auto_20190101_1618.py | 35 +++++++++++++++++++ .../migrations/0018_auto_20190101_1618.py | 25 +++++++++++++ .../migrations/0011_auto_20190101_1618.py | 25 +++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 sapl/materia/migrations/0034_auto_20190101_1618.py create mode 100644 sapl/norma/migrations/0018_auto_20190101_1618.py create mode 100644 sapl/protocoloadm/migrations/0011_auto_20190101_1618.py diff --git a/sapl/materia/migrations/0034_auto_20190101_1618.py b/sapl/materia/migrations/0034_auto_20190101_1618.py new file mode 100644 index 000000000..4c90de970 --- /dev/null +++ b/sapl/materia/migrations/0034_auto_20190101_1618.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.8 on 2019-01-01 18:18 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0033_auto_20181030_1039'), + ] + + operations = [ + migrations.AlterField( + model_name='materialegislativa', + name='ano', + field=models.PositiveSmallIntegerField(choices=[(2019, 2019), (2018, 2018), (2017, 2017), (2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], verbose_name='Ano'), + ), + migrations.AlterField( + model_name='materialegislativa', + name='ano_origem_externa', + field=models.PositiveSmallIntegerField(blank=True, choices=[(2019, 2019), (2018, 2018), (2017, 2017), (2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], null=True, verbose_name='Ano'), + ), + migrations.AlterField( + model_name='numeracao', + name='ano_materia', + field=models.PositiveSmallIntegerField(choices=[(2019, 2019), (2018, 2018), (2017, 2017), (2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], verbose_name='Ano'), + ), + migrations.AlterField( + model_name='proposicao', + name='ano', + field=models.PositiveSmallIntegerField(blank=True, choices=[(2019, 2019), (2018, 2018), (2017, 2017), (2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], default=None, null=True, verbose_name='Ano'), + ), + ] diff --git a/sapl/norma/migrations/0018_auto_20190101_1618.py b/sapl/norma/migrations/0018_auto_20190101_1618.py new file mode 100644 index 000000000..e2fa03289 --- /dev/null +++ b/sapl/norma/migrations/0018_auto_20190101_1618.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.8 on 2019-01-01 18:18 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('norma', '0017_normaestatisticas'), + ] + + operations = [ + migrations.AlterField( + model_name='anexonormajuridica', + name='ano', + field=models.PositiveSmallIntegerField(choices=[(2019, 2019), (2018, 2018), (2017, 2017), (2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], verbose_name='Ano'), + ), + migrations.AlterField( + model_name='normajuridica', + name='ano', + field=models.PositiveSmallIntegerField(choices=[(2019, 2019), (2018, 2018), (2017, 2017), (2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], verbose_name='Ano'), + ), + ] diff --git a/sapl/protocoloadm/migrations/0011_auto_20190101_1618.py b/sapl/protocoloadm/migrations/0011_auto_20190101_1618.py new file mode 100644 index 000000000..5f3d7c51d --- /dev/null +++ b/sapl/protocoloadm/migrations/0011_auto_20190101_1618.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.8 on 2019-01-01 18:18 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('protocoloadm', '0010_auto_20181212_1900'), + ] + + operations = [ + migrations.AlterField( + model_name='documentoadministrativo', + name='ano', + field=models.PositiveSmallIntegerField(choices=[(2019, 2019), (2018, 2018), (2017, 2017), (2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], verbose_name='Ano'), + ), + migrations.AlterField( + model_name='protocolo', + name='ano', + field=models.PositiveSmallIntegerField(choices=[(2019, 2019), (2018, 2018), (2017, 2017), (2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], verbose_name='Ano do Protocolo'), + ), + ] From bf45e90eb5118130025be76d6fd00300a2554dd9 Mon Sep 17 00:00:00 2001 From: Edward de Oliveira Date: Tue, 1 Jan 2019 16:24:02 -0200 Subject: [PATCH 20/41] HOT-FIX: bump python version for TravisCI --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f54ee6d20..9f1c2e55d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: python python: - - 3.5 + - 3.7 services: - postgresql From 2073305da76fd64dc47d256c9b69a677a677f949 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Fri, 4 Jan 2019 08:59:30 -0200 Subject: [PATCH 21/41] Fix #2442 --- sapl/api/forms.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sapl/api/forms.py b/sapl/api/forms.py index b9ad11aca..14a6ef114 100644 --- a/sapl/api/forms.py +++ b/sapl/api/forms.py @@ -100,9 +100,9 @@ class AutorChoiceFilterSet(SaplGenericRelationSearchFilterSet): 'tipo', 'nome', ] - def filter_q(self, queryset, name,value): - return SaplGenericRelationSearchFilterSet.filter_q( - self, queryset, value).distinct('nome').order_by('nome') + def filter_q(self, queryset, name, value): + return super().filter_q( + queryset, name, value).distinct('nome').order_by('nome') class AutorSearchForFieldFilterSet(AutorChoiceFilterSet): From f8c38d6ac246a17dcbb2425c4a1bd96ea45e1081 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Fri, 4 Jan 2019 09:20:19 -0200 Subject: [PATCH 22/41] =?UTF-8?q?ajustes=20de=20pep8=20feito=20IDE=20em=20?= =?UTF-8?q?arquivos=20que=20ser=C3=A3o=20alterados=20no=20pr=C3=B3ximo=20c?= =?UTF-8?q?ommit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/materia/forms.py | 189 ++++++++++++++++++++----------------- sapl/norma/forms.py | 59 +++++++----- sapl/protocoloadm/forms.py | 88 ++++++++++------- sapl/sessao/forms.py | 56 ++++++----- 4 files changed, 223 insertions(+), 169 deletions(-) diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index 454cd9890..3c2c8c36e 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -1,11 +1,11 @@ -import os import logging -import django_filters -from crispy_forms.bootstrap import Alert, FormActions, InlineRadios +import os + +from crispy_forms.bootstrap import Alert, InlineRadios from crispy_forms.helper import FormHelper from crispy_forms.layout import (HTML, Button, Column, Div, Field, Fieldset, - Layout, Submit) + Layout) from django import forms from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ObjectDoesNotExist, ValidationError @@ -22,6 +22,7 @@ from django.utils.encoding import force_text from django.utils.html import format_html from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ +import django_filters import sapl from sapl.base.models import AppConfig, Autor, TipoAutor @@ -135,7 +136,8 @@ class MateriaSimplificadaForm(ModelForm): row1 = to_row([('tipo', 6), ('numero', 3), ('ano', 3)]) row2 = to_row([('data_apresentacao', 6), ('numero_protocolo', 6)]) - row3 = to_row([('regime_tramitacao', 6), ('em_tramitacao', 3), ('tipo_apresentacao', 3)]) + row3 = to_row([('regime_tramitacao', 6), + ('em_tramitacao', 3), ('tipo_apresentacao', 3)]) row4 = to_row([('ementa', 12)]) row5 = to_row([('texto_original', 12)]) @@ -162,7 +164,7 @@ class MateriaSimplificadaForm(ModelForm): if data_apresentacao.year != ano: self.logger.error("O ano da matéria ({}) é diferente" - " do ano na data de apresentação ({}).".format(ano, data_apresentacao.year)) + " do ano na data de apresentação ({}).".format(ano, data_apresentacao.year)) raise ValidationError("O ano da matéria não pode ser " "diferente do ano na data de apresentação") @@ -212,41 +214,42 @@ class MateriaLegislativaForm(ModelForm): protocolo_antigo = self.instance.numero_protocolo if protocolo: - if not Protocolo.objects.filter(numero=protocolo,ano=ano).exists(): + if not Protocolo.objects.filter(numero=protocolo, ano=ano).exists(): self.logger.error("Protocolo %s/%s não" - " existe" % (protocolo, ano)) + " existe" % (protocolo, ano)) raise ValidationError(_('Protocolo %s/%s não' ' existe' % (protocolo, ano))) if protocolo_antigo != protocolo: exist_materia = MateriaLegislativa.objects.filter( - numero_protocolo=protocolo, - ano=ano).exists() + numero_protocolo=protocolo, + ano=ano).exists() exist_doc = DocumentoAdministrativo.objects.filter( - protocolo_id=protocolo, - ano=ano).exists() + protocolo_id=protocolo, + ano=ano).exists() if exist_materia or exist_doc: self.logger.error("Protocolo %s/%s ja possui" - " documento vinculado" - % (protocolo, ano)) + " documento vinculado" + % (protocolo, ano)) raise ValidationError(_('Protocolo %s/%s ja possui' ' documento vinculado' - % (protocolo, ano))) + % (protocolo, ano))) - p = Protocolo.objects.get(numero=protocolo,ano=ano) + p = Protocolo.objects.get(numero=protocolo, ano=ano) if p.tipo_materia != cleaned_data['tipo']: self.logger.error("Tipo do Protocolo ({}) deve ser o mesmo do Tipo Matéria ({})." - .format(cleaned_data['tipo'], p.tipo_materia)) - raise ValidationError(_('Tipo do Protocolo deve ser o mesmo do Tipo Matéria')) + .format(cleaned_data['tipo'], p.tipo_materia)) + raise ValidationError( + _('Tipo do Protocolo deve ser o mesmo do Tipo Matéria')) if data_apresentacao.year != ano: self.logger.error("O ano da matéria ({}) é diferente " - "do ano na data de apresentação ({})." - .format(ano, data_apresentacao.year)) + "do ano na data de apresentação ({})." + .format(ano, data_apresentacao.year)) raise ValidationError(_("O ano da matéria não pode ser " - "diferente do ano na data de apresentação")) + "diferente do ano na data de apresentação")) ano_origem_externa = cleaned_data['ano_origem_externa'] data_origem_externa = cleaned_data['data_origem_externa'] @@ -254,11 +257,11 @@ class MateriaLegislativaForm(ModelForm): if ano_origem_externa and data_origem_externa and \ ano_origem_externa != data_origem_externa.year: self.logger.error("O ano de origem externa da matéria ({}) é " - " diferente do ano na data de origem externa ({})." - .format(ano_origem_externa, data_origem_externa)) + " diferente do ano na data de origem externa ({})." + .format(ano_origem_externa, data_origem_externa)) raise ValidationError(_("O ano de origem externa da matéria não " - "pode ser diferente do ano na data de " - "origem externa")) + "pode ser diferente do ano na data de " + "origem externa")) return cleaned_data @@ -280,6 +283,7 @@ class MateriaLegislativaForm(ModelForm): return materia + class UnidadeTramitacaoForm(ModelForm): logger = logging.getLogger(__name__) @@ -379,8 +383,8 @@ class RelatoriaForm(ModelForm): comissao = Comissao.objects.get(id=self.initial['comissao']) except ObjectDoesNotExist as e: self.logger.error("Objeto Comissao não encontrado com id={} " - ".A localização atual deve ser uma comissão. " - .format(self.initial['comissao']) + str(e)) + ".A localização atual deve ser uma comissão. " + .format(self.initial['comissao']) + str(e)) msg = _('A localização atual deve ser uma comissão.') raise ValidationError(msg) else: @@ -441,15 +445,15 @@ class TramitacaoForm(ModelForm): destino = ultima_tramitacao.unidade_tramitacao_destino if (destino != self.cleaned_data['unidade_tramitacao_local']): self.logger.error("A origem da nova tramitação ({}) não é igual ao " - "destino da última adicionada ({})!" - .format(self.cleaned_data['unidade_tramitacao_local'], destino)) + "destino da última adicionada ({})!" + .format(self.cleaned_data['unidade_tramitacao_local'], destino)) msg = _('A origem da nova tramitação deve ser igual ao ' 'destino da última adicionada!') raise ValidationError(msg) if cleaned_data['data_tramitacao'] > timezone.now().date(): self.logger.error('A data de tramitação informada ({}) não é ' + - 'menor ou igual a data de hoje!'.format(cleaned_data['data_tramitacao'])) + 'menor ou igual a data de hoje!'.format(cleaned_data['data_tramitacao'])) msg = _( 'A data de tramitação deve ser ' + 'menor ou igual a data de hoje!') @@ -460,8 +464,8 @@ class TramitacaoForm(ModelForm): msg = _('A data da nova tramitação deve ser ' + 'maior que a data da última tramitação!') self.logger.error("A data da nova tramitação ({}) deve ser " - "maior que a data da última tramitação ({})!" - .format(data_tram_form, ultima_tramitacao.data_tramitacao)) + "maior que a data da última tramitação ({})!" + .format(data_tram_form, ultima_tramitacao.data_tramitacao)) raise ValidationError(msg) if data_enc_form: @@ -469,8 +473,8 @@ class TramitacaoForm(ModelForm): msg = _('A data de encaminhamento deve ser ' + 'maior que a data de tramitação!') self.logger.error("A data de encaminhamento ({}) deve ser " - "maior que a data de tramitação! ({})" - .format(data_enc_form, data_tram_form)) + "maior que a data de tramitação! ({})" + .format(data_enc_form, data_tram_form)) raise ValidationError(msg) if data_prazo_form: @@ -478,8 +482,8 @@ class TramitacaoForm(ModelForm): msg = _('A data fim de prazo deve ser ' + 'maior que a data de tramitação!') self.logger.error("A data fim de prazo ({}) deve ser " + - "maior que a data de tramitação ({})!" - .format(data_prazo_form, data_tram_form)) + "maior que a data de tramitação ({})!" + .format(data_prazo_form, data_tram_form)) raise ValidationError(msg) return cleaned_data @@ -529,10 +533,10 @@ class TramitacaoUpdateForm(TramitacaoForm): if self.cleaned_data['unidade_tramitacao_destino'] != \ self.instance.unidade_tramitacao_destino: self.logger.error("Você não pode mudar a Unidade de Destino desta " - "tramitação para {}, pois irá conflitar com a Unidade " - "Local da tramitação seguinte ({})." - .format(self.cleaned_data['unidade_tramitacao_destino'], - self.instance.unidade_tramitacao_destino)) + "tramitação para {}, pois irá conflitar com a Unidade " + "Local da tramitação seguinte ({})." + .format(self.cleaned_data['unidade_tramitacao_destino'], + self.instance.unidade_tramitacao_destino)) raise ValidationError( 'Você não pode mudar a Unidade de Destino desta ' 'tramitação, pois irá conflitar com a Unidade ' @@ -589,15 +593,15 @@ class LegislacaoCitadaForm(ModelForm): try: self.logger.debug("Tentando obter objeto NormalJuridica (numero={}, ano={}, tipo={})." - .format(cleaned_data['numero'], cleaned_data['ano'], cleaned_data['tipo'])) + .format(cleaned_data['numero'], cleaned_data['ano'], cleaned_data['tipo'])) norma = NormaJuridica.objects.get( numero=cleaned_data['numero'], ano=cleaned_data['ano'], tipo=cleaned_data['tipo']) except ObjectDoesNotExist: self.logger.error("A norma a ser inclusa (numero={}, ano={}, tipo={}) " - "não existe no cadastro de Normas." - .format(cleaned_data['numero'], cleaned_data['ano'], cleaned_data['tipo'])) + "não existe no cadastro de Normas." + .format(cleaned_data['numero'], cleaned_data['ano'], cleaned_data['tipo'])) msg = _('A norma a ser inclusa não existe no cadastro' ' de Normas.') raise ValidationError(msg) @@ -643,6 +647,7 @@ class LegislacaoCitadaForm(ModelForm): class NumeracaoForm(ModelForm): logger = logging.getLogger(__name__) + class Meta: model = Numeracao fields = ['tipo_materia', @@ -658,8 +663,8 @@ class NumeracaoForm(ModelForm): try: self.logger.info("Tentando obter objeto MateriaLegislativa (numero={}, ano={}. tipo={})." - .format(self.cleaned_data['numero_materia'], - self.cleaned_data['ano_materia'], self.cleaned_data['tipo_materia'])) + .format(self.cleaned_data['numero_materia'], + self.cleaned_data['ano_materia'], self.cleaned_data['tipo_materia'])) MateriaLegislativa.objects.get( numero=self.cleaned_data['numero_materia'], ano=self.cleaned_data['ano_materia'], @@ -668,8 +673,8 @@ class NumeracaoForm(ModelForm): msg = _('A matéria a ser inclusa não existe no cadastro' ' de matérias legislativas.') self.logger.error("A MateriaLegislativa a ser inclusa (numero={}, ano={}. tipo={}) não existe no cadastro de matérias legislativas." - .format(self.cleaned_data['numero_materia'], - self.cleaned_data['ano_materia'], self.cleaned_data['tipo_materia'])) + .format(self.cleaned_data['numero_materia'], + self.cleaned_data['ano_materia'], self.cleaned_data['tipo_materia'])) raise ValidationError(msg) if Numeracao.objects.filter( @@ -680,8 +685,8 @@ class NumeracaoForm(ModelForm): ).exists(): msg = _('Essa numeração já foi cadastrada.') self.logger.error("Essa numeração (materia={}, tipo_materia={}, ano_materia={}, numero_materia={}) " - "já foi cadastrada.".format(self.instance.materia, self.cleaned_data['tipo_materia'], - self.cleaned_data['ano_materia'], self.cleaned_data['numero_materia'])) + "já foi cadastrada.".format(self.instance.materia, self.cleaned_data['tipo_materia'], + self.cleaned_data['ano_materia'], self.cleaned_data['numero_materia'])) raise ValidationError(msg) return self.cleaned_data @@ -716,7 +721,7 @@ class AnexadaForm(ModelForm): try: self.logger.info("Tentando obter objeto MateriaLegislativa (numero={}, ano={}, tipo={})." - .format(cleaned_data['numero'], cleaned_data['ano'], cleaned_data['tipo'])) + .format(cleaned_data['numero'], cleaned_data['ano'], cleaned_data['tipo'])) materia_anexada = MateriaLegislativa.objects.get( numero=cleaned_data['numero'], ano=cleaned_data['ano'], @@ -725,7 +730,7 @@ class AnexadaForm(ModelForm): msg = _('A MateriaLegislativa a ser anexada (numero={}, ano={}, tipo={}) não existe no cadastro' ' de matérias legislativas.'.format(cleaned_data['numero'], cleaned_data['ano'], cleaned_data['tipo'])) self.logger.error("A matéria a ser anexada não existe no cadastro" - " de matérias legislativas.") + " de matérias legislativas.") raise ValidationError(msg) materia_principal = self.instance.materia_principal @@ -971,7 +976,8 @@ class AutoriaForm(ModelForm): if ((not pk and autorias.exists()) or (pk and autorias.exclude(pk=pk).exists())): - self.logger.error("Esse Autor (pk={}) já foi cadastrado.".format(pk)) + self.logger.error( + "Esse Autor (pk={}) já foi cadastrado.".format(pk)) raise ValidationError(_('Esse Autor já foi cadastrado.')) return cd @@ -1022,7 +1028,8 @@ class AutoriaMultiCreateForm(Form): del self.errors['autores'] if 'autor' not in cd or not cd['autor'].exists(): - self.logger.error("Ao menos um autor deve ser selecionado para inclusão") + self.logger.error( + "Ao menos um autor deve ser selecionado para inclusão") raise ValidationError( _('Ao menos um autor deve ser selecionado para inclusão')) @@ -1204,7 +1211,7 @@ class TipoProposicaoForm(ModelForm): if not content_type.model_class().objects.filter( pk=cd['tipo_conteudo_related']).exists(): self.logger.error("O Registro definido (%s) não está na base de %s." - % (cd['tipo_conteudo_related'], content_type)) + % (cd['tipo_conteudo_related'], content_type)) raise ValidationError( _('O Registro definido (%s) não está na base de %s.' ) % (cd['tipo_conteudo_related'], content_type)) @@ -1377,11 +1384,11 @@ class ProposicaoForm(forms.ModelForm): 'texto_original', 7 if self.texto_articulado_proposicao else 12))) fields.append(to_column((Fieldset(_('Outras informações - Vincular a Matéria Legislativa Existente'), - to_column(('tipo_materia', 12)), - to_column(('numero_materia', 6)), - to_column(('ano_materia', 6)) - ), 12)), - ) + to_column(('tipo_materia', 12)), + to_column(('numero_materia', 6)), + to_column(('ano_materia', 6)) + ), 12)), + ) self.helper = FormHelper() self.helper.layout = SaplFormLayout(*fields) @@ -1410,9 +1417,10 @@ class ProposicaoForm(forms.ModelForm): texto_original = self.cleaned_data.get('texto_original', False) if texto_original and texto_original.size > MAX_DOC_UPLOAD_SIZE: max_size = str(MAX_DOC_UPLOAD_SIZE / (1024 * 1024)) - self.logger.error("- Arquivo muito grande. ( > {0}MB )".format(max_size)) + self.logger.error( + "- Arquivo muito grande. ( > {0}MB )".format(max_size)) raise ValidationError( - "Arquivo muito grande. ( > {0}MB )".format(max_size)) + "Arquivo muito grande. ( > {0}MB )".format(max_size)) return texto_original def gerar_hash(self, inst, receber_recibo): @@ -1443,7 +1451,7 @@ class ProposicaoForm(forms.ModelForm): if tm and am and nm: try: self.logger.debug("Tentando obter objeto MateriaLegislativa (tipo_id={}, ano={}, numero={})." - .format(tm, am, nm)) + .format(tm, am, nm)) materia_de_vinculo = MateriaLegislativa.objects.get( tipo_id=tm, ano=am, @@ -1451,11 +1459,11 @@ class ProposicaoForm(forms.ModelForm): ) except ObjectDoesNotExist: self.logger.error("Objeto MateriaLegislativa vinculada (tipo_id={}, ano={}, numero={}) não existe!" - .format(tm, am, nm)) + .format(tm, am, nm)) raise ValidationError(_('Matéria Vinculada não existe!')) else: self.logger.info("MateriaLegislativa vinculada (tipo_id={}, ano={}, numero={}) com sucesso." - .format(tm, am, nm)) + .format(tm, am, nm)) cd['materia_de_vinculo'] = materia_de_vinculo return cd @@ -1479,7 +1487,6 @@ class ProposicaoForm(forms.ModelForm): inst.texto_original.delete() self.gerar_hash(inst, receber_recibo) - return super().save(commit) inst.ano = timezone.now().year @@ -1732,8 +1739,8 @@ class ConfirmarProposicaoForm(ProposicaoForm): if not numeracao: self.logger.error("A sequência de numeração (por ano ou geral)" - " não foi configurada para a aplicação em " - "tabelas auxiliares") + " não foi configurada para a aplicação em " + "tabelas auxiliares") raise ValidationError("A sequência de numeração (por ano ou geral)" " não foi configurada para a aplicação em " "tabelas auxiliares") @@ -1751,7 +1758,7 @@ class ConfirmarProposicaoForm(ProposicaoForm): elif self.instance.tipo.content_type.model_class( ) == TipoDocumento and not cd['materia_de_vinculo']: self.logger.error("Documentos não podem ser incorporados sem definir " - "para qual Matéria Legislativa ele se destina.") + "para qual Matéria Legislativa ele se destina.") raise ValidationError( _('Documentos não podem ser incorporados sem definir ' 'para qual Matéria Legislativa ele se destina.')) @@ -1803,7 +1810,8 @@ class ConfirmarProposicaoForm(ProposicaoForm): numeracao = None try: - self.logger.debug("Tentando obter modelo de sequência de numeração.") + self.logger.debug( + "Tentando obter modelo de sequência de numeração.") numeracao = sapl.base.models.AppConfig.objects.last( ).sequencia_numeracao except AttributeError as e: @@ -1829,12 +1837,14 @@ class ConfirmarProposicaoForm(ProposicaoForm): tipo=tipo).aggregate( Max('numero')) elif numeracao == 'U': - numero = MateriaLegislativa.objects.filter(tipo=tipo).aggregate(Max('numero')) + numero = MateriaLegislativa.objects.filter( + tipo=tipo).aggregate(Max('numero')) if numeracao is None: numero['numero__max'] = 0 - max_numero = numero['numero__max'] + 1 if numero['numero__max'] else 1 + max_numero = numero['numero__max'] + \ + 1 if numero['numero__max'] else 1 # dados básicos materia = MateriaLegislativa() @@ -1974,7 +1984,8 @@ class ConfirmarProposicaoForm(ProposicaoForm): protocolo.tipo_protocolo = '1' - protocolo.interessado = str(proposicao.autor)[:200] # tamanho máximo 200 + protocolo.interessado = str(proposicao.autor)[ + :200] # tamanho máximo 200 protocolo.autor = proposicao.autor protocolo.assunto_ementa = proposicao.descricao protocolo.numero_paginas = cd['numero_de_paginas'] @@ -2083,7 +2094,7 @@ class EtiquetaPesquisaForm(forms.Form): if (not cleaned_data['data_inicial'] or not cleaned_data['data_final']): self.logger.error("Caso pesquise por data, os campos de Data Incial e " - "Data Final devem ser preenchidos obrigatoriamente") + "Data Final devem ser preenchidos obrigatoriamente") raise ValidationError(_( 'Caso pesquise por data, os campos de Data Incial e ' + 'Data Final devem ser preenchidos obrigatoriamente')) @@ -2091,7 +2102,7 @@ class EtiquetaPesquisaForm(forms.Form): # a inicial elif cleaned_data['data_final'] < cleaned_data['data_inicial']: self.logger.error("A Data Final ({}) não pode ser menor que a Data Inicial({})." - .format(cleaned_data['data_final'], cleaned_data['data_inicial'])) + .format(cleaned_data['data_final'], cleaned_data['data_inicial'])) raise ValidationError(_( 'A Data Final não pode ser menor que a Data Inicial')) @@ -2200,22 +2211,22 @@ class ExcluirTramitacaoEmLote(forms.Form): logger = logging.getLogger(__name__) data_tramitacao = forms.DateField(required=True, - label=_('Data da Tramitação')) + label=_('Data da Tramitação')) unidade_tramitacao_local = forms.ModelChoiceField(label=_('Unidade Local'), - required=True, - queryset=UnidadeTramitacao.objects.all(), - empty_label='------') + required=True, + queryset=UnidadeTramitacao.objects.all(), + empty_label='------') unidade_tramitacao_destino = forms.ModelChoiceField(label=_('Unidade Destino'), - required=True, - queryset=UnidadeTramitacao.objects.all(), - empty_label='------') + required=True, + queryset=UnidadeTramitacao.objects.all(), + empty_label='------') status = forms.ModelChoiceField(label=_('Status'), - required=True, - queryset=StatusTramitacao.objects.all(), - empty_label='------') + required=True, + queryset=StatusTramitacao.objects.all(), + empty_label='------') def clean(self): super(ExcluirTramitacaoEmLote, self).clean() @@ -2231,15 +2242,15 @@ class ExcluirTramitacaoEmLote(forms.Form): status = cleaned_data['status'] tramitacao_set = Tramitacao.objects.filter(data_tramitacao=data_tramitacao, - unidade_tramitacao_local=unidade_tramitacao_local, - unidade_tramitacao_destino=unidade_tramitacao_destino, - status=status) + unidade_tramitacao_local=unidade_tramitacao_local, + unidade_tramitacao_destino=unidade_tramitacao_destino, + status=status) if not tramitacao_set.exists(): self.logger.error("Não existem tramitações com os dados informados " " (data_tramitacao={}, unidade_tramitacao_local={})." "unidade_tramitacao_destino={}, status={})." .format(data_tramitacao, unidade_tramitacao_local, - unidade_tramitacao_destino, status)) + unidade_tramitacao_destino, status)) raise forms.ValidationError( _("Não existem tramitações com os dados informados.")) @@ -2250,7 +2261,7 @@ class ExcluirTramitacaoEmLote(forms.Form): row1 = to_row( [('data_tramitacao', 6), - ('status', 6),]) + ('status', 6), ]) row2 = to_row( [('unidade_tramitacao_local', 6), ('unidade_tramitacao_destino', 6)]) diff --git a/sapl/norma/forms.py b/sapl/norma/forms.py index 7cd8368f7..3429e1267 100644 --- a/sapl/norma/forms.py +++ b/sapl/norma/forms.py @@ -1,6 +1,6 @@ -import django_filters import logging + from crispy_forms.helper import FormHelper from crispy_forms.layout import Fieldset, Layout from django import forms @@ -9,6 +9,7 @@ from django.db import models from django.forms import ModelForm, widgets, ModelChoiceField from django.utils import timezone 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 @@ -73,7 +74,7 @@ class NormaFilterSet(django_filters.FilterSet): row2 = to_row([('data', 6), ('data_publicacao', 6)]) row3 = to_row([('ementa', 6), ('assuntos', 6)]) row4 = to_row([('data_vigencia', 12)]) - row5 = to_row([('o',6), ('indexacao', 6)]) + row5 = to_row([('o', 6), ('indexacao', 6)]) self.form.helper = FormHelper() self.form.helper.form_method = 'GET' @@ -131,9 +132,8 @@ class NormaJuridicaForm(ModelForm): 'assuntos'] widgets = {'assuntos': widgets.CheckboxSelectMultiple} - def clean(self): - + cleaned_data = super(NormaJuridicaForm, self).clean() if not self.is_valid(): @@ -142,8 +142,10 @@ class NormaJuridicaForm(ModelForm): import re has_digits = re.sub('[^0-9]', '', cleaned_data['numero']) if not has_digits: - self.logger.error("Número de norma ({}) não pode conter somente letras.".format(cleaned_data['numero'])) - raise ValidationError('Número de norma não pode conter somente letras') + self.logger.error("Número de norma ({}) não pode conter somente letras.".format( + cleaned_data['numero'])) + raise ValidationError( + 'Número de norma não pode conter somente letras') if self.instance.numero != cleaned_data['numero']: norma = NormaJuridica.objects.filter(ano=cleaned_data['ano'], @@ -157,7 +159,7 @@ class NormaJuridicaForm(ModelForm): "e Número no sistema") if (cleaned_data['tipo_materia'] and cleaned_data['numero_materia'] and - cleaned_data['ano_materia']): + cleaned_data['ano_materia']): try: self.logger.debug("Tentando obter objeto MateriaLegislativa com tipo={}, numero={}, ano={}." .format(cleaned_data['tipo_materia'], cleaned_data['numero_materia'], cleaned_data['ano_materia'])) @@ -168,9 +170,9 @@ class NormaJuridicaForm(ModelForm): except ObjectDoesNotExist: self.logger.error("Matéria Legislativa %s/%s (%s) é inexistente." % ( - self.cleaned_data['numero_materia'], - self.cleaned_data['ano_materia'], - cleaned_data['tipo_materia'].descricao)) + self.cleaned_data['numero_materia'], + self.cleaned_data['ano_materia'], + cleaned_data['tipo_materia'].descricao)) raise forms.ValidationError( _("Matéria Legislativa %s/%s (%s) é inexistente." % ( self.cleaned_data['numero_materia'], @@ -178,7 +180,7 @@ class NormaJuridicaForm(ModelForm): cleaned_data['tipo_materia'].descricao))) else: self.logger.info("MateriaLegislativa com tipo={}, numero={}, ano={} obtida com sucesso." - .format(cleaned_data['tipo_materia'], cleaned_data['numero_materia'], cleaned_data['ano_materia'])) + .format(cleaned_data['tipo_materia'], cleaned_data['numero_materia'], cleaned_data['ano_materia'])) cleaned_data['materia'] = materia else: @@ -198,10 +200,11 @@ class NormaJuridicaForm(ModelForm): texto_integral = self.cleaned_data.get('texto_integral', False) if texto_integral and texto_integral.size > MAX_DOC_UPLOAD_SIZE: max_size = str(MAX_DOC_UPLOAD_SIZE / (1024 * 1024)) - tam_fornecido = str( texto_integral.size / (1024*1024) ) - self.logger.error("Arquivo muito grande ({}MB). ( Tamanho máximo permitido: {}MB )".format(tam_fornecido, max_size)) + tam_fornecido = str(texto_integral.size / (1024 * 1024)) + self.logger.error("Arquivo muito grande ({}MB). ( Tamanho máximo permitido: {}MB )".format( + tam_fornecido, max_size)) raise ValidationError( - "Arquivo muito grande. ( > {0}MB )".format(max_size)) + "Arquivo muito grande. ( > {0}MB )".format(max_size)) return texto_integral def save(self, commit=False): @@ -256,11 +259,13 @@ class AutoriaNormaForm(ModelForm): if ((not pk and autorias.exists()) or (pk and autorias.exclude(pk=pk).exists())): - self.logger.error("Autor ({}) já foi cadastrado.".format(cd['autor'])) + self.logger.error( + "Autor ({}) já foi cadastrado.".format(cd['autor'])) raise ValidationError(_('Esse Autor já foi cadastrado.')) return cd + class AnexoNormaJuridicaForm(ModelForm): class Meta: model = AnexoNormaJuridica @@ -270,6 +275,7 @@ class AnexoNormaJuridicaForm(ModelForm): } logger = logging.getLogger(__name__) + def clean(self): cleaned_data = super(AnexoNormaJuridicaForm, self).clean() if not self.is_valid(): @@ -277,10 +283,11 @@ class AnexoNormaJuridicaForm(ModelForm): anexo_arquivo = self.cleaned_data.get('anexo_arquivo', False) if anexo_arquivo and anexo_arquivo.size > MAX_DOC_UPLOAD_SIZE: max_size = str(MAX_DOC_UPLOAD_SIZE / (1024 * 1024)) - tam_fornecido = str( anexo_arquivo.size / (1024*1024) ) - self.logger.error("Arquivo muito grande ({}MB). ( Tamanho máximo permitido: {}MB )".format(tam_fornecido, max_size)) + tam_fornecido = str(anexo_arquivo.size / (1024 * 1024)) + self.logger.error("Arquivo muito grande ({}MB). ( Tamanho máximo permitido: {}MB )".format( + tam_fornecido, max_size)) raise ValidationError( - "Arquivo muito grande. ( > {0}MB )".format(max_size)) + "Arquivo muito grande. ( > {0}MB )".format(max_size)) return cleaned_data def save(self, commit=False): @@ -294,7 +301,6 @@ class AnexoNormaJuridicaForm(ModelForm): return anexo - class NormaRelacionadaForm(ModelForm): tipo = forms.ModelChoiceField( @@ -310,6 +316,7 @@ class NormaRelacionadaForm(ModelForm): widget=forms.Textarea(attrs={'disabled': 'disabled'})) logger = logging.getLogger(__name__) + class Meta: model = NormaRelacionada fields = ['tipo', 'numero', 'ano', 'ementa', 'tipo_vinculo'] @@ -325,17 +332,20 @@ class NormaRelacionadaForm(ModelForm): cleaned_data = self.cleaned_data try: - self.logger.debug("Tentando obter objeto NormaJuridica com numero={}, ano={}, tipo={}.".format(cleaned_data['numero'], cleaned_data['ano'], cleaned_data['tipo'])) + self.logger.debug("Tentando obter objeto NormaJuridica com numero={}, ano={}, tipo={}.".format( + cleaned_data['numero'], cleaned_data['ano'], cleaned_data['tipo'])) norma_relacionada = NormaJuridica.objects.get( numero=cleaned_data['numero'], ano=cleaned_data['ano'], tipo=cleaned_data['tipo']) except ObjectDoesNotExist: - self.logger.info("NormaJuridica com numero={}, ano={}, tipo={} não existe.".format(cleaned_data['numero'], cleaned_data['ano'], cleaned_data['tipo'])) + self.logger.info("NormaJuridica com numero={}, ano={}, tipo={} não existe.".format( + cleaned_data['numero'], cleaned_data['ano'], cleaned_data['tipo'])) msg = _('A norma a ser relacionada não existe.') raise ValidationError(msg) else: - self.logger.info("NormaJuridica com numero={}, ano={}, tipo={} obtida com sucesso.".format(cleaned_data['numero'], cleaned_data['ano'], cleaned_data['tipo'])) + self.logger.info("NormaJuridica com numero={}, ano={}, tipo={} obtida com sucesso.".format( + cleaned_data['numero'], cleaned_data['ano'], cleaned_data['tipo'])) cleaned_data['norma_relacionada'] = norma_relacionada return cleaned_data @@ -408,7 +418,8 @@ class NormaPesquisaSimplesForm(forms.Form): if (data_inicial and data_final and data_inicial > data_final): - self.logger.error("Data Final ({}) menor que a Data Inicial ({}).".format(data_final, data_inicial)) + self.logger.error("Data Final ({}) menor que a Data Inicial ({}).".format( + data_final, data_inicial)) raise ValidationError(_( 'A Data Final não pode ser menor que a Data Inicial')) else: @@ -416,7 +427,7 @@ class NormaPesquisaSimplesForm(forms.Form): condicao2 = not data_inicial and data_final if condicao1 or condicao2: self.logger.error("Caso pesquise por data, os campos de Data Inicial e " - "Data Final devem ser preenchidos obrigatoriamente") + "Data Final devem ser preenchidos obrigatoriamente") raise ValidationError(_('Caso pesquise por data, os campos de Data Inicial e ' + 'Data Final devem ser preenchidos obrigatoriamente')) diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 97cab4eee..bd017fc8e 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -1,6 +1,6 @@ -import django_filters import logging + from crispy_forms.bootstrap import InlineRadios from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Button, Column, Fieldset, Layout @@ -12,6 +12,7 @@ from django.db.models import Max from django.forms import ModelForm from django.utils import timezone from django.utils.translation import ugettext_lazy as _ +import django_filters from sapl.base.models import Autor, TipoAutor from sapl.crispy_layout_mixin import SaplFormLayout, form_actions, to_row @@ -25,8 +26,11 @@ from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo, Protocolo, TipoDocumentoAdministrativo, TramitacaoAdministrativo) -TIPOS_PROTOCOLO = [('0', 'Recebido'), ('1', 'Enviado'), ('2', 'Interno'), ('', '---------')] -TIPOS_PROTOCOLO_CREATE = [('0', 'Recebido'), ('1', 'Enviado'), ('2', 'Interno')] + +TIPOS_PROTOCOLO = [('0', 'Recebido'), ('1', 'Enviado'), + ('2', 'Interno'), ('', '---------')] +TIPOS_PROTOCOLO_CREATE = [ + ('0', 'Recebido'), ('1', 'Enviado'), ('2', 'Interno')] NATUREZA_PROCESSO = [('', '---------'), ('0', 'Administrativo'), @@ -41,6 +45,7 @@ EM_TRAMITACAO = [('', '---------'), (0, 'Sim'), (1, 'Não')] + class AcompanhamentoDocumentoForm(ModelForm): class Meta: @@ -253,10 +258,12 @@ class AnularProcoloAdmForm(ModelForm): ano = cleaned_data['ano'] try: - self.logger.debug("Tentando obter Protocolo com numero={} e ano={}.".format(numero, ano)) + self.logger.debug( + "Tentando obter Protocolo com numero={} e ano={}.".format(numero, ano)) protocolo = Protocolo.objects.get(numero=numero, ano=ano) if protocolo.anulado: - self.logger.error("Protocolo %s/%s já encontra-se anulado" % (numero, ano)) + self.logger.error( + "Protocolo %s/%s já encontra-se anulado" % (numero, ano)) raise forms.ValidationError( _("Protocolo %s/%s já encontra-se anulado") % (numero, ano)) @@ -341,7 +348,8 @@ class ProtocoloDocumentForm(ModelForm): observacao = forms.CharField(required=False, widget=forms.Textarea, label=_('Observação')) - numero = forms.IntegerField(required=False, label=_('Número de Protocolo (opcional)')) + numero = forms.IntegerField( + required=False, label=_('Número de Protocolo (opcional)')) class Meta: model = Protocolo @@ -431,7 +439,8 @@ class ProtocoloMateriaForm(ModelForm): assunto_ementa = forms.CharField(required=True, widget=forms.Textarea, label=_('Ementa')) - numero = forms.IntegerField(required=False, label=_('Número de Protocolo (opcional)')) + numero = forms.IntegerField( + required=False, label=_('Número de Protocolo (opcional)')) class Meta: model = Protocolo @@ -450,13 +459,16 @@ class ProtocoloMateriaForm(ModelForm): def clean_autor(self): autor_field = self.cleaned_data['autor'] try: - self.logger.debug("Tentando obter Autor com id={}.".format(autor_field.id)) + self.logger.debug( + "Tentando obter Autor com id={}.".format(autor_field.id)) autor = Autor.objects.get(id=autor_field.id) except ObjectDoesNotExist: - self.logger.error("Autor com id={} não encontrado. Definido como None.".format(autor_field.id)) + self.logger.error( + "Autor com id={} não encontrado. Definido como None.".format(autor_field.id)) autor_field = None else: - self.logger.info("Autor com id={} encontrado com sucesso.".format(autor_field.id)) + self.logger.info( + "Autor com id={} encontrado com sucesso.".format(autor_field.id)) autor_field = autor return autor_field @@ -471,7 +483,8 @@ class ProtocoloMateriaForm(ModelForm): if data['vincular_materia'] == 'True': try: if not data['ano_materia'] or not data['numero_materia']: - self.logger.error("Não foram informados o número ou ano da matéria a ser vinculada") + self.logger.error( + "Não foram informados o número ou ano da matéria a ser vinculada") raise ValidationError( 'Favor informar o número e ano da matéria a ser vinculada') self.logger.debug("Tentando obter MateriaLegislativa com ano={}, numero={} e data={}." @@ -481,13 +494,14 @@ class ProtocoloMateriaForm(ModelForm): tipo=data['tipo_materia']) if self.materia.numero_protocolo: self.logger.error("MateriaLegislativa informada já possui o protocolo {}/{} vinculado." - .format(self.materia.numero_protocolo, self.materia.ano)) + .format(self.materia.numero_protocolo, self.materia.ano)) raise ValidationError(_('Matéria Legislativa informada já possui o protocolo {}/{} vinculado.' .format(self.materia.numero_protocolo, self.materia.ano))) except ObjectDoesNotExist: self.logger.error("MateriaLegislativa informada (ano={}, numero={} e data={}) não existente." .format(data['ano_materia'], data['numero_materia'], data['tipo_materia'])) - raise ValidationError(_('Matéria Legislativa informada não existente.')) + raise ValidationError( + _('Matéria Legislativa informada não existente.')) return data @@ -520,9 +534,9 @@ class ProtocoloMateriaForm(ModelForm): ), Fieldset(_('Número do Protocolo (Apenas se quiser que a numeração comece' ' a partir do número a ser informado)'), - row5, - HTML(" "), - form_actions(label=_('Protocolar Matéria'))) + row5, + HTML(" "), + form_actions(label=_('Protocolar Matéria'))) ) super(ProtocoloMateriaForm, self).__init__( @@ -703,9 +717,9 @@ class DocumentoAdministrativoForm(ModelForm): get_field('numero').verbose_name) restrito = forms.ChoiceField(label=_('Acesso Restrito'), - widget=forms.RadioSelect(), - choices=YES_NO_CHOICES, - initial=False) + widget=forms.RadioSelect(), + choices=YES_NO_CHOICES, + initial=False) class Meta: model = DocumentoAdministrativo @@ -746,8 +760,8 @@ class DocumentoAdministrativoForm(ModelForm): # não permite atualizar para numero/ano/tipo existente if self.instance.pk: mudanca_doc = numero_documento != self.instance.numero \ - or ano_documento != self.instance.ano \ - or tipo_documento != self.instance.tipo.pk + or ano_documento != self.instance.ano \ + or tipo_documento != self.instance.tipo.pk if not self.instance.pk or mudanca_doc: doc_exists = DocumentoAdministrativo.objects.filter(numero=numero_documento, @@ -773,7 +787,8 @@ class DocumentoAdministrativoForm(ModelForm): numero_protocolo, ano_protocolo)) raise ValidationError(msg) except MultipleObjectsReturned: - self.logger.error("Existe mais de um Protocolo com este ano ({}) e número ({}).".format(ano_protocolo,numero_protocolo)) + self.logger.error("Existe mais de um Protocolo com este ano ({}) e número ({}).".format( + ano_protocolo, numero_protocolo)) msg = _( 'Existe mais de um Protocolo com este ano e número.' % ( numero_protocolo, ano_protocolo)) @@ -784,12 +799,12 @@ class DocumentoAdministrativoForm(ModelForm): if str(protocolo_antigo) != numero_protocolo: exist_materia = MateriaLegislativa.objects.filter( - numero_protocolo=numero_protocolo, - ano=ano_protocolo).exists() + numero_protocolo=numero_protocolo, + ano=ano_protocolo).exists() exist_doc = DocumentoAdministrativo.objects.filter( - protocolo__numero=numero_protocolo, - protocolo__ano=ano_protocolo).exists() + protocolo__numero=numero_protocolo, + protocolo__ano=ano_protocolo).exists() if exist_materia or exist_doc: self.logger.error('Protocolo com numero=%s e ano=%s já possui' ' documento vinculado' % (numero_protocolo, ano_protocolo)) @@ -871,13 +886,16 @@ class DesvincularDocumentoForm(ModelForm): try: self.logger.debug("Tentando obter DocumentoAdministrativo com numero={}, ano={} e tipo={}." .format(numero, ano, tipo)) - documento = DocumentoAdministrativo.objects.get(numero=numero, ano=ano, tipo=tipo) + documento = DocumentoAdministrativo.objects.get( + numero=numero, ano=ano, tipo=tipo) if not documento.protocolo: - self.logger.error("DocumentoAdministrativo %s %s/%s não se encontra vinculado a nenhum protocolo." % (tipo, numero, ano)) + self.logger.error( + "DocumentoAdministrativo %s %s/%s não se encontra vinculado a nenhum protocolo." % (tipo, numero, ano)) raise forms.ValidationError( _("%s %s/%s não se encontra vinculado a nenhum protocolo" % (tipo, numero, ano))) except ObjectDoesNotExist: - self.logger.error("DocumentoAdministrativo %s %s/%s não existe" % (tipo, numero, ano)) + self.logger.error( + "DocumentoAdministrativo %s %s/%s não existe" % (tipo, numero, ano)) raise forms.ValidationError( _("%s %s/%s não existe" % (tipo, numero, ano))) @@ -939,13 +957,16 @@ class DesvincularMateriaForm(forms.Form): try: self.logger.info("Tentando obter MateriaLegislativa com numero={}, ano={} e tipo={}." .format(numero, ano, tipo)) - materia = MateriaLegislativa.objects.get(numero=numero, ano=ano, tipo=tipo) + materia = MateriaLegislativa.objects.get( + numero=numero, ano=ano, tipo=tipo) if not materia.numero_protocolo: - self.logger.error("MateriaLegislativa %s %s/%s não se encontra vinculada a nenhum protocolo" % (tipo, numero, ano)) + self.logger.error( + "MateriaLegislativa %s %s/%s não se encontra vinculada a nenhum protocolo" % (tipo, numero, ano)) raise forms.ValidationError( _("%s %s/%s não se encontra vinculada a nenhum protocolo" % (tipo, numero, ano))) except ObjectDoesNotExist: - self.logger.error("MateriaLegislativa %s %s/%s não existe" % (tipo, numero, ano)) + self.logger.error( + "MateriaLegislativa %s %s/%s não existe" % (tipo, numero, ano)) raise forms.ValidationError( _("%s %s/%s não existe" % (tipo, numero, ano))) @@ -999,6 +1020,7 @@ def filtra_tramitacao_adm_destino_and_status(status, destino): unidade_tramitacao_destino=destino).distinct().values_list( 'documento_id', flat=True) + class FichaPesquisaAdmForm(forms.Form): logger = logging.getLogger(__name__) @@ -1074,4 +1096,4 @@ class FichaSelecionaAdmForm(forms.Form): row1, form_actions(label='Gerar Impresso') ) - ) \ No newline at end of file + ) diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index 87f7b9c47..e508a0608 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -1,9 +1,9 @@ -from django.contrib import messages from datetime import datetime from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Button, Fieldset, Layout from django import forms +from django.contrib import messages from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.db import transaction @@ -23,6 +23,7 @@ from sapl.parlamentares.models import Parlamentar, Legislatura, Mandato from sapl.utils import (RANGE_DIAS_MES, RANGE_MESES, MateriaPesquisaOrderingFilter, autor_label, autor_modal, timezone) + from .models import (Bancada, Bloco, ExpedienteMateria, JustificativaAusencia, Orador, OradorExpediente, OrdemDia, PresencaOrdemDia, SessaoPlenaria, SessaoPlenariaPresenca, TipoJustificativa, TipoResultadoVotacao, @@ -218,11 +219,11 @@ class RetiradaPautaForm(ModelForm): def __init__(self, *args, **kwargs): row1 = to_row([('tipo_de_retirada', 5), - ('parlamentar', 4), - ('data', 3)]) + ('parlamentar', 4), + ('data', 3)]) row2 = to_row([('ordem', 6), - ('expediente', 6)]) - row3 = to_row([('observacao',12)]) + ('expediente', 6)]) + row3 = to_row([('observacao', 12)]) self.helper = FormHelper() self.helper.layout = SaplFormLayout( @@ -232,8 +233,10 @@ class RetiradaPautaForm(ModelForm): q = Q(sessao_plenaria=kwargs['initial']['sessao_plenaria']) ordens = OrdemDia.objects.filter(q) expedientes = ExpedienteMateria.objects.filter(q) - retiradas_ordem = [r.ordem for r in RetiradaPauta.objects.filter(q, ordem__in=ordens)] - retiradas_expediente = [r.expediente for r in RetiradaPauta.objects.filter(q, expediente__in=expedientes)] + retiradas_ordem = [ + r.ordem for r in RetiradaPauta.objects.filter(q, ordem__in=ordens)] + retiradas_expediente = [r.expediente for r in RetiradaPauta.objects.filter( + q, expediente__in=expedientes)] setOrdem = set(ordens) - set(retiradas_ordem) setExpediente = set(expedientes) - set(retiradas_expediente) @@ -264,19 +267,23 @@ class RetiradaPautaForm(ModelForm): sessao_plenaria = self.instance.sessao_plenaria if self.cleaned_data['data'] < sessao_plenaria.data_inicio: - raise ValidationError(_("Data de retirada de pauta anterior à abertura da Sessão.")) + raise ValidationError( + _("Data de retirada de pauta anterior à abertura da Sessão.")) if sessao_plenaria.data_fim and self.cleaned_data['data'] > sessao_plenaria.data_fim: - raise ValidationError(_("Data de retirada de pauta posterior ao encerramento da Sessão.")) + raise ValidationError( + _("Data de retirada de pauta posterior ao encerramento da Sessão.")) if self.cleaned_data['ordem'] and self.cleaned_data['ordem'].registrovotacao_set.exists(): - raise ValidationError(_("Essa matéria já foi votada, portanto não pode ser retirada de pauta.")) + raise ValidationError( + _("Essa matéria já foi votada, portanto não pode ser retirada de pauta.")) elif self.cleaned_data['expediente'] and self.cleaned_data['expediente'].registrovotacao_set.exists(): - raise ValidationError(_("Essa matéria já foi votada, portanto não pode ser retirada de pauta.")) + raise ValidationError( + _("Essa matéria já foi votada, portanto não pode ser retirada de pauta.")) return self.cleaned_data def save(self, commit=False): - retirada = super(RetiradaPautaForm, self).save(commit=False) + retirada = super(RetiradaPautaForm, self).save(commit=commit) if retirada.ordem: retirada.materia = retirada.ordem.materia elif retirada.expediente: @@ -284,6 +291,7 @@ class RetiradaPautaForm(ModelForm): retirada.save() return retirada + class BancadaForm(ModelForm): class Meta: @@ -522,10 +530,12 @@ class VotacaoForm(forms.Form): votos_sim = forms.IntegerField(label='Sim') votos_nao = forms.IntegerField(label='Não') abstencoes = forms.IntegerField(label='Abstenções') - total_presentes = forms.IntegerField(required=False, widget=forms.HiddenInput()) - voto_presidente = forms.IntegerField(label='A totalização inclui o voto do Presidente?') + total_presentes = forms.IntegerField( + required=False, widget=forms.HiddenInput()) + voto_presidente = forms.IntegerField( + label='A totalização inclui o voto do Presidente?') total_votos = forms.IntegerField(required=False, label='total') - observacao = forms.CharField(required=False , label='Observação') + observacao = forms.CharField(required=False, label='Observação') resultado_votacao = forms.CharField(label='Resultado da Votação') def clean(self): @@ -544,14 +554,15 @@ class VotacaoForm(forms.Form): qtde_presentes -= 1 if qtde_presentes and qtde_votos != qtde_presentes: - raise ValidationError('O total de votos não corresponde com a quantidade de presentes!') + raise ValidationError( + 'O total de votos não corresponde com a quantidade de presentes!') return cleaned_data # def save(self, commit=False): # #TODO Verificar se esse códido é utilizado - # votacao = super(VotacaoForm, self).save(commit) + # votacao = super(VotacaoForm, self).save(commit) # votacao.materia = self.cleaned_data['materia'] # votacao.save() # return votacao @@ -764,7 +775,7 @@ class ResumoOrdenacaoForm(forms.Form): decimo = forms.ChoiceField(label='10°', choices=ORDENACAO_RESUMO) decimo_primeiro = forms.ChoiceField(label='11°', - choices=ORDENACAO_RESUMO) + choices=ORDENACAO_RESUMO) def __init__(self, *args, **kwargs): super(ResumoOrdenacaoForm, self).__init__(*args, **kwargs) @@ -796,7 +807,7 @@ class ResumoOrdenacaoForm(forms.Form): self.helper.layout = Layout( Fieldset(_(''), row1, row2, row3, row4, row5, - row6, row7, row8, row9, row10,row11, + row6, row7, row8, row9, row10, row11, form_actions(label='Atualizar')) ) @@ -875,7 +886,6 @@ class JustificativaAusenciaForm(ModelForm): legislatura=legislatura).order_by('parlamentar__nome_parlamentar') parlamentares = [m.parlamentar for m in mandato] - super(JustificativaAusenciaForm, self).__init__( *args, **kwargs) @@ -900,7 +910,7 @@ class JustificativaAusenciaForm(ModelForm): ("0", "------------")] + [(p.id, p) for p in setFinal] def clean(self): - cleaned_data = super(JustificativaAusenciaForm, self).clean() + super(JustificativaAusenciaForm, self).clean() if not self.is_valid(): return self.cleaned_data @@ -913,7 +923,7 @@ class JustificativaAusenciaForm(ModelForm): else: return self.cleaned_data - def save(self, commit=False): + def save(self): justificativa = super().save(True) @@ -996,4 +1006,4 @@ class VotacaoEmBlocoFilterSet(MateriaLegislativaFilterSet): HTML(autor_modal), row4, row5, row6, row7, row8, row9, form_actions(label='Pesquisar')) - ) \ No newline at end of file + ) From 812a9e2ba06117e2ee373882f91eb4d71ffa0a91 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Fri, 4 Jan 2019 09:34:53 -0200 Subject: [PATCH 23/41] retira empty label duplicado de choices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit a nova versão do django_filter addicionada ao sapl já gerencia os empty labels. Adicioná-los manualmente estava fazendo com os fossem duplicados. --- sapl/materia/forms.py | 6 +----- sapl/norma/forms.py | 8 ++------ sapl/protocoloadm/forms.py | 8 ++------ sapl/sessao/forms.py | 6 +++--- sapl/utils.py | 5 +++++ 5 files changed, 13 insertions(+), 20 deletions(-) diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index 3c2c8c36e..63941e2c4 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -51,10 +51,6 @@ from .models import (AcompanhamentoMateria, Anexada, Autoria, DespachoInicial, TipoMateriaLegislativa, Tramitacao, UnidadeTramitacao) -def ANO_CHOICES(): - return [('', '---------')] + RANGE_ANOS - - def em_tramitacao(): return [('', 'Tanto Faz'), (1, 'Sim'), @@ -764,7 +760,7 @@ class MateriaLegislativaFilterSet(django_filters.FilterSet): ano = django_filters.ChoiceFilter(required=False, label='Ano da Matéria', - choices=ANO_CHOICES) + choices=RANGE_ANOS) autoria__autor = django_filters.CharFilter(widget=forms.HiddenInput()) diff --git a/sapl/norma/forms.py b/sapl/norma/forms.py index 3429e1267..bdac45d89 100644 --- a/sapl/norma/forms.py +++ b/sapl/norma/forms.py @@ -21,10 +21,6 @@ from .models import (AnexoNormaJuridica, AssuntoNorma, NormaJuridica, NormaRelac TipoNormaJuridica, AutoriaNorma) -def ANO_CHOICES(): - return [('', '---------')] + RANGE_ANOS - - def get_esferas(): return [('E', 'Estadual'), ('F', 'Federal'), @@ -44,7 +40,7 @@ class NormaFilterSet(django_filters.FilterSet): ano = django_filters.ChoiceFilter(required=False, label='Ano', - choices=ANO_CHOICES) + choices=RANGE_ANOS) ementa = django_filters.CharFilter(lookup_expr='icontains') @@ -103,7 +99,7 @@ class NormaJuridicaForm(ModelForm): ano_materia = forms.ChoiceField( label='Ano Matéria', required=False, - choices=ANO_CHOICES, + choices=RANGE_ANOS, widget=forms.Select(attrs={'autocomplete': 'off'}) ) diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index bd017fc8e..76f3a4986 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -37,10 +37,6 @@ NATUREZA_PROCESSO = [('', '---------'), ('1', 'Legislativo')] -def ANO_CHOICES(): - return [('', '---------')] + RANGE_ANOS - - EM_TRAMITACAO = [('', '---------'), (0, 'Sim'), (1, 'Não')] @@ -73,7 +69,7 @@ class ProtocoloFilterSet(django_filters.FilterSet): ano = django_filters.ChoiceFilter(required=False, label='Ano', - choices=ANO_CHOICES) + choices=RANGE_ANOS) assunto_ementa = django_filters.CharFilter(lookup_expr='icontains') @@ -160,7 +156,7 @@ class DocumentoAdministrativoFilterSet(django_filters.FilterSet): ano = django_filters.ChoiceFilter(required=False, label='Ano', - choices=ANO_CHOICES) + choices=RANGE_ANOS) tramitacao = django_filters.ChoiceFilter(required=False, label='Em Tramitação?', diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index e508a0608..a09f04053 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -43,11 +43,11 @@ def recupera_anos(): def ANO_CHOICES(): - return [('', '---------')] + recupera_anos() + return recupera_anos() -MES_CHOICES = [('', '---------')] + RANGE_MESES -DIA_CHOICES = [('', '---------')] + RANGE_DIAS_MES +MES_CHOICES = RANGE_MESES +DIA_CHOICES = RANGE_DIAS_MES ORDENACAO_RESUMO = [('cont_mult', 'Conteúdo Multimídia'), diff --git a/sapl/utils.py b/sapl/utils.py index 77e1cec2d..7b00b3f9e 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -322,6 +322,11 @@ LISTA_DE_UFS = [ RANGE_ANOS = [(year, year) for year in range(timezone.now().year, 1889, -1)] + +def ANO_CHOICES(): + return [('', '---------')] + RANGE_ANOS + + RANGE_MESES = [ (1, 'Janeiro'), (2, 'Fevereiro'), From 2078b4c7e46d380f4995a087d1fe8bd0388414c0 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Fri, 4 Jan 2019 10:26:13 -0200 Subject: [PATCH 24/41] Fix #1659 --- sapl/base/forms.py | 156 ++++++++++-------- sapl/materia/forms.py | 7 +- .../migrations/0035_auto_20190104_1021.py | 35 ++++ sapl/materia/models.py | 9 +- sapl/norma/forms.py | 8 +- .../migrations/0019_auto_20190104_1021.py | 25 +++ sapl/protocoloadm/forms.py | 5 +- .../migrations/0012_auto_20190104_1021.py | 25 +++ sapl/sessao/forms.py | 26 +-- sapl/utils.py | 48 +++++- 10 files changed, 240 insertions(+), 104 deletions(-) create mode 100644 sapl/materia/migrations/0035_auto_20190104_1021.py create mode 100644 sapl/norma/migrations/0019_auto_20190104_1021.py create mode 100644 sapl/protocoloadm/migrations/0012_auto_20190104_1021.py diff --git a/sapl/base/forms.py b/sapl/base/forms.py index a82dcab53..ec1a70d61 100644 --- a/sapl/base/forms.py +++ b/sapl/base/forms.py @@ -1,4 +1,3 @@ -import django_filters import logging from crispy_forms.bootstrap import FieldWithButtons, InlineRadios, StrictButton @@ -14,15 +13,17 @@ from django.core.exceptions import ValidationError from django.db import models, transaction from django.db.models import Q from django.forms import Form, ModelForm -from django.utils.translation import ugettext_lazy as _ 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.base.models import Autor, TipoAutor +from sapl.comissoes.models import Reuniao, Comissao from sapl.crispy_layout_mixin import (SaplFormLayout, form_actions, to_column, to_row) -from sapl.audiencia.models import AudienciaPublica,TipoAudienciaPublica -from sapl.comissoes.models import Reuniao, Comissao -from sapl.materia.models import (MateriaLegislativa, UnidadeTramitacao, StatusTramitacao) +from sapl.materia.models import ( + MateriaLegislativa, UnidadeTramitacao, StatusTramitacao) from sapl.norma.models import (NormaJuridica) from sapl.parlamentares.models import SessaoLegislativa from sapl.sessao.models import SessaoPlenaria @@ -30,10 +31,12 @@ 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) + models_with_gr_for_model, qs_override_django_filter, + choice_anos_com_normas) from .models import AppConfig, CasaLegislativa + ACTION_CREATE_USERS_AUTOR_CHOICE = [ ('A', _('Associar um usuário existente')), ('N', _('Autor sem Usuário de Acesso ao Sapl')), @@ -84,7 +87,8 @@ class UsuarioCreateForm(ModelForm): data = self.cleaned_data if data['password1'] != data['password2']: - self.logger.error('Erro de validação. Senhas informadas ({}, {}) são diferentes.'.format(data['password1'], data['password2'])) + self.logger.error('Erro de validação. Senhas informadas ({}, {}) são diferentes.'.format( + data['password1'], data['password2'])) raise ValidationError('Senhas informadas são diferentes') return data @@ -121,8 +125,10 @@ class UsuarioEditForm(ModelForm): # ROLES = [(g.id, g.name) for g in Group.objects.all().order_by('name')] ROLES = [] - password1 = forms.CharField(required=False, widget=forms.PasswordInput, label='Senha') - password2 = forms.CharField(required=False, widget=forms.PasswordInput, label='Confirmar senha') + password1 = forms.CharField( + required=False, widget=forms.PasswordInput, label='Senha') + password2 = forms.CharField( + required=False, widget=forms.PasswordInput, label='Confirmar senha') user_active = forms.ChoiceField(choices=YES_NO_CHOICES, required=True, label="Usuário ativo?", initial='True') roles = forms.MultipleChoiceField( @@ -159,19 +165,22 @@ class UsuarioEditForm(ModelForm): data = self.cleaned_data if data['password1'] and data['password1'] != data['password2']: - self.logger.error('Erro de validação. Senhas informadas ({}, {}) são diferentes.'.format(data['password1'], data['password2'])) + self.logger.error('Erro de validação. Senhas informadas ({}, {}) são diferentes.'.format( + data['password1'], data['password2'])) raise ValidationError('Senhas informadas são diferentes') return data + class SessaoLegislativaForm(ModelForm): logger = logging.getLogger(__name__) + class Meta: model = SessaoLegislativa exclude = [] def clean(self): - + cleaned_data = super(SessaoLegislativaForm, self).clean() if not self.is_valid(): @@ -186,13 +195,18 @@ class SessaoLegislativaForm(ModelForm): data_fim_leg = legislatura.data_fim pk = self.initial['id'] if self.initial else None # Queries para verificar se existem Sessões Legislativas no período selecionado no form - # Caso onde a data_inicio e data_fim são iguais a de alguma sessão já criada + # Caso onde a data_inicio e data_fim são iguais a de alguma sessão já + # criada primeiro_caso = Q(data_inicio=data_inicio, data_fim=data_fim) - # Caso onde a data_inicio está entre o início e o fim de uma Sessão já existente - segundo_caso = Q(data_inicio__lt=data_inicio, data_fim__range=(data_inicio, data_fim)) - # Caso onde a data_fim está entre o início e o fim de uma Sessão já existente - terceiro_caso = Q(data_inicio__range=(data_inicio, data_fim), data_fim__gt=data_fim) - sessoes_existentes = SessaoLegislativa.objects.filter(primeiro_caso|segundo_caso|terceiro_caso).\ + # Caso onde a data_inicio está entre o início e o fim de uma Sessão já + # existente + segundo_caso = Q(data_inicio__lt=data_inicio, + data_fim__range=(data_inicio, data_fim)) + # Caso onde a data_fim está entre o início e o fim de uma Sessão já + # existente + terceiro_caso = Q(data_inicio__range=( + data_inicio, data_fim), data_fim__gt=data_fim) + sessoes_existentes = SessaoLegislativa.objects.filter(primeiro_caso | segundo_caso | terceiro_caso).\ exclude(pk=pk) if sessoes_existentes: @@ -216,39 +230,41 @@ class SessaoLegislativaForm(ModelForm): if numero <= ult and flag_edit: self.logger.error('O número da SessaoLegislativa ({}) é menor ou igual ' - 'que o de Sessões Legislativas passadas ({})'.format(numero, ult)) + 'que o de Sessões Legislativas passadas ({})'.format(numero, ult)) raise ValidationError('O número da Sessão Legislativa não pode ser menor ou igual ' 'que o de Sessões Legislativas passadas') if data_inicio < data_inicio_leg or \ - data_inicio > data_fim_leg: + data_inicio > data_fim_leg: self.logger.error('A data de início ({}) da SessaoLegislativa está compreendida ' - 'fora da data início ({}) e fim ({}) da Legislatura ' - 'selecionada'.format(data_inicio, data_inicio_leg, data_fim_leg)) + 'fora da data início ({}) e fim ({}) da Legislatura ' + 'selecionada'.format(data_inicio, data_inicio_leg, data_fim_leg)) raise ValidationError('A data de início da Sessão Legislativa deve estar compreendida ' 'entre a data início e fim da Legislatura selecionada') if data_fim > data_fim_leg or \ - data_fim < data_inicio_leg: + data_fim < data_inicio_leg: self.logger.error('A data de fim ({}) da SessaoLegislativa está compreendida ' - 'fora da data início ({}) e fim ({}) da Legislatura ' - 'selecionada.'.format(data_fim, data_inicio_leg, data_fim_leg)) + 'fora da data início ({}) e fim ({}) da Legislatura ' + 'selecionada.'.format(data_fim, data_inicio_leg, data_fim_leg)) raise ValidationError('A data de fim da Sessão Legislativa deve estar compreendida ' 'entre a data início e fim da Legislatura selecionada') if data_inicio > data_fim: - self.logger.error('Data início ({}) superior à data fim ({}).'.format(data_inicio, data_fim)) - raise ValidationError('Data início não pode ser superior à data fim') + self.logger.error( + 'Data início ({}) superior à data fim ({}).'.format(data_inicio, data_fim)) + raise ValidationError( + 'Data início não pode ser superior à data fim') data_inicio_intervalo = cleaned_data['data_inicio_intervalo'] data_fim_intervalo = cleaned_data['data_fim_intervalo'] if data_inicio_intervalo and data_fim_intervalo and \ - data_inicio_intervalo > data_fim_intervalo: - self.logger.error('Data início de intervalo ({}) superior à ' - 'data fim de intervalo ({}).'.format(data_inicio_intervalo, data_fim_intervalo)) - raise ValidationError('Data início de intervalo não pode ser ' - 'superior à data fim de intervalo') + data_inicio_intervalo > data_fim_intervalo: + self.logger.error('Data início de intervalo ({}) superior à ' + 'data fim de intervalo ({}).'.format(data_inicio_intervalo, data_fim_intervalo)) + raise ValidationError('Data início de intervalo não pode ser ' + 'superior à data fim de intervalo') if data_inicio_intervalo: if data_inicio_intervalo < data_inicio or \ @@ -256,9 +272,9 @@ class SessaoLegislativaForm(ModelForm): data_inicio_intervalo > data_fim or \ data_inicio_intervalo > data_fim_leg: self.logger.error('A data de início do intervalo ({}) não está compreendida entre ' - 'as datas de início ({}) e fim ({}) tanto da Legislatura quanto da ' - 'própria Sessão Legislativa ({} e {}).' - .format(data_inicio_intervalo, data_inicio_leg, data_fim_leg, data_inicio, data_fim)) + 'as datas de início ({}) e fim ({}) tanto da Legislatura quanto da ' + 'própria Sessão Legislativa ({} e {}).' + .format(data_inicio_intervalo, data_inicio_leg, data_fim_leg, data_inicio, data_fim)) raise ValidationError('A data de início do intervalo deve estar compreendida entre ' 'as datas de início e fim tanto da Legislatura quanto da ' 'própria Sessão Legislativa') @@ -268,9 +284,9 @@ class SessaoLegislativaForm(ModelForm): data_fim_intervalo < data_inicio or \ data_fim_intervalo < data_inicio_leg: self.logger.error('A data de fim do intervalo ({}) não está compreendida entre ' - 'as datas de início ({}) e fim ({}) tanto da Legislatura quanto da ' - 'própria Sessão Legislativa ({} e {}).' - .format(data_fim_intervalo, data_inicio_leg, data_fim_leg, data_inicio, data_fim)) + 'as datas de início ({}) e fim ({}) tanto da Legislatura quanto da ' + 'própria Sessão Legislativa ({} e {}).' + .format(data_fim_intervalo, data_inicio_leg, data_fim_leg, data_inicio, data_fim)) raise ValidationError('A data de fim do intervalo deve estar compreendida entre ' 'as datas de início e fim tanto da Legislatura quanto da ' 'própria Sessão Legislativa') @@ -464,7 +480,8 @@ class AutorForm(ModelForm): def valida_igualdade(self, texto1, texto2, msg): if texto1 != texto2: - self.logger.error('Textos diferentes. ("{}" e "{}")'.format(texto1, texto2)) + self.logger.error( + 'Textos diferentes. ("{}" e "{}")'.format(texto1, texto2)) raise ValidationError(msg) return True @@ -479,7 +496,7 @@ class AutorForm(ModelForm): if 'action_user' not in cd or not cd['action_user']: self.logger.error('Não Informado se o Autor terá usuário ' - 'vinculado para acesso ao Sistema.') + 'vinculado para acesso ao Sistema.') raise ValidationError(_('Informe se o Autor terá usuário ' 'vinculado para acesso ao Sistema.')) @@ -490,9 +507,9 @@ class AutorForm(ModelForm): get_user_model().USERNAME_FIELD) != cd['username']: if 'status_user' not in cd or not cd['status_user']: self.logger.error('Foi trocado ou removido o usuário deste Autor ({}), ' - 'mas não foi informado como se deve proceder ' - 'com o usuário que está sendo desvinculado? ({})' - .format(cd['username'], get_user_model().USERNAME_FIELD)) + 'mas não foi informado como se deve proceder ' + 'com o usuário que está sendo desvinculado? ({})' + .format(cd['username'], get_user_model().USERNAME_FIELD)) raise ValidationError( _('Foi trocado ou removido o usuário deste Autor, ' 'mas não foi informado como se deve proceder ' @@ -509,7 +526,8 @@ class AutorForm(ModelForm): if cd['action_user'] == 'A': param_username = {get_user_model().USERNAME_FIELD: cd['username']} if not User.objects.filter(**param_username).exists(): - self.logger.error('Não existe usuário com username "%s". ' % cd['username']) + self.logger.error( + 'Não existe usuário com username "%s". ' % cd['username']) raise ValidationError( _('Não existe usuário com username "%s". ' 'Para utilizar esse username você deve selecionar ' @@ -524,7 +542,8 @@ class AutorForm(ModelForm): param_username = { 'user__' + get_user_model().USERNAME_FIELD: cd['username']} if qs_autor.filter(**param_username).exists(): - self.logger.error('Já existe um Autor para este usuário ({}).'.format(cd['username'])) + self.logger.error( + 'Já existe um Autor para este usuário ({}).'.format(cd['username'])) raise ValidationError( _('Já existe um Autor para este usuário.')) @@ -548,7 +567,7 @@ class AutorForm(ModelForm): else: if 'autor_related' not in cd or not cd['autor_related']: self.logger.error('Registro de %s não escolhido para ser ' - 'vinculado ao cadastro de Autor' % tipo.descricao) + 'vinculado ao cadastro de Autor' % tipo.descricao) raise ValidationError( _('Um registro de %s deve ser escolhido para ser ' 'vinculado ao cadastro de Autor') % tipo.descricao) @@ -556,7 +575,7 @@ class AutorForm(ModelForm): if not tipo.content_type.model_class().objects.filter( pk=cd['autor_related']).exists(): self.logger.error('O Registro definido (%s-%s) não está na base ' - 'de %s.' % (cd['autor_related'], cd['q'], tipo.descricao)) + 'de %s.' % (cd['autor_related'], cd['q'], tipo.descricao)) raise ValidationError( _('O Registro definido (%s-%s) não está na base de %s.' ) % (cd['autor_related'], cd['q'], tipo.descricao)) @@ -567,7 +586,7 @@ class AutorForm(ModelForm): if qs_autor_selected.exists(): autor = qs_autor_selected.first() self.logger.error('Já existe um autor Cadastrado para ' - '%s' % autor.autor_related) + '%s' % autor.autor_related) raise ValidationError( _('Já existe um autor Cadastrado para %s' ) % autor.autor_related) @@ -692,7 +711,7 @@ class RelatorioNormasMesFilterSet(django_filters.FilterSet): ano = django_filters.ChoiceFilter(required=True, label='Ano da Norma', - choices=RANGE_ANOS) + choices=choice_anos_com_normas) class Meta: filter_overrides = {models.DateField: { @@ -703,7 +722,7 @@ class RelatorioNormasMesFilterSet(django_filters.FilterSet): }} model = NormaJuridica fields = ['ano'] - + def __init__(self, *args, **kwargs): super(RelatorioNormasMesFilterSet, self).__init__( *args, **kwargs) @@ -738,11 +757,10 @@ class RelatorioNormasVigenciaFilterSet(django_filters.FilterSet): widget=forms.RadioSelect(), required=True) - def __init__(self, *args, **kwargs): super(RelatorioNormasVigenciaFilterSet, self).__init__( *args, **kwargs) - + self.filters['ano'].label = 'Ano' self.form.fields['ano'].required = True self.form.fields['vigencia'] = self.vigencia @@ -885,7 +903,7 @@ class RelatorioReuniaoFilterSet(django_filters.FilterSet): class Meta: model = Reuniao fields = ['comissao', 'data', - 'nome','tema'] + 'nome', 'tema'] def __init__(self, *args, **kwargs): super(RelatorioReuniaoFilterSet, self).__init__( @@ -905,6 +923,7 @@ class RelatorioReuniaoFilterSet(django_filters.FilterSet): form_actions(label='Pesquisar')) ) + class RelatorioAudienciaFilterSet(django_filters.FilterSet): @property @@ -935,7 +954,6 @@ class RelatorioAudienciaFilterSet(django_filters.FilterSet): ) - class RelatorioMateriasTramitacaoilterSet(django_filters.FilterSet): ano = django_filters.ChoiceFilter(required=True, @@ -955,7 +973,6 @@ class RelatorioMateriasTramitacaoilterSet(django_filters.FilterSet): parent = super(RelatorioMateriasTramitacaoilterSet, self).qs return parent.distinct().order_by('-ano', 'tipo', '-numero') - class Meta: model = MateriaLegislativa fields = ['ano', 'tipo', 'tramitacao__unidade_tramitacao_destino', @@ -1143,7 +1160,6 @@ class ConfiguracoesAppForm(ModelForm): self.fields['cronometro_ordem'].widget.attrs['class'] = 'cronometro' self.fields['cronometro_consideracoes'].widget.attrs['class'] = 'cronometro' - def clean_mostrar_brasao_painel(self): mostrar_brasao_painel = self.cleaned_data.get( 'mostrar_brasao_painel', False) @@ -1155,7 +1171,7 @@ class ConfiguracoesAppForm(ModelForm): if (not bool(casa.logotipo) and mostrar_brasao_painel): self.logger.error('Não há logitipo configurado para esta ' - 'CasaLegislativa ({}).'.format(casa)) + 'CasaLegislativa ({}).'.format(casa)) raise ValidationError("Não há logitipo configurado para esta " "Casa legislativa.") @@ -1190,7 +1206,7 @@ class RecuperarSenhaForm(PasswordResetForm): if not email_existente: msg = 'Não existe nenhum usuário cadastrado com este e-mail.' self.logger.error('Não existe nenhum usuário cadastrado com este e-mail ({}).' - .format(self.data['email'])) + .format(self.data['email'])) raise ValidationError(msg) return self.cleaned_data @@ -1257,33 +1273,41 @@ class AlterarSenhaForm(Form): new_password2 = data['new_password2'] if new_password1 != new_password2: - self.logger.error("'Nova Senha' ({}) diferente de 'Confirmar Senha' ({})".format(new_password1, new_password2)) - raise ValidationError("'Nova Senha' diferente de 'Confirmar Senha'") + self.logger.error("'Nova Senha' ({}) diferente de 'Confirmar Senha' ({})".format( + new_password1, new_password2)) + raise ValidationError( + "'Nova Senha' diferente de 'Confirmar Senha'") # TODO: colocar mais regras como: tamanho mínimo, # TODO: caracteres alfanuméricos, maiúsculas (?), # TODO: senha atual igual a senha anterior, etc if len(new_password1) < 6: - self.logger.error('A senha informada ({}) não tem o mínimo de 6 caracteres.'.format(new_password1)) - raise ValidationError("A senha informada deve ter no mínimo 6 caracteres") + self.logger.error( + 'A senha informada ({}) não tem o mínimo de 6 caracteres.'.format(new_password1)) + raise ValidationError( + "A senha informada deve ter no mínimo 6 caracteres") username = data['username'] old_password = data['old_password'] user = User.objects.get(username=username) if user.is_anonymous(): - self.logger.error('Não é possível alterar senha de usuário anônimo ({}).'.format(username)) - raise ValidationError("Não é possível alterar senha de usuário anônimo") + self.logger.error( + 'Não é possível alterar senha de usuário anônimo ({}).'.format(username)) + raise ValidationError( + "Não é possível alterar senha de usuário anônimo") if not user.check_password(old_password): self.logger.error('Senha atual informada ({}) não confere ' - 'com a senha armazenada.'.format(old_password)) + 'com a senha armazenada.'.format(old_password)) raise ValidationError("Senha atual informada não confere " "com a senha armazenada") if user.check_password(new_password1): - self.logger.error('Nova senha ({}) igual à senha anterior.'.format(new_password1)) - raise ValidationError("Nova senha não pode ser igual à senha anterior") + self.logger.error( + 'Nova senha ({}) igual à senha anterior.'.format(new_password1)) + raise ValidationError( + "Nova senha não pode ser igual à senha anterior") return self.cleaned_data diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index 63941e2c4..01814f723 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -40,11 +40,12 @@ from sapl.norma.models import (LegislacaoCitada, NormaJuridica, from sapl.parlamentares.models import Legislatura from sapl.protocoloadm.models import Protocolo, DocumentoAdministrativo from sapl.settings import MAX_DOC_UPLOAD_SIZE -from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, SEPARADOR_HASH_PROPOSICAO, +from sapl.utils import (YES_NO_CHOICES, SEPARADOR_HASH_PROPOSICAO, ChoiceWithoutValidationField, MateriaPesquisaOrderingFilter, RangeWidgetOverride, autor_label, autor_modal, gerar_hash_arquivo, - models_with_gr_for_model, qs_override_django_filter) + models_with_gr_for_model, qs_override_django_filter, + choice_anos_com_materias) from .models import (AcompanhamentoMateria, Anexada, Autoria, DespachoInicial, DocumentoAcessorio, Numeracao, Proposicao, Relatoria, @@ -760,7 +761,7 @@ class MateriaLegislativaFilterSet(django_filters.FilterSet): ano = django_filters.ChoiceFilter(required=False, label='Ano da Matéria', - choices=RANGE_ANOS) + choices=choice_anos_com_materias) autoria__autor = django_filters.CharFilter(widget=forms.HiddenInput()) diff --git a/sapl/materia/migrations/0035_auto_20190104_1021.py b/sapl/materia/migrations/0035_auto_20190104_1021.py new file mode 100644 index 000000000..655b8c692 --- /dev/null +++ b/sapl/materia/migrations/0035_auto_20190104_1021.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.8 on 2019-01-04 12:21 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0034_auto_20190101_1618'), + ] + + operations = [ + migrations.AlterField( + model_name='materialegislativa', + name='ano', + field=models.PositiveSmallIntegerField(choices=[(2020, 2020), (2019, 2019), (2018, 2018), (2017, 2017), (2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], verbose_name='Ano'), + ), + migrations.AlterField( + model_name='materialegislativa', + name='ano_origem_externa', + field=models.PositiveSmallIntegerField(blank=True, choices=[(2020, 2020), (2019, 2019), (2018, 2018), (2017, 2017), (2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], null=True, verbose_name='Ano'), + ), + migrations.AlterField( + model_name='numeracao', + name='ano_materia', + field=models.PositiveSmallIntegerField(choices=[(2020, 2020), (2019, 2019), (2018, 2018), (2017, 2017), (2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], verbose_name='Ano'), + ), + migrations.AlterField( + model_name='proposicao', + name='ano', + field=models.PositiveSmallIntegerField(blank=True, choices=[(2020, 2020), (2019, 2019), (2018, 2018), (2017, 2017), (2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], default=None, null=True, verbose_name='Ano'), + ), + ] diff --git a/sapl/materia/models.py b/sapl/materia/models.py index cfcb71ffc..e48446aee 100644 --- a/sapl/materia/models.py +++ b/sapl/materia/models.py @@ -2,7 +2,6 @@ from django.contrib.auth.models import Group from django.contrib.contenttypes.fields import GenericRelation from django.contrib.contenttypes.models import ContentType -from django.core.exceptions import ObjectDoesNotExist,MultipleObjectsReturned from django.db import models from django.db.models.functions import Concat from django.template import defaultfilters @@ -269,9 +268,9 @@ class MateriaLegislativa(models.Model): if protocolo.timestamp: return protocolo.timestamp.date() elif protocolo.data: - return protocolo.data + return protocolo.data - return '' + return '' def delete(self, using=None, keep_parents=False): if self.texto_original: @@ -728,8 +727,8 @@ class Proposicao(models.Model): observacao = models.TextField( blank=True, verbose_name=_('Observação')) cancelado = models.BooleanField(verbose_name=_('Cancelada ?'), - choices=YES_NO_CHOICES, - default=False) + choices=YES_NO_CHOICES, + default=False) """# Ao ser recebida, irá gerar uma nova matéria ou um documento acessorio # de uma já existente diff --git a/sapl/norma/forms.py b/sapl/norma/forms.py index bdac45d89..55541b48f 100644 --- a/sapl/norma/forms.py +++ b/sapl/norma/forms.py @@ -13,9 +13,11 @@ import django_filters from sapl.base.models import Autor, TipoAutor from sapl.crispy_layout_mixin import form_actions, to_row +from sapl.materia.forms import choice_anos_com_materias from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa from sapl.settings import MAX_DOC_UPLOAD_SIZE -from sapl.utils import NormaPesquisaOrderingFilter, RANGE_ANOS, RangeWidgetOverride +from sapl.utils import NormaPesquisaOrderingFilter, RangeWidgetOverride,\ + choice_anos_com_normas from .models import (AnexoNormaJuridica, AssuntoNorma, NormaJuridica, NormaRelacionada, TipoNormaJuridica, AutoriaNorma) @@ -40,7 +42,7 @@ class NormaFilterSet(django_filters.FilterSet): ano = django_filters.ChoiceFilter(required=False, label='Ano', - choices=RANGE_ANOS) + choices=choice_anos_com_normas) ementa = django_filters.CharFilter(lookup_expr='icontains') @@ -99,7 +101,7 @@ class NormaJuridicaForm(ModelForm): ano_materia = forms.ChoiceField( label='Ano Matéria', required=False, - choices=RANGE_ANOS, + choices=choice_anos_com_materias, widget=forms.Select(attrs={'autocomplete': 'off'}) ) diff --git a/sapl/norma/migrations/0019_auto_20190104_1021.py b/sapl/norma/migrations/0019_auto_20190104_1021.py new file mode 100644 index 000000000..b11fc4235 --- /dev/null +++ b/sapl/norma/migrations/0019_auto_20190104_1021.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.8 on 2019-01-04 12:21 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('norma', '0018_auto_20190101_1618'), + ] + + operations = [ + migrations.AlterField( + model_name='anexonormajuridica', + name='ano', + field=models.PositiveSmallIntegerField(choices=[(2020, 2020), (2019, 2019), (2018, 2018), (2017, 2017), (2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], verbose_name='Ano'), + ), + migrations.AlterField( + model_name='normajuridica', + name='ano', + field=models.PositiveSmallIntegerField(choices=[(2020, 2020), (2019, 2019), (2018, 2018), (2017, 2017), (2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], verbose_name='Ano'), + ), + ] diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 76f3a4986..63474be8e 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -19,7 +19,8 @@ from sapl.crispy_layout_mixin import SaplFormLayout, form_actions, to_row from sapl.materia.models import (MateriaLegislativa, TipoMateriaLegislativa, UnidadeTramitacao) from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, AnoNumeroOrderingFilter, - RangeWidgetOverride, autor_label, autor_modal) + RangeWidgetOverride, autor_label, autor_modal, + choice_anos_com_protocolo) from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo, DocumentoAdministrativo, @@ -69,7 +70,7 @@ class ProtocoloFilterSet(django_filters.FilterSet): ano = django_filters.ChoiceFilter(required=False, label='Ano', - choices=RANGE_ANOS) + choices=choice_anos_com_protocolo) assunto_ementa = django_filters.CharFilter(lookup_expr='icontains') diff --git a/sapl/protocoloadm/migrations/0012_auto_20190104_1021.py b/sapl/protocoloadm/migrations/0012_auto_20190104_1021.py new file mode 100644 index 000000000..356b578a8 --- /dev/null +++ b/sapl/protocoloadm/migrations/0012_auto_20190104_1021.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.8 on 2019-01-04 12:21 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('protocoloadm', '0011_auto_20190101_1618'), + ] + + operations = [ + migrations.AlterField( + model_name='documentoadministrativo', + name='ano', + field=models.PositiveSmallIntegerField(choices=[(2020, 2020), (2019, 2019), (2018, 2018), (2017, 2017), (2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], verbose_name='Ano'), + ), + migrations.AlterField( + model_name='protocolo', + name='ano', + field=models.PositiveSmallIntegerField(choices=[(2020, 2020), (2019, 2019), (2018, 2018), (2017, 2017), (2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], verbose_name='Ano do Protocolo'), + ), + ] diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index a09f04053..35d49e277 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -22,7 +22,7 @@ from sapl.materia.models import (MateriaLegislativa, StatusTramitacao, from sapl.parlamentares.models import Parlamentar, Legislatura, Mandato from sapl.utils import (RANGE_DIAS_MES, RANGE_MESES, MateriaPesquisaOrderingFilter, autor_label, - autor_modal, timezone) + autor_modal, timezone, choice_anos_com_sessaoplenaria) from .models import (Bancada, Bloco, ExpedienteMateria, JustificativaAusencia, Orador, OradorExpediente, OrdemDia, PresencaOrdemDia, SessaoPlenaria, @@ -30,22 +30,6 @@ from .models import (Bancada, Bloco, ExpedienteMateria, JustificativaAusencia, OcorrenciaSessao, RegistroVotacao, RetiradaPauta, TipoRetiradaPauta) -def recupera_anos(): - try: - anos_list = SessaoPlenaria.objects.all().dates('data_inicio', 'year') - # a listagem deve ser em ordem descrescente, mas por algum motivo - # a adicao de .order_by acima depois do all() nao surte efeito - # apos a adicao do .dates(), por isso o reversed() abaixo - anos = [(k.year, k.year) for k in reversed(anos_list)] - return anos - except Exception: - return [] - - -def ANO_CHOICES(): - return recupera_anos() - - MES_CHOICES = RANGE_MESES DIA_CHOICES = RANGE_DIAS_MES @@ -580,9 +564,11 @@ class VotacaoEditForm(forms.Form): class SessaoPlenariaFilterSet(django_filters.FilterSet): - data_inicio__year = django_filters.ChoiceFilter(required=False, - label='Ano', - choices=ANO_CHOICES) + data_inicio__year = django_filters.ChoiceFilter( + required=False, + label='Ano', + choices=choice_anos_com_sessaoplenaria + ) data_inicio__month = django_filters.ChoiceFilter(required=False, label='Mês', choices=MES_CHOICES) diff --git a/sapl/utils.py b/sapl/utils.py index 7b00b3f9e..5dabd2cf6 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -319,14 +319,10 @@ LISTA_DE_UFS = [ ('EX', 'Exterior'), ] -RANGE_ANOS = [(year, year) for year in range(timezone.now().year, +RANGE_ANOS = [(year, year) for year in range(timezone.now().year + 1, 1889, -1)] -def ANO_CHOICES(): - return [('', '---------')] + RANGE_ANOS - - RANGE_MESES = [ (1, 'Janeiro'), (2, 'Fevereiro'), @@ -344,6 +340,48 @@ RANGE_MESES = [ RANGE_DIAS_MES = [(n, n) for n in range(1, 32)] + +def ANO_CHOICES(): + return [('', '---------')] + RANGE_ANOS + + +def choice_anos(model): + try: + anos_list = model.objects.all().distinct( + 'ano').order_by('-ano').values_list('ano', 'ano') + return anos_list + except Exception: + return [] + + +def choice_anos_com_materias(): + from sapl.materia.models import MateriaLegislativa + return choice_anos(MateriaLegislativa) + + +def choice_anos_com_normas(): + from sapl.norma.models import NormaJuridica + return choice_anos(NormaJuridica) + + +def choice_anos_com_protocolo(): + from sapl.protocoloadm.models import Protocolo + return choice_anos(Protocolo) + + +def choice_anos_com_sessaoplenaria(): + try: + from sapl.sessao.models import SessaoPlenaria + anos_list = SessaoPlenaria.objects.all().dates('data_inicio', 'year') + # a listagem deve ser em ordem descrescente, mas por algum motivo + # a adicao de .order_by acima depois do all() nao surte efeito + # apos a adicao do .dates(), por isso o reversed() abaixo + anos = [(k.year, k.year) for k in reversed(anos_list)] + return anos + except Exception: + return [] + + TIPOS_TEXTO_PERMITIDOS = ( 'application/vnd.oasis.opendocument.text', 'application/x-vnd.oasis.opendocument.text', From dcb45e8909c48a662ccd4c8d4d72076bd9bc6d49 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Fri, 4 Jan 2019 10:41:33 -0200 Subject: [PATCH 25/41] =?UTF-8?q?ajusta=20choice=5Fanos=20em=20relat=C3=B3?= =?UTF-8?q?rios?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/base/forms.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sapl/base/forms.py b/sapl/base/forms.py index ec1a70d61..5aa3315fb 100644 --- a/sapl/base/forms.py +++ b/sapl/base/forms.py @@ -32,7 +32,7 @@ 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, - choice_anos_com_normas) + choice_anos_com_normas, choice_anos_com_materias) from .models import AppConfig, CasaLegislativa @@ -749,7 +749,7 @@ class RelatorioNormasVigenciaFilterSet(django_filters.FilterSet): ano = django_filters.ChoiceFilter(required=True, label='Ano da Norma', - choices=RANGE_ANOS) + choices=choice_anos_com_normas) vigencia = forms.ChoiceField( label=_('Vigência'), @@ -958,7 +958,7 @@ class RelatorioMateriasTramitacaoilterSet(django_filters.FilterSet): ano = django_filters.ChoiceFilter(required=True, label='Ano da Matéria', - choices=RANGE_ANOS) + choices=choice_anos_com_materias) tramitacao__unidade_tramitacao_destino = django_filters.ModelChoiceFilter( queryset=UnidadeTramitacao.objects.all(), @@ -1002,7 +1002,7 @@ class RelatorioMateriasPorAnoAutorTipoFilterSet(django_filters.FilterSet): ano = django_filters.ChoiceFilter(required=True, label='Ano da Matéria', - choices=RANGE_ANOS) + choices=choice_anos_com_materias) class Meta: model = MateriaLegislativa From f204483ad13c1bfe1ab171aee71984c0f9716420 Mon Sep 17 00:00:00 2001 From: Edward de Oliveira Date: Fri, 4 Jan 2019 22:33:38 -0200 Subject: [PATCH 26/41] HOT-FIX: disable haystack signal by default --- sapl/settings.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sapl/settings.py b/sapl/settings.py index dba421f72..80bf18273 100755 --- a/sapl/settings.py +++ b/sapl/settings.py @@ -100,8 +100,7 @@ INSTALLED_APPS = ( # FTS = Full Text Search # Desabilita a indexação textual até encontramos uma solução para a issue # https://github.com/interlegis/sapl/issues/2055 -#HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.BaseSignalProcessor' # Disable auto index -HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor' +HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.BaseSignalProcessor' # Disable auto index SEARCH_BACKEND = 'haystack.backends.whoosh_backend.WhooshEngine' SEARCH_URL = ('PATH', PROJECT_DIR.child('whoosh')) @@ -111,10 +110,10 @@ SOLR_URL = config('SOLR_URL', cast=str, default='http://localhost:8983') SOLR_COLLECTION = config('SOLR_COLLECTION', cast=str, default='sapl') if USE_SOLR: + HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor' #enable auto-index SEARCH_BACKEND = 'haystack.backends.solr_backend.SolrEngine' SEARCH_URL = ('URL', '{}/solr/{}'.format(SOLR_URL, SOLR_COLLECTION)) - # BATCH_SIZE: default is 1000 if omitted, avoid Too Large Entity Body errors HAYSTACK_CONNECTIONS = { 'default': { From 10fd2cc57ebb0db9f8bdb7b2cf7721e00043673d Mon Sep 17 00:00:00 2001 From: Edward de Oliveira Date: Fri, 4 Jan 2019 22:38:52 -0200 Subject: [PATCH 27/41] Revert "HOT-FIX: bump python version for TravisCI" This reverts commit bf45e90eb5118130025be76d6fd00300a2554dd9. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9f1c2e55d..f54ee6d20 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: python python: - - 3.7 + - 3.5 services: - postgresql From ebce6a1647216fec36bed5262006585012091e0e Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Sat, 5 Jan 2019 00:03:25 -0200 Subject: [PATCH 28/41] HOT-FIX: converte queryset para list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no caso da criação de um banco novo, os models ainda não existem no banco e não é possivel fazer a consulta que é feita ao subir o código do sapl pelo proprio migrate. --- sapl/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapl/utils.py b/sapl/utils.py index 5dabd2cf6..c812fdcb9 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -349,7 +349,7 @@ def choice_anos(model): try: anos_list = model.objects.all().distinct( 'ano').order_by('-ano').values_list('ano', 'ano') - return anos_list + return list(anos_list) except Exception: return [] From 912683f24409574dc111dc9396adfbd2a6f6a136 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Sat, 5 Jan 2019 00:34:42 -0200 Subject: [PATCH 29/41] =?UTF-8?q?HOT-FIX:=20corrige=20testes=20em=20mat?= =?UTF-8?q?=C3=A9ria=20e=20norma?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/materia/tests/test_materia.py | 11 +++++++---- sapl/norma/tests/test_norma.py | 16 +++++++++++++--- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/sapl/materia/tests/test_materia.py b/sapl/materia/tests/test_materia.py index 4af9df7ea..80f3f244f 100644 --- a/sapl/materia/tests/test_materia.py +++ b/sapl/materia/tests/test_materia.py @@ -1,10 +1,10 @@ -import pytest from django.contrib.auth import get_user_model from django.contrib.contenttypes.models import ContentType from django.core.files.uploadedfile import SimpleUploadedFile from django.core.urlresolvers import reverse from django.db.models import Max from model_mommy import mommy +import pytest from sapl.base.models import Autor, TipoAutor from sapl.comissoes.models import Comissao, TipoComissao @@ -528,11 +528,13 @@ def test_numeracao_materia_legislativa_por_legislatura(admin_client): ) # Cria uma materia na legislatura1 - tipo_materia = mommy.make(TipoMateriaLegislativa, id=1, sequencia_numeracao='L') + tipo_materia = mommy.make(TipoMateriaLegislativa, + id=1, sequencia_numeracao='L') materia = mommy.make(MateriaLegislativa, tipo=tipo_materia, ano=2017, - numero=1 + numero=1, + data_apresentacao='2017-03-05' ) url = reverse('sapl.materia:recuperar_materia') @@ -556,7 +558,8 @@ def test_numeracao_materia_legislativa_por_legislatura(admin_client): def test_numeracao_materia_legislativa_por_ano(admin_client): # Cria uma materia - tipo_materia = mommy.make(TipoMateriaLegislativa, id=1, sequencia_numeracao='A') + tipo_materia = mommy.make(TipoMateriaLegislativa, + id=1, sequencia_numeracao='A') materia = mommy.make(MateriaLegislativa, tipo=tipo_materia, ano=2017, diff --git a/sapl/norma/tests/test_norma.py b/sapl/norma/tests/test_norma.py index 5c2a76a6a..277ed47ed 100644 --- a/sapl/norma/tests/test_norma.py +++ b/sapl/norma/tests/test_norma.py @@ -1,13 +1,13 @@ -import pytest from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ from model_mommy import mommy +import pytest +from sapl.base.models import AppConfig from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa from sapl.norma.forms import (NormaJuridicaForm, NormaPesquisaSimplesForm, NormaRelacionadaForm) from sapl.norma.models import NormaJuridica, TipoNormaJuridica -from sapl.base.models import AppConfig @pytest.mark.django_db(transaction=False) @@ -81,6 +81,15 @@ def test_norma_juridica_materia_inexistente(): tipo = mommy.make(TipoNormaJuridica) tipo_materia = mommy.make(TipoMateriaLegislativa, descricao='VETO') + # cria uma matéria qualquer em 2017 pois, no teste, o campo ano_materia + # está vazio + materia = mommy.make(MateriaLegislativa, + tipo=tipo_materia, + ano=2017, + numero=1, + data_apresentacao='2017-03-05' + ) + form = NormaJuridicaForm(data={'tipo': str(tipo.pk), 'numero': '1', 'ano': '2017', @@ -94,7 +103,8 @@ def test_norma_juridica_materia_inexistente(): assert not form.is_valid() - assert form.errors['__all__'] == [_("Matéria Legislativa 2/2017 (VETO) é inexistente.")] + assert form.errors['__all__'] == [ + _("Matéria Legislativa 2/2017 (VETO) é inexistente.")] @pytest.mark.django_db(transaction=False) From 2c13a13f8b6d564d11e2729bf7f19af92067a9eb Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Sat, 5 Jan 2019 01:00:19 -0200 Subject: [PATCH 30/41] bump pyyaml --- requirements/requirements.txt | 9 +++++---- setup.py | 11 ++++------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index bb93e9f0e..3c4d2e135 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,7 +1,6 @@ dj-database-url==0.4.1 django-haystack==2.6.0 django>=1.10,<1.11 -git+git://github.com/rubgombar1/django-admin-bootstrapped.git django-bootstrap3==7.0.1 django-bower==5.2.0 django-braces==1.9.0 @@ -14,15 +13,13 @@ django-floppyforms==1.6.2 django-model-utils==3.1.1 django-sass-processor==0.5.8 djangorestframework==3.4.0 -git+git://github.com/jasperlittle/django-rest-framework-docs easy-thumbnails==2.5 django-image-cropping==1.2 -git+git://github.com/interlegis/trml2pdf.git libsass==0.11.1 psycopg2-binary==2.7.4 python-decouple==3.0 pytz==2016.4 -pyyaml==3.11 +pyyaml==4.2b1 rtyaml==0.0.3 textract==1.5.0 unipath==1.1 @@ -34,3 +31,7 @@ WeasyPrint==0.42 whoosh==2.7.4 django-speedinfo==1.3.5 django-reversion-compare==0.8.4 + +git+git://github.com/interlegis/trml2pdf.git +git+git://github.com/jasperlittle/django-rest-framework-docs +git+git://github.com/rubgombar1/django-admin-bootstrapped.git \ No newline at end of file diff --git a/setup.py b/setup.py index aa79dc5b8..6b7c5a248 100644 --- a/setup.py +++ b/setup.py @@ -12,11 +12,6 @@ install_requires = [ 'dj-database-url==0.4.1', 'django-haystack==2.6.0', 'django>=1.10,<1.11', - # TODO O django-admin-bootstrapped 2.5.7 não inseriu a mudança que permite - # a compatibilidade com Django 1.9+. A linha abaixo será mudada quando uma - # nova versão do django-admin-bootstrapped for lançada - # 'git+git://github.com/django-admin-bootstrapped/ - # django-admin-bootstrapped.git', 'django-bootstrap3==7.0.1', 'django-bower==5.2.0', 'django-braces==1.9.0', @@ -32,12 +27,11 @@ install_requires = [ 'drfdocs', 'easy-thumbnails==2.5', 'django-image-cropping==1.1.0', - # 'git+git://github.com/interlegis/trml2pdf.git', 'libsass==0.11.1', 'psycopg2==2.7.4', 'python-decouple==3.0', 'pytz==2016.4', - 'pyyaml==3.11', + 'pyyaml==4.2b1', 'rtyaml==0.0.3', 'textract==1.5.0', 'unipath==1.1', @@ -49,6 +43,9 @@ install_requires = [ 'whoosh==2.7.4', 'django-speedinfo==1.3.5', 'django-reversion-compare==0.8.4' + # 'git+git://github.com/interlegis/trml2pdf.git', + # 'git+git://github.com/jasperlittle/django-rest-framework-docs' + # 'git+git://github.com/rubgombar1/django-admin-bootstrapped.git'' ] setup( name='interlegis-sapl', From 0124d4daeefcf89e093a4a13c93ceebc0a0631fe Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Sat, 5 Jan 2019 01:43:31 -0200 Subject: [PATCH 31/41] =?UTF-8?q?corrige=20erro=20no=20filtro=20de=20poss?= =?UTF-8?q?=C3=ADveis=20autores?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/api/forms.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sapl/api/forms.py b/sapl/api/forms.py index 14a6ef114..fecfbf598 100644 --- a/sapl/api/forms.py +++ b/sapl/api/forms.py @@ -160,14 +160,12 @@ class AutoresPossiveisFilterSet(FilterSet): tipo = self.form.cleaned_data['tipo'] \ if 'tipo' in self.form.cleaned_data else None - if not tipo and not data_relativa: + if not tipo: 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 + tipo = TipoAutor.objects.get(pk=tipo) + if not tipo.content_type: + return qs filter_for_model = 'filter_%s' % tipo.content_type.model From f4eccaa4c7e0b76d7f73beedc1cc6c54c2cb89f6 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Sat, 5 Jan 2019 02:10:46 -0200 Subject: [PATCH 32/41] =?UTF-8?q?corrige=20checkbox=20limpar=20nos=20campo?= =?UTF-8?q?s=20de=20adi=C3=A7=C3=A3o=20de=20arquivos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/static/js/app.js | 12 + sapl/static/styles/app.css | 503 ------------- sapl/static/styles/app.scss | 47 +- sapl/static/styles/compilacao.css | 1136 ----------------------------- 4 files changed, 16 insertions(+), 1682 deletions(-) delete mode 100644 sapl/static/styles/app.css delete mode 100644 sapl/static/styles/compilacao.css diff --git a/sapl/static/js/app.js b/sapl/static/js/app.js index 4341cb784..48777c0e3 100644 --- a/sapl/static/js/app.js +++ b/sapl/static/js/app.js @@ -195,10 +195,22 @@ function OptionalCustomFrontEnd() { if (this.type === "checkbox") { _label.prepend(_this); + + var _div = _label.closest('.checkbox'); + if (_div.length == 0) { + _label.addClass('checkbox-inline') + } + _this.checkbox(); } else if (this.type === "radio") { _label.prepend(_this); + + var _div = _label.closest('.radio'); + if (_div.length == 0) { + _label.addClass('radio-inline') + } + _this.radio(); } diff --git a/sapl/static/styles/app.css b/sapl/static/styles/app.css deleted file mode 100644 index 3561a3e06..000000000 --- a/sapl/static/styles/app.css +++ /dev/null @@ -1,503 +0,0 @@ -.container-home { - position: relative; - padding: 2em 1.5em 1.5em 1.5em; - max-width: 1000px; - margin: 0 auto; } - .container-home a:hover { - color: #444; - -webkit-transition: 0.3s ease-in; - -moz-transition: 0.3s ease-in; - -o-transition: 0.3s ease-in; } - .container-home #homeIndex { - text-align: center; } - .container-home .homeBanner span { - color: white; - font-size: 32px; - font-weight: 600; - display: inline-block; - vertical-align: middle; - padding: 2px 45px 4px; - border: 2px solid; } - .container-home .homeBanner::after { - display: inline-block; - vertical-align: middle; - height: 100%; } - .container-home .homeBlock { - display: inline-block; - position: relative; - background-color: #F3F3F3; - width: 190px; - height: 260px; - margin: 3px; - text-align: center; - font-size: 0; - overflow: hidden; } - .container-home .homeBlock > a { - display: block; - position: absolute; - width: 100%; - height: 100%; - top: 0; - left: 0; } - .container-home .homeBlock::after { - content: ''; - display: inline-block; - vertical-align: middle; - height: 100%; - overflow: visible; - clear: none; - visibility: initial; } - .container-home .homeContent { - position: relative; - padding: 10px; - text-align: justify; - font-size: 14px; - color: #FFF; - opacity: 0; - transition: opacity 0.5s ease; - display: inline-block; - vertical-align: middle; } - .container-home .homeContent p { - display: block; - line-height: 13px; - font-size: 80%; - color: white; } - .container-home .homeIcon { - position: relative; - display: inline-block; - width: 105px; - height: 105px; - border-radius: 50%; - background: #364347; - z-index: 1; } - .container-home .homeIcon::before { - content: ''; - position: absolute; - width: 100%; - height: 100%; - border-radius: 50%; - background: #364347; - top: 0; - left: 0; - transform: scale(0.95); - transition: transform 0.6s ease; } - .container-home .homeIcon img { - position: absolute; - margin: auto; - top: 0; - bottom: 0; - right: 0; - left: 0; - transition: opacity 0.4s 0.4s ease; } - .container-home .homeFront { - position: absolute; - top: 46%; - width: 100%; - font-size: 0; - transform: translateY(-60%); } - .container-home .homeFront h2 { - position: absolute; - margin-top: 18px; - font-size: 22px; - font-weight: 700; - color: #595959 !important; - width: 100%; - padding: 0 6%; - z-index: 0; } - .container-home .homeTitle { - display: block; - height: 32px; - text-align: center; - width: 100%; - opacity: 0; - transition: opacity 0.4s ease; } - .container-home .homeTitle::before { - content: ''; - display: inline-block; - vertical-align: middle; - height: 100%; } - .container-home .homeTitle h2 { - display: inline-block; - vertical-align: middle; - max-width: 110px; - font-size: 14px; - color: white !important; - line-height: 1em; } - .container-home .homeTitle img { - display: inline-block; - vertical-align: middle; - height: 30px; - margin-right: 5px; } - .container-home .homeBlock:hover .homeIcon::before { - transform: scale(3.6) translateY(7px); } - .container-home .homeBlock:hover .homeContent { - opacity: 1; - transition-delay: 0.2s; } - .container-home .homeBlock:hover .homeIcon img { - opacity: 0; - transition-duration: 0.2s; - transition-delay: 0s; } - .container-home .homeBlock:hover .homeTitle { - opacity: 1; } - -html { - position: relative; - min-height: 100%; } - -body { - margin-bottom: 160px; } - -h1, h2, h3, h4, h5, h6, form, dl, dt, dd, p, div, img, a { - margin: 0; - padding: 0; } - -h1, .h1 { - font-size: 30px; } - -h2, .h2 { - font-size: 24px; } - -h3, .h3 { - font-size: 20px; } - -h4, .h4 { - font-size: 16px; } - -h5, .h5 { - font-size: 14px; } - -h6, .h6 { - font-size: 12px; } - -p { - margin: 0.5em 0; } - p .control-label { - font-weight: bold; } - -label { - margin-bottom: 0; - line-height: 1; } - -fieldset fieldset { - font-size: 95%; } - fieldset fieldset legend { - font-size: 18px; } - -.page-header { - margin: 20px 0px 10px; } - -.caret.top { - transform: rotate(180deg); } - -.btn:hover, .btn:focus { - color: inherit; } - -.btn-default.btn-excluir { - color: #d9534f; } - .btn-default.btn-excluir:hover { - color: #fff; - border-color: #de6764; - background-color: #de6764; } - -.btn-cancel-iframe { - position: relative; - text-align: right; - opacity: 0.5; } - .btn-cancel-iframe:hover { - opacity: 1; } - .btn-cancel-iframe a { - padding: 10px; - display: inline-block; } - -.legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: inherit; - color: #333333; - border: 0; - border-bottom: 1px solid #e5e5e5; - clear: both; } - -.grid-gutter-width-right { - margin-right: 15px; } - -.controls-file { - padding: 10px; - border: 1px solid #d6e1e5; - border-radius: 4px; } - .controls-file label.checkbox-inline { - margin: 0px; - display: block; } - -.help-block-danger { - margin: 15px; - padding: 15px; - border: 2px dashed #f00; } - -.control-label { - margin: 0; } - -.form-control-static { - padding-top: 0; - min-height: auto; } - .form-control-static img { - max-width: 100%; } - -.pagination { - padding-top: 25px; } - -.modal .alert { - margin-bottom: 0; } - -.avatar-parlamentar { - height: 128px; - width: 128px; - margin: 0 auto; - display: table; } - -.masthead { - padding: 10px; } - .masthead .nav { - clear: both; } - .masthead .navbar-brand { - padding: 0px; - color: inherit; - font-size: 24px; } - .masthead .navbar-brand img.img-responsive { - height: 95px; - margin-right: 15px; - display: inline-block; } - .masthead .navbar-brand small { - color: #93A4AA; - font-size: 75%; - line-height: 25px; } - .masthead .navbar-brand .vcenter { - display: inline-block; - vertical-align: middle; - float: none; - padding: 10px; } - -nav.navbar { - margin-bottom: 0; - border-radius: 0; - font-size: 15px; } - -nav .navbar-nav > li > a { - padding-top: 0px; - padding-bottom: 0px; - line-height: 75px; } - nav .navbar-nav > li > a:hover { - background-color: #23527c; } - -nav .navbar-nav > li:nth-child(2) > .dropdown-menu { - right: auto; } - -nav .navbar-nav:last-child > li:last-child a { - padding-right: 0px; } - -.controls-radio-checkbox { - padding: 0px; - border: 1px solid #d6e1e5; - border-radius: 4px; - min-height: 20px; } - .controls-radio-checkbox .checkbox, .controls-radio-checkbox .radio, .controls-radio-checkbox .checkbox-inline, .controls-radio-checkbox .radio-inline { - padding: 8px 8px 8px 36px; - margin: 0; - line-height: 1.6; - display: block; } - .controls-radio-checkbox .checkbox:hover, .controls-radio-checkbox .radio:hover, .controls-radio-checkbox .checkbox-inline:hover, .controls-radio-checkbox .radio-inline:hover { - background-color: #d6e1e5; } - .controls-radio-checkbox .checkbox .icons, .controls-radio-checkbox .radio .icons, .controls-radio-checkbox .checkbox-inline .icons, .controls-radio-checkbox .radio-inline .icons { - top: auto; - left: 8px; } - .controls-radio-checkbox .checkbox-inline, .controls-radio-checkbox .radio-inline { - display: inline-block; } - .controls-radio-checkbox .help-block { - margin: 15px; - padding: 15px; - border: 2px dashed #d6e1e5; } - -.controls-radio-checkbox__old { - padding: 0px; - border: 1px solid #d6e1e5; - border-radius: 4px; - min-height: 20px; } - .controls-radio-checkbox__old label { - padding: 0; - line-height: 2.7; - padding-left: 36px; } - .controls-radio-checkbox__old label .icons { - top: 8px; - left: 8px; } - .controls-radio-checkbox__old label.checkbox-inline, .controls-radio-checkbox__old label.radio-inline { - padding-right: 8px; } - .controls-radio-checkbox__old label.checkbox-inline .icons, .controls-radio-checkbox__old label.radio-inline .icons { - top: 8px; - left: 8px; } - .controls-radio-checkbox__old .checkbox, .controls-radio-checkbox__old .radio, .controls-radio-checkbox__old .checkbox-inline, .controls-radio-checkbox__old .radio-inline { - margin: 0; } - .controls-radio-checkbox__old .checkbox:hover, .controls-radio-checkbox__old .radio:hover, .controls-radio-checkbox__old .checkbox-inline:hover, .controls-radio-checkbox__old .radio-inline:hover { - background-color: #d6e1e5; } - -.manual, .manual ul { - padding-left: 1.5em; - list-style-type: none; - margin-top: 0; - font-size: 100%; } - -.manual li { - display: list-item; - line-height: 1.5em; - padding-right: 0; } - .manual li a { - background-color: transparent; - border: none; - border-radius: none; - padding: 0; } - -.container-tabaux .sidebar-tabaux { - background: #fafafa; - margin-top: -70px; - padding: 10px; - border: 1px solid #eee; } - .container-tabaux .sidebar-tabaux .navbar-right { - margin: 0; } - .container-tabaux .sidebar-tabaux .nav-pills > li + li { - margin-left: 0px; } - .container-tabaux .sidebar-tabaux li { - width: 100%; } - .container-tabaux .sidebar-tabaux span { - display: none; } - .container-tabaux .sidebar-tabaux .dropdown-menu { - padding: 0px; - right: 10px; - margin-top: -5px; - overflow: hidden; } - .container-tabaux .sidebar-tabaux .dropdown-menu a { - border: 0px; } - -.container-tabaux ul { - list-style: none; - padding: 0; } - -.container-tabaux .list { - font-family: "SourceSansProSemiBold", Helvetica, Arial, sans-serif; - font-size: 0px; - display: table; - width: 100%; - margin: 0; } - .container-tabaux .list ul { - display: table; - width: 100%; - margin: 0; } - .container-tabaux .list li { - width: calc(50%); - display: inline-block; - position: relative; } - .container-tabaux .list > li { - width: 100%; - border-bottom: 1px solid #eee; - padding-bottom: 20px; - margin-bottom: 20px; } - .container-tabaux .list .head_title { - color: #364347; - font-size: 2.4rem; - text-transform: none; } - .container-tabaux .list a span { - display: none; } - -#styleparlamentar { - border: 0px solid #d6e1e5; - border-top-color: #d6e1e5; - border-right-color: #d6e1e5; - border-bottom-color: #d6e1e5; - border-left-color: #d6e1e5; - border-image-source: initial; - border-image-slice: initial; - border-image-repeat: initial; - font-size: 16px; - line-height: 1.467; - padding: 7px 12px; - height: 40px; - -webkit-appearance: none; - border-radius: 4px; - -webkit-box-shadow: none; - box-shadow: none; - margin-left: 1.0em; } - -.footer { - background: #364347; - color: white; - text-align: center; - position: absolute; - width: 100%; - bottom: 0px; } - .footer p { - color: white; - margin-top: 10px; } - .footer .container { - padding-top: 25px; } - -@media (max-width: 1199px) { - nav .container { - width: auto !important; } - .navbar-nav > li > a { - padding-left: 10.71429px; - padding-right: 10.71429px; } } - -@media (max-width: 1091px) { - .container { - width: auto; } - .navbar-nav > li > a { - padding-left: 7.5px; - padding-right: 7.5px; } - .masthead .navbar-brand { - font-size: 22px; } - .masthead .navbar-brand img.img-responsive { - height: 60px; - margin-right: 7.5px; } } - -@media (max-width: 991px) { - body { - margin: 0; } - .footer { - position: relative; } - .caret { - margin-left: 1px; } - .navbar-nav > li > a { - padding-left: 4px; - padding-right: 4px; } } - -@media (max-width: 767px) { - nav .navbar-nav > li > a { - line-height: 2.5; } - nav .navbar-right { - position: absolute; - top: 0; - margin: 10px; } - nav .navbar-right > li { - vertical-align: top; - display: inline-block; } - nav .navbar-right > li a { - padding-left: 10px; - padding-right: 10px; } - nav .navbar-right .pesquisa.open ul { - position: absolute; } - nav .navbar-right .navbar-form { - margin: 8px 0; } - .table { - width: auto; - white-space: normal; - display: block; - overflow-x: auto; } } - -@media (min-width: 1092px) and (max-width: 1199px) { - .container { - width: 1070px; } } - -@media print { - a[href]:after { - content: none !important; } } diff --git a/sapl/static/styles/app.scss b/sapl/static/styles/app.scss index 57736d3a7..a0540b8e1 100644 --- a/sapl/static/styles/app.scss +++ b/sapl/static/styles/app.scss @@ -110,16 +110,6 @@ fieldset { margin-right: $grid-gutter-width / 2; } -.controls-file { - padding: 10px; - border: 1px solid #d6e1e5; - border-radius: 4px; - label.checkbox-inline { - margin: 0px; - display: block; - } -} - .help-block-danger { margin: $grid-gutter-width / 2; padding: $grid-gutter-width / 2; @@ -217,12 +207,11 @@ nav { } } -.controls-radio-checkbox { +.controls-radio-checkbox, .controls-file { padding: 0px; border: 1px solid #d6e1e5; border-radius: 4px; min-height: 20px; - .checkbox, .radio, .checkbox-inline, .radio-inline { padding: 8px 8px 8px 36px; @@ -247,36 +236,6 @@ nav { padding: $grid-gutter-width / 2; border: 2px dashed #d6e1e5; } - -} - .controls-radio-checkbox__old { - padding: 0px; - border: 1px solid #d6e1e5; - border-radius: 4px; - min-height: 20px; - label { - padding: 0; - line-height: 2.7; - padding-left: 36px; - .icons { - top: 8px; - left: 8px; - } - - &.checkbox-inline, &.radio-inline, { - padding-right: 8px; - .icons { - top: 8px; - left: 8px; - } - } - } - .checkbox, .radio, .checkbox-inline, .radio-inline { - margin: 0; - &:hover { - background-color: #d6e1e5; - } - } } .manual { @@ -298,7 +257,9 @@ nav { } } } - +.controls-file { + padding: 15px; +} .container-tabaux { .sidebar-tabaux { background: #fafafa; diff --git a/sapl/static/styles/compilacao.css b/sapl/static/styles/compilacao.css deleted file mode 100644 index 557ef057a..000000000 --- a/sapl/static/styles/compilacao.css +++ /dev/null @@ -1,1136 +0,0 @@ -a:link:after, a:visited:after { - content: ""; } - -.test_import:nth-child(even) { - background-color: #ccc; } - -#wait_message { - display: block; - position: fixed; - top: 0; - bottom: 0; - left: 0; - right: 0; - background-color: rgba(220, 220, 220, 0.75); - z-index: 99; } - #wait_message #msg { - position: relative; - margin: 20% auto; - padding: 1.2em 2em; - max-width: 600px; - text-align: center; - font-size: 1.5em; - color: #677; - border: 1px solid #eee; - background-color: #fff !important; - box-shadow: 0 1px 2px #999; } - -.text-center { - text-align: center; } - -.cp-notify { - z-index: 9999; - position: fixed; - top: 2em; - left: 50%; - min-width: 600px; - transform: translate(-50%, 0); - transition: all 0.4s ease; - opacity: 0.97; } - .cp-notify.hide { - opacity: 0; - top: -1000px; - display: block !important; - transition: all 0.4s ease; } - .cp-notify .message { - padding: 1em; - border: 2px solid rgba(0, 0, 0, 0.1); - border-radius: 4px; - color: rgba(0, 0, 0, 0.6); - line-height: 1em; - font-size: 1.3em; - text-align: center; - box-shadow: 0 0 100px rgba(0, 0, 0, 0.2); } - -.cp { - /* and dpt */ } - .cp .desativado .dtxt, .cp .dpt .dptt > a.desativado .dtxt, .cp .desativado .dtxt *, .cp .dpt .dptt > a.desativado .dtxt *, .cp .desativado .dpt-link, .cp .dpt .dptt > a.desativado .dpt-link, .cp .desativado .dpt-link *, .cp .dpt .dptt > a.desativado .dpt-link * { - text-decoration: line-through; - color: #999 !important; } - .cp .desativado .dtxt table, .cp .dpt .dptt > a.desativado .dtxt table, .cp .desativado .dtxt table td, .cp .dpt .dptt > a.desativado .dtxt table td, .cp .desativado .dtxt * table, .cp .dpt .dptt > a.desativado .dtxt * table, .cp .desativado .dtxt * table td, .cp .dpt .dptt > a.desativado .dtxt * table td, .cp .desativado .dpt-link table, .cp .dpt .dptt > a.desativado .dpt-link table, .cp .desativado .dpt-link table td, .cp .dpt .dptt > a.desativado .dpt-link table td, .cp .desativado .dpt-link * table, .cp .dpt .dptt > a.desativado .dpt-link * table, .cp .desativado .dpt-link * table td, .cp .dpt .dptt > a.desativado .dpt-link * table td { - border: 1px dotted #ccc; } - .cp a { - text-decoration: none; - cursor: pointer; } - .cp .diff .desativado, .cp .diff .dpt .dptt > a.desativado, .cp .dpt .diff .dptt > a.desativado, .cp .diff .desativado *, .cp .diff .dpt .dptt > a.desativado *, .cp .dpt .diff .dptt > a.desativado * { - text-decoration: line-through; - color: #ddd !important; - font-size: 90%; } - .cp .diff .added { - color: #04DE2C; } - .cp .dpt { - font-size: 1em; - position: relative; } - .cp .dpt.indent { - padding-left: 1em; } - .cp .dpt .ementa { - padding: 2em 0em 2em 35%; - font-weight: bold; } - .cp .dpt .titulo_generico, .cp .dpt .anexo, .cp .dpt .disp_preliminares, .cp .dpt .disp_gerais, .cp .dpt .disp_transitorias, .cp .dpt .disp_finais, .cp .dpt .parte, .cp .dpt .livro, .cp .dpt .titulo, .cp .dpt .capitulo, .cp .dpt .secao, .cp .dpt .subsecao, .cp .dpt .itemsecao { - text-align: center; - margin-bottom: 1em; - font-size: 1.15em; - margin-top: 3em; } - .cp .dpt .titulo { - margin-top: 2em; } - .cp .dpt .capitulo { - margin-top: 1.5em; - font-size: 1.15em; } - .cp .dpt .secao { - margin-top: 1.2em; - margin-bottom: 0.7em; - font-weight: bold; - font-size: 1.15em; } - .cp .dpt .subsecao, - .cp .dpt .itemsecao { - margin-top: 1em; - margin-bottom: 0.6em; - font-weight: bold; - font-size: 1.15em; } - .cp .dpt .artigo { - font-size: 1.15em; - float: left; } - .cp .dpt .artigo .dptt { - position: relative; } - .cp .dpt .caput { - margin-top: 0.3333em; - font-size: 1.15em; } - .cp .dpt .paragrafo { - font-size: 1.1em; - margin-top: 0.2222em; } - .cp .dpt .inciso { - font-size: 1.1em; - margin-top: 0.1667em; } - .cp .dpt .alinea { - font-size: 1.0em; - margin-top: 2px; } - .cp .dpt .item { - font-size: 1.0em; - margin-top: 2px; } - .cp .dpt .assinatura { - margin-top: 0.6em; - font-size: 1.15em; } - .cp .dpt .fecho_lei { - margin-top: 0.6em; - font-size: 1.15em; } - .cp .dpt .page-break { - page-break-before: always; } - .cp .dpt .bloco_alteracao { - padding-left: 10%; - font-style: italic; - color: #018; } - .cp .dpt .bloco_alteracao a { - text-decoration: underline; } - .cp .dpt .bloco_alteracao a, .cp .dpt .bloco_alteracao table, .cp .dpt .bloco_alteracao table td { - color: #018 !important; } - .cp .dpt .dn { - /* Notas de Dispositivo*/ - font-weight: normal; - position: relative; - font-size: 70%; } - .cp .dpt .dn p, .cp .dpt .dn ul { - font-weight: normal; - margin: 0 0 0 0; - list-style: none; - padding: 0; } - .cp .dpt .dn .dnl { - /* Lista Notas de Dispositivo*/ - display: block; - text-align: left !important; } - .cp .dpt .dn .dnl * { - display: inline; } - .cp .dpt .dn .dnl .bullet { - padding: 0 0.333em; - display: inline-block; } - .cp .dpt .dn .dnl .dnli { - min-height: 2.5em; } - .cp .dpt .dn .dnl .dnli:hover ul { - transition: opacity 0.5s linear, clip 0s 0.3s; - clip: auto; - opacity: 1; - background: rgba(230, 230, 230, 0.9); } - .cp .dpt .dn .dnl .dnli ul { - transition: opacity 0.5s linear, clip 0s 0.3s; - clip: rect(0, 0, 0, 0); - opacity: 0; - position: absolute; - background: transparent; - right: 0; - padding: 0.2em 0.5em 0em 0.5em; - border: 1px solid #c7e3d3; - border-top: 0px; - font-size: 1.5rem; } - .cp .dpt .dn .dnl .dnli ul li { - display: table-cell; - color: #aaa; } - .cp .dpt .dn .dnl .dnli ul li:hover { - color: #787; } - .cp .dpt .dn .dnl .dnli ul li:hover a { - color: #27AE60 !important; } - .cp .dpt .dn .dnl .dnli ul li .nowner { - color: #27AE60 !important; } - .cp .dpt .dn .dnl .dnli .ntitulo { - font-weight: bold; - color: #03A203; - text-decoration: none; } - .cp .dpt .dn .dnl .dnli .ntitulo a { - color: #294 !important; } - .cp .dpt .dn .dnl .dnli .ntexto { - color: #06D806; } - .cp .dpt .dn .dnl .dnli .ntexto a { - color: #03A203 !important; } - .cp .dpt .dn .dnl:hover { - display: block; } - .cp .dpt .dn .dnl:hover * { - display: block; } - .cp .dpt .dn .dnl:hover > .bullet { - display: none; } - .cp .dpt .dn .dnl:hover .dnli { - margin-top: 0.5em; - border-top: 1px solid #c7e3d3; } - .cp .dpt .dptt { - clear: left; } - .cp .dpt .dptt > a { - color: #000000; } - .cp .dpt .dptt > a.nota-alteracao { - color: #02baf2; - font-size: 0.75em; } - .cp .dpt .dptt > a.nota-alteracao:hover { - text-decoration: underline; } - .cp .dpt .dptt .dne { - position: absolute; - display: block; - right: 0; - left: 0; - top: 0; - height: 0; - transform: scaleX(0); - transform-origin: right; - transition: all 0.3s ease; - border-top: 1px solid #2980B9; } - .cp .dpt .dptt .dne ul.btns-action { - list-style: none; - padding: 0; - position: absolute; - right: 0; - background-color: #2980B9; } - .cp .dpt .dptt .dne ul.btns-action li { - float: left; } - .cp .dpt .dptt .dne ul.btns-action li:hover { - background-color: rgba(0, 0, 0, 0.1); } - .cp .dpt .dptt .dne ul.btns-action li a { - color: white; - padding: 0.15em 1em 0; - display: inline-block; } - .cp .dpt .dptt .dne-nota { - position: relative; - transform: scaleX(1); - height: auto; - border-top: 0px; } - .cp .dpt .dptt .dne-nota ul.btns-action { - display: none; } - .cp .dpt .dptt .dne-nota .dne-form { - margin: 1em -2em 0em; - text-align: left; - font-size: 1.6rem; } - .cp .dpt .dptt:hover .dne { - height: 0.1667rem; - transform: scaleX(1); - transition-delay: 1s; } - .cp .dpt .dptt:hover .dne-nota { - height: auto; - transition-delay: 0s; } - .cp .tipo-vigencias { - list-style: none; - position: fixed; - bottom: 0px; - left: 50%; - transform: translate(-50%, 0); - margin: 0; - padding: 0; - background-color: #2980B9; - z-index: 1000; - opacity: 0.9; - transition: all 0.3s ease-in-out; } - .cp .tipo-vigencias li { - display: inline-block; - border-left: 1px solid #fff; - float: left; } - .cp .tipo-vigencias li a { - color: white; - padding: 0.3em 1em 0; - display: inline-block; - font-size: 110%; - cursor: pointer; } - .cp .tipo-vigencias li a.selected { - background-color: rgba(0, 0, 0, 0.5); } - .cp .tipo-vigencias li:hover { - background-color: rgba(0, 0, 0, 0.2); } - .cp .tipo-vigencias:hover { - opacity: 1; } - -/* end cp */ -.cp.cpe { - /* fim .dpt */ - /* fim dpt-alts */ } - .cp.cpe .desativado, .cp.cpe .dpt .dptt > a.desativado { - text-decoration: line-through; - color: #999 !important; } - .cp.cpe .desativado table, .cp.cpe .dpt .dptt > a.desativado table, .cp.cpe .desativado table td, .cp.cpe .dpt .dptt > a.desativado table td { - border: 1px dotted #ccc; } - .cp.cpe .desativado a.nota-alteracao * { - color: #02baf2 !important; } - .cp.cpe .dpt { - display: block; } - .cp.cpe .dpt > .dpt-actions-fixed { - position: absolute; - right: -0.8em; - top: -0.8em; - z-index: 3; - opacity: 0; } - .cp.cpe .dpt > .dpt-actions-fixed .activate { - display: none; } - .cp.cpe .dpt > .dpt-actions-fixed .deactivate { - display: inline; } - .cp.cpe .dpt > .dpt-actions-fixed .btn-dpt-edit.btn-default { - color: #333; } - .cp.cpe .dpt > .dpt-actions-fixed .btn-dpt-edit.btn-default:hover { - color: #fff; - background-color: #02baf2; } - .cp.cpe .dpt > .dpt-actions, .cp.cpe .dpt > .dpt-actions-bottom { - display: none; } - .cp.cpe .dpt > .dpt-text { - cursor: text; - min-height: 30px; - border: 1px solid transparent; } - .cp.cpe .dpt > .dpt-text:hover, .cp.cpe .dpt > .dpt-text.hover-fixed { - background-color: rgba(0, 0, 0, 0.01); - color: #2980B9; - border: 1px solid #eee; - transition: color 0.3s ease; } - .cp.cpe .dpt > .dpt-text.artigo { - float: none; } - .cp.cpe .dpt > .dpt-text a.link-rotulo { - color: #000; } - .cp.cpe .dpt:hover > .dpt-actions-fixed { - opacity: 1; } - .cp.cpe .dpt:hover > .dpt-actions-fixed:hover ~ .dpt-text { - background-color: rgba(0, 0, 0, 0.01); - color: #2980B9; - border: 1px solid #eee; - transition: color 0.3s ease; } - .cp.cpe .dpt .semtexto { - font-weight: bold; - color: #9aaed6; } - .cp.cpe .dpt .semtexto:hover { - color: #5f76a4; } - .cp.cpe .dpt-alts { - margin: 0; - margin-bottom: 1em; - padding: 0; - background-color: transparent; - min-height: 100px; - border: 2px dashed #fff; } - .cp.cpe .dpt-alts:hover { - border-color: #d9ddde; } - .cp.cpe .dpt-alts:empty { - border-color: #ddd; } - .cp.cpe .dpt-alts.drag { - width: 100% !important; - border-color: #d9ddde; } - .cp.cpe .dpt-alts.drag .dpt { - transition-duration: 0s !important; } - .cp.cpe .dpt-alts .dpt { - width: 100% !important; - box-shadow: 0 -1px 0 #e5e5e5, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24); - padding: 0; - margin: 0; - background-color: #edf0f1; - height: auto !important; - min-height: 2em; - z-index: 1; } - .cp.cpe .dpt-alts .dpt:not(:first-child) { - border-top: 1px solid white; } - .cp.cpe .dpt-alts .dpt > .dpt-text { - padding: 0.3em 1em; - margin-top: 0; - margin-bottom: 0; } - .cp.cpe .dpt-alts .dpt > .dpt-text a.link-rotulo { - text-decoration: underline; } - .cp.cpe .dpt-alts .dpt-selected.dpt { - margin: 0em -0.5em; } - .cp.cpe .dpt-selected.dpt { - width: auto !important; - margin: 1em -0.5em; - border: 1px solid #fad46b !important; - padding: 0; - background-color: #fafafa; - border-radius: 3px; - z-index: 4; } - .cp.cpe .dpt-selected.dpt > .dpt-text { - border: 1px solid transparent; } - .cp.cpe .dpt-selected.dpt > .dpt-text:hover { - border: 1px solid transparent; - background-color: transparent; } - .cp.cpe .dpt-selected.dpt > .dpt-form { - margin-bottom: 0em; } - .cp.cpe .dpt-selected.dpt > .dpt-actions, .cp.cpe .dpt-selected.dpt > .dpt-actions-bottom { - display: table; - background-color: #e5e5e5; - padding: 1em; - margin-bottom: 0em; - width: 100%; } - .cp.cpe .dpt-selected.dpt > .dpt-actions > .btn-action, .cp.cpe .dpt-selected.dpt > .dpt-actions-bottom > .btn-action { - display: table-cell; - float: none; } - .cp.cpe .dpt-selected.dpt > .dpt-actions .btn-excluir, .cp.cpe .cp.cpe1_old_apagar .dpt-selected.dpt > .dpt-actions .csform .actions_inserts > li > a.btn-salvar, .cp.cpe1_old_apagar .cp.cpe .dpt-selected.dpt > .dpt-actions .csform .actions_inserts > li > a.btn-salvar, .cp.cpe .dpt-selected.dpt > .dpt-actions-bottom .btn-excluir, .cp.cpe .cp.cpe1_old_apagar .dpt-selected.dpt > .dpt-actions-bottom .csform .actions_inserts > li > a.btn-salvar, .cp.cpe1_old_apagar .cp.cpe .dpt-selected.dpt > .dpt-actions-bottom .csform .actions_inserts > li > a.btn-salvar { - display: inline-block; - opacity: 0.3; } - .cp.cpe .dpt-selected.dpt > .dpt-actions .btn-excluir:hover, .cp.cpe .cp.cpe1_old_apagar .dpt-selected.dpt > .dpt-actions .csform .actions_inserts > li > a.btn-salvar:hover, .cp.cpe1_old_apagar .cp.cpe .dpt-selected.dpt > .dpt-actions .csform .actions_inserts > li > a.btn-salvar:hover, .cp.cpe .dpt-selected.dpt > .dpt-actions-bottom .btn-excluir:hover, .cp.cpe .cp.cpe1_old_apagar .dpt-selected.dpt > .dpt-actions-bottom .csform .actions_inserts > li > a.btn-salvar:hover, .cp.cpe1_old_apagar .cp.cpe .dpt-selected.dpt > .dpt-actions-bottom .csform .actions_inserts > li > a.btn-salvar:hover { - opacity: 1; } - .cp.cpe .dpt-selected.dpt > .dpt-actions-bottom { - margin: 0; } - .cp.cpe .dpt-selected .dpt-block { - border-top: 1px solid #e5e5e5 !important; - opacity: 0.6; - transition: opacity 0.4s ease; } - .cp.cpe .dpt-selected .dpt-block:hover { - opacity: 1; } - .cp.cpe .dpt-selected .dpt:only-child { - /*border-bottom: 1px solid #e5e5e5 !important;*/ } - .cp.cpe .dpt-selected .dpt:not(:last-child) { - /*border-bottom: 1px solid #e5e5e5 !important;*/ } - .cp.cpe .dpt-selected .dpt-text { - opacity: 0.7; - margin: 0; - padding: 0.7em; } - .cp.cpe .dpt-selected .dpt-text:hover { - opacity: 1; - background-color: #f5f5f5; } - .cp.cpe .dpt-selected .dpt-alts { - margin: 1em; } - .cp.cpe .dpt-selected .dpt-alts .dpt { - box-shadow: 0 0 0; } - .cp.cpe .dpt-selected > .dpt-actions-fixed { - opacity: 1; - top: -12px; - right: 0.5em; } - .cp.cpe .dpt-selected > .dpt-actions-fixed .activate { - display: inline; } - .cp.cpe .dpt-selected > .dpt-actions-fixed .deactivate { - display: none; } - .cp.cpe .dpt-selected > .dpt-actions-fixed .btn-dpt-edit { - padding-top: 2px; - padding-bottom: 1px; } - .cp.cpe .dpt-selected > .dpt-actions-fixed .btn-dpt-edit.btn-default { - background-color: #fad46b; - border: 1px solid #fad46b; } - .cp.cpe .dpt-selected .dropdown-menu.dropdown-menu-left { - right: auto !important; - left: 0; - padding: 2px 0; } - .cp.cpe .dpt-selected .dropdown-menu.dropdown-menu-left > .top.arrow { - right: 88%; - left: auto; } - .cp.cpe .dpt-selected .dropdown-menu li a { - padding-top: 2px; - padding-bottom: 2px; } - .cp.cpe .dpt-selected .btn-group .radius-right { - border-bottom-right-radius: 4px !important; - border-top-right-radius: 4px !important; } - .cp.cpe .dpt-selected:hover > .dpt-actions-fixed { - opacity: 1; } - -.cp.cpe1_old_apagar { - margin-bottom: 15em; - /* fim dpt */ - /* fim dpt-selected */ } - .cp.cpe1_old_apagar .desativado, .cp.cpe1_old_apagar .dpt .dptt > a.desativado, .cp.cpe1_old_apagar .desativado *, .cp.cpe1_old_apagar .dpt .dptt > a.desativado * { - text-decoration: line-through; - color: #999 !important; } - .cp.cpe1_old_apagar .desativado table, .cp.cpe1_old_apagar .dpt .dptt > a.desativado table, .cp.cpe1_old_apagar .desativado table td, .cp.cpe1_old_apagar .dpt .dptt > a.desativado table td, .cp.cpe1_old_apagar .desativado * table, .cp.cpe1_old_apagar .dpt .dptt > a.desativado * table, .cp.cpe1_old_apagar .desativado * table td, .cp.cpe1_old_apagar .dpt .dptt > a.desativado * table td { - border: 1px dotted #ccc; } - .cp.cpe1_old_apagar a { - text-decoration: none; - cursor: pointer; } - .cp.cpe1_old_apagar .dpt { - position: relative; - display: block; } - .cp.cpe1_old_apagar .dpt .semtexto { - font-weight: bold; - color: #BFD1F6; } - .cp.cpe1_old_apagar .dpt .artigo { - float: none; } - .cp.cpe1_old_apagar .dpt .caput { - margin-top: 0; } - .cp.cpe1_old_apagar .dpt > .actions_right, .cp.cpe1_old_apagar .dpt-selected .csform .dpt > .actions_left { - color: #fff; - right: 0em; - position: absolute; - opacity: 0; - transition: all 0.4s ease-in-out; - z-index: 1000; } - .cp.cpe1_old_apagar .dpt > .actions_right a.btn-bloco, .cp.cpe1_old_apagar .dpt-selected .csform .dpt > .actions_left a.btn-bloco { - background-color: #3498db; - color: #ffffff !important; - padding: 8px 18px 6px; - display: inline-block; - line-height: 1; - float: right; } - .cp.cpe1_old_apagar .dpt > .actions_right a.btn-bloco:hover, .cp.cpe1_old_apagar .dpt-selected .csform .dpt > .actions_left a.btn-bloco:hover { - opacity: 1; - background-image: -webkit-linear-gradient(top, #1c81c4, #0b6dad); - background-image: -moz-linear-gradient(top, #1c81c4, #0b6dad); - background-image: -ms-linear-gradient(top, #1c81c4, #0b6dad); - background-image: -o-linear-gradient(top, #1c81c4, #0b6dad); - background-image: linear-gradient(to bottom, #1c81c4, #0b6dad); } - .cp.cpe1_old_apagar .dpt:hover > .actions_right, .cp.cpe1_old_apagar .dpt-selected .csform .dpt:hover > .actions_left { - opacity: 1; } - .cp.cpe1_old_apagar .dpt .bloco { - display: block; - clear: both; } - .cp.cpe1_old_apagar .dpt .bloco *:hover { - color: #27AE60; } - .cp.cpe1_old_apagar .dpt .bloco .de { - cursor: pointer; } - .cp.cpe1_old_apagar .dpt .articulacao { - border-top: 2px solid #e5e5e5; - margin: 2em 0; } - .cp.cpe1_old_apagar .dpt .bloco_alteracao { - margin: 1em 0; - padding: 0em; - background-color: transparent; - min-height: 100px; - border: 2px dashed #fff; } - .cp.cpe1_old_apagar .dpt .bloco_alteracao:hover { - border-color: #d9ddde; } - .cp.cpe1_old_apagar .dpt .bloco_alteracao.drag { - width: 100% !important; - border-color: #d9ddde; } - .cp.cpe1_old_apagar .dpt .bloco_alteracao.drag .dpt { - transition-duration: 0s !important; } - .cp.cpe1_old_apagar .dpt .bloco_alteracao .dpt { - width: 100% !important; - box-shadow: 0 -1px 0 #e5e5e5, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24); - padding: 0.3em 1em; - margin: 0; - background-color: #edf0f1; - z-index: 1; } - .cp.cpe1_old_apagar .dpt .bloco_alteracao .dpt:not(:first-child) { - border-top: 1px solid white; } - .cp.cpe1_old_apagar .dpt .bloco_alteracao .dpt.ui-draggable div { - cursor: pointer; } - .cp.cpe1_old_apagar .dpt .bloco_alteracao .dpt.dpt-comp-selected { - transition: all 0.3s ease; - width: auto !important; - margin: 2em -3.7em; - box-shadow: 0 0 6px rgba(0, 0, 0, 0.16), 0 6px 12px rgba(0, 0, 0, 0.32); } - .cp.cpe1_old_apagar .dpt-selected { - font-size: 1em; - border: 0px solid #CCC; - margin: 1em -1.8em 1em -1.8em; - padding: 2.2em 2.2em 1.6em 2.2em; - box-shadow: -4px 15px 15px rgba(0, 0, 0, 0.1), 0px 6px 6px rgba(0, 0, 0, 0.23); - background-image: -webkit-linear-gradient(top, #eaeaee, #ddd); - background-image: -moz-linear-gradient(top, #eaeaee, #ddd); - background-image: -ms-linear-gradient(top, #eaeaee, #ddd); - background-image: -o-linear-gradient(top, #eaeaee, #ddd); - background-image: linear-gradient(to bottom, #eaeaee, #ddd); - /* fim csform*/ } - .cp.cpe1_old_apagar .dpt-selected ul { - list-style: none; - margin: 0; - padding: 0; } - .cp.cpe1_old_apagar .dpt-selected .semtexto { - color: #999; } - .cp.cpe1_old_apagar .dpt-selected .bloco { - opacity: 0.5; } - .cp.cpe1_old_apagar .dpt-selected .bloco:hover { - opacity: 1; } - .cp.cpe1_old_apagar .dpt-selected .bloco a:hover { - background: transparent; } - .cp.cpe1_old_apagar .dpt-selected > .bloco { - opacity: 1; - margin: 1em; } - .cp.cpe1_old_apagar .dpt-selected .bloco_alteracao { - margin: 0; - padding: 1em; - border: 0 transparent; - background-image: -webkit-linear-gradient(top, #eaeaee, #ddd); - background-image: -moz-linear-gradient(top, #eaeaee, #ddd); - background-image: -ms-linear-gradient(top, #eaeaee, #ddd); - background-image: -o-linear-gradient(top, #eaeaee, #ddd); - background-image: linear-gradient(to bottom, #eaeaee, #ddd); } - .cp.cpe1_old_apagar .dpt-selected .bloco_alteracao:hover { - border-color: transparent; } - .cp.cpe1_old_apagar .dpt-selected .bloco_alteracao.drag { - width: 100% !important; } - .cp.cpe1_old_apagar .dpt-selected .bloco_alteracao.drag .dpt { - transition-duration: 0s !important; } - .cp.cpe1_old_apagar .dpt-selected .bloco_alteracao .dpt { - width: auto !important; - transition: all 0.3s ease; - background-color: white; } - .cp.cpe1_old_apagar .dpt-selected .bloco_alteracao .dpt:not(:first-child) { - border-top: 0px solid white; } - .cp.cpe1_old_apagar .dpt-selected > .dpt { - padding: 0; } - .cp.cpe1_old_apagar .dpt-selected > .dpt:last-child { - padding-bottom: 1em; } - .cp.cpe1_old_apagar .dpt-selected > .actions_right a.btn-bloco, .cp.cpe1_old_apagar .dpt-selected .csform .dpt-selected > .actions_left a.btn-bloco { - display: none; } - .cp.cpe1_old_apagar .dpt-selected .csform { - /* compilacao simple form */ - display: block; - clear: both; - z-index: 9; - position: static; - /* actions_inserts */ } - .cp.cpe1_old_apagar .dpt-selected .csform .btns-action { - -webkit-animation: fadeIn 1s ease-in-out; - -moz-animation: fadeIn 1s ease-in-out; - -o-animation: fadeIn 1s ease-in-out; - opacity: 1; - position: absolute; - display: table; - transition: all 0.4s ease-in-out; } - .cp.cpe1_old_apagar .dpt-selected .csform .btns-action a { - color: #16407c; - display: block; - background: transparent; - vertical-align: middle; - text-align: center; - font-weight: normal; - text-shadow: 0 0 10px rgba(0, 0, 0, 0.3); - padding: 0.33em 0.4em; } - .cp.cpe1_old_apagar .dpt-selected .csform .btns-action > li { - position: relative; - display: table-cell; - vertical-align: top; } - .cp.cpe1_old_apagar .dpt-selected .csform .btns-action > li:hover { - background-color: rgba(255, 255, 255, 0.5); } - .cp.cpe1_old_apagar .dpt-selected .csform .btns-action > li:hover > a { - text-shadow: 0 0 5px #777; - color: #0a5; } - .cp.cpe1_old_apagar .dpt-selected .csform .label_status { - position: absolute; - bottom: 0; - right: 0; - color: #889; - padding: 0.3em; - font-size: 80%; - text-align: right; - z-index: 15; - display: table; } - .cp.cpe1_old_apagar .dpt-selected .csform .label_status li { - display: table-cell; - padding: 0 0.5em; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_parents { - z-index: 11; - top: 0em; - left: 0em; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_parents a { - padding: 0.62em; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_parents div, .cp.cpe1_old_apagar .dpt-selected .csform .actions_parents li { - font-size: 80%; - display: table-cell; - vertical-align: middle; - border-right: 1px solid #CCC; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_parents div { - padding: 0 0.4em; - font-stretch: condensed; - font-variant: small-caps; - font-weight: bold; - text-shadow: 0 0 10px #fff; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_parents > li:hover a { - color: #16407c; - font-weight: normal; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_top, .cp.cpe1_old_apagar .dpt-selected .csform .actions_bottom { - top: 0em; - right: 0em; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_top a, .cp.cpe1_old_apagar .dpt-selected .csform .actions_bottom a { - padding-right: 1em; - padding-left: 1em; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_top li, .cp.cpe1_old_apagar .dpt-selected .csform .actions_bottom li { - display: table-cell; - vertical-align: middle; - border-left: 1px solid #CCC; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_bottom { - top: auto; - left: 0; - bottom: 0; - display: inline-block; - border-top: 1px solid #CCC; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_bottom a { - padding: 0 0.4em; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_bottom li { - border: 0px; - border-right: 1px solid #CCC; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_right, .cp.cpe1_old_apagar .dpt-selected .csform .actions_left { - top: 2.2em; - right: 0em; - bottom: 0; - display: block; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_right li, .cp.cpe1_old_apagar .dpt-selected .csform .actions_left li { - width: 2.2em; - display: block; - border-bottom: 1px solid #CCC; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_right li:first-child, .cp.cpe1_old_apagar .dpt-selected .csform .actions_left li:first-child { - border-top: 1px solid #CCC; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_left { - right: auto; - left: 0em; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts { - background: transparent; - position: relative; - z-index: 19; - display: table; - width: 100%; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li { - display: table-cell; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li:hover > a { - background-image: -webkit-linear-gradient(top, #1c81c4, #0b6dad); - background-image: -moz-linear-gradient(top, #1c81c4, #0b6dad); - background-image: -ms-linear-gradient(top, #1c81c4, #0b6dad); - background-image: -o-linear-gradient(top, #1c81c4, #0b6dad); - background-image: linear-gradient(to bottom, #1c81c4, #0b6dad); } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li > a { - background-image: -webkit-linear-gradient(top, #3498DB, #2980C9); - background-image: -moz-linear-gradient(top, #3498DB, #2980C9); - background-image: -ms-linear-gradient(top, #3498DB, #2980C9); - background-image: -o-linear-gradient(top, #3498DB, #2980C9); - background-image: linear-gradient(to bottom, #3498DB, #2980C9); - border-right: 1px solid #fff; - padding: 0.2em; - display: block; - color: white; - text-align: center; - white-space: nowrap; - /* btn-excluir */ } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li > a.btn-excluir, .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li > a.btn-salvar { - text-align: left; - background: #A70808; - color: #c99; - padding-left: 1.7em; - position: relative; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li > a.btn-excluir:hover, .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li > a.btn-salvar:hover { - background-color: #c70808; - color: #ecc; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li > a.btn-excluir::before, .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li > a.btn-salvar::before { - z-index: 20; - position: absolute; - background: url(/static/img/icon_delete_white.png) no-repeat 50% 50%; - content: ""; - top: 0; - left: 0; - display: block; - color: black; - margin-left: 0.4em; - height: 100%; - width: 2em; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li > a.btn-salvar { - background: #1f8b4d; - color: white; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li > a.btn-salvar:hover { - background: #2d9c5c; - color: white; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li > a.btn-salvar::before { - background: url(/static/img/icon_save_white.png) no-repeat 50% 50%; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li > a span { - padding: 0 0.7em; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li:last-child > a { - border-right: 0px solid #fff; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li > ul li:nth-child(even) a { - background: #3385CA; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li > ul li a { - border-right: 1px solid #fff; - display: block; - color: white; - background: #2980C9; - font-size: 80%; - padding: 0.23em 1em; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li > ul li a:hover { - background: #0a5ea4; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.add_prior { - table-layout: fixed; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.add_prior > ul { - transform: translateY(30px); - transition: transform 0.1s linear, opacity 0.1s linear, clip 0s 0.3s; - clip: rect(0, 0, 0, 0); - opacity: 0; - position: absolute; - margin-left: 0.5em; - box-shadow: 0px 6px 18px rgba(0, 0, 0, 0.19), 0px 2px 6px rgba(0, 0, 0, 0.23); - -webkit-transition-delay: 0.4s; - /* Safari */ - transition-delay: 0.4s; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.add_prior > ul li a { - border-right: 0px !important; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.add_prior > ul li:first-child::before { - border-width: 0.375rem; - border-style: inset inset solid; - content: ""; - display: block; - height: 0px; - width: 0px; - border-color: transparent transparent #3385CA; - position: absolute; - top: -0.71rem; - left: 0.9375rem; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.add_prior > ul li:first-child:hover::before { - border-color: transparent transparent #0A5EA4; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.add_prior > ul::after { - content: ""; - position: absolute; - z-index: -1; - left: 0; - top: rem-calc(-25px); - height: rem-calc(25px); - width: 100%; - transition: all 0.3s cubic-bezier(0.55, 0, 0.1, 1); } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.add_prior:hover > ul { - transform: translateY(7px); - transition: transform 0.4s linear, opacity 0.4s linear, clip 0s 0.2s; - opacity: 1; - clip: rect(-100px, 2000px, 2000px, -100px); } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.menu_excluir { - display: block; - position: static; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.menu_excluir > ul { - transform: translateY(30px); - transition: transform 0.1s linear, opacity 0.1s linear, clip 0s 0.3s; - clip: rect(0, 0, 0, 0); - opacity: 0; - position: absolute; - margin-left: 0.5em; - box-shadow: 0px 6px 18px rgba(0, 0, 0, 0.19), 0px 2px 6px rgba(0, 0, 0, 0.23); - -webkit-transition-delay: 0.4s; - /* Safari */ - transition-delay: 0.4s; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.menu_excluir > ul li a { - border-right: 0px !important; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.menu_excluir > ul li:first-child::before { - border-width: 0.375rem; - border-style: inset inset solid; - content: ""; - display: block; - height: 0px; - width: 0px; - border-color: transparent transparent #3385CA; - position: absolute; - top: -0.71rem; - left: 0.9375rem; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.menu_excluir > ul li:first-child:hover::before { - border-color: transparent transparent #0A5EA4; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.menu_excluir > ul::after { - content: ""; - position: absolute; - z-index: -1; - left: 0; - top: rem-calc(-25px); - height: rem-calc(25px); - width: 100%; - transition: all 0.3s cubic-bezier(0.55, 0, 0.1, 1); } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.menu_excluir:hover > ul { - transform: translateY(7px); - transition: transform 0.4s linear, opacity 0.4s linear, clip 0s 0.2s; - opacity: 1; - clip: rect(-100px, 2000px, 2000px, -100px); } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.menu_excluir > ul { - right: 0.5em; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.menu_excluir > ul li a { - background-color: #A70808; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.menu_excluir > ul li a:hover { - background: #c70808; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.menu_excluir > ul li:first-child::before { - border-color: transparent transparent #A70808; - right: 10%; - left: auto; } - .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li.menu_excluir > ul li:first-child:hover::before { - border-color: transparent transparent #c70808; } - .cp.cpe1_old_apagar .dpt-selected .csform .menu_flutuante, .cp.cpe1_old_apagar .dpt-selected .csform .menu_flutuante_fixo { - z-index: 2000; } - .cp.cpe1_old_apagar .dpt-selected .csform .menu_flutuante > li > ul, .cp.cpe1_old_apagar .dpt-selected .csform .menu_flutuante_fixo > li > ul { - transform: translateY(30px); - transition: transform 0.1s linear, opacity 0.1s linear, clip 0s 0.3s; - clip: rect(0, 0, 0, 0); - opacity: 0; - position: absolute; - margin-left: 0.5em; - box-shadow: 0px 6px 18px rgba(0, 0, 0, 0.19), 0px 2px 6px rgba(0, 0, 0, 0.23); - -webkit-transition-delay: 0.4s; - /* Safari */ - transition-delay: 0.4s; } - .cp.cpe1_old_apagar .dpt-selected .csform .menu_flutuante > li > ul li a, .cp.cpe1_old_apagar .dpt-selected .csform .menu_flutuante_fixo > li > ul li a { - border-right: 0px !important; } - .cp.cpe1_old_apagar .dpt-selected .csform .menu_flutuante > li > ul li:first-child::before, .cp.cpe1_old_apagar .dpt-selected .csform .menu_flutuante_fixo > li > ul li:first-child::before { - border-width: 0.375rem; - border-style: inset inset solid; - content: ""; - display: block; - height: 0px; - width: 0px; - border-color: transparent transparent #3385CA; - position: absolute; - top: -0.71rem; - left: 0.9375rem; } - .cp.cpe1_old_apagar .dpt-selected .csform .menu_flutuante > li > ul li:first-child:hover::before, .cp.cpe1_old_apagar .dpt-selected .csform .menu_flutuante_fixo > li > ul li:first-child:hover::before { - border-color: transparent transparent #0A5EA4; } - .cp.cpe1_old_apagar .dpt-selected .csform .menu_flutuante > li > ul::after, .cp.cpe1_old_apagar .dpt-selected .csform .menu_flutuante_fixo > li > ul::after { - content: ""; - position: absolute; - z-index: -1; - left: 0; - top: rem-calc(-25px); - height: rem-calc(25px); - width: 100%; - transition: all 0.3s cubic-bezier(0.55, 0, 0.1, 1); } - .cp.cpe1_old_apagar .dpt-selected .csform .menu_flutuante > li:hover > ul, .cp.cpe1_old_apagar .dpt-selected .csform .menu_flutuante_fixo > li:hover > ul { - transform: translateY(7px); - transition: transform 0.4s linear, opacity 0.4s linear, clip 0s 0.2s; - opacity: 1; - clip: rect(-100px, 2000px, 2000px, -100px); } - .cp.cpe1_old_apagar .dpt-selected .csform .menu_flutuante > li.menu_excluir > ul li:first-child::before, .cp.cpe1_old_apagar .dpt-selected .csform .menu_flutuante_fixo > li.menu_excluir > ul li:first-child::before { - right: auto; - left: 0.9375rem; } - .cp.cpe1_old_apagar .dpt-selected .csform textarea { - margin: 0; - resize: vertical; - min-height: 12.6em; - border: 0px; - font-size: 120%; - width: 100%; } - .cp.cpe1_old_apagar .dpt-selected .csform textarea:focus { - background: #fff; } - .cp.cpe1_old_apagar .dpt-selected .csform textarea::-webkit-input-placeholder { - color: #c70808; - opacity: 0.6; - font-size: 80%; } - .cp.cpe1_old_apagar .dpt-selected .csform textarea:-moz-placeholder { - /* Firefox 18- */ - color: #c70808; } - .cp.cpe1_old_apagar .dpt-selected .csform textarea::-moz-placeholder { - /* Firefox 19+ */ - color: #c70808; } - .cp.cpe1_old_apagar .dpt-selected .csform textarea:-ms-input-placeholder { - color: #c70808; - opacity: 0.6; } - .cp.cpe1_old_apagar .selected { - background-color: rgba(255, 255, 255, 0.5); } - .cp.cpe1_old_apagar .selected a:hover { - color: #16407c !important; - font-weight: normal !important; } - -.result-busca-dispositivo, .lista-dispositivo { - padding: 0 0 1em; - min-height: 3em; } - .result-busca-dispositivo ul, .lista-dispositivo ul { - list-style: none; - margin: 0; - padding: 1em 0 0; - transition: all 2s linear; - clear: both; } - .result-busca-dispositivo ul li, .lista-dispositivo ul li { - display: table; - border-collapse: separate; - border-bottom: 1px solid white; - width: 100%; } - .result-busca-dispositivo ul li.ta_title, .lista-dispositivo ul li.ta_title { - background-color: rgba(0, 0, 0, 0.15); - border-radius: 4px 4px 0 0; - width: 100%; } - .result-busca-dispositivo ul li:last-child .itemlabel, .lista-dispositivo ul li:last-child .itemlabel { - border-radius: 0 0 4px 0px; - margin: 0px; } - .result-busca-dispositivo ul li:last-child .iteminput, .lista-dispositivo ul li:last-child .iteminput { - border-radius: 0 0 0px 4px; } - .result-busca-dispositivo ul li .iteminput, .lista-dispositivo ul li .iteminput { - background-color: rgba(0, 0, 0, 0.1); - border-right: 1px solid white; - display: table-cell; - padding: 0.5em; - vertical-align: middle; - text-align: center; } - .result-busca-dispositivo ul li .iteminput input, .lista-dispositivo ul li .iteminput input { - margin: 0; } - .result-busca-dispositivo ul li .itemlabel, .lista-dispositivo ul li .itemlabel { - background-color: rgba(0, 0, 0, 0.1); - display: table-cell; - padding: 0.5em; - vertical-align: middle; - width: 100%; } - .result-busca-dispositivo ul li .itemlabel .artigo, .lista-dispositivo ul li .itemlabel .artigo { - float: none; } - .result-busca-dispositivo .nomenclatura_heranca, .lista-dispositivo .nomenclatura_heranca { - font-size: 90%; - color: #057dba; - display: inline; } - -.lista-dispositivo.controls-radio-checkbox { - border: 0px; } - -.label_vigencia { - border-top: 1px solid white; - display: inline-block; - color: #555; } - .label_vigencia span { - color: gray; } - -.cp-nav-parents > .dropdown-menu { - left: 0; - right: auto; } - .cp-nav-parents > .dropdown-menu::before { - content: ''; - position: absolute; - top: -11px; - width: 100%; - height: 11px; } - -.cp-nav-parents:hover > .dropdown-menu { - display: block; } - -.table-notificacoes tbody tr td { - border-top: 1px solid white; - padding: 5px; - vertical-align: middle; } - .table-notificacoes tbody tr td ul { - margin: 0px; - /*padding: 0px; - list-style: none;*/ } - .table-notificacoes tbody tr td ul li:hover { - background-color: rgba(0, 0, 0, 0.1); } - -.btn-modal-open { - float: right; } - -.class_color_container { - background: #ddd !important; } - -.clear { - clear: both; } - -.mce-tinymce.mce-container { - border: 1px solid #ccc !important; - margin-right: 2px; } - -.mce-btn button:hover { - background-color: rgba(0, 0, 0, 0.1) !important; - text-shadow: 0 0 5px #fff; - box-shadow: 0 0 5px #777; } - -.mce-menu { - background: #eee !important; } - -.displaynone { - display: none !important; } - -@media only screen and (max-width: 800px) { - .cp .fixed { - z-index: 98; - position: relative; } - .cp.cpe1 .dpt-selected { - margin: 1em 0; } - .cp.cpe1 .dpt-selected .csform .actions_parents, .cp.cpe1 .dpt-selected .csform .label_status { - font-size: 80%; - position: static !important; - display: block !important; - padding: 0em; - height: auto !important; - left: 0; - right: auto; - text-align: left; } - .cp.cpe1 .dpt-selected .csform .actions_parents div, .cp.cpe1 .dpt-selected .csform .actions_parents li, .cp.cpe1 .dpt-selected .csform .label_status div, .cp.cpe1 .dpt-selected .csform .label_status li { - display: inline-block !important; } - .cp.cpe1 .dpt-selected .csform .actions_inserts > li > ul { - transform: translateY(30px); - transition: transform 0.1s linear, opacity 0.1s linear, clip 0s 0.3s; - clip: rect(0, 0, 0, 0); - opacity: 0; - position: absolute; - margin-left: 0.5em; - box-shadow: 0px 6px 18px rgba(0, 0, 0, 0.19), 0px 2px 6px rgba(0, 0, 0, 0.23); - -webkit-transition-delay: 0.4s; - /* Safari */ - transition-delay: 0.4s; } - .cp.cpe1 .dpt-selected .csform .actions_inserts > li > ul li a { - border-right: 0px !important; } - .cp.cpe1 .dpt-selected .csform .actions_inserts > li > ul li:first-child::before { - border-width: 0.375rem; - border-style: inset inset solid; - content: ""; - display: block; - height: 0px; - width: 0px; - border-color: transparent transparent #3385CA; - position: absolute; - top: -0.71rem; - left: 0.9375rem; } - .cp.cpe1 .dpt-selected .csform .actions_inserts > li > ul li:first-child:hover::before { - border-color: transparent transparent #0A5EA4; } - .cp.cpe1 .dpt-selected .csform .actions_inserts > li > ul::after { - content: ""; - position: absolute; - z-index: -1; - left: 0; - top: rem-calc(-25px); - height: rem-calc(25px); - width: 100%; - transition: all 0.3s cubic-bezier(0.55, 0, 0.1, 1); } - .cp.cpe1 .dpt-selected .csform .actions_inserts > li:hover > ul { - transform: translateY(7px); - transition: transform 0.4s linear, opacity 0.4s linear, clip 0s 0.2s; - opacity: 1; - clip: rect(-100px, 2000px, 2000px, -100px); } - .cp.cpe1 .dpt-selected .csform .actions_inserts > li > a span { - display: none; } - .cp.cpe1 .dpt-selected .csform .actions_inserts > li > a.btn-excluir, .cp.cpe1 .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li > a.btn-salvar, .cp.cpe1_old_apagar .cp.cpe1 .dpt-selected .csform .actions_inserts > li > a.btn-salvar, .cp.cpe1 .dpt-selected .csform .actions_inserts > li > a.btn-salvar { - padding-left: 0; - min-width: 1em; } - .cp.cpe1 .dpt-selected .csform .actions_inserts > li > a.btn-excluir::before, .cp.cpe1 .cp.cpe1_old_apagar .dpt-selected .csform .actions_inserts > li > a.btn-salvar::before, .cp.cpe1_old_apagar .cp.cpe1 .dpt-selected .csform .actions_inserts > li > a.btn-salvar::before, .cp.cpe1 .dpt-selected .csform .actions_inserts > li > a.btn-salvar::before { - width: 100%; - margin: 0; } - .cp.cpe1 .dpt-selected .csform .actions_inserts > li.add_in, .cp.cpe1 .dpt-selected .csform .actions_inserts > li.add_next, .cp.cpe1 .dpt-selected .csform .actions_inserts > li.add_prior { - position: static; } - .cp.cpe1 .dpt-selected .csform .actions_inserts > li.add_in > ul { - left: 1em !important; - right: 1em !important; - margin-left: 0; } - .cp.cpe1 .dpt-selected .csform .actions_inserts > li.add_in > ul li:first-child::before { - left: 37%; } - .cp.cpe1 .dpt-selected .csform .actions_inserts > li.add_next > ul { - left: 0 !important; - right: 1em !important; } - .cp.cpe1 .dpt-selected .csform .actions_inserts > li.add_prior > ul { - left: 1em !important; - right: 0 !important; - margin-left: 0; - margin-right: 0.5em; } - .cp.cpe1 .dpt-selected .csform .actions_inserts > li.add_prior > ul li:first-child::before { - right: 42%; - left: auto; } - .cp.cpe1 .dpt-selected .csform .actions_inserts > li.menu_excluir > ul { - left: 10% !important; - right: 0 !important; - margin-left: 0; - margin-right: 0.5em; } - .cp.cpe1 .dpt-selected .csform .actions_inserts > li.menu_excluir > ul li:first-child::before { - right: 0; - left: auto; } } - -@media print { - .cp .vigencias, .toggle-topbar, .menu-icon, .button, .tipo-vigencias, .dne { - display: none; } - #btn_font_menos, #btn_font_mais { - display: none; } - .container { - width: 100%; } } From 9d62e1e626acdd7ed6a67d90030f9488e04f6f7b Mon Sep 17 00:00:00 2001 From: Edward de Oliveira Date: Sat, 5 Jan 2019 04:58:15 -0200 Subject: [PATCH 33/41] HOT-FIX: fix env var in docker-compose.yml --- docker-compose.yml | 2 +- solr/docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index e3980a639..b379cf46c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,8 +17,8 @@ sapl: ADMIN_PASSWORD: interlegis ADMIN_EMAIL: email@dominio.net DEBUG: 'False' - USE_TLS: 'False' EMAIL_PORT: 587 + EMAIL_USE_TLS: 'False' EMAIL_HOST: smtp.dominio.net EMAIL_HOST_USER: usuariosmtp EMAIL_HOST_PASSWORD: senhasmtp diff --git a/solr/docker-compose.yml b/solr/docker-compose.yml index 2f97a7e10..8d331443e 100644 --- a/solr/docker-compose.yml +++ b/solr/docker-compose.yml @@ -31,8 +31,8 @@ services: ADMIN_PASSWORD: interlegis ADMIN_EMAIL: email@dominio.net DEBUG: 'False' - USE_TLS: 'False' EMAIL_PORT: 587 + EMAIL_USE_TLS: 'False' EMAIL_HOST: smtp.dominio.net EMAIL_HOST_USER: usuariosmtp EMAIL_HOST_PASSWORD: senhasmtp From 5fff880249d48d968c5a1bd13a27f7c624ecfd40 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Sun, 6 Jan 2019 04:43:53 -0200 Subject: [PATCH 34/41] =?UTF-8?q?Refatora=20formul=C3=A1rio=20de=20pesquis?= =?UTF-8?q?a=20de=20mat=C3=A9rias?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/materia/forms.py | 153 ++++++++++++----- .../migrations/0036_auto_20190106_0330.py | 41 +++++ sapl/materia/models.py | 16 +- sapl/materia/views.py | 80 +++++---- sapl/parlamentares/models.py | 3 +- .../materia/materialegislativa_filter.html | 156 +++++++++--------- 6 files changed, 292 insertions(+), 157 deletions(-) create mode 100644 sapl/materia/migrations/0036_auto_20190106_0330.py diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index 01814f723..06d5bada8 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -12,7 +12,7 @@ from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.core.files.base import File from django.core.urlresolvers import reverse from django.db import models, transaction -from django.db.models import Max +from django.db.models import Max, Q, F from django.forms import ModelChoiceField, ModelForm, widgets from django.forms.forms import Form from django.forms.models import ModelMultipleChoiceField @@ -37,7 +37,7 @@ from sapl.materia.models import (AssuntoMateria, Autoria, MateriaAssunto, UnidadeTramitacao) from sapl.norma.models import (LegislacaoCitada, NormaJuridica, TipoNormaJuridica) -from sapl.parlamentares.models import Legislatura +from sapl.parlamentares.models import Legislatura, Partido from sapl.protocoloadm.models import Protocolo, DocumentoAdministrativo from sapl.settings import MAX_DOC_UPLOAD_SIZE from sapl.utils import (YES_NO_CHOICES, SEPARADOR_HASH_PROPOSICAO, @@ -52,12 +52,19 @@ from .models import (AcompanhamentoMateria, Anexada, Autoria, DespachoInicial, TipoMateriaLegislativa, Tramitacao, UnidadeTramitacao) -def em_tramitacao(): +def CHOICE_TRAMITACAO(): return [('', 'Tanto Faz'), (1, 'Sim'), (0, 'Não')] +def CHOICE_TIPO_LISTAGEM(): + return [ + (1, _('Detalhada')), + (2, _('Simplificada')), + ] + + class AdicionarVariasAutoriasFilterSet(django_filters.FilterSet): class Meta: @@ -767,32 +774,43 @@ class MateriaLegislativaFilterSet(django_filters.FilterSet): autoria__primeiro_autor = django_filters.BooleanFilter( required=False, - label='Primeiro Autor', - widget=forms.HiddenInput()) + label=_('Primeiro Autor')) - ementa = django_filters.CharFilter(lookup_expr='icontains') + autoria__autor__parlamentar_set__filiacao__partido = django_filters.ModelChoiceFilter( + queryset=Partido.objects.all(), + label=_('Matérias por Partido')) + + ementa = django_filters.CharFilter( + label=_('Pesquisar expressões na ementa'), + method='filter_ementa' + ) indexacao = django_filters.CharFilter(lookup_expr='icontains', label=_('Indexação')) em_tramitacao = django_filters.ChoiceFilter(required=False, label='Em tramitação', - choices=em_tramitacao) + choices=CHOICE_TRAMITACAO) materiaassunto__assunto = django_filters.ModelChoiceFilter( queryset=AssuntoMateria.objects.all(), - label=_('Assunto da Matéria')) + label=_('Assunto')) numeracao__numero_materia = django_filters.NumberFilter( required=False, - label=_('Número do Processo')) + label=_('Número do processo')) + + o = MateriaPesquisaOrderingFilter(help_text='') - o = MateriaPesquisaOrderingFilter() + tipo_listagem = forms.ChoiceField( + required=True, + choices=CHOICE_TIPO_LISTAGEM, + label=_('Tipo da Listagem do Resultado da Pesquisa')) class Meta: filter_overrides = {models.DateField: { 'filter_class': django_filters.DateFromToRangeFilter, 'extra': lambda f: { - 'label': '%s (%s)' % (f.verbose_name, _('Inicial Final')), + 'label': '%s (%s)' % (f.verbose_name, _('Inicial / Final')), 'widget': RangeWidgetOverride} }} model = MateriaLegislativa @@ -805,7 +823,7 @@ class MateriaLegislativaFilterSet(django_filters.FilterSet): 'data_publicacao', 'autoria__autor__tipo', 'autoria__primeiro_autor', - # FIXME 'autoria__autor__partido', + 'autoria__autor__parlamentar_set__filiacao__partido', 'relatoria__parlamentar_id', 'local_origem_externa', 'tramitacao__unidade_tramitacao_destino', @@ -814,16 +832,36 @@ class MateriaLegislativaFilterSet(django_filters.FilterSet): 'em_tramitacao', ] + def filter_ementa(self, queryset, name, value): + texto = value.split() + q = Q() + for t in texto: + q &= Q(ementa__icontains=t) + + return queryset.filter(q) + def __init__(self, *args, **kwargs): super(MateriaLegislativaFilterSet, self).__init__(*args, **kwargs) - self.filters['tipo'].label = 'Tipo de Matéria' - self.filters['autoria__autor__tipo'].label = 'Tipo de Autor' - # self.filters['autoria__autor__partido'].label = 'Partido do Autor' - self.filters['relatoria__parlamentar_id'].label = 'Relatoria' + # self.filters['tipo'].label = 'Tipo de Matéria' + self.filters[ + 'autoria__autor__parlamentar_set__filiacao__partido' + ].label = 'Partido do Autor' + + self.filters['autoria__autor__tipo'].label = _('Tipo de Autor') + self.filters['relatoria__parlamentar_id'].label = _('Relatoria') + self.filters['tramitacao__unidade_tramitacao_destino'].label = _( + 'Unidade de tramitação atual') + self.filters['tramitacao__status'].label = _( + 'Status da tramitação atual') + self.filters['tramitacao__status'].label = _( + 'Status da tramitação atual') + + self.filters['o'].label = _('Ordenação') + self.form.fields['tipo_listagem'] = self.tipo_listagem row1 = to_row( - [('tipo', 12)]) + [('tipo', 5), ('ementa', 7)]) row2 = to_row( [('numero', 3), ('numeracao__numero_materia', 3), @@ -832,47 +870,78 @@ class MateriaLegislativaFilterSet(django_filters.FilterSet): row3 = to_row( [('data_apresentacao', 6), ('data_publicacao', 6)]) - row4 = to_row( - [('autoria__autor', 0), - ('autoria__primeiro_autor', 0), - (Button('pesquisar', - 'Pesquisar Autor', - css_class='btn btn-primary btn-sm'), 2), - (Button('limpar', - 'limpar Autor', - css_class='btn btn-primary btn-sm'), 10)]) - row5 = to_row( - [('autoria__autor__tipo', 12), - # ('autoria__autor__partido', 6) - ]) + row4 = to_row([ + ('autoria__autor', 0), + (Button('pesquisar', + 'Pesquisar Autor', + css_class='btn btn-primary btn-sm'), 2), + (Button('limpar', + 'limpar Autor', + css_class='btn btn-primary btn-sm'), 2), + ('autoria__primeiro_autor', 2), + ('autoria__autor__tipo', 3), + ('autoria__autor__parlamentar_set__filiacao__partido', 3) + ]) row6 = to_row( [('relatoria__parlamentar_id', 6), ('local_origem_externa', 6)]) row7 = to_row( - [('tramitacao__unidade_tramitacao_destino', 6), - ('tramitacao__status', 6)]) - row8 = to_row( - [('em_tramitacao', 6), - ('o', 6)]) + [('tramitacao__unidade_tramitacao_destino', 5), + ('tramitacao__status', 5), + ('em_tramitacao', 2) + ]) row9 = to_row( [('materiaassunto__assunto', 6), ('indexacao', 6)]) - row10 = to_row( - [('ementa', 12)]) + + row8 = to_row( + [ + ('o', 8), + ('tipo_listagem', 4) + ]) self.form.helper = FormHelper() self.form.helper.form_method = 'GET' self.form.helper.layout = Layout( - Fieldset(_('Pesquisa de Matéria'), - row1, row2, row3, + Fieldset(_('Pesquisa Básica'), + row1, row2), + + Fieldset(_('Como listar os resultados da pesquisa'), + row8 + ), + Fieldset(_('Pesquisa Avançada'), + row3, HTML(autor_label), HTML(autor_modal), - row4, row5, row6, row7, row8, row9, row10, - form_actions(label='Pesquisar')) + row4, row6, row7, row9, + form_actions(label=_('Pesquisar'))) + + + ) @property def qs(self): - return qs_override_django_filter(self) + qs = qs_override_django_filter(self) + + if hasattr(self.form, 'cleaned_data') and self.form.cleaned_data[ + 'autoria__autor__parlamentar_set__filiacao__partido']: + + q_data_inicio_e_fim = Q(data_apresentacao__gte=F( + 'autoria__autor__parlamentar_set__filiacao__data'), + data_apresentacao__lte=F( + 'autoria__autor__parlamentar_set__filiacao__data_desfiliacao')) + + q_data_inicio = Q( + data_apresentacao__gte=F( + 'autoria__autor__parlamentar_set__filiacao__data'), + autoria__autor__parlamentar_set__filiacao__data_desfiliacao__isnull=True + ) + + qs = qs.filter( + q_data_inicio_e_fim | q_data_inicio + ) + + return qs def pega_ultima_tramitacao(): diff --git a/sapl/materia/migrations/0036_auto_20190106_0330.py b/sapl/materia/migrations/0036_auto_20190106_0330.py new file mode 100644 index 000000000..d8adb9678 --- /dev/null +++ b/sapl/materia/migrations/0036_auto_20190106_0330.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.8 on 2019-01-06 05:30 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0035_auto_20190104_1021'), + ] + + operations = [ + migrations.AlterField( + model_name='materialegislativa', + name='data_apresentacao', + field=models.DateField(verbose_name='Data de Apresentação'), + ), + migrations.AlterField( + model_name='materialegislativa', + name='data_publicacao', + field=models.DateField(blank=True, null=True, verbose_name='Data de Publicação'), + ), + migrations.AlterField( + model_name='materialegislativa', + name='local_origem_externa', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='materia.Origem', verbose_name='Local de Origem'), + ), + migrations.AlterField( + model_name='materialegislativa', + name='numero_protocolo', + field=models.PositiveIntegerField(blank=True, null=True, verbose_name='Número do Protocolo'), + ), + migrations.AlterField( + model_name='materialegislativa', + name='tipo', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='materia.TipoMateriaLegislativa', verbose_name='Tipo de Matéria Legislativa'), + ), + ] diff --git a/sapl/materia/models.py b/sapl/materia/models.py index e48446aee..221078811 100644 --- a/sapl/materia/models.py +++ b/sapl/materia/models.py @@ -142,15 +142,17 @@ def anexo_upload_path(instance, filename): @reversion.register() class MateriaLegislativa(models.Model): - tipo = models.ForeignKey(TipoMateriaLegislativa, - on_delete=models.PROTECT, - verbose_name=_('Tipo')) + tipo = models.ForeignKey( + TipoMateriaLegislativa, + on_delete=models.PROTECT, + verbose_name=TipoMateriaLegislativa._meta.verbose_name) numero = models.PositiveIntegerField(verbose_name=_('Número')) ano = models.PositiveSmallIntegerField(verbose_name=_('Ano'), choices=RANGE_ANOS) numero_protocolo = models.PositiveIntegerField( - blank=True, null=True, verbose_name=_('Núm. Protocolo')) - data_apresentacao = models.DateField(verbose_name=_('Data Apresentação')) + blank=True, null=True, verbose_name=_('Número do Protocolo')) + data_apresentacao = models.DateField( + verbose_name=_('Data de Apresentação')) tipo_apresentacao = models.CharField( max_length=1, blank=True, verbose_name=_('Tipo de Apresentação'), @@ -160,7 +162,7 @@ class MateriaLegislativa(models.Model): on_delete=models.PROTECT, verbose_name=_('Regime Tramitação')) data_publicacao = models.DateField( - blank=True, null=True, verbose_name=_('Data Publicação')) + blank=True, null=True, verbose_name=_('Data de Publicação')) tipo_origem_externa = models.ForeignKey( TipoMateriaLegislativa, blank=True, @@ -176,7 +178,7 @@ class MateriaLegislativa(models.Model): blank=True, null=True, verbose_name=_('Data')) local_origem_externa = models.ForeignKey( Origem, blank=True, null=True, - on_delete=models.PROTECT, verbose_name=_('Local Origem')) + on_delete=models.PROTECT, verbose_name=_('Local de Origem')) apelido = models.CharField( max_length=50, blank=True, verbose_name=_('Apelido')) dias_prazo = models.PositiveIntegerField( diff --git a/sapl/materia/views.py b/sapl/materia/views.py index 8af8a19e2..07911f09b 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -1747,42 +1747,52 @@ class MateriaLegislativaPesquisaView(FilterView): kwargs = {'data': self.request.GET or None} - status_tramitacao = self.request.GET.get('tramitacao__status') - unidade_destino = self.request.GET.get( - 'tramitacao__unidade_tramitacao_destino') + tipo_listagem = self.request.GET.get('tipo_listagem', '1') + tipo_listagem = '1' if not tipo_listagem else tipo_listagem qs = self.get_queryset().distinct() + if tipo_listagem == '1': + + status_tramitacao = self.request.GET.get('tramitacao__status') + unidade_destino = self.request.GET.get( + 'tramitacao__unidade_tramitacao_destino') + + if status_tramitacao and unidade_destino: + lista = filtra_tramitacao_destino_and_status(status_tramitacao, + unidade_destino) + qs = qs.filter(id__in=lista).distinct() + + elif status_tramitacao: + lista = filtra_tramitacao_status(status_tramitacao) + qs = qs.filter(id__in=lista).distinct() + + elif unidade_destino: + lista = filtra_tramitacao_destino(unidade_destino) + qs = qs.filter(id__in=lista).distinct() + + qs = qs.prefetch_related("autoria_set", + "autoria_set__autor", + "numeracao_set", + "anexadas", + "tipo", + "texto_articulado", + "tramitacao_set", + "tramitacao_set__status", + "tramitacao_set__unidade_tramitacao_local", + "tramitacao_set__unidade_tramitacao_destino", + "normajuridica_set", + "registrovotacao_set", + "documentoacessorio_set") + else: - if status_tramitacao and unidade_destino: - lista = filtra_tramitacao_destino_and_status(status_tramitacao, - unidade_destino) - qs = qs.filter(id__in=lista).distinct() - - elif status_tramitacao: - lista = filtra_tramitacao_status(status_tramitacao) - qs = qs.filter(id__in=lista).distinct() - - elif unidade_destino: - lista = filtra_tramitacao_destino(unidade_destino) - qs = qs.filter(id__in=lista).distinct() + qs = qs.prefetch_related("autoria_set", + "numeracao_set", + "autoria_set__autor", + "tipo",) if 'o' in self.request.GET and not self.request.GET['o']: qs = qs.order_by('-ano', 'tipo__sigla', '-numero') - qs = qs.prefetch_related("autoria_set", - "autoria_set__autor", - "numeracao_set", - "anexadas", - "tipo", - "texto_articulado", - "tramitacao_set", - "tramitacao_set__status", - "tramitacao_set__unidade_tramitacao_local", - "tramitacao_set__unidade_tramitacao_destino", - "normajuridica_set", - "registrovotacao_set", - "documentoacessorio_set") - kwargs.update({ 'queryset': qs, }) @@ -1794,7 +1804,10 @@ class MateriaLegislativaPesquisaView(FilterView): context['title'] = _('Pesquisar Matéria Legislativa') - self.filterset.form.fields['o'].label = _('Ordenação') + tipo_listagem = self.request.GET.get('tipo_listagem', '1') + tipo_listagem = '1' if not tipo_listagem else tipo_listagem + + context['tipo_listagem'] = tipo_listagem qr = self.request.GET.copy() if 'page' in qr: @@ -1810,7 +1823,8 @@ class MateriaLegislativaPesquisaView(FilterView): context['show_results'] = show_results_filter_set(qr) - context['USE_SOLR'] = settings.USE_SOLR if hasattr(settings, 'USE_SOLR') else False + context['USE_SOLR'] = settings.USE_SOLR if hasattr( + settings, 'USE_SOLR') else False return context @@ -2067,12 +2081,12 @@ class PrimeiraTramitacaoEmLoteView(PermissionRequiredMixin, FilterView): for materia_id in marcadas: try: data_tramitacao = tz.localize(datetime.strptime( - request.POST['data_tramitacao'], "%d/%m/%Y")) + request.POST['data_tramitacao'], "%d/%m/%Y")) except ValueError: msg = _('Formato da data da tramitação incorreto.') messages.add_message(request, messages.ERROR, msg) return self.get(request, self.kwargs) - + t = Tramitacao( materia_id=materia_id, data_tramitacao=data_tramitacao, diff --git a/sapl/parlamentares/models.py b/sapl/parlamentares/models.py index 60df66462..8c07914c4 100644 --- a/sapl/parlamentares/models.py +++ b/sapl/parlamentares/models.py @@ -1,10 +1,10 @@ -import reversion from django.db import models from django.utils import timezone from django.utils.translation import ugettext_lazy as _ from image_cropping.fields import ImageCropField, ImageRatioField from model_utils import Choices +import reversion from sapl.base.models import Autor from sapl.decorators import vigencia_atual @@ -281,6 +281,7 @@ class Parlamentar(models.Model): ('nome_completo', '__icontains'), ('nome_parlamentar', '__icontains'), ('filiacao__partido__sigla', '__icontains'), + ('filiacao__partido', '__exact'), )) class Meta: diff --git a/sapl/templates/materia/materialegislativa_filter.html b/sapl/templates/materia/materialegislativa_filter.html index 5ff3eaee0..74e179d42 100644 --- a/sapl/templates/materia/materialegislativa_filter.html +++ b/sapl/templates/materia/materialegislativa_filter.html @@ -34,7 +34,11 @@ {% if paginator.count %} {% if paginator.count > 1 %} -

{% blocktrans with paginator.count as total_materias %}Pesquisa concluída com sucesso! Foram encontradas {{total_materias}} matérias.{% endblocktrans %}

+ {% if not tipo_listagem or tipo_listagem == '1' %} +

{% blocktrans with paginator.count as total_materias %}Pesquisa detalhada concluída com sucesso! Foram encontradas {{total_materias}} matérias.{% endblocktrans %}

+ {% else %} +

{% blocktrans with paginator.count as total_materias %}Pesquisa simplificada concluída com sucesso! Foram encontradas {{total_materias}} matérias.{% endblocktrans %}

+ {% endif %} {% elif paginator.count == 1 %}

{% trans 'Pesquisa concluída com sucesso! Foi encontrada 1 matéria.'%}

{% endif %} @@ -63,92 +67,96 @@ {% endif %} {% if m.autoria_set.all %} - Autor: - {% for a in m.autoria_set.all %} + Autor: + {% for a in m.autoria_set.all %} {% if not forloop.first %}
{{a.autor}} {% else %}  {{a.autor}} {% endif %} - {% endfor %} -
- {% endif %} - {% if m.tramitacao_set.last.unidade_tramitacao_destino %} - Localização Atual:  {{m.tramitacao_set.last.unidade_tramitacao_destino}}
- {% endif %} - {% if m.tramitacao_set.last.status %} - Status:  {{m.tramitacao_set.last.status}}
- Data Fim Prazo (Tramitação): {{m.tramitacao_set.last.data_fim_prazo|default_if_none:""}}
- {% endif %} - {% if m.registrovotacao_set.exists %} - Data Votação: - {% for rv in m.registrovotacao_set.all %} - {% if rv.ordem %} - - {{ rv.ordem.sessao_plenaria.data_inicio }} - - {% elif rv.expediente %} - - {{ rv.expediente.sessao_plenaria.data_inicio }} - - {% endif %} -
- {% endfor %} - {% endif %} - {% if m.tramitacao_set.last.data_tramitacao %} - Data da última Tramitação:  {{m.tramitacao_set.last.data_tramitacao}}
- Ultima Ação:   {{m.tramitacao_set.last.texto}}
- {% endif %} - {% if m.anexo_de.exists %} - {% for a in m.materia_anexada_set.all %} - Matéria Anexadora:   - - {{ a.materia_principal }}  - - Data Anexação: {{a.data_anexacao}} -
{% endfor %} - {% endif %} - {% if m.anexadas.all.exists %} - {% for anexada in m.materia_principal_set.all %} - Matéria Anexada:   - - {{ anexada.materia_anexada }}  - - Data Anexação: {{anexada.data_anexacao}}
- {% endfor %} {% endif %} - {% if m.documentoacessorio_set.all.exists %} - Documentos Acessórios: - - {{ m.documentoacessorio_set.all.count }} + + {% if not tipo_listagem or tipo_listagem == '1' %} + + {% if m.tramitacao_set.last.unidade_tramitacao_destino %} + Localização Atual:  {{m.tramitacao_set.last.unidade_tramitacao_destino}}
+ {% endif %} + {% if m.tramitacao_set.last.status %} + Status:  {{m.tramitacao_set.last.status}}
+ Data Fim Prazo (Tramitação): {{m.tramitacao_set.last.data_fim_prazo|default_if_none:""}}
+ {% endif %} + {% if m.registrovotacao_set.exists %} + Data Votação: + {% for rv in m.registrovotacao_set.all %} + {% if rv.ordem %} +
+ {{ rv.ordem.sessao_plenaria.data_inicio }} + + {% elif rv.expediente %} + + {{ rv.expediente.sessao_plenaria.data_inicio }} + + {% endif %} +
+ {% endfor %} + {% endif %} + {% if m.tramitacao_set.last.data_tramitacao %} + Data da última Tramitação:  {{m.tramitacao_set.last.data_tramitacao}}
+ Ultima Ação:   {{m.tramitacao_set.last.texto}}
+ {% endif %} + {% if m.anexo_de.exists %} + {% for a in m.materia_anexada_set.all %} + Matéria Anexadora:   + + {{ a.materia_principal }}  + Data Anexação: {{a.data_anexacao}}
- {% endif %} - {% if m.texto_original %}Texto Original
{% endif %} - {% if m.texto_articulado.exists %}Texto Articulado
{% endif %} - {% if m.normajuridica_set.exists %} - {% for nr in m.normajuridica_set.all %} - Norma Jurídica Vinculada: - - {{ nr }} + {% endfor %} + {% endif %} + {% if m.anexadas.all.exists %} + {% for anexada in m.materia_principal_set.all %} + Matéria Anexada:   + + {{ anexada.materia_anexada }}  + + Data Anexação: {{anexada.data_anexacao}} +
+ {% endfor %} + {% endif %} + {% if m.documentoacessorio_set.all.exists %} + Documentos Acessórios: + + {{ m.documentoacessorio_set.all.count }}
+ {% endif %} + {% if m.texto_original %}Texto Original
{% endif %} + {% if m.texto_articulado.exists %}Texto Articulado
{% endif %} + {% if m.normajuridica_set.exists %} + {% for nr in m.normajuridica_set.all %} + Norma Jurídica Vinculada: + + {{ nr }} + +
+ {% endfor %} + {% endif %} + {% if m.audienciapublica_set.exists %} + Audiência(s) Pública(s): + {% for ap in m.audienciapublica_set.all %} + + {{ ap.nome }} + + {% if not forloop.last %}, {% endif %} {% endfor %} - {% endif %} - {% if m.audienciapublica_set.exists %} - Audiência(s) Pública(s): - {% for ap in m.audienciapublica_set.all %} - - {{ ap.nome }} - - {% if not forloop.last %}, {% endif %} - {% endfor %} - {% endif %} -

- {% if m.em_tramitacao and mail_service_configured %} - Acompanhar Matéria + {% endif %} +

+ {% if m.em_tramitacao and mail_service_configured %} + Acompanhar Matéria + {% endif %} {% endif %} From 93e394d3f5c677427716574e6a5070932fcc1696 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Sun, 6 Jan 2019 04:54:38 -0200 Subject: [PATCH 35/41] =?UTF-8?q?Refatora=20formul=C3=A1rio=20de=20pesquis?= =?UTF-8?q?a=20de=20normas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/norma/forms.py | 15 +++++++-- .../migrations/0020_auto_20190106_0454.py | 31 +++++++++++++++++++ sapl/norma/models.py | 21 +++++++------ 3 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 sapl/norma/migrations/0020_auto_20190106_0454.py diff --git a/sapl/norma/forms.py b/sapl/norma/forms.py index 55541b48f..cd5a091a1 100644 --- a/sapl/norma/forms.py +++ b/sapl/norma/forms.py @@ -6,6 +6,7 @@ from crispy_forms.layout import Fieldset, Layout from django import forms from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.db import models +from django.db.models import Q from django.forms import ModelForm, widgets, ModelChoiceField from django.utils import timezone from django.utils.translation import ugettext_lazy as _ @@ -44,7 +45,9 @@ class NormaFilterSet(django_filters.FilterSet): label='Ano', choices=choice_anos_com_normas) - ementa = django_filters.CharFilter(lookup_expr='icontains') + ementa = django_filters.CharFilter( + method='filter_ementa', + label=_('Pesquisar expressões na ementa da norma')) indexacao = django_filters.CharFilter(lookup_expr='icontains', label=_('Indexação')) @@ -52,7 +55,7 @@ class NormaFilterSet(django_filters.FilterSet): assuntos = django_filters.ModelChoiceFilter( queryset=AssuntoNorma.objects.all()) - o = NormaPesquisaOrderingFilter() + o = NormaPesquisaOrderingFilter(help_text='') class Meta: filter_overrides = {models.DateField: { @@ -82,6 +85,14 @@ class NormaFilterSet(django_filters.FilterSet): form_actions(label='Pesquisar')) ) + def filter_ementa(self, queryset, name, value): + texto = value.split() + q = Q() + for t in texto: + q &= Q(ementa__icontains=t) + + return queryset.filter(q) + class NormaJuridicaForm(ModelForm): diff --git a/sapl/norma/migrations/0020_auto_20190106_0454.py b/sapl/norma/migrations/0020_auto_20190106_0454.py new file mode 100644 index 000000000..09c5caa6f --- /dev/null +++ b/sapl/norma/migrations/0020_auto_20190106_0454.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.8 on 2019-01-06 06:54 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('norma', '0019_auto_20190104_1021'), + ] + + operations = [ + migrations.AlterField( + model_name='normajuridica', + name='data_publicacao', + field=models.DateField(blank=True, null=True, verbose_name='Data de Publicação'), + ), + migrations.AlterField( + model_name='normajuridica', + name='tipo', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='norma.TipoNormaJuridica', verbose_name='Tipo da Norma Jurídica'), + ), + migrations.AlterField( + model_name='normajuridica', + name='veiculo_publicacao', + field=models.CharField(blank=True, max_length=30, verbose_name='Veículo de Publicação'), + ), + ] diff --git a/sapl/norma/models.py b/sapl/norma/models.py index 80075f113..21834cc4d 100644 --- a/sapl/norma/models.py +++ b/sapl/norma/models.py @@ -83,7 +83,7 @@ class NormaJuridica(models.Model): tipo = models.ForeignKey( TipoNormaJuridica, on_delete=models.PROTECT, - verbose_name=_('Tipo da Norma Juridica')) + verbose_name=_('Tipo da Norma Jurídica')) materia = models.ForeignKey( MateriaLegislativa, blank=True, null=True, on_delete=models.PROTECT, verbose_name=_('Matéria')) @@ -98,11 +98,11 @@ class NormaJuridica(models.Model): choices=ESFERA_FEDERACAO_CHOICES) data = models.DateField(blank=False, null=True, verbose_name=_('Data')) data_publicacao = models.DateField( - blank=True, null=True, verbose_name=_('Data Publicação')) + blank=True, null=True, verbose_name=_('Data de Publicação')) veiculo_publicacao = models.CharField( max_length=30, blank=True, - verbose_name=_('Veículo Publicação')) + verbose_name=_('Veículo de Publicação')) pagina_inicio_publicacao = models.PositiveIntegerField( blank=True, null=True, verbose_name=_('Pg. Início')) pagina_fim_publicacao = models.PositiveIntegerField( @@ -119,7 +119,8 @@ class NormaJuridica(models.Model): assuntos = models.ManyToManyField( AssuntoNorma, blank=True, verbose_name=_('Assuntos')) - data_vigencia = models.DateField(blank=True, null=True, verbose_name=_('Data Fim Vigência')) + data_vigencia = models.DateField( + blank=True, null=True, verbose_name=_('Data Fim Vigência')) timestamp = models.DateTimeField(null=True) texto_articulado = GenericRelation( @@ -197,7 +198,8 @@ class NormaEstatisticas(models.Model): blank=True, null=True, auto_now=True) norma = models.ForeignKey(NormaJuridica, - on_delete=models.CASCADE) + on_delete=models.CASCADE) + def __str__(self): return _('Usuário: %(usuario)s, Norma: %(norma)s') % { 'usuario': self.usuario, 'norma': self.norma} @@ -225,6 +227,7 @@ class AutoriaNorma(models.Model): return _('Autoria: %(autor)s - %(norma)s') % { 'autor': self.autor, 'norma': self.norma} + @reversion.register() class LegislacaoCitada(models.Model): materia = models.ForeignKey(MateriaLegislativa, on_delete=models.CASCADE) @@ -271,8 +274,8 @@ class TipoVinculoNormaJuridica(models.Model): descricao_passiva = models.CharField( max_length=50, blank=True, verbose_name=_('Descrição Passiva')) revoga_integralmente = models.BooleanField(verbose_name=_('Revoga Integralmente?'), - choices=YES_NO_CHOICES, - default=False) + choices=YES_NO_CHOICES, + default=False) class Meta: verbose_name = _('Tipo de Vínculo entre Normas Jurídicas') @@ -318,8 +321,8 @@ class AnexoNormaJuridica(models.Model): on_delete=models.PROTECT, verbose_name=_('Norma Juridica')) assunto_anexo = models.TextField( - blank = True, - default = "", + blank=True, + default="", verbose_name=_('Assunto do Anexo'), max_length=250 ) From c8e520509e0225527883605ec0f5e6d980a225d3 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Sun, 6 Jan 2019 13:42:04 -0200 Subject: [PATCH 36/41] Refatora form de pesquisa de protocolos --- sapl/protocoloadm/forms.py | 32 +++++++++---------- .../migrations/0013_auto_20190106_1336.py | 26 +++++++++++++++ sapl/protocoloadm/models.py | 10 +++--- 3 files changed, 48 insertions(+), 20 deletions(-) create mode 100644 sapl/protocoloadm/migrations/0013_auto_20190106_1336.py diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 63474be8e..90fb7c7ce 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -29,12 +29,11 @@ from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo, TIPOS_PROTOCOLO = [('0', 'Recebido'), ('1', 'Enviado'), - ('2', 'Interno'), ('', '---------')] + ('2', 'Interno')] TIPOS_PROTOCOLO_CREATE = [ ('0', 'Recebido'), ('1', 'Enviado'), ('2', 'Interno')] -NATUREZA_PROCESSO = [('', '---------'), - ('0', 'Administrativo'), +NATUREZA_PROCESSO = [('0', 'Administrativo'), ('1', 'Legislativo')] @@ -68,13 +67,18 @@ class AcompanhamentoDocumentoForm(ModelForm): class ProtocoloFilterSet(django_filters.FilterSet): - ano = django_filters.ChoiceFilter(required=False, - label='Ano', - choices=choice_anos_com_protocolo) + ano = django_filters.ChoiceFilter( + required=False, + label='Ano', + choices=choice_anos_com_protocolo) - assunto_ementa = django_filters.CharFilter(lookup_expr='icontains') + assunto_ementa = django_filters.CharFilter( + label=_('Assunto'), + lookup_expr='icontains') - interessado = django_filters.CharFilter(lookup_expr='icontains') + interessado = django_filters.CharFilter( + label=_('Interessado'), + lookup_expr='icontains') autor = django_filters.CharFilter(widget=forms.HiddenInput()) @@ -91,7 +95,7 @@ class ProtocoloFilterSet(django_filters.FilterSet): widget=forms.Select( attrs={'class': 'selector'})) - o = AnoNumeroOrderingFilter() + o = AnoNumeroOrderingFilter(help_text='') class Meta: filter_overrides = {models.DateTimeField: { @@ -110,9 +114,6 @@ class ProtocoloFilterSet(django_filters.FilterSet): 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 = to_row( [('numero', 4), ('ano', 4), @@ -136,9 +137,7 @@ class ProtocoloFilterSet(django_filters.FilterSet): 'Limpar Autor', css_class='btn btn-primary btn-sm'), 10)]) row5 = to_row( - [('tipo_processo', 12)]) - row6 = to_row( - [('o', 12)]) + [('tipo_processo', 6), ('o', 6)]) self.form.helper = FormHelper() self.form.helper.form_method = 'GET' @@ -146,9 +145,10 @@ class ProtocoloFilterSet(django_filters.FilterSet): Fieldset(_('Pesquisar Protocolo'), row1, row2, row3, + row5, HTML(autor_label), HTML(autor_modal), - row4, row5, row6, + row4, form_actions(label='Pesquisar')) ) diff --git a/sapl/protocoloadm/migrations/0013_auto_20190106_1336.py b/sapl/protocoloadm/migrations/0013_auto_20190106_1336.py new file mode 100644 index 000000000..3cd58e085 --- /dev/null +++ b/sapl/protocoloadm/migrations/0013_auto_20190106_1336.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.8 on 2019-01-06 15:36 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('protocoloadm', '0012_auto_20190104_1021'), + ] + + operations = [ + migrations.AlterField( + model_name='protocolo', + name='tipo_documento', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='protocoloadm.TipoDocumentoAdministrativo', verbose_name='Tipo de Documento'), + ), + migrations.AlterField( + model_name='protocolo', + name='tipo_materia', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='materia.TipoMateriaLegislativa', verbose_name='Tipo de Matéria'), + ), + ] diff --git a/sapl/protocoloadm/models.py b/sapl/protocoloadm/models.py index 1b061fa18..438037205 100644 --- a/sapl/protocoloadm/models.py +++ b/sapl/protocoloadm/models.py @@ -1,8 +1,8 @@ -import reversion from django.db import models from django.utils import timezone 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 TipoMateriaLegislativa, UnidadeTramitacao @@ -78,13 +78,13 @@ class Protocolo(models.Model): blank=True, null=True, on_delete=models.PROTECT, - verbose_name=_('Tipo de documento')) + verbose_name=_('Tipo de Documento')) tipo_materia = models.ForeignKey( TipoMateriaLegislativa, blank=True, null=True, on_delete=models.PROTECT, - verbose_name=_('Tipo Matéria')) + verbose_name=_('Tipo de Matéria')) numero_paginas = models.PositiveIntegerField( blank=True, null=True, verbose_name=_('Número de Páginas')) observacao = models.TextField( @@ -299,10 +299,12 @@ class TramitacaoAdministrativo(models.Model): 'documento': self.documento, 'status': self.status } + @reversion.register() class AcompanhamentoDocumento(models.Model): usuario = models.CharField(max_length=50) - documento = models.ForeignKey(DocumentoAdministrativo, on_delete=models.CASCADE) + documento = models.ForeignKey( + DocumentoAdministrativo, on_delete=models.CASCADE) email = models.EmailField( max_length=100, verbose_name=_('E-mail')) data_cadastro = models.DateField(auto_now_add=True) From a19a8c0b1b0fbdc8d4dfed3c94a082a49e84c1a8 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Sun, 6 Jan 2019 14:08:36 -0200 Subject: [PATCH 37/41] Refatora form de pesquisa de Documentos Administrativos --- sapl/protocoloadm/forms.py | 51 +++++++++++++++++++++----------------- sapl/utils.py | 5 ++++ 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 90fb7c7ce..2b43e7ab3 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -20,7 +20,8 @@ from sapl.materia.models import (MateriaLegislativa, TipoMateriaLegislativa, UnidadeTramitacao) from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, AnoNumeroOrderingFilter, RangeWidgetOverride, autor_label, autor_modal, - choice_anos_com_protocolo) + choice_anos_com_protocolo, + choice_anos_com_documentoadministrativo) from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo, DocumentoAdministrativo, @@ -37,9 +38,7 @@ NATUREZA_PROCESSO = [('0', 'Administrativo'), ('1', 'Legislativo')] -EM_TRAMITACAO = [('', '---------'), - (0, 'Sim'), - (1, 'Não')] +EM_TRAMITACAO = [(0, 'Sim'), (1, 'Não')] class AcompanhamentoDocumentoForm(ModelForm): @@ -155,19 +154,24 @@ class ProtocoloFilterSet(django_filters.FilterSet): class DocumentoAdministrativoFilterSet(django_filters.FilterSet): - ano = django_filters.ChoiceFilter(required=False, - label='Ano', - choices=RANGE_ANOS) + ano = django_filters.ChoiceFilter( + required=False, + label='Ano', + choices=choice_anos_com_documentoadministrativo) tramitacao = django_filters.ChoiceFilter(required=False, label='Em Tramitação?', - choices=EM_TRAMITACAO) + choices=YES_NO_CHOICES) - assunto = django_filters.CharFilter(lookup_expr='icontains') + assunto = django_filters.CharFilter( + label=_('Assunto'), + lookup_expr='icontains') - interessado = django_filters.CharFilter(lookup_expr='icontains') + interessado = django_filters.CharFilter( + label=_('Interessado'), + lookup_expr='icontains') - o = AnoNumeroOrderingFilter() + o = AnoNumeroOrderingFilter(help_text='') class Meta: filter_overrides = {models.DateField: { @@ -190,37 +194,38 @@ class DocumentoAdministrativoFilterSet(django_filters.FilterSet): local_atual = 'tramitacaoadministrativo__unidade_tramitacao_destino' self.filters['tipo'].label = 'Tipo de Documento' + self.filters['protocolo__numero'].label = 'Núm. Protocolo' self.filters['tramitacaoadministrativo__status'].label = 'Situação' self.filters[local_atual].label = 'Localização Atual' row1 = to_row( - [('tipo', 6), - ('numero', 6)]) + [('tipo', 8), + ('o', 4), ]) row2 = to_row( - [('ano', 4), + [('numero', 2), + ('ano', 2), ('protocolo__numero', 2), ('numero_externo', 2), ('data', 4)]) row3 = to_row( - [('interessado', 4), - ('assunto', 4), - ('tramitacao', 4)]) + [('interessado', 6), + ('assunto', 6)]) row4 = to_row( - [('tramitacaoadministrativo__unidade_tramitacao_destino', 6), - ('tramitacaoadministrativo__status', 6)]) - - row5 = to_row( - [('o', 12)]) + [ + ('tramitacao', 2), + ('tramitacaoadministrativo__status', 5), + ('tramitacaoadministrativo__unidade_tramitacao_destino', 5), + ]) self.form.helper = FormHelper() self.form.helper.form_method = 'GET' self.form.helper.layout = Layout( Fieldset(_('Pesquisar Documento'), row1, row2, - row3, row4, row5, + row3, row4, form_actions(label='Pesquisar')) ) diff --git a/sapl/utils.py b/sapl/utils.py index c812fdcb9..b1970c46b 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -369,6 +369,11 @@ def choice_anos_com_protocolo(): return choice_anos(Protocolo) +def choice_anos_com_documentoadministrativo(): + from sapl.protocoloadm.models import DocumentoAdministrativo + return choice_anos(DocumentoAdministrativo) + + def choice_anos_com_sessaoplenaria(): try: from sapl.sessao.models import SessaoPlenaria From 94fc4db6260389b97ea8e36bc33d58ae2608a7a4 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Sun, 6 Jan 2019 14:19:32 -0200 Subject: [PATCH 38/41] corrige form de cadastro de documento administrativo --- sapl/protocoloadm/forms.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 2b43e7ab3..9e8920f7f 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -21,7 +21,7 @@ from sapl.materia.models import (MateriaLegislativa, TipoMateriaLegislativa, from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, AnoNumeroOrderingFilter, RangeWidgetOverride, autor_label, autor_modal, choice_anos_com_protocolo, - choice_anos_com_documentoadministrativo) + choice_anos_com_documentoadministrativo, ANO_CHOICES) from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo, DocumentoAdministrativo, @@ -707,12 +707,13 @@ class DocumentoAdministrativoForm(ModelForm): data = forms.DateField(initial=timezone.now) - ano_protocolo = forms.ChoiceField(required=False, - label=Protocolo._meta. - get_field('ano').verbose_name, - choices=RANGE_ANOS, - widget=forms.Select( - attrs={'class': 'selector'})) + ano_protocolo = forms.ChoiceField( + required=False, + label=Protocolo._meta. + get_field('ano').verbose_name, + choices=[('', '---------')] + choice_anos_com_protocolo(), + widget=forms.Select( + attrs={'class': 'selector'})) numero_protocolo = forms.IntegerField(required=False, label=Protocolo._meta. @@ -829,7 +830,7 @@ class DocumentoAdministrativoForm(ModelForm): def __init__(self, *args, **kwargs): row1 = to_row( - [('tipo', 4), ('numero', 4), ('ano', 4)]) + [('tipo', 6), ('numero', 3), ('ano', 3)]) row2 = to_row( [('data', 4), ('numero_protocolo', 4), ('ano_protocolo', 4)]) @@ -838,7 +839,7 @@ class DocumentoAdministrativoForm(ModelForm): [('assunto', 12)]) row4 = to_row( - [('interessado', 8), ('tramitacao', 2), (InlineRadios('restrito'), 2)]) + [('interessado', 7), ('tramitacao', 2), (InlineRadios('restrito'), 3)]) row5 = to_row( [('texto_integral', 12)]) From ae370faf189a7318cc821f9d45b45148ae1c3df3 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Sun, 6 Jan 2019 17:02:45 -0200 Subject: [PATCH 39/41] altera teste de documento administrativo inexistente --- sapl/protocoloadm/tests/test_protocoloadm.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sapl/protocoloadm/tests/test_protocoloadm.py b/sapl/protocoloadm/tests/test_protocoloadm.py index 2f61d359f..d61d7b2b3 100644 --- a/sapl/protocoloadm/tests/test_protocoloadm.py +++ b/sapl/protocoloadm/tests/test_protocoloadm.py @@ -1,10 +1,10 @@ from datetime import date, timedelta -import pytest from django.core.urlresolvers import reverse from django.utils.encoding import force_text from django.utils.translation import ugettext_lazy as _ from model_mommy import mommy +import pytest from sapl.materia.models import UnidadeTramitacao from sapl.protocoloadm.forms import (AnularProcoloAdmForm, @@ -368,6 +368,9 @@ def test_documento_administrativo_invalido(): def test_documento_administrativo_protocolo_inexistente(): tipo = mommy.make(TipoDocumentoAdministrativo) + protocolo = mommy.make(Protocolo, + ano=2017, + numero=10) form = DocumentoAdministrativoForm(data={'ano': '2017', 'tipo': str(tipo.pk), From 6c3ca7e57b4ab027f4f76147802e7be14fa0f3d8 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Mon, 7 Jan 2019 00:03:10 -0200 Subject: [PATCH 40/41] corrige erro apontado pelo teste de doc adms inexistentes --- sapl/protocoloadm/forms.py | 6 +++--- sapl/protocoloadm/tests/test_protocoloadm.py | 7 +++++-- sapl/utils.py | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 9e8920f7f..9a9bda40b 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -20,8 +20,8 @@ from sapl.materia.models import (MateriaLegislativa, TipoMateriaLegislativa, UnidadeTramitacao) from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, AnoNumeroOrderingFilter, RangeWidgetOverride, autor_label, autor_modal, - choice_anos_com_protocolo, - choice_anos_com_documentoadministrativo, ANO_CHOICES) + choice_anos_com_protocolo, choice_force_optional, + choice_anos_com_documentoadministrativo) from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo, DocumentoAdministrativo, @@ -711,7 +711,7 @@ class DocumentoAdministrativoForm(ModelForm): required=False, label=Protocolo._meta. get_field('ano').verbose_name, - choices=[('', '---------')] + choice_anos_com_protocolo(), + choices=choice_force_optional(choice_anos_com_protocolo), widget=forms.Select( attrs={'class': 'selector'})) diff --git a/sapl/protocoloadm/tests/test_protocoloadm.py b/sapl/protocoloadm/tests/test_protocoloadm.py index d61d7b2b3..2a4c9f53c 100644 --- a/sapl/protocoloadm/tests/test_protocoloadm.py +++ b/sapl/protocoloadm/tests/test_protocoloadm.py @@ -1,6 +1,7 @@ from datetime import date, timedelta from django.core.urlresolvers import reverse +from django.utils import timezone from django.utils.encoding import force_text from django.utils.translation import ugettext_lazy as _ from model_mommy import mommy @@ -191,7 +192,7 @@ def test_create_tramitacao(admin_client): 'unidade_tramitacao_destino': unidade_tramitacao_destino_2.pk, 'documento': documento_adm.pk, 'status': status.pk, - 'data_tramitacao': date.today() + timedelta( + 'data_tramitacao': timezone.now().date() + timedelta( days=1)}, follow=True) @@ -370,7 +371,9 @@ def test_documento_administrativo_protocolo_inexistente(): tipo = mommy.make(TipoDocumentoAdministrativo) protocolo = mommy.make(Protocolo, ano=2017, - numero=10) + numero=10, + anulado=False, + tipo_documento=tipo) form = DocumentoAdministrativoForm(data={'ano': '2017', 'tipo': str(tipo.pk), diff --git a/sapl/utils.py b/sapl/utils.py index b1970c46b..ee8271b4f 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -387,6 +387,26 @@ def choice_anos_com_sessaoplenaria(): return [] +def choice_force_optional(callable): + """ Django-filter faz algo que tenha o mesmo sentido em ChoiceFilter, + no entanto, as funções choice_anos_... podem ser usadas em formulários + comuns de adição e/ou edição, com a particularidade de terem + required=False. + Neste caso para ser possível contar com a otimização de apenas mostrar anos + que estejam na base de dados e ainda colocar o item opcional '---------', + é necessário encapsular então, as funções choice_anos_... com a + esta função choice_force_optional... isso ocorre e foi aplicado + inicialmente no cadastro de documentos administrativos onde tem-se + opcionalmente a possibilidade de colocar o ano do protocolo. + Em ChoiceFilter choice_force_optional não deve ser usado pois duplicaria + o item opcional '---------' já que ChoiceFilter já o adiciona, como dito + anteriormente. + """ + def _func(): + return [('', '---------')] + callable() + return _func + + TIPOS_TEXTO_PERMITIDOS = ( 'application/vnd.oasis.opendocument.text', 'application/x-vnd.oasis.opendocument.text', From 0605581e2ede90a2161b2c48f554b73297416857 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Mon, 7 Jan 2019 09:45:39 -0200 Subject: [PATCH 41/41] =?UTF-8?q?remove=20duplicidade=20de=20c=C3=B3digo?= =?UTF-8?q?=20de=20filter=5Foverrides?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/base/forms.py | 49 ++++++------------------------------- sapl/materia/forms.py | 34 ++++--------------------- sapl/norma/forms.py | 8 +----- sapl/protocoloadm/forms.py | 18 +++----------- sapl/protocoloadm/models.py | 5 ++-- sapl/utils.py | 16 ++++++++++++ 6 files changed, 36 insertions(+), 94 deletions(-) diff --git a/sapl/base/forms.py b/sapl/base/forms.py index 5aa3315fb..5b246a47f 100644 --- a/sapl/base/forms.py +++ b/sapl/base/forms.py @@ -32,7 +32,8 @@ 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, - choice_anos_com_normas, choice_anos_com_materias) + choice_anos_com_normas, choice_anos_com_materias, + FilterOverridesMetaMixin) from .models import AppConfig, CasaLegislativa @@ -674,13 +675,7 @@ class AutorFormForAdmin(AutorForm): class RelatorioAtasFilterSet(django_filters.FilterSet): - class Meta: - filter_overrides = {models.DateField: { - 'filter_class': django_filters.DateFromToRangeFilter, - 'extra': lambda f: { - 'label': '%s (%s)' % (f.verbose_name, _('Inicial - Final')), - 'widget': RangeWidgetOverride} - }} + class Meta(FilterOverridesMetaMixin): model = SessaoPlenaria fields = ['data_inicio'] @@ -714,12 +709,6 @@ class RelatorioNormasMesFilterSet(django_filters.FilterSet): choices=choice_anos_com_normas) class Meta: - filter_overrides = {models.DateField: { - 'filter_class': django_filters.DateFromToRangeFilter, - 'extra': lambda f: { - 'label': '%s (%s)' % (f.verbose_name, _('Ano')), - 'widget': RangeWidgetOverride} - }} model = NormaJuridica fields = ['ano'] @@ -784,13 +773,7 @@ class RelatorioNormasVigenciaFilterSet(django_filters.FilterSet): class RelatorioPresencaSessaoFilterSet(django_filters.FilterSet): - class Meta: - filter_overrides = {models.DateField: { - 'filter_class': django_filters.DateFromToRangeFilter, - 'extra': lambda f: { - 'label': '%s (%s)' % (f.verbose_name, _('Inicial - Final')), - 'widget': RangeWidgetOverride} - }} + class Meta(FilterOverridesMetaMixin): model = SessaoPlenaria fields = ['data_inicio'] @@ -822,13 +805,7 @@ class RelatorioHistoricoTramitacaoFilterSet(django_filters.FilterSet): parent = super(RelatorioHistoricoTramitacaoFilterSet, self).qs return parent.distinct().prefetch_related('tipo').order_by('-ano', 'tipo', 'numero') - class Meta: - filter_overrides = {models.DateField: { - 'filter_class': django_filters.DateFromToRangeFilter, - 'extra': lambda f: { - 'label': '%s (%s)' % (f.verbose_name, _('Inicial - Final')), - 'widget': RangeWidgetOverride} - }} + class Meta(FilterOverridesMetaMixin): model = MateriaLegislativa fields = ['tipo', 'tramitacao__unidade_tramitacao_local', 'tramitacao__status', 'tramitacao__data_tramitacao'] @@ -861,13 +838,7 @@ class RelatorioDataFimPrazoTramitacaoFilterSet(django_filters.FilterSet): parent = super(RelatorioDataFimPrazoTramitacaoFilterSet, self).qs return parent.distinct().prefetch_related('tipo').order_by('-ano', 'tipo', 'numero') - class Meta: - filter_overrides = {models.DateField: { - 'filter_class': django_filters.DateFromToRangeFilter, - 'extra': lambda f: { - 'label': '%s (%s)' % (f.verbose_name, _('Inicial - Final')), - 'widget': RangeWidgetOverride} - }} + class Meta(FilterOverridesMetaMixin): model = MateriaLegislativa fields = ['tipo', 'tramitacao__unidade_tramitacao_local', 'tramitacao__status', 'tramitacao__data_fim_prazo'] @@ -1034,13 +1005,7 @@ class RelatorioMateriasPorAutorFilterSet(django_filters.FilterSet): return parent.distinct().filter(autoria__primeiro_autor=True)\ .order_by('autoria__autor', '-autoria__primeiro_autor', 'tipo', '-ano', '-numero') - class Meta: - filter_overrides = {models.DateField: { - 'filter_class': django_filters.DateFromToRangeFilter, - 'extra': lambda f: { - 'label': '%s (%s)' % (f.verbose_name, _('Inicial - Final')), - 'widget': RangeWidgetOverride} - }} + class Meta(FilterOverridesMetaMixin): model = MateriaLegislativa fields = ['tipo', 'data_apresentacao'] diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index 06d5bada8..a043d024d 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -45,7 +45,7 @@ from sapl.utils import (YES_NO_CHOICES, SEPARADOR_HASH_PROPOSICAO, MateriaPesquisaOrderingFilter, RangeWidgetOverride, autor_label, autor_modal, gerar_hash_arquivo, models_with_gr_for_model, qs_override_django_filter, - choice_anos_com_materias) + choice_anos_com_materias, FilterOverridesMetaMixin) from .models import (AcompanhamentoMateria, Anexada, Autoria, DespachoInicial, DocumentoAcessorio, Numeracao, Proposicao, Relatoria, @@ -806,13 +806,7 @@ class MateriaLegislativaFilterSet(django_filters.FilterSet): choices=CHOICE_TIPO_LISTAGEM, label=_('Tipo da Listagem do Resultado da Pesquisa')) - class Meta: - filter_overrides = {models.DateField: { - 'filter_class': django_filters.DateFromToRangeFilter, - 'extra': lambda f: { - 'label': '%s (%s)' % (f.verbose_name, _('Inicial / Final')), - 'widget': RangeWidgetOverride} - }} + class Meta(FilterOverridesMetaMixin): model = MateriaLegislativa fields = ['numero', 'numero_protocolo', @@ -1104,13 +1098,7 @@ class AutoriaMultiCreateForm(Form): class AcessorioEmLoteFilterSet(django_filters.FilterSet): - class Meta: - filter_overrides = {models.DateField: { - 'filter_class': django_filters.DateFromToRangeFilter, - 'extra': lambda f: { - 'label': '%s (%s)' % (f.verbose_name, _('Inicial - Final')), - 'widget': RangeWidgetOverride} - }} + class Meta(FilterOverridesMetaMixin): model = MateriaLegislativa fields = ['tipo', 'data_apresentacao'] @@ -1134,13 +1122,7 @@ class AcessorioEmLoteFilterSet(django_filters.FilterSet): class PrimeiraTramitacaoEmLoteFilterSet(django_filters.FilterSet): - class Meta: - filter_overrides = {models.DateField: { - 'filter_class': django_filters.DateFromToRangeFilter, - 'extra': lambda f: { - 'label': '%s (%s)' % (f.verbose_name, _('Inicial - Final')), - 'widget': RangeWidgetOverride} - }} + class Meta(FilterOverridesMetaMixin): model = MateriaLegislativa fields = ['tipo', 'data_apresentacao'] @@ -1165,13 +1147,7 @@ class PrimeiraTramitacaoEmLoteFilterSet(django_filters.FilterSet): class TramitacaoEmLoteFilterSet(django_filters.FilterSet): - class Meta: - filter_overrides = {models.DateField: { - 'filter_class': django_filters.DateFromToRangeFilter, - 'extra': lambda f: { - 'label': '%s (%s)' % (f.verbose_name, _('Inicial - Final')), - 'widget': RangeWidgetOverride} - }} + class Meta(FilterOverridesMetaMixin): model = MateriaLegislativa fields = ['tipo', 'data_apresentacao', 'tramitacao__status', 'tramitacao__unidade_tramitacao_destino'] diff --git a/sapl/norma/forms.py b/sapl/norma/forms.py index cd5a091a1..512308e4f 100644 --- a/sapl/norma/forms.py +++ b/sapl/norma/forms.py @@ -57,13 +57,7 @@ class NormaFilterSet(django_filters.FilterSet): o = NormaPesquisaOrderingFilter(help_text='') - class Meta: - filter_overrides = {models.DateField: { - 'filter_class': django_filters.DateFromToRangeFilter, - 'extra': lambda f: { - 'label': '%s (%s)' % (f.verbose_name, _('Inicial - Final')), - 'widget': RangeWidgetOverride} - }} + class Meta(FilterOverridesMetaMixin): model = NormaJuridica fields = ['tipo', 'numero', 'ano', 'data', 'data_vigencia', 'data_publicacao', 'ementa', 'assuntos'] diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 9a9bda40b..2a324543b 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -96,13 +96,7 @@ class ProtocoloFilterSet(django_filters.FilterSet): o = AnoNumeroOrderingFilter(help_text='') - class Meta: - filter_overrides = {models.DateTimeField: { - 'filter_class': django_filters.DateFromToRangeFilter, - 'extra': lambda f: { - 'label': 'Data (%s)' % (_('Inicial - Final')), - 'widget': RangeWidgetOverride} - }} + class Meta(FilterOverridesMetaMixin): model = Protocolo fields = ['numero', 'tipo_documento', @@ -113,6 +107,8 @@ class ProtocoloFilterSet(django_filters.FilterSet): def __init__(self, *args, **kwargs): super(ProtocoloFilterSet, self).__init__(*args, **kwargs) + self.filters['timestamp'].label = 'Data (Inicial - Final)' + row1 = to_row( [('numero', 4), ('ano', 4), @@ -173,13 +169,7 @@ class DocumentoAdministrativoFilterSet(django_filters.FilterSet): o = AnoNumeroOrderingFilter(help_text='') - class Meta: - filter_overrides = {models.DateField: { - 'filter_class': django_filters.DateFromToRangeFilter, - 'extra': lambda f: { - 'label': 'Data (%s)' % (_('Inicial - Final')), - 'widget': RangeWidgetOverride} - }} + class Meta(FilterOverridesMetaMixin): model = DocumentoAdministrativo fields = ['tipo', 'numero', diff --git a/sapl/protocoloadm/models.py b/sapl/protocoloadm/models.py index 438037205..6d3d90671 100644 --- a/sapl/protocoloadm/models.py +++ b/sapl/protocoloadm/models.py @@ -56,10 +56,11 @@ class Protocolo(models.Model): null=False, choices=RANGE_ANOS, verbose_name=_('Ano do Protocolo')) - # TODO: Remover esses dois campos após migração, - # TODO: pois timestamp supre a necessidade + + # FIXME: https://github.com/interlegis/sapl/issues/2337 data = models.DateField(null=True, blank=True) hora = models.TimeField(null=True, blank=True) + # Não foi utilizado auto_now_add=True em timestamp porque # ele usa datetime.now que não é timezone aware. timestamp = models.DateTimeField(default=timezone.now) diff --git a/sapl/utils.py b/sapl/utils.py index ee8271b4f..def839eb1 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -16,6 +16,7 @@ from django.contrib.contenttypes.fields import (GenericForeignKey, GenericRel, GenericRelation) from django.core.exceptions import ValidationError from django.core.mail import get_connection +from django.db import models from django.db.models import Q from django.utils import six, timezone from django.utils.translation import ugettext_lazy as _ @@ -407,6 +408,21 @@ def choice_force_optional(callable): return _func +FILTER_OVERRIDES_DATEFIELD = { + 'filter_class': django_filters.DateFromToRangeFilter, + 'extra': lambda f: { + 'label': '%s (%s)' % (f.verbose_name, _('Inicial - Final')), + 'widget': RangeWidgetOverride + } +} + + +class FilterOverridesMetaMixin: + filter_overrides = { + models.DateField: FILTER_OVERRIDES_DATEFIELD + } + + TIPOS_TEXTO_PERMITIDOS = ( 'application/vnd.oasis.opendocument.text', 'application/x-vnd.oasis.opendocument.text',