Browse Source

Fix #2720 - Adiciona usuários às tramitações (#2736)

* Fix 2720 - Adiciona usuarios em tramitacoes

* Corrige os testes

* adicionar visualizacao para superusers

* adiciona ip e user para docadm

* corrige migrations

* Adiciona tela usuario em DocAdm e correcoes de testes

* Apenas atualiza o usuario e ip na edicao se houve alteracao
pull/2811/head
Cesar Augusto de Carvalho 6 years ago
committed by Cesar Carvalho
parent
commit
9515c049a5
  1. 46
      sapl/materia/forms.py
  2. 28
      sapl/materia/migrations/0046_auto_20190417_1212.py
  3. 16
      sapl/materia/migrations/0048_merge_20190426_0828.py
  4. 11
      sapl/materia/models.py
  5. 26
      sapl/materia/views.py
  6. 41
      sapl/protocoloadm/forms.py
  7. 28
      sapl/protocoloadm/migrations/0019_auto_20190426_0833.py
  8. 12
      sapl/protocoloadm/models.py
  9. 2
      sapl/protocoloadm/tests/test_protocoloadm.py
  10. 18
      sapl/protocoloadm/views.py
  11. 38
      sapl/templates/materia/tramitacao_detail.html
  12. 37
      sapl/templates/protocoloadm/tramitacaoadministrativo_detail.html

46
sapl/materia/forms.py

@ -461,7 +461,11 @@ class TramitacaoForm(ModelForm):
'unidade_tramitacao_destino',
'data_encaminhamento',
'data_fim_prazo',
'texto']
'texto',
'user',
'ip']
widgets = {'user': forms.HiddenInput(),
'ip': forms.HiddenInput()}
def __init__(self, *args, **kwargs):
super(TramitacaoForm, self).__init__(*args, **kwargs)
@ -580,11 +584,15 @@ class TramitacaoUpdateForm(TramitacaoForm):
'data_encaminhamento',
'data_fim_prazo',
'texto',
'user',
'ip'
]
widgets = {
'data_encaminhamento': forms.DateInput(format='%d/%m/%Y'),
'data_fim_prazo': forms.DateInput(format='%d/%m/%Y'),
'user': forms.HiddenInput(),
'ip': forms.HiddenInput()
}
def clean(self):
@ -593,32 +601,44 @@ class TramitacaoUpdateForm(TramitacaoForm):
if not self.is_valid():
return self.cleaned_data
cd = self.cleaned_data
obj = self.instance
ultima_tramitacao = Tramitacao.objects.filter(
materia_id=self.instance.materia_id).order_by(
materia_id=obj.materia_id).order_by(
'-data_tramitacao',
'-id').first()
# Se a Tramitação que está sendo editada não for a mais recente,
# ela não pode ter seu destino alterado.
if ultima_tramitacao != self.instance:
if self.cleaned_data['unidade_tramitacao_destino'] != \
self.instance.unidade_tramitacao_destino:
if ultima_tramitacao != obj:
if cd['unidade_tramitacao_destino'] != \
obj.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))
.format(cd['unidade_tramitacao_destino'],
obj.unidade_tramitacao_destino))
raise ValidationError(
'Você não pode mudar a Unidade de Destino desta '
'tramitação, pois irá conflitar com a Unidade '
'Local da tramitação seguinte')
# Se não houve qualquer alteração em um dos dados, mantém o usuário e ip
if not (cd['data_tramitacao'] != obj.data_tramitacao or \
cd['unidade_tramitacao_destino'] != obj.unidade_tramitacao_destino or \
cd['status'] != obj.status or cd['texto'] != obj.texto or \
cd['data_encaminhamento'] != obj.data_encaminhamento or \
cd['data_fim_prazo'] != obj.data_fim_prazo or \
cd['urgente'] != obj.urgente or \
cd['turno'] != obj.turno):
cd['user'] = obj.user
cd['ip'] = obj.ip
cd['data_tramitacao'] = obj.data_tramitacao
cd['unidade_tramitacao_local'] = obj.unidade_tramitacao_local
self.cleaned_data['data_tramitacao'] = \
self.instance.data_tramitacao
self.cleaned_data['unidade_tramitacao_local'] = \
self.instance.unidade_tramitacao_local
return self.cleaned_data
return cd
class LegislacaoCitadaForm(ModelForm):

28
sapl/materia/migrations/0046_auto_20190417_1212.py

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-04-17 15:12
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('materia', '0045_auto_20190415_1050'),
]
operations = [
migrations.AddField(
model_name='tramitacao',
name='ip',
field=models.CharField(blank=True, default='', max_length=30, verbose_name='IP'),
),
migrations.AddField(
model_name='tramitacao',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Usuário'),
),
]

16
sapl/materia/migrations/0048_merge_20190426_0828.py

@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-04-26 11:28
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('materia', '0046_auto_20190417_1212'),
('materia', '0047_auto_20190417_1432'),
]
operations = [
]

11
sapl/materia/models.py

@ -18,7 +18,7 @@ from sapl.parlamentares.models import Parlamentar
#from sapl.protocoloadm.models import Protocolo
from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, SaplGenericForeignKey,
SaplGenericRelation, restringe_tipos_de_arquivo_txt,
texto_upload_path)
texto_upload_path, get_settings_auth_user_model)
EM_TRAMITACAO = [(1, 'Sim'),
@ -1003,6 +1003,15 @@ class Tramitacao(models.Model):
texto = models.TextField(verbose_name=_('Texto da Ação'))
data_fim_prazo = models.DateField(
blank=True, null=True, verbose_name=_('Data Fim Prazo'))
user = models.ForeignKey(get_settings_auth_user_model(),
verbose_name=_('Usuário'),
on_delete=models.PROTECT,
null=True,
blank=True)
ip = models.CharField(verbose_name=_('IP'),
max_length=30,
blank=True,
default='')
class Meta:
verbose_name = _('Tramitação')

26
sapl/materia/views.py

@ -53,7 +53,7 @@ from sapl.parlamentares.models import Legislatura
from sapl.protocoloadm.models import Protocolo
from sapl.settings import MEDIA_ROOT
from sapl.utils import (YES_NO_CHOICES, autor_label, autor_modal, SEPARADOR_HASH_PROPOSICAO,
gerar_hash_arquivo, get_base_url,
gerar_hash_arquivo, get_base_url, get_client_ip,
get_mime_type_from_file_extension, montar_row_autor,
show_results_filter_set, mail_service_configured)
@ -1189,6 +1189,8 @@ class TramitacaoCrud(MasterDetailCrud):
else:
initial['unidade_tramitacao_local'] = ''
initial['data_tramitacao'] = timezone.now().date()
initial['ip'] = get_client_ip(self.request)
initial['user'] = self.request.user
return initial
def get_context_data(self, **kwargs):
@ -1234,7 +1236,6 @@ class TramitacaoCrud(MasterDetailCrud):
post=self.object,
request=self.request)
except Exception as e:
# TODO log error
msg = _('Tramitação criada, mas e-mail de acompanhamento '
'de matéria não enviado. Há problemas na configuração '
'do e-mail.')
@ -1251,6 +1252,12 @@ class TramitacaoCrud(MasterDetailCrud):
layout_key = 'TramitacaoUpdate'
def get_initial(self):
initial = super(UpdateView, self).get_initial()
initial['ip'] = get_client_ip(self.request)
initial['user'] = self.request.user
return initial
def form_valid(self, form):
self.object = form.save()
username = self.request.user.username
@ -1316,6 +1323,15 @@ class TramitacaoCrud(MasterDetailCrud):
tramitacao.delete()
return HttpResponseRedirect(url)
class DetailView(MasterDetailCrud.DetailView):
template_name = "materia/tramitacao_detail.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['user'] = self.request.user
return context
def montar_helper_documento_acessorio(self):
autor_row = montar_row_autor('autor')
@ -2273,6 +2289,8 @@ class PrimeiraTramitacaoEmLoteView(PermissionRequiredMixin, FilterView):
messages.add_message(request, messages.ERROR, msg)
return self.get(request, self.kwargs)
user = request.user
ip = get_client_ip(request)
t = Tramitacao(
materia=materia,
data_tramitacao=data_tramitacao,
@ -2285,7 +2303,9 @@ class PrimeiraTramitacaoEmLoteView(PermissionRequiredMixin, FilterView):
urgente=urgente,
status_id=request.POST['status'],
turno=request.POST['turno'],
texto=request.POST['texto']
texto=request.POST['texto'],
user=user,
ip=ip
)
t.save()
try:

