diff --git a/Dockerfile b/Dockerfile index 3f3adc78e..f4953de84 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 bash RUN apk update --update-cache && apk upgrade diff --git a/check_solr.sh b/check_solr.sh new file mode 100644 index 000000000..b3c4760c4 --- /dev/null +++ b/check_solr.sh @@ -0,0 +1,18 @@ +#!/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" + 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 diff --git a/docker-compose.yml b/docker-compose.yml index 3691de798..b379cf46c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,14 +11,14 @@ sapldb: ports: - "5432:5432" sapl: - image: interlegis/sapl:3.1.138 + image: interlegis/sapl:3.1.140 restart: always environment: 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/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/sapl/api/forms.py b/sapl/api/forms.py index b9ad11aca..fecfbf598 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): @@ -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 diff --git a/sapl/base/forms.py b/sapl/base/forms.py index fe73915f7..3ed28e8fc 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,10 +13,13 @@ 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 @@ -30,10 +32,13 @@ 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, choice_anos_com_materias, + FilterOverridesMetaMixin) 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 +89,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 +127,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 +167,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 +197,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 +232,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 +274,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 +286,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 +482,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 +498,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 +509,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 +528,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 +544,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 +569,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 +577,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 +588,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) @@ -655,13 +676,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'] @@ -692,20 +707,12 @@ class RelatorioNormasMesFilterSet(django_filters.FilterSet): ano = django_filters.ChoiceFilter(required=True, 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} - }} - + choices=choice_anos_com_normas) class Meta: model = NormaJuridica fields = ['ano'] - + def __init__(self, *args, **kwargs): super(RelatorioNormasMesFilterSet, self).__init__( *args, **kwargs) @@ -760,7 +767,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'), @@ -769,11 +776,10 @@ class RelatorioNormasVigenciaFilterSet(django_filters.FilterSet): required=True, initial=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 @@ -796,13 +802,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'] @@ -834,13 +834,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'] @@ -873,13 +867,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'] @@ -915,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__( @@ -935,6 +923,7 @@ class RelatorioReuniaoFilterSet(django_filters.FilterSet): form_actions(label='Pesquisar')) ) + class RelatorioAudienciaFilterSet(django_filters.FilterSet): @property @@ -965,12 +954,11 @@ class RelatorioAudienciaFilterSet(django_filters.FilterSet): ) - 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(), @@ -985,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', @@ -1015,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 @@ -1047,13 +1034,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'] @@ -1173,7 +1154,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) @@ -1185,7 +1165,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.") @@ -1220,7 +1200,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 @@ -1287,33 +1267,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/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/base/views.py b/sapl/base/views.py index 9b3863e55..e25be4bda 100644 --- a/sapl/base/views.py +++ b/sapl/base/views.py @@ -11,7 +11,7 @@ from django.core.exceptions import ObjectDoesNotExist, PermissionDenied from django.core.mail import send_mail from django.core.urlresolvers import reverse from django.db import connection -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 @@ -375,8 +375,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/materia/forms.py b/sapl/materia/forms.py index 454cd9890..a043d024d 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -1,18 +1,18 @@ -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 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 @@ -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 @@ -36,30 +37,34 @@ 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 (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, FilterOverridesMetaMixin) from .models import (AcompanhamentoMateria, Anexada, Autoria, DespachoInicial, DocumentoAcessorio, Numeracao, Proposicao, Relatoria, TipoMateriaLegislativa, Tramitacao, UnidadeTramitacao) -def ANO_CHOICES(): - return [('', '---------')] + RANGE_ANOS - - -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: @@ -135,7 +140,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 +168,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 +218,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 +261,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 +287,7 @@ class MateriaLegislativaForm(ModelForm): return materia + class UnidadeTramitacaoForm(ModelForm): logger = logging.getLogger(__name__) @@ -379,8 +387,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 +449,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 +468,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 +477,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 +486,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 +537,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 +597,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 +651,7 @@ class LegislacaoCitadaForm(ModelForm): class NumeracaoForm(ModelForm): logger = logging.getLogger(__name__) + class Meta: model = Numeracao fields = ['tipo_materia', @@ -658,8 +667,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 +677,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 +689,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 +725,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 +734,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 @@ -759,40 +768,45 @@ class MateriaLegislativaFilterSet(django_filters.FilterSet): ano = django_filters.ChoiceFilter(required=False, label='Ano da Matéria', - choices=ANO_CHOICES) + choices=choice_anos_com_materias) autoria__autor = django_filters.CharFilter(widget=forms.HiddenInput()) autoria__primeiro_autor = django_filters.BooleanFilter( required=False, - label='Primeiro Autor', - widget=forms.HiddenInput()) + label=_('Primeiro Autor')) + + autoria__autor__parlamentar_set__filiacao__partido = django_filters.ModelChoiceFilter( + queryset=Partido.objects.all(), + label=_('Matérias por Partido')) - ementa = django_filters.CharFilter(lookup_expr='icontains') + 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() + o = MateriaPesquisaOrderingFilter(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} - }} + tipo_listagem = forms.ChoiceField( + required=True, + choices=CHOICE_TIPO_LISTAGEM, + label=_('Tipo da Listagem do Resultado da Pesquisa')) + + class Meta(FilterOverridesMetaMixin): model = MateriaLegislativa fields = ['numero', 'numero_protocolo', @@ -803,7 +817,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', @@ -812,16 +826,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), @@ -830,47 +864,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(): @@ -971,7 +1036,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 +1088,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')) @@ -1031,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'] @@ -1061,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'] @@ -1092,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'] @@ -1204,7 +1253,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 +1426,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 +1459,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 +1493,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 +1501,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 +1529,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 +1781,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 +1800,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 +1852,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 +1879,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 +2026,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 +2136,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 +2144,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 +2253,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 +2284,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 +2303,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/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/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/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 cfcb71ffc..221078811 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 @@ -143,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'), @@ -161,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, @@ -177,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( @@ -269,9 +270,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 +729,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/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/materia/views.py b/sapl/materia/views.py index ebce51a5d..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,6 +1823,9 @@ 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 @@ -2039,24 +2055,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[ diff --git a/sapl/norma/forms.py b/sapl/norma/forms.py index 7cd8368f7..512308e4f 100644 --- a/sapl/norma/forms.py +++ b/sapl/norma/forms.py @@ -1,29 +1,29 @@ -import django_filters import logging + from crispy_forms.helper import FormHelper 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 _ +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) -def ANO_CHOICES(): - return [('', '---------')] + RANGE_ANOS - - def get_esferas(): return [('E', 'Estadual'), ('F', 'Federal'), @@ -43,9 +43,11 @@ class NormaFilterSet(django_filters.FilterSet): ano = django_filters.ChoiceFilter(required=False, label='Ano', - choices=ANO_CHOICES) + 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')) @@ -53,15 +55,9 @@ 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: { - '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'] @@ -73,7 +69,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' @@ -83,6 +79,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): @@ -102,7 +106,7 @@ class NormaJuridicaForm(ModelForm): ano_materia = forms.ChoiceField( label='Ano Matéria', required=False, - choices=ANO_CHOICES, + choices=choice_anos_com_materias, widget=forms.Select(attrs={'autocomplete': 'off'}) ) @@ -131,9 +135,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 +145,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 +162,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 +173,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 +183,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 +203,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 +262,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 +278,7 @@ class AnexoNormaJuridicaForm(ModelForm): } logger = logging.getLogger(__name__) + def clean(self): cleaned_data = super(AnexoNormaJuridicaForm, self).clean() if not self.is_valid(): @@ -277,10 +286,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 +304,6 @@ class AnexoNormaJuridicaForm(ModelForm): return anexo - class NormaRelacionadaForm(ModelForm): tipo = forms.ModelChoiceField( @@ -310,6 +319,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 +335,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 +421,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 +430,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/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/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/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 6082818d0..48d2f3558 100644 --- a/sapl/norma/models.py +++ b/sapl/norma/models.py @@ -85,7 +85,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')) @@ -100,11 +100,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( @@ -121,7 +121,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( @@ -204,7 +205,8 @@ class NormaEstatisticas(models.Model): ano = models.PositiveSmallIntegerField(verbose_name=_('Ano'), choices=RANGE_ANOS, default=get_ano_atual) 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} @@ -232,6 +234,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) @@ -278,8 +281,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') @@ -325,8 +328,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 ) 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) diff --git a/sapl/norma/views.py b/sapl/norma/views.py index cfdbf2779..8740505bd 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/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/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 97cab4eee..2a324543b 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,34 +12,34 @@ 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 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, choice_force_optional, + choice_anos_com_documentoadministrativo) from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo, DocumentoAdministrativo, Protocolo, TipoDocumentoAdministrativo, TramitacaoAdministrativo) -TIPOS_PROTOCOLO = [('0', 'Recebido'), ('1', 'Enviado'), ('2', 'Interno'), ('', '---------')] -TIPOS_PROTOCOLO_CREATE = [('0', 'Recebido'), ('1', 'Enviado'), ('2', 'Interno')] -NATUREZA_PROCESSO = [('', '---------'), - ('0', 'Administrativo'), - ('1', 'Legislativo')] +TIPOS_PROTOCOLO = [('0', 'Recebido'), ('1', 'Enviado'), + ('2', 'Interno')] +TIPOS_PROTOCOLO_CREATE = [ + ('0', 'Recebido'), ('1', 'Enviado'), ('2', 'Interno')] +NATUREZA_PROCESSO = [('0', 'Administrativo'), + ('1', 'Legislativo')] -def ANO_CHOICES(): - return [('', '---------')] + RANGE_ANOS +EM_TRAMITACAO = [(0, 'Sim'), (1, 'Não')] -EM_TRAMITACAO = [('', '---------'), - (0, 'Sim'), - (1, 'Não')] class AcompanhamentoDocumentoForm(ModelForm): @@ -66,13 +66,18 @@ class AcompanhamentoDocumentoForm(ModelForm): class ProtocoloFilterSet(django_filters.FilterSet): - ano = django_filters.ChoiceFilter(required=False, - label='Ano', - choices=ANO_CHOICES) + 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()) @@ -89,15 +94,9 @@ class ProtocoloFilterSet(django_filters.FilterSet): widget=forms.Select( attrs={'class': 'selector'})) - o = AnoNumeroOrderingFilter() + 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', @@ -108,8 +107,7 @@ 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' + self.filters['timestamp'].label = 'Data (Inicial - Final)' row1 = to_row( [('numero', 4), @@ -134,9 +132,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' @@ -144,36 +140,36 @@ 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')) ) class DocumentoAdministrativoFilterSet(django_filters.FilterSet): - ano = django_filters.ChoiceFilter(required=False, - label='Ano', - choices=ANO_CHOICES) + 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: { - 'filter_class': django_filters.DateFromToRangeFilter, - 'extra': lambda f: { - 'label': 'Data (%s)' % (_('Inicial - Final')), - 'widget': RangeWidgetOverride} - }} + class Meta(FilterOverridesMetaMixin): model = DocumentoAdministrativo fields = ['tipo', 'numero', @@ -188,37 +184,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')) ) @@ -253,10 +250,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 +340,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 +431,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 +451,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 +475,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 +486,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 +526,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__( @@ -691,21 +697,22 @@ 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_force_optional(choice_anos_com_protocolo), + widget=forms.Select( + attrs={'class': 'selector'})) numero_protocolo = forms.IntegerField(required=False, label=Protocolo._meta. 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 +753,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 +780,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 +792,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)) @@ -812,7 +820,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)]) @@ -821,7 +829,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)]) @@ -871,13 +879,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 +950,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 +1013,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 +1089,4 @@ class FichaSelecionaAdmForm(forms.Form): row1, form_actions(label='Gerar Impresso') ) - ) \ No newline at end of file + ) 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'), + ), + ] 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/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..6d3d90671 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 @@ -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) @@ -78,13 +79,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 +300,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) diff --git a/sapl/protocoloadm/tests/test_protocoloadm.py b/sapl/protocoloadm/tests/test_protocoloadm.py index 2f61d359f..2a4c9f53c 100644 --- a/sapl/protocoloadm/tests/test_protocoloadm.py +++ b/sapl/protocoloadm/tests/test_protocoloadm.py @@ -1,10 +1,11 @@ from datetime import date, timedelta -import pytest 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 +import pytest from sapl.materia.models import UnidadeTramitacao from sapl.protocoloadm.forms import (AnularProcoloAdmForm, @@ -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) @@ -368,6 +369,11 @@ def test_documento_administrativo_invalido(): def test_documento_administrativo_protocolo_inexistente(): tipo = mommy.make(TipoDocumentoAdministrativo) + protocolo = mommy.make(Protocolo, + ano=2017, + numero=10, + anulado=False, + tipo_documento=tipo) form = DocumentoAdministrativoForm(data={'ano': '2017', 'tipo': str(tipo.pk), diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index 5a3cde342..35d49e277 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 @@ -22,31 +22,16 @@ 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, SessaoPlenariaPresenca, TipoJustificativa, TipoResultadoVotacao, 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 +MES_CHOICES = RANGE_MESES +DIA_CHOICES = RANGE_DIAS_MES ORDENACAO_RESUMO = [('cont_mult', 'Conteúdo Multimídia'), @@ -218,11 +203,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 +217,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 +251,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 +275,7 @@ class RetiradaPautaForm(ModelForm): retirada.save() return retirada + class BancadaForm(ModelForm): class Meta: @@ -522,10 +514,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): @@ -540,18 +534,19 @@ 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: - raise ValidationError('O total de votos não corresponde com a quantidade de 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 # 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 @@ -569,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) @@ -764,7 +761,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 +793,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 +872,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 +896,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 +909,7 @@ class JustificativaAusenciaForm(ModelForm): else: return self.cleaned_data - def save(self, commit=False): + def save(self): justificativa = super().save(True) @@ -996,4 +992,4 @@ class VotacaoEmBlocoFilterSet(MateriaLegislativaFilterSet): HTML(autor_modal), row4, row5, row6, row7, row8, row9, form_actions(label='Pesquisar')) - ) \ No newline at end of file + ) diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index b705e302f..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: @@ -3280,7 +3281,7 @@ class JustificativaAusenciaCrud(MasterDetailCrud): pass -class VotacaoEmBlocoExpediente(ListView): +class VotacaoEmBlocoExpediente(PermissionRequiredForAppCrudMixin, ListView): model = ExpedienteMateria template_name = 'sessao/votacao/votacao_bloco_expediente.html' @@ -3303,7 +3304,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,12 +3326,12 @@ class VotacaoEmBlocoOrdemDia(ListView): return context -class VotacaoEmBlocoSimbolicaView(TemplateView): +class VotacaoEmBlocoSimbolicaView(PermissionRequiredForAppCrudMixin, TemplateView): """ Votação Simbólica """ - + app_label = AppConfig.label template_name = 'sessao/votacao/votacao_simbolica_bloco.html' logger = logging.getLogger(__name__) @@ -3502,10 +3503,11 @@ class VotacaoEmBlocoSimbolicaView(TemplateView): return self.render_to_response(context) -class VotacaoEmBlocoNominalView(TemplateView): +class VotacaoEmBlocoNominalView(PermissionRequiredForAppCrudMixin, TemplateView): """ Votação Nominal """ + app_label = AppConfig.label template_name = 'sessao/votacao/votacao_nominal_bloco.html' logger = logging.getLogger(__name__) diff --git a/sapl/settings.py b/sapl/settings.py index d30b4df3c..80bf18273 100755 --- a/sapl/settings.py +++ b/sapl/settings.py @@ -100,23 +100,27 @@ 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 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: - 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', +# 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: + 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': { 'ENGINE': SEARCH_BACKEND, - SEARCH_URL[0]: SEARCH_URL[1] + SEARCH_URL[0]: SEARCH_URL[1], + 'BATCH_SIZE': 1000, + 'TIMEOUT': 60, }, } 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%; } } diff --git a/sapl/templates/base.html b/sapl/templates/base.html index 0291ef7ba..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.138 + Release: 3.1.140