diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index 0ba1ca7f0..b9a11ac92 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -1597,7 +1597,8 @@ class TipoProposicaoForm(ModelForm): 'content_type', 'tipo_conteudo_related_radio', 'tipo_conteudo_related', - 'perfis'] + 'perfis', + 'dispensa_protocolo'] widgets = {'tipo_conteudo_related': forms.HiddenInput(), 'perfis': widgets.CheckboxSelectMultiple()} @@ -1612,6 +1613,7 @@ class TipoProposicaoForm(ModelForm): Row( to_column(('descricao', 12)), to_column(('perfis', 12)), + to_column(('dispensa_protocolo', 12)), ), 5 ) diff --git a/sapl/materia/migrations/0097_add_dispensa_protocolo_tipoproposicao.py b/sapl/materia/migrations/0097_add_dispensa_protocolo_tipoproposicao.py new file mode 100644 index 000000000..44cbcec1d --- /dev/null +++ b/sapl/materia/migrations/0097_add_dispensa_protocolo_tipoproposicao.py @@ -0,0 +1,19 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0096_add_permite_remover_assinatura_e_permissoes'), + ] + + operations = [ + migrations.AddField( + model_name='tipoproposicao', + name='dispensa_protocolo', + field=models.BooleanField( + default=False, + help_text='Quando marcado, proposições deste tipo não são enviadas ao Protocolo e não se tornam Matéria Legislativa. Ficam restritas ao gabinete do autor. Use para documentos de uso próprio do gabinete, como Ofícios, que não precisam de validação da Casa.', + verbose_name='Documento de gabinete'), + ), + ] diff --git a/sapl/materia/models.py b/sapl/materia/models.py index 0d490ded0..1ac78ce2b 100644 --- a/sapl/materia/models.py +++ b/sapl/materia/models.py @@ -71,6 +71,15 @@ class TipoProposicao(models.Model): menos um Perfil Estrutural de Texto Articulado. """)) + dispensa_protocolo = models.BooleanField( + default=False, + verbose_name=_('Documento de gabinete'), + help_text=_('Quando marcado, proposições deste tipo não são enviadas ' + 'ao Protocolo e não se tornam Matéria Legislativa. Ficam ' + 'restritas ao gabinete do autor. Use para documentos de ' + 'uso próprio do gabinete, como Ofícios, que não precisam ' + 'de validação da Casa.')) + class Meta: verbose_name = _('Tipo de Proposição') verbose_name_plural = _('Tipos de Proposições') diff --git a/sapl/materia/views.py b/sapl/materia/views.py index d621006ee..9430ca909 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -483,7 +483,8 @@ class TipoProposicaoCrud(CrudAux): class BaseMixin(CrudAux.BaseMixin): list_field_names = [ - "descricao", "content_type", 'tipo_conteudo_related'] + "descricao", "content_type", 'tipo_conteudo_related', + 'dispensa_protocolo'] class CreateView(CrudAux.CreateView): form_class = TipoProposicaoForm @@ -1033,6 +1034,13 @@ class UnidadeTramitacaoCrud(CrudAux): form_class = UnidadeTramitacaoForm +# Tipos de proposição marcados como "Documento de gabinete" não saem do +# gabinete do autor: não vão ao Protocolo nem ao Setor Legislativo. +MSG_DISPENSA_PROTOCOLO = _( + 'Este é um documento de gabinete e não passa pelo Protocolo. ' + 'Ele fica restrito ao seu gabinete.') + + class ProposicaoCrud(Crud): model = Proposicao help_topic = 'proposicao' @@ -1118,7 +1126,9 @@ class ProposicaoCrud(Crud): msg_error = '' if p and p.autor.operadores.filter(id=request.user.id).exists(): if action == 'send': - if p.data_envio and p.data_recebimento: + if p.tipo and p.tipo.dispensa_protocolo: + msg_error = MSG_DISPENSA_PROTOCOLO + elif p.data_envio and p.data_recebimento: msg_error = _('Proposição já foi enviada e recebida.') elif p.data_envio: msg_error = _('Proposição já foi enviada.') @@ -1214,7 +1224,9 @@ class ProposicaoCrud(Crud): elif action == 'send_setor': app_config = sapl.base.models.AppConfig.objects.all().last() - if not app_config or not app_config.revisao_setor_legislativo: + if p.tipo and p.tipo.dispensa_protocolo: + msg_error = MSG_DISPENSA_PROTOCOLO + elif not app_config or not app_config.revisao_setor_legislativo: msg_error = _('Revisão pelo Setor Legislativo não está habilitada.') elif p.data_envio: msg_error = _('Proposição já foi enviada ao protocolo.') @@ -1469,7 +1481,12 @@ class ProposicaoCrud(Crud): status_filter = self.request.GET.get('status', '') if status_filter == 'elaboracao': - qs = qs.filter(data_envio__isnull=True, cancelado=False) + qs = qs.filter( + data_envio__isnull=True, cancelado=False + ).exclude(tipo__dispensa_protocolo=True) + elif status_filter == 'gabinete': + qs = qs.filter(tipo__dispensa_protocolo=True, + data_envio__isnull=True, cancelado=False) elif status_filter == 'aguardando': qs = qs.filter(data_envio__isnull=False, data_recebimento__isnull=True, data_devolucao__isnull=True, cancelado=False) elif status_filter == 'incorporada': @@ -1486,7 +1503,8 @@ class ProposicaoCrud(Crud): qs_base = super().get_queryset() stats = { 'total': qs_base.count(), - 'elaboracao': qs_base.filter(data_envio__isnull=True, cancelado=False).count(), + 'elaboracao': qs_base.filter(data_envio__isnull=True, cancelado=False).exclude(tipo__dispensa_protocolo=True).count(), + 'gabinete': qs_base.filter(tipo__dispensa_protocolo=True, data_envio__isnull=True, cancelado=False).count(), 'aguardando': qs_base.filter(data_envio__isnull=False, data_recebimento__isnull=True, data_devolucao__isnull=True, cancelado=False).count(), 'incorporada': qs_base.filter(data_recebimento__isnull=False, cancelado=False).count(), 'devolvida': qs_base.filter(data_devolucao__isnull=False, cancelado=False).count(), @@ -1521,6 +1539,10 @@ class ProposicaoCrud(Crud): status = 'aguardando' status_label = 'Aguardando Recebimento' status_icon = 'fa-clock-o' + elif obj.tipo and obj.tipo.dispensa_protocolo: + status = 'gabinete' + status_label = 'Documento de Gabinete' + status_icon = 'fa-briefcase' else: status = 'elaboracao' status_label = 'Em Elaboração' diff --git a/sapl/templates/materia/proposicao_detail.html b/sapl/templates/materia/proposicao_detail.html index a84a23e63..ad7bfb789 100644 --- a/sapl/templates/materia/proposicao_detail.html +++ b/sapl/templates/materia/proposicao_detail.html @@ -351,7 +351,13 @@ {% trans "Editar Documento" %} - {% if object.texto_original or object.texto_articulado.exists %} + {% if object.tipo.dispensa_protocolo %} + {# Documento de gabinete: não vai ao Protocolo nem ao Setor Legislativo #} + + + {% trans "Documento de gabinete — não passa pelo Protocolo" %} + + {% elif object.texto_original or object.texto_articulado.exists %} {% trans "Enviar Proposição" %} diff --git a/sapl/templates/materia/proposicao_list.html b/sapl/templates/materia/proposicao_list.html index b42372ddf..b40fd85b1 100644 --- a/sapl/templates/materia/proposicao_list.html +++ b/sapl/templates/materia/proposicao_list.html @@ -213,6 +213,9 @@ {{ stats.elaboracao|default:"0" }} em elaboração + + {{ stats.gabinete|default:"0" }} de gabinete + {{ stats.aguardando|default:"0" }} enviadas