41
sapl/protocoloadm/forms.py

@ -654,7 +654,11 @@ class TramitacaoAdmForm(ModelForm):
'data_encaminhamento',
'data_fim_prazo',
'texto',
]
'user',
'ip']
widgets = {'user': forms.HiddenInput(),
'ip': forms.HiddenInput()}
def clean(self):
cleaned_data = super(TramitacaoAdmForm, self).clean()
@ -747,7 +751,10 @@ class TramitacaoAdmEditForm(TramitacaoAdmForm):
'data_encaminhamento',
'data_fim_prazo',
'texto',
]
'user',
'ip']
widgets = {'user': forms.HiddenInput(),
'ip': forms.HiddenInput()}
def clean(self):
super(TramitacaoAdmEditForm, self).clean()
@ -755,30 +762,40 @@ class TramitacaoAdmEditForm(TramitacaoAdmForm):
if not self.is_valid():
return self.cleaned_data
cd = self.cleaned_data
obj = self.instance
ultima_tramitacao = TramitacaoAdministrativo.objects.filter(
documento_id=self.instance.documento_id).order_by(
documento_id=obj.documento_id).order_by(
'-data_tramitacao',
'-id').first()
# Se a Tramitação que está sendo editada não for a mais recente,
# ela não pode ter seu destino alterado.
if ultima_tramitacao != self.instance:
if self.cleaned_data['unidade_tramitacao_destino'] != \
self.instance.unidade_tramitacao_destino:
if ultima_tramitacao != obj:
if cd['unidade_tramitacao_destino'] != \
obj.unidade_tramitacao_destino:
self.logger.error('Você não pode mudar a Unidade de Destino desta '
'tramitação (id={}), pois irá conflitar com a Unidade '
'Local da tramitação seguinte'.format(self.instance.documento_id))
'Local da tramitação seguinte'.format(obj.documento_id))
raise ValidationError(
'Você não pode mudar a Unidade de Destino desta '
'tramitação, pois irá conflitar com a Unidade '
'Local da tramitação seguinte')
self.cleaned_data['data_tramitacao'] = \
self.instance.data_tramitacao
self.cleaned_data['unidade_tramitacao_local'] = \
self.instance.unidade_tramitacao_local
# Se não houve qualquer alteração em um dos dados, mantém o usuário e ip
if not (cd['data_tramitacao'] != obj.data_tramitacao or \
cd['unidade_tramitacao_destino'] != obj.unidade_tramitacao_destino or \
cd['status'] != obj.status or cd['texto'] != obj.texto or \
cd['data_encaminhamento'] != obj.data_encaminhamento or \
cd['data_fim_prazo'] != obj.data_fim_prazo):
cd['user'] = obj.user
cd['ip'] = obj.ip
return self.cleaned_data
cd['data_tramitacao'] = obj.data_tramitacao
cd['unidade_tramitacao_local'] = obj.unidade_tramitacao_local
return cd
class AnexadoForm(ModelForm):

28
sapl/protocoloadm/migrations/0019_auto_20190426_0833.py

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-04-26 11:33
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('protocoloadm', '0018_auto_20190314_1532'),
]
operations = [
migrations.AddField(
model_name='tramitacaoadministrativo',
name='ip',
field=models.CharField(blank=True, default='', max_length=30, verbose_name='IP'),
),
migrations.AddField(
model_name='tramitacaoadministrativo',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Usuário'),
),
]

12
sapl/protocoloadm/models.py

@ -6,7 +6,8 @@ import reversion
from sapl.base.models import Autor
from sapl.materia.models import TipoMateriaLegislativa, UnidadeTramitacao
from sapl.utils import RANGE_ANOS, YES_NO_CHOICES, texto_upload_path
from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, texto_upload_path,
get_settings_auth_user_model)
@reversion.register()
@ -318,6 +319,15 @@ class TramitacaoAdministrativo(models.Model):
blank=True, verbose_name=_('Texto da Ação'))
data_fim_prazo = models.DateField(
blank=True, null=True, verbose_name=_('Data Fim do Prazo'))
user = models.ForeignKey(get_settings_auth_user_model(),
verbose_name=_('Usuário'),
on_delete=models.PROTECT,
null=True,
blank=True)
ip = models.CharField(verbose_name=_('IP'),
max_length=30,
blank=True,
default='')
class Meta:
verbose_name = _('Tramitação de Documento Administrativo')

