Browse Source

Adicionar Adicionar Anexado no mód. Doc. Adm.

Alterações iniciais - Anexados em Lote
pull/2630/head
João Rodrigues 7 years ago
committed by João Matheus
parent
commit
9ac5b34109
  1. 4
      sapl/materia/forms.py
  2. 2
      sapl/materia/views.py
  3. 98
      sapl/protocoloadm/forms.py
  4. 35
      sapl/protocoloadm/migrations/0018_auto_20190314_1532.py
  5. 41
      sapl/protocoloadm/models.py
  6. 7
      sapl/protocoloadm/urls.py
  7. 102
      sapl/protocoloadm/views.py
  8. 1
      sapl/rules/map_rules.py
  9. 13
      sapl/templates/protocoloadm/anexado_list.html
  10. 13
      sapl/templates/protocoloadm/layouts.yaml
  11. 2
      sapl/templates/protocoloadm/subnav.yaml

4
sapl/materia/forms.py

@ -798,8 +798,8 @@ class AnexadaForm(ModelForm):
ano=cleaned_data['ano'],
tipo=cleaned_data['tipo'])
except ObjectDoesNotExist:
msg = _('A {} {}/{} não existe no cadastro de matérias legislativas.'
.format(cleaned_data['tipo'], cleaned_data['numero'], cleaned_data['ano']))
msg = _('A Matéria Legislativa 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.")
raise ValidationError(msg)

2
sapl/materia/views.py

@ -2108,7 +2108,7 @@ class MateriaAnexadaEmLoteView(PermissionRequiredMixin, FilterView):
anexada.data_desanexacao = data_desanexacao
anexada.save()
msg = _('Materia(s) anexada(s).')
msg = _('Matéria(s) anexada(s).')
messages.add_message(request, messages.SUCCESS, msg)
return self.get(request, self.kwargs)

98
sapl/protocoloadm/forms.py

@ -29,7 +29,7 @@ from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, AnoNumeroOrderingFilter,
from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo,
DocumentoAdministrativo,
Protocolo, TipoDocumentoAdministrativo,
TramitacaoAdministrativo)
TramitacaoAdministrativo, Anexado)
TIPOS_PROTOCOLO = [('0', 'Recebido'), ('1', 'Enviado'),
@ -781,6 +781,102 @@ class TramitacaoAdmEditForm(TramitacaoAdmForm):
return self.cleaned_data
class AnexadoForm(ModelForm):
logger = logging.getLogger(__name__)
tipo = forms.ModelChoiceField(
label='Tipo',
required=True,
queryset=TipoDocumentoAdministrativo.objects.all(),
empty_label='Selecione'
)
numero = forms.CharField(label='Número', required=True)
ano = forms.CharField(label='Ano', required=True)
def __init__(self, *args, **kwargs):
return super(AnexadoForm, self).__init__(*args, **kwargs)
def clean(self):
super(AnexadoForm, self).clean()
if not self.is_valid():
return self.cleaned_data
cleaned_data = self.cleaned_data
try:
self.logger.info(
"Tentando obter objeto DocumentoAdministrativo (numero={}, ano={}, tipo={})."
.format(cleaned_data['numero'], cleaned_data['ano'], cleaned_data['tipo'])
)
documento_anexado = DocumentoAdministrativo.objects.get(
numero=cleaned_data['numero'],
ano=cleaned_data['ano'],
tipo=cleaned_data['tipo']
)
except ObjectDoesNotExist:
msg = _('O Documento Administrativo a ser anexado (numero={}, ano={}, tipo={}) não existe no cadastro'
' de documentos administrativos.'.format(cleaned_data['numero'], cleaned_data['ano'], cleaned_data['tipo']))
self.logger.error("O documento a ser anexado não existe no cadastro"
" de documentos administrativos")
raise ValidationError(msg)
documento_principal = self.instance.documento_principal
if documento_principal == documento_anexado:
self.logger.error("O documento não pode ser anexado a si mesmo.")
raise ValidationError(_("O documento não pode ser anexado a si mesmo"))
is_anexado = Anexado.objects.filter(documento_principal=documento_principal,
documento_anexado=documento_anexado
).exists()
if is_anexado:
self.logger.error("Documento já se encontra anexado.")
raise ValidationError(_('Documento já se encontra anexado'))
cleaned_data['documento_anexado'] = documento_anexado
return cleaned_data
def save(self, commit=False):
anexado = super(AnexadoForm, self).save(commit)
anexado.documento_anexado = self.cleaned_data['documento_anexado']
anexado.save()
return anexado
class Meta:
model = Anexado
fields = ['tipo', 'numero', 'ano', 'data_anexacao', 'data_desanexacao']
class AnexadoEmLoteFilterSet(django_filters.FilterSet):
class Meta(FilterOverridesMetaMixin):
model = DocumentoAdministrativo
fields = ['tipo', 'data']
def __init__(self, *args, **kwargs):
super(AnexadoEmLoteFilterSet, self).__init__(*args, **kwargs)
self.filters['tipo'].label = 'Tipo de Documento'
self.filters['data'].label = 'Data (Inicial - Final)'
self.form.fields['tipo'].required = True
self.form.fields['data'].required = True
row1 = to_row([('tipo', 12)])
row2 = to_row([('data', 12)])
self.form.helper = SaplFormHelper()
self.form.helper.form_method = 'GET'
self.form.helper.layout = Layout(
Fieldset(_('Pesquisa de Documentos'),
row1, row2, form_actions(label='Pesquisar'))
)
class DocumentoAdministrativoForm(FileFieldCheckMixin, ModelForm):
logger = logging.getLogger(__name__)

35
sapl/protocoloadm/migrations/0018_auto_20190314_1532.py

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-03-14 18:32
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('protocoloadm', '0017_merge_20190121_1552'),
]
operations = [
migrations.CreateModel(
name='Anexado',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('data_anexacao', models.DateField(verbose_name='Data Anexação')),
('data_desanexacao', models.DateField(blank=True, null=True, verbose_name='Data Desanexação')),
('documento_anexado', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='documento_anexado_set', to='protocoloadm.DocumentoAdministrativo', verbose_name='Documento Anexado')),
('documento_principal', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='documento_principal_set', to='protocoloadm.DocumentoAdministrativo', verbose_name='Documento Principal')),
],
options={
'verbose_name': 'Anexado',
'verbose_name_plural': 'Anexados',
},
),
migrations.AddField(
model_name='documentoadministrativo',
name='anexados',
field=models.ManyToManyField(blank=True, related_name='anexo_de', through='protocoloadm.Anexado', to='protocoloadm.DocumentoAdministrativo'),
),
]

