diff --git a/sapl/base/forms.py b/sapl/base/forms.py index d0ab0786f..2ccde243a 100644 --- a/sapl/base/forms.py +++ b/sapl/base/forms.py @@ -17,8 +17,8 @@ from django.forms import Form, ModelForm from django.utils import timezone from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ -from haystack.forms import ModelSearchForm import django_filters +from haystack.forms import ModelSearchForm from sapl.audiencia.models import AudienciaPublica from sapl.base.models import Autor, TipoAutor, OperadorAutor @@ -880,11 +880,11 @@ class RelatorioNormasMesFilterSet(django_filters.FilterSet): label='Ano da Norma', choices=choice_anos_com_normas, initial=ultimo_ano_com_norma) - + tipo = django_filters.ChoiceFilter(required=False, - label='Tipo Norma', - choices=choice_tipos_normas, - initial=0) + label='Tipo Norma', + choices=choice_tipos_normas, + initial=0) class Meta: model = NormaJuridica @@ -977,9 +977,9 @@ class RelatorioNormasVigenciaFilterSet(django_filters.FilterSet): initial=ultimo_ano_com_norma) tipo = django_filters.ChoiceFilter(required=False, - label='Tipo Norma', - choices=choice_tipos_normas, - initial=0) + label='Tipo Norma', + choices=choice_tipos_normas, + initial=0) vigencia = forms.ChoiceField( label=_('Vigência'), @@ -1163,8 +1163,8 @@ class RelatorioHistoricoTramitacaoFilterSet(django_filters.FilterSet): class RelatorioDataFimPrazoTramitacaoFilterSet(django_filters.FilterSet): ano = django_filters.ChoiceFilter(required=False, - label='Ano da Matéria', - choices=choice_anos_com_materias) + label='Ano da Matéria', + choices=choice_anos_com_materias) @property def qs(self): @@ -1578,6 +1578,7 @@ class ConfiguracoesAppForm(ModelForm): 'assinatura_ata', 'estatisticas_acesso_normas', 'escolher_numero_materia_proposicao', + 'tramitacao_origem_fixa', 'tramitacao_materia', 'tramitacao_documento', 'google_recaptcha_site_key', diff --git a/sapl/base/migrations/0048_appconfig_tramitacao_origem_fixa.py b/sapl/base/migrations/0048_appconfig_tramitacao_origem_fixa.py new file mode 100644 index 000000000..933d42a84 --- /dev/null +++ b/sapl/base/migrations/0048_appconfig_tramitacao_origem_fixa.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.28 on 2022-06-27 11:56 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('base', '0047_auto_20210315_1522'), + ] + + operations = [ + migrations.AddField( + model_name='appconfig', + name='tramitacao_origem_fixa', + field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=True, + verbose_name='Fixar Origem das tramitações como sendo a tramitação de destino da última tramitação?'), + ), + ] diff --git a/sapl/base/models.py b/sapl/base/models.py index fb2a3bd66..b1954aed2 100644 --- a/sapl/base/models.py +++ b/sapl/base/models.py @@ -185,6 +185,19 @@ class AppConfig(models.Model): 'Indicar número da matéria a ser gerada na proposição?'), choices=YES_NO_CHOICES, default=False) + tramitacao_origem_fixa = models.BooleanField( + verbose_name=_( + 'Fixar origem de novas tramitações como sendo a tramitação de destino da última tramitação?'), + choices=YES_NO_CHOICES, + default=True, + help_text=_('Ao utilizar a opção NÂO, você compreende que os controles ' + 'de origem e destino das tramitações são anulados, ' + 'podendo seu operador registrar quaisquer origem e ' + 'destino para as tramitações. Se você colocar Não, ' + 'fizer tramitações aleatórias e voltar para SIM, ' + 'o destino da tramitação mais recente será utilizado ' + 'para a origem de uma nova inserção!')) + tramitacao_materia = models.BooleanField( verbose_name=_( 'Tramitar matérias anexadas junto com as matérias principais?'), diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index 70c5a82be..06bb15f7a 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -18,7 +18,7 @@ from django.utils import timezone from django.utils.translation import ugettext_lazy as _ import django_filters -from sapl.base.models import AppConfig, Autor, TipoAutor +from sapl.base.models import AppConfig as BaseAppConfig, Autor, TipoAutor from sapl.comissoes.models import Comissao, Composicao, Participacao from sapl.compilacao.models import (STATUS_TA_IMMUTABLE_PUBLIC, STATUS_TA_PRIVATE) @@ -43,7 +43,6 @@ from sapl.utils import (autor_label, autor_modal, timing, SEPARADOR_HASH_PROPOSICAO, validar_arquivo, YES_NO_CHOICES, GoogleRecapthaMixin) -import sapl from .models import (AcompanhamentoMateria, Anexada, Autoria, DespachoInicial, DocumentoAcessorio, Numeracao, @@ -509,7 +508,7 @@ class TramitacaoForm(ModelForm): if not self.instance.data_tramitacao: - if ultima_tramitacao: + if ultima_tramitacao and BaseAppConfig.attr('tramitacao_origem_fixa'): 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 " @@ -562,7 +561,7 @@ class TramitacaoForm(ModelForm): materia.em_tramitacao = False if tramitacao.status.indicador == "F" else True materia.save() - tramitar_anexadas = sapl.base.models.AppConfig.attr( + tramitar_anexadas = BaseAppConfig.attr( 'tramitacao_materia') if tramitar_anexadas: lista_tramitacao = [] @@ -664,7 +663,7 @@ class TramitacaoUpdateForm(TramitacaoForm): # ela não pode ter seu destino alterado. if ultima_tramitacao != obj: if cd['unidade_tramitacao_destino'] != \ - obj.unidade_tramitacao_destino: + obj.unidade_tramitacao_destino and BaseAppConfig.attr('tramitacao_origem_fixa'): 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 ({})." @@ -701,7 +700,7 @@ class TramitacaoUpdateForm(TramitacaoForm): materia.em_tramitacao = False if nova_tram_principal.status.indicador == "F" else True materia.save() - tramitar_anexadas = sapl.base.models.AppConfig.attr( + tramitar_anexadas = BaseAppConfig.attr( 'tramitacao_materia') if tramitar_anexadas: anexadas_list = lista_anexados(materia) @@ -1783,7 +1782,7 @@ class TramitacaoEmLoteForm(ModelForm): ip = self.initial['ip'] if 'ip' in self.initial else '' ultima_edicao = self.initial['ultima_edicao'] if 'ultima_edicao' in self.initial else '' - tramitar_anexadas = AppConfig.attr('tramitacao_materia') + tramitar_anexadas = BaseAppConfig.attr('tramitacao_materia') for mat_id in materias: mat = MateriaLegislativa.objects.get(id=mat_id) tramitacao = Tramitacao.objects.create( @@ -1902,10 +1901,10 @@ class ProposicaoForm(FileFieldCheckMixin, forms.ModelForm): } def __init__(self, *args, **kwargs): - self.texto_articulado_proposicao = AppConfig.attr( + self.texto_articulado_proposicao = BaseAppConfig.attr( 'texto_articulado_proposicao') - self.receber_recibo = AppConfig.attr( + self.receber_recibo = BaseAppConfig.attr( 'receber_recibo_proposicao') if not self.texto_articulado_proposicao: @@ -1927,7 +1926,7 @@ class ProposicaoForm(FileFieldCheckMixin, forms.ModelForm): ] - if AppConfig.objects.last().escolher_numero_materia_proposicao: + if BaseAppConfig.objects.last().escolher_numero_materia_proposicao: fields.append(to_column(('numero_materia_futuro', 12)),) else: if 'numero_materia_futuro' in self._meta.fields: @@ -2043,7 +2042,7 @@ class ProposicaoForm(FileFieldCheckMixin, forms.ModelForm): def save(self, commit=True): cd = self.cleaned_data inst = self.instance - receber_recibo = AppConfig.objects.last().receber_recibo_proposicao + receber_recibo = BaseAppConfig.objects.last().receber_recibo_proposicao if inst.pk: if 'tipo_texto' in cd: @@ -2063,7 +2062,8 @@ class ProposicaoForm(FileFieldCheckMixin, forms.ModelForm): return super().save(commit) inst.ano = timezone.now().year - sequencia_numeracao = AppConfig.attr('sequencia_numeracao_proposicao') + sequencia_numeracao = BaseAppConfig.attr( + 'sequencia_numeracao_proposicao') if sequencia_numeracao == 'A': numero__max = Proposicao.objects.filter( autor=inst.autor, @@ -2220,7 +2220,7 @@ class ConfirmarProposicaoForm(ProposicaoForm): def __init__(self, *args, **kwargs): self.proposicao_incorporacao_obrigatoria = \ - AppConfig.attr('proposicao_incorporacao_obrigatoria') + BaseAppConfig.attr('proposicao_incorporacao_obrigatoria') if self.proposicao_incorporacao_obrigatoria != 'C': if 'gerar_protocolo' in self._meta.fields: @@ -2272,7 +2272,7 @@ class ConfirmarProposicaoForm(ProposicaoForm): ) ] - if not AppConfig.objects.last().escolher_numero_materia_proposicao or \ + if not BaseAppConfig.objects.last().escolher_numero_materia_proposicao or \ not self.instance.numero_materia_futuro: if 'numero_materia_futuro' in self._meta.fields: del fields[0][0][3] @@ -2352,7 +2352,7 @@ class ConfirmarProposicaoForm(ProposicaoForm): if not self.is_valid(): return self.cleaned_data - numeracao = AppConfig.attr('sequencia_numeracao_proposicao') + numeracao = BaseAppConfig.attr('sequencia_numeracao_proposicao') if not numeracao: self.logger.error("A sequência de numeração (por ano ou geral)" @@ -2435,7 +2435,7 @@ class ConfirmarProposicaoForm(ProposicaoForm): try: self.logger.debug( "Tentando obter modelo de sequência de numeração.") - numeracao = AppConfig.objects.last( + numeracao = BaseAppConfig.objects.last( ).sequencia_numeracao_protocolo except AttributeError as e: self.logger.error("Erro ao obter modelo. " + str(e)) @@ -2587,7 +2587,7 @@ class ConfirmarProposicaoForm(ProposicaoForm): GenericForeignKey """ - numeracao = AppConfig.attr('sequencia_numeracao_protocolo') + numeracao = BaseAppConfig.attr('sequencia_numeracao_protocolo') if numeracao == 'A': nm = Protocolo.objects.filter( ano=timezone.now().year).aggregate(Max('numero')) diff --git a/sapl/materia/views.py b/sapl/materia/views.py index daf0fe0cb..d0cdc07c3 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -1,11 +1,11 @@ from datetime import datetime from io import BytesIO -from random import choice -from string import ascii_letters, digits import logging import os +from random import choice import shutil +from string import ascii_letters, digits import time import zipfile @@ -31,6 +31,7 @@ from django.views.generic.edit import FormView from django_filters.views import FilterView import weasyprint +import sapl from sapl.base.email_utils import do_envia_email_confirmacao from sapl.base.models import Autor, CasaLegislativa, AppConfig as BaseAppConfig from sapl.comissoes.models import Participacao @@ -53,7 +54,6 @@ from sapl.utils import (autor_label, autor_modal, gerar_hash_arquivo, get_base_u mail_service_configured, montar_row_autor, SEPARADOR_HASH_PROPOSICAO, show_results_filter_set, get_tempfile_dir, google_recaptcha_configured) -import sapl from .forms import (AcessorioEmLoteFilterSet, AcompanhamentoMateriaForm, AnexadaEmLoteFilterSet, AdicionarVariasAutoriasFilterSet, @@ -437,7 +437,8 @@ class PesquisarStatusTramitacaoView(FilterView): url = '' if 'descricao' in self.request.META['QUERY_STRING'] or\ - 'page' in self.request.META['QUERY_STRING']: resultados = self.object_list + 'page' in self.request.META['QUERY_STRING']: + resultados = self.object_list else: resultados = [] @@ -1395,10 +1396,11 @@ class TramitacaoCrud(MasterDetailCrud): # necessária? if ultima_tramitacao: if ultima_tramitacao.unidade_tramitacao_destino: - context['form'].fields[ - 'unidade_tramitacao_local'].choices = [ - (ultima_tramitacao.unidade_tramitacao_destino.pk, - ultima_tramitacao.unidade_tramitacao_destino)] + if BaseAppConfig.attr('tramitacao_origem_fixa'): + context['form'].fields[ + 'unidade_tramitacao_local'].choices = [ + (ultima_tramitacao.unidade_tramitacao_destino.pk, + ultima_tramitacao.unidade_tramitacao_destino)] else: self.logger.error('user=' + username + '. Unidade de tramitação destino ' 'da última tramitação não pode ser vazia!') @@ -1411,7 +1413,7 @@ class TramitacaoCrud(MasterDetailCrud): # Se não for a primeira tramitação daquela matéria, o campo # não pode ser modificado - if not primeira_tramitacao: + if not primeira_tramitacao and BaseAppConfig.attr('tramitacao_origem_fixa'): context['form'].fields[ 'unidade_tramitacao_local'].widget.attrs['readonly'] = True diff --git a/sapl/templates/base/layouts.yaml b/sapl/templates/base/layouts.yaml index 658eb8e17..69c06a1c4 100644 --- a/sapl/templates/base/layouts.yaml +++ b/sapl/templates/base/layouts.yaml @@ -38,7 +38,7 @@ AppConfig: - proposicao_incorporacao_obrigatoria escolher_numero_materia_proposicao {% trans 'Módulo Matéria Legislativa' %}: - - tramitacao_materia tramitacao_documento + - tramitacao_origem_fixa tramitacao_materia tramitacao_documento {% trans 'Módulo Textos Articulados' %}: - texto_articulado_proposicao texto_articulado_materia texto_articulado_norma