2
sapl/protocoloadm/tests/test_protocoloadm.py

@ -162,7 +162,7 @@ def test_create_tramitacao(admin_client):
msg = force_text(_('A origem da nova tramitação deve ser igual ao '
'destino da última adicionada!'))
# Verifica se a origem da nova tramitacao é igual ao destino da última
assert msg in response.context_data[
'form'].errors['__all__']

18
sapl/protocoloadm/views.py

@ -1116,6 +1116,8 @@ class TramitacaoAdmCrud(MasterDetailCrud):
else:
initial['unidade_tramitacao_local'] = ''
initial['data_tramitacao'] = timezone.now().date()
initial['ip'] = get_client_ip(self.request)
initial['user'] = self.request.user
return initial
def get_context_data(self, **kwargs):
@ -1154,6 +1156,12 @@ class TramitacaoAdmCrud(MasterDetailCrud):
form_class = TramitacaoAdmEditForm
logger = logging.getLogger(__name__)
def get_initial(self):
initial = super(UpdateView, self).get_initial()
initial['ip'] = get_client_ip(self.request)
initial['user'] = self.request.user
return initial
def form_valid(self, form):
self.object = form.save()
username = self.request.user.username
@ -1162,7 +1170,6 @@ class TramitacaoAdmCrud(MasterDetailCrud):
post=self.object,
request=self.request)
except Exception as e:
# TODO log error
self.logger.error('user=' + username + '. Tramitação criada, mas e-mail de acompanhamento de documento '
'não enviado. A não configuração do servidor de e-mail '
'impede o envio de aviso de tramitação. ' + str(e))
@ -1183,7 +1190,14 @@ class TramitacaoAdmCrud(MasterDetailCrud):
class DetailView(DocumentoAdministrativoMixin,
MasterDetailCrud.DetailView):
pass
template_name = 'protocoloadm/tramitacaoadministrativo_detail.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['user'] = self.request.user
return context
class DeleteView(MasterDetailCrud.DeleteView):

38
sapl/templates/materia/tramitacao_detail.html

@ -0,0 +1,38 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% block detail_content %}
{{ block.super }}
{% if user.is_superuser %}
<div class="row">
{% if tramitacao.user %}
<div class="col-sm-6">
<div id="div_id_user" class="form-group">
<p class="control-label">Usuário</p>
<div class="controls">
<div class="form-control-static">
<div class="dont-break-out">
<a href="{% url 'sapl.base:user_edit' user.pk %}">{{tramitacao.user}}</a>
</div>
</div>
</div>
</div>
</div>
{% endif %}
{% if tramitacao.ip %}
<div class="col-sm-6">
<div id="div_ip_user" class="form-group">
<p class="control-label">IP</p>
<div class="controls">
<div class="form-control-static">
<div class="dont-break-out">
{{tramitacao.ip}}
</div>
</div>
</div>
</div>
</div>
{% endif %}
</div>
{% endif %}
{% endblock detail_content %}

37
sapl/templates/protocoloadm/tramitacaoadministrativo_detail.html

@ -1,5 +1,6 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% block actions %}
{% load common_tags %}
@ -13,3 +14,39 @@
{% endif %}
</div>
{% endblock actions %}
{% block detail_content %}
{{ block.super }}
{% if user.is_superuser %}
<div class="row">
{% if tramitacaoadministrativo.user %}
<div class="col-sm-6">
<div id="div_id_user" class="form-group">
<p class="control-label">Usuário</p>
<div class="controls">
<div class="form-control-static">
<div class="dont-break-out">
<a href="{% url 'sapl.base:user_edit' user.pk %}">{{tramitacaoadministrativo.user}}</a>
</div>
</div>
</div>
</div>
</div>
{% endif %}
{% if tramitacaoadministrativo.ip %}
<div class="col-sm-6">
<div id="div_ip_user" class="form-group">
<p class="control-label">IP</p>
<div class="controls">
<div class="form-control-static">
<div class="dont-break-out">
{{tramitacaoadministrativo.ip}}
</div>
</div>
</div>
</div>
</div>
{% endif %}
</div>
{% endif %}
{% endblock detail_content %}

Loading…
Cancel
Save