41
sapl/protocoloadm/models.py

@ -170,6 +170,18 @@ class DocumentoAdministrativo(models.Model):
verbose_name=_('Acesso Restrito'),
blank=True)
anexados = models.ManyToManyField(
'self',
blank=True,
through='Anexado',
symmetrical=False,
related_name='anexo_de',
through_fields=(
'documento_principal',
'documento_anexado'
)
)
class Meta:
verbose_name = _('Documento Administrativo')
verbose_name_plural = _('Documentos Administrativos')
@ -317,6 +329,35 @@ class TramitacaoAdministrativo(models.Model):
}
@reversion.register()
class Anexado(models.Model):
documento_principal = models.ForeignKey(
DocumentoAdministrativo, related_name='documento_principal_set',
on_delete = models.CASCADE,
verbose_name=_('Documento Principal')
)
documento_anexado = models.ForeignKey(
DocumentoAdministrativo, related_name='documento_anexado_set',
on_delete = models.CASCADE,
verbose_name=_('Documento Anexado')
)
data_anexacao = models.DateField(verbose_name=_('Data Anexação'))
data_desanexacao = models.DateField(
blank=True, null=True, verbose_name=_('Data Desanexação')
)
class Meta:
verbose_name = _('Anexado')
verbose_name_plural = _('Anexados')
def __str__(self):
return _('Principal: %(documento_principal)s'
' - Anexada: %(documento_anexado)s') % {
'documento_principal': self.documento_principal,
'documento_anexado': self.documento_anexado
}
@reversion.register()
class AcompanhamentoDocumento(models.Model):
usuario = models.CharField(max_length=50)

7
sapl/protocoloadm/urls.py

@ -21,7 +21,8 @@ from sapl.protocoloadm.views import (AcompanhamentoDocumentoView,
atualizar_numero_documento,
doc_texto_integral,
DesvincularDocumentoView,
DesvincularMateriaView)
DesvincularMateriaView,
AnexadoCrud, DocumentoAnexadoEmLoteView)
from .apps import AppConfig
@ -30,6 +31,7 @@ app_name = AppConfig.name
urlpatterns_documento_administrativo = [
url(r'^docadm/',
include(DocumentoAdministrativoCrud.get_urls() +
AnexadoCrud.get_urls() +
TramitacaoAdmCrud.get_urls() +
DocumentoAcessorioAdministrativoCrud.get_urls())),
@ -38,6 +40,9 @@ urlpatterns_documento_administrativo = [
url(r'^docadm/texto_integral/(?P<pk>\d+)$', doc_texto_integral,
name='doc_texto_integral'),
url(r'^docadm/(?P<pk>\d+)/anexado_em_lote', DocumentoAnexadoEmLoteView.as_view(),
name='anexado_em_lote'),
]
urlpatterns_protocolo = [

102
sapl/protocoloadm/views.py

@ -17,7 +17,7 @@ from django.http.response import HttpResponseRedirect
from django.shortcuts import redirect
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django.views.generic import ListView, CreateView
from django.views.generic import ListView, CreateView, UpdateView
from django.views.generic.base import RedirectView, TemplateView
from django.views.generic.edit import FormView
from django_filters.views import FilterView
@ -27,7 +27,8 @@ from sapl.base.email_utils import do_envia_email_confirmacao
from sapl.base.models import Autor, CasaLegislativa
from sapl.base.signals import tramitacao_signal
from sapl.comissoes.models import Comissao
from sapl.crud.base import Crud, CrudAux, MasterDetailCrud, make_pagination
from sapl.crud.base import (Crud, CrudAux, MasterDetailCrud, make_pagination,
RP_LIST, RP_DETAIL)
from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa
from sapl.materia.views import gerar_pdf_impressos
from sapl.parlamentares.models import Legislatura, Parlamentar
@ -44,10 +45,11 @@ from .forms import (AcompanhamentoDocumentoForm, AnularProcoloAdmForm,
TramitacaoAdmEditForm, TramitacaoAdmForm,
DesvincularDocumentoForm, DesvincularMateriaForm,
filtra_tramitacao_adm_destino_and_status,
filtra_tramitacao_adm_destino, filtra_tramitacao_adm_status)
filtra_tramitacao_adm_destino, filtra_tramitacao_adm_status,
AnexadoForm, AnexadoEmLoteFilterSet)
from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo,
DocumentoAdministrativo, StatusTramitacaoAdministrativo,
TipoDocumentoAdministrativo, TramitacaoAdministrativo)
TipoDocumentoAdministrativo, TramitacaoAdministrativo, Anexado)
TipoDocumentoAdministrativoCrud = CrudAux.build(
@ -941,6 +943,98 @@ class PesquisarDocumentoAdministrativoView(DocumentoAdministrativoMixin,
return self.render_to_response(context)
class AnexadoCrud(MasterDetailCrud):
model = Anexado
parent_field = 'documento_principal'
help_topic = 'documento_anexado'
public = [RP_LIST, RP_DETAIL]
class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['documento_anexado', 'data_anexacao']
class CreateView(MasterDetailCrud.CreateView):
form_class = AnexadoForm
class UpdateView(MasterDetailCrud.UpdateView):
form_class = AnexadoForm
def get_initial(self):
initial = super(UpdateView, self).get_initial()
initial['tipo'] = self.object.documento_anexado.tipo.id
initial['numero'] = self.object.documento_anexado.numero
initial['ano'] = self.object.documento_anexado.ano
return initial
class DetailView(MasterDetailCrud.DetailView):
@property
def layout_key(self):
return 'AnexadoDetail'
class DocumentoAnexadoEmLoteView(PermissionRequiredMixin, FilterView):
filterset_class = AnexadoEmLoteFilterSet
template_name = 'protocoloadm/em_lote/anexado.html'
permission_required = ('protocoloadm.list_documentoadministrativo', ) ##d
def get_context_data(self, **kwargs):
context = super(
DocumentoAnexadoEmLoteView,self
).get_context_data(**kwargs)
context['root_pk'] = self.kwargs['pk']
context['subnav_template_name'] = 'protocoloadm/subnav.yaml'
context['title'] = _('Documentos Anexados em Lote')
if not self.filterset.form.is_valid():
return context
qr = self.request.GET.copy()
context['object_List'] = context['object_list'].order_by(
'numero', '-ano'
)
context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
context['show_results'] = show_results_filter_set(qr)
return context
def post(self, request, *args, **kwargs):
marcados = request.POST.getlist('documento_id')
if len(marcados) == 0:
msg =_('Nenhum documento foi selecionado')
messages.add_message(request, messages.ERROR, msg)
return self.get(request, self.kwargs)
data_anexacao = datetime.strptime(
request.POST['data_anexacao'], "%d/%m/%Y"
).date()
if request.POST['data_desanexacao'] == '':
data_desanexacao = None
else:
data_desanexacao = datetime.strptime(
request.POST['data_desanexacao'], "%d/%m/%Y"
).date()
principal = DocumentoAdministrativo.objects.get(pk = kwargs['pk'])
for documento in DocumentoAdministrativo.objects.filter(id__in = marcados):
anexado = Anexado()
anexado.documento_principal = principal
anexado.documento_anexado = documento
anexado.data_anexacao = data_anexacao
anexado.data_desanexacao = data_desanexacao
anexado.save()
msg = _('Documento(s) anexado(s).')
messages.add_message(request, messages.SUCCESS, msg)
return self.get(request, self.kwargs)
class TramitacaoAdmCrud(MasterDetailCrud):
model = TramitacaoAdministrativo
parent_field = 'documento'

1
sapl/rules/map_rules.py

@ -60,6 +60,7 @@ rules_group_administrativo = {
'can_access_impressos'], __perms_publicas__),
# TODO: tratar em sapl.api a questão de ostencivo e restritivo
(protocoloadm.DocumentoAdministrativo, __base__, set()),
(protocoloadm.Anexado, __base__, set()),
(protocoloadm.DocumentoAcessorioAdministrativo, __base__, set()),
(protocoloadm.TramitacaoAdministrativo, __base__, set()),
]

13
sapl/templates/protocoloadm/anexado_list.html

@ -0,0 +1,13 @@
{% extends "crud/list.html" %}
{% load i18n %}
{% load common_tags %}
{% block more_buttons %}
{% if perms|get_add_perm:view %}
<a href="{% url 'sapl.protocoloadm:anexado_em_lote' root_pk %}" class="btn btn-outline-primary">
{% trans "Adicionar Anexado em Lote" %}
</a>
{% endif %}
{% endblock more_buttons %}

13
sapl/templates/protocoloadm/layouts.yaml

@ -10,6 +10,8 @@ DocumentoAdministrativo:
- assunto
- interessado tramitacao
- texto_integral
- documento_anexado_set__documento_principal|m2m_urlize_for_detail
- documento_principal_set__documento_anexado|m2m_urlize_for_detail
{% trans 'Outras Informações' %}:
- numero_externo
- dias_prazo data_fim_prazo
@ -33,6 +35,17 @@ TramitacaoAdministrativo:
- data_encaminhamento data_fim_prazo
- texto
Anexado:
{% trans 'Documento Anexado' %}:
- tipo numero ano
- data_anexacao data_desanexacao
AnexadoDetail:
{% trans 'Documento Anexado' %}:
- documento_principal|fk_urlize_for_detail
- documento_anexado|fk_urlize_for_detail
- data_anexacao data_desanexacao
Protocolo:
{% trans 'Indentificação Documento' %}:
- tipo_protocolo

2
sapl/templates/protocoloadm/subnav.yaml

@ -1,6 +1,8 @@
{% load i18n common_tags %}
- title: {% trans 'Início' %}
url: documentoadministrativo_detail
- title: {% trans 'Anexado' %}
url: anexado_list
- title: {% trans 'Tramitação' %}
url: tramitacaoadministrativo_list
- title: {% trans 'Documento Acessório' %}

Loading…
Cancel
Save