From 62d29f68466e38b3bcadf18d27128a380fb0f3c4 Mon Sep 17 00:00:00 2001 From: cristian-longhi Date: Wed, 5 Oct 2022 11:34:00 -0300 Subject: [PATCH] =?UTF-8?q?Documento=20Acess=C3=B3rio=20Restrito=20em=20Do?= =?UTF-8?q?cumento=20Administrativo=20e=20em=20Mat=C3=A9ria=20Legislativa?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/api/views_materia.py | 15 +++- sapl/api/views_protocoloadm.py | 5 +- sapl/materia/forms.py | 8 +- sapl/materia/models.py | 5 ++ sapl/materia/views.py | 60 ++++++++++++++- sapl/protocoloadm/forms.py | 10 ++- sapl/protocoloadm/models.py | 5 ++ sapl/protocoloadm/views.py | 47 +++++++++++- .../materia/documentoacessorio_list.html | 73 ++++++++++++++++++- sapl/templates/materia/layouts.yaml | 4 +- sapl/templates/protocoloadm/layouts.yaml | 2 + 11 files changed, 220 insertions(+), 14 deletions(-) diff --git a/sapl/api/views_materia.py b/sapl/api/views_materia.py index 8c5515d88..a2cca4a09 100644 --- a/sapl/api/views_materia.py +++ b/sapl/api/views_materia.py @@ -8,7 +8,7 @@ from drfautoapi.drfautoapi import ApiViewSetConstrutor, \ customize, wrapper_queryset_response_for_drf_action from sapl.api.permissions import SaplModelPermissions from sapl.materia.models import TipoMateriaLegislativa, Tramitacao,\ - MateriaLegislativa, Proposicao + MateriaLegislativa, Proposicao, DocumentoAcessorio ApiViewSetConstrutor.build_class( @@ -111,6 +111,19 @@ class _MateriaLegislativaViewSet: return self.list(request, *args, **kwargs) + +@customize(DocumentoAcessorio) +class _DocumentoAcessorioViewSet: + + def get_queryset(self): + user = self.request.user + qs = super().get_queryset() + + if user.is_anonymous or 'materia.change_documentoacessorio' not in user.get_all_permissions(): + qs = qs.exclude(restrito=True) + return qs + + @customize(TipoMateriaLegislativa) class _TipoMateriaLegislativaViewSet: diff --git a/sapl/api/views_protocoloadm.py b/sapl/api/views_protocoloadm.py index 5ebe77ec1..30d033ecf 100644 --- a/sapl/api/views_protocoloadm.py +++ b/sapl/api/views_protocoloadm.py @@ -60,9 +60,12 @@ class _DocumentoAcessorioAdministrativoViewSet: def get_queryset(self): qs = super().get_queryset() + user = self.request.user - if self.request.user.is_anonymous: + if user.is_anonymous or 'protocoloadm.change_documentoacessorioadministrativo' not in user.get_all_permissions(): +# if self.request.user.is_anonymous: qs = qs.exclude(documento__restrito=True) + qs = qs.exclude(restrito=True) return qs diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index 1af4b7aa9..e5085491e 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -330,11 +330,17 @@ class AcompanhamentoMateriaForm(GoogleRecapthaMixin, ModelForm): class DocumentoAcessorioForm(FileFieldCheckMixin, ModelForm): data = forms.DateField(required=True) + restrito = forms.ChoiceField( + label=_('Documento Restrito?'), + widget=forms.RadioSelect(), + choices=YES_NO_CHOICES, + initial=False) class Meta: model = DocumentoAcessorio fields = ['tipo', 'nome', 'data', 'autor', - 'ementa', 'indexacao', 'arquivo'] + 'ementa', 'indexacao', 'arquivo', + 'restrito', 'justificativa_restricao'] def clean(self): super(DocumentoAcessorioForm, self).clean() diff --git a/sapl/materia/models.py b/sapl/materia/models.py index 426b02168..c73f39db5 100644 --- a/sapl/materia/models.py +++ b/sapl/materia/models.py @@ -554,6 +554,11 @@ class DocumentoAcessorio(models.Model): proposicao = GenericRelation('Proposicao', related_query_name='proposicao') data_ultima_atualizacao = models.DateTimeField( blank=True, null=True, auto_now=True, verbose_name=_('Data')) + restrito = models.BooleanField(default=False, + verbose_name=_('Restrito'), + blank=True) + justificativa_restricao = models.TextField( + blank=True, verbose_name=_('Justificativa de Restrição')) class Meta: verbose_name = _('Documento Acessório') diff --git a/sapl/materia/views.py b/sapl/materia/views.py index 3a6e22977..0e7f087ed 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -1588,6 +1588,46 @@ class DocumentoAcessorioCrud(MasterDetailCrud): context = super(UpdateView, self).get_context_data(**kwargs) return context + class ListView(MasterDetailCrud.ListView): + + def get_queryset(self): + qs = super(MasterDetailCrud.ListView, self).get_queryset() + kwargs = {self.crud.parent_field: self.kwargs['pk']} + exibir_restritos = 'materia.change_documentoacessorio' in self.request.user.get_all_permissions() + if 'o' in self.request.GET: + o = self.request.GET['o'] + indice_field = abs(int(o)) - 1 + if '-' in o: + order_by = '-' + self.list_field_names[indice_field] + else: + order_by = self.list_field_names[indice_field] + if exibir_restritos: + return qs.filter(**kwargs).order_by(order_by, '-data', '-id') + else: + return qs.filter(**kwargs).order_by('restrito', order_by, '-data', '-id') + + if exibir_restritos: + return qs.filter(**kwargs).order_by('-data', '-id') + else: + return qs.filter(**kwargs).order_by('restrito', '-data', '-id') + + class DetailView(MasterDetailCrud.DetailView): + layout_key = 'DocumentoAcessorioAdministrativo' + template_name = "materia/documentoacessorio_detail.html" + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['AppConfig'] = sapl.base.models.AppConfig.objects.all().last() + context['user'] = self.request.user + + doc = DocumentoAcessorio.objects.get( + pk=self.kwargs['pk'] + ) + context['object'] = doc + if doc.restrito and not 'materia.change_documentoacessorio' in self.request.user.get_all_permissions(): + context['title'] = 'Documento Restrito' + return context + class AutoriaCrud(MasterDetailCrud): model = Autoria @@ -2867,13 +2907,15 @@ class TipoMateriaCrud(CrudAux): return fv -def create_zip_docacessorios(materia): +def create_zip_docacessorios(materia, excluir_restritos): """ Creates in memory zip files """ logger = logging.getLogger(__name__) docs = materia.documentoacessorio_set. \ all().values_list('arquivo', flat=True) + if excluir_restritos: + docs = docs.filter(restrito=False) if not docs: return None, None @@ -2903,10 +2945,14 @@ def create_zip_docacessorios(materia): def get_zip_docacessorios(request, pk): logger = logging.getLogger(__name__) username = 'Usuário anônimo' if request.user.is_anonymous else request.user.username + if request.user.is_anonymous or not 'protocoloadm.change_documentoacessorioadministrativo' in request.user.get_all_permissions(): + excluir_restritos = True + else: + excluir_restritos = False materia = get_object_or_404(MateriaLegislativa, pk=pk) data = None try: - external_name, data = create_zip_docacessorios(materia) + external_name, data = create_zip_docacessorios(materia, excluir_restritos) logger.info( "user= {}. Gerou o zip compilado de documento acessorios".format(username)) except FileNotFoundError: @@ -2935,13 +2981,15 @@ def get_zip_docacessorios(request, pk): return response -def create_pdf_docacessorios(materia): +def create_pdf_docacessorios(materia,excluir_restritos): """ Creates a unified in memory PDF file """ logger = logging.getLogger(__name__) docs = materia.documentoacessorio_set. \ all().values_list('arquivo', flat=True) + if excluir_restritos: + docs = docs.filter(restrito=False) if not docs: return None, None @@ -2976,8 +3024,12 @@ def get_pdf_docacessorios(request, pk): materia = get_object_or_404(MateriaLegislativa, pk=pk) logger = logging.getLogger(__name__) username = 'Usuário anônimo' if request.user.is_anonymous else request.user.username + if request.user.is_anonymous or not 'protocoloadm.change_documentoacessorioadministrativo' in request.user.get_all_permissions(): + excluir_restritos = True + else: + excluir_restritos = False try: - external_name, data = create_pdf_docacessorios(materia) + external_name, data = create_pdf_docacessorios(materia, excluir_restritos) logger.info( "user= {}. Gerou o pdf compilado de documento acessorios".format(username)) except FileNotFoundError: diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 58223f21c..076884efa 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -623,14 +623,22 @@ class ProtocoloMateriaForm(ModelForm): class DocumentoAcessorioAdministrativoForm(FileFieldCheckMixin, ModelForm): + restrito = forms.ChoiceField( + label=_('Documento Restrito?'), + widget=forms.RadioSelect(), + choices=YES_NO_CHOICES, + initial=False) + class Meta: model = DocumentoAcessorioAdministrativo fields = ['tipo', 'nome', + 'restrito', 'data', 'autor', 'arquivo', - 'assunto'] + 'assunto', + 'justificativa_restricao'] widgets = { 'data': forms.DateInput(format='%d/%m/%Y') diff --git a/sapl/protocoloadm/models.py b/sapl/protocoloadm/models.py index 3cdf32735..96735d774 100644 --- a/sapl/protocoloadm/models.py +++ b/sapl/protocoloadm/models.py @@ -362,6 +362,11 @@ class DocumentoAcessorioAdministrativo(models.Model): assunto = models.TextField( blank=True, verbose_name=_('Assunto')) indexacao = models.TextField(blank=True) + restrito = models.BooleanField(default=False, + verbose_name=_('Restrito'), + blank=True) + justificativa_restricao = models.TextField( + blank=True, verbose_name=_('Justificativa de Restrição')) class Meta: verbose_name = _('Documento Acessório') diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py index 2b1346f7b..30daffb73 100755 --- a/sapl/protocoloadm/views.py +++ b/sapl/protocoloadm/views.py @@ -329,10 +329,15 @@ class AcompanhamentoDocumentoView(CreateView): class DocumentoAdministrativoMixin: def has_permission(self): + + if self.model == DocumentoAcessorioAdministrativo and 'docadm/' + self.kwargs['pk'] in str(self.request): + doc_adm = DocumentoAdministrativo.objects.get(id=self.kwargs['pk']) + if doc_adm.restrito and not 'protocoloadm.change_documentoacessorioadministrativo' in self.request.user.get_all_permissions(): + return False + app_config = AppConfig.objects.last() if app_config and app_config.documentos_administrativos == 'O': return True - return super().has_permission() @@ -1390,15 +1395,51 @@ class DocumentoAcessorioAdministrativoCrud(MasterDetailCrud): form_class = DocumentoAcessorioAdministrativoForm class ListView(DocumentoAdministrativoMixin, MasterDetailCrud.ListView): + template_name = "protocoloadm/documentoacessorioadministrativo_list.html" def get_queryset(self): qs = super(MasterDetailCrud.ListView, self).get_queryset() kwargs = {self.crud.parent_field: self.kwargs['pk']} - return qs.filter(**kwargs).order_by('-data', '-id') + exibir_restritos = 'protocoloadm.change_documentoacessorioadministrativo' in self.request.user.get_all_permissions() + if 'o' in self.request.GET: + o = self.request.GET['o'] + indice_field = abs(int(o)) - 1 + if '-' in o: + order_by = '-' + self.list_field_names[indice_field] + else: + order_by = self.list_field_names[indice_field] + if exibir_restritos: + return qs.filter(**kwargs).order_by(order_by, '-data', '-id') + else: + return qs.filter(**kwargs).order_by('restrito', order_by, '-data', '-id') + + if exibir_restritos: + return qs.filter(**kwargs).order_by('-data', '-id') + else: + return qs.filter(**kwargs).order_by('restrito', '-data', '-id') + class DetailView(DocumentoAdministrativoMixin, MasterDetailCrud.DetailView): - pass + layout_key = 'DocumentoAcessorioAdministrativo' + template_name = "protocoloadm/documentoacessorioadministrativo_detail.html" + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['AppConfig'] = sapl.base.models.AppConfig.objects.all().last() + context['user'] = self.request.user + doc_acessorio = DocumentoAcessorioAdministrativo.objects.get( + pk=self.kwargs['pk']) + doc_adm = DocumentoAdministrativo.objects.get( + id=doc_acessorio.documento_id) + if not doc_adm.restrito: + context['doc_adm_restrito'] = False + context['object'] = doc_acessorio + else: + context['doc_adm_restrito'] = True + if (doc_adm.restrito or doc_acessorio.restrito) and not 'protocoloadm.change_documentoacessorioadministrativo' in self.request.user.get_all_permissions(): + context['title'] = 'Documento Restrito' + return context def atualizar_numero_documento(request): diff --git a/sapl/templates/materia/documentoacessorio_list.html b/sapl/templates/materia/documentoacessorio_list.html index 08bae0819..9a73a5d5a 100644 --- a/sapl/templates/materia/documentoacessorio_list.html +++ b/sapl/templates/materia/documentoacessorio_list.html @@ -1,5 +1,74 @@ {% extends "crud/list.html" %} -{% load i18n %} +{% load i18n common_tags %} + +{% block container_table_list %} + {% if not rows %} +

{{ NO_ENTRIES_MSG }}

+ {% else %} +
+
{% blocktrans with verbose_name_plural=view.verbose_name_plural %}Total de {{ verbose_name_plural }}: {{count}}{% endblocktrans %}
+ + + + {% for name in headers %} +{% comment %} +{% if name != 'Restrito' and name != 'Justificativa de Restrição' %} +{% endcomment %} + +{% comment %} +{% endif %} +{% endcomment %} + {% endfor %} + + + + {% for doc in object_list %} + + {% if not doc.restrito or 'materia.change_documentoacessorio' in request.user.get_all_permissions %} + + + + + + {% else %} + + {% endif %} + + {% endfor %} + + +
+ {% endif %} +{% endblock container_table_list %} + + {% block base_content %} {{ block.super }}
@@ -10,4 +79,4 @@ {% trans 'Baixar documentos compactados' %}
-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/sapl/templates/materia/layouts.yaml b/sapl/templates/materia/layouts.yaml index 6ab3dbf2e..634291cb2 100644 --- a/sapl/templates/materia/layouts.yaml +++ b/sapl/templates/materia/layouts.yaml @@ -75,6 +75,8 @@ DocumentoAcessorio: - ementa - indexacao - arquivo + - restrito + - justificativa_restricao Numeracao: {% trans 'Numeração' %}: @@ -163,4 +165,4 @@ ConfigEtiquetaMateriaLegislativa: {% trans 'Configurações de Etiqueta' %}: - largura - altura - - mostrar_em_arquivo \ No newline at end of file + - mostrar_em_arquivo diff --git a/sapl/templates/protocoloadm/layouts.yaml b/sapl/templates/protocoloadm/layouts.yaml index cbfe3210f..b08ef9997 100644 --- a/sapl/templates/protocoloadm/layouts.yaml +++ b/sapl/templates/protocoloadm/layouts.yaml @@ -24,6 +24,8 @@ DocumentoAcessorioAdministrativo: - nome data - arquivo - assunto + - restrito + - justificativa_restricao StatusTramitacaoAdministrativo: {% trans 'Status Tramitação Administrativo' %}: