diff --git a/sapl/base/templatetags/common_tags.py b/sapl/base/templatetags/common_tags.py index 472b490c2..0c589e847 100644 --- a/sapl/base/templatetags/common_tags.py +++ b/sapl/base/templatetags/common_tags.py @@ -45,7 +45,10 @@ def get_add_perm(value, arg): perm = value view = arg - nome_app = view.__class__.model._meta.app_label + try: + nome_app = view.__class__.model._meta.app_label + except AttributeError: + return None nome_model = view.__class__.model.__name__.lower() can_add = '.add_' + nome_model @@ -57,7 +60,10 @@ def get_change_perm(value, arg): perm = value view = arg - nome_app = view.__class__.model._meta.app_label + try: + nome_app = view.__class__.model._meta.app_label + except AttributeError: + return None nome_model = view.__class__.model.__name__.lower() can_change = '.change_' + nome_model @@ -69,7 +75,10 @@ def get_delete_perm(value, arg): perm = value view = arg - nome_app = view.__class__.model._meta.app_label + try: + nome_app = view.__class__.model._meta.app_label + except AttributeError: + return None nome_model = view.__class__.model.__name__.lower() can_delete = '.delete_' + nome_model diff --git a/sapl/base/urls.py b/sapl/base/urls.py index f619423f2..cc94d8b83 100644 --- a/sapl/base/urls.py +++ b/sapl/base/urls.py @@ -20,5 +20,5 @@ urlpatterns = [ url(r'^login/$', views.login, { 'template_name': 'base/login.html', 'authentication_form': LoginForm}, name='login'), - url(r'^logout/$', views.logout, {'next_page': '/login'}, name='logout') + url(r'^logout/$', views.logout, {'next_page': '/login'}, name='logout'), ] diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index de0ebf143..7c21c3ae6 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -4,8 +4,10 @@ import django_filters from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Button, Column, Fieldset, Layout from django import forms +from django.contrib.auth.models import Group, User +from django.contrib.auth.password_validation import validate_password from django.core.exceptions import ObjectDoesNotExist, ValidationError -from django.db import models +from django.db import models, transaction from django.db.models import Max from django.forms import ModelForm from django.utils.translation import ugettext_lazy as _ @@ -98,7 +100,8 @@ class ProposicaoForm(ModelForm): class Meta: model = Proposicao - fields = ['tipo', 'data_envio', 'descricao', 'texto_original'] + fields = ['tipo', 'data_envio', 'descricao', 'texto_original', 'autor'] + widgets = {'autor': forms.HiddenInput()} class AcompanhamentoMateriaForm(ModelForm): @@ -542,3 +545,105 @@ class AutoriaForm(ModelForm): raise ValidationError(msg) return self.cleaned_data + + +class AutorForm(ModelForm): + senha = forms.CharField( + max_length=20, + label=_('Senha'), + required=True, + widget=forms.PasswordInput()) + + senha_confirma = forms.CharField( + max_length=20, + label=_('Confirmar Senha'), + required=True, + widget=forms.PasswordInput()) + + confirma_email = forms.EmailField( + required=True, + label=_('Confirmar Email')) + + class Meta: + model = Autor + fields = ['username', + 'senha', + 'email', + 'nome', + 'tipo', + 'cargo', + 'parlamentar', + 'comissao'] + + def valida_igualdade(self, texto1, texto2, msg): + if texto1 != texto2: + raise ValidationError(msg) + return True + + def valida_email_existente(self): + return User.objects.filter( + email=self.cleaned_data['email']).exists() + + def usuario_existente(self): + return User.objects.filter( + username=self.cleaned_data['username']).exists() + + def clean(self): + if ('senha' not in self.cleaned_data or + 'senha_confirma' not in self.cleaned_data): + raise ValidationError(_('Favor informar as senhas')) + + msg = _('As senhas não conferem.') + self.valida_igualdade( + self.cleaned_data['senha'], + self.cleaned_data['senha_confirma'], + msg) + + if ('email' not in self.cleaned_data or + 'confirma_email' not in self.cleaned_data): + raise ValidationError(_('Favor informar endereços de email')) + + msg = _('Os emails não conferem.') + self.valida_igualdade( + self.cleaned_data['email'], + self.cleaned_data['confirma_email'], + msg) + + email_existente = self.valida_email_existente() + + if email_existente: + msg = _('Este email já foi cadastrado.') + raise ValidationError(msg) + + if self.usuario_existente(): + msg = _('Este nome de usuario já foi cadastrado.') + raise ValidationError(msg) + + try: + validate_password(self.cleaned_data['senha']) + except ValidationError as error: + raise ValidationError(error) + + return self.cleaned_data + + @transaction.atomic + def save(self, commit=False): + + autor = super(AutorForm, self).save(commit) + + u = User.objects.get_or_create( + username=autor.username, + email=autor.email) + u = u[0] + u.set_password(self.cleaned_data['senha']) + u.is_active = False + u.save() + + autor.user = u + + autor.save() + + grupo = Group.objects.filter(name='Autor')[0] + u.groups.add(grupo) + + return autor diff --git a/sapl/materia/migrations/0039_auto_20160628_1251.py b/sapl/materia/migrations/0039_auto_20160628_1251.py new file mode 100644 index 000000000..a730729e2 --- /dev/null +++ b/sapl/materia/migrations/0039_auto_20160628_1251.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.5 on 2016-06-28 15:51 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import sapl.materia.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0007_alter_validators_add_error_messages'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('materia', '0038_auto_20160612_1506'), + ] + + operations = [ + migrations.AddField( + model_name='autor', + name='email', + field=models.EmailField(default=' ', max_length=254, verbose_name='Email'), + preserve_default=False, + ), + migrations.AddField( + model_name='autor', + name='grupo_usuario', + field=models.ForeignKey(default=sapl.materia.models.grupo_autor, on_delete=django.db.models.deletion.CASCADE, to='auth.Group'), + ), + migrations.AddField( + model_name='autor', + name='user', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + preserve_default=False, + ), + ] diff --git a/sapl/materia/models.py b/sapl/materia/models.py index ca433d7a6..741635e93 100644 --- a/sapl/materia/models.py +++ b/sapl/materia/models.py @@ -1,3 +1,4 @@ +from django.contrib.auth.models import Group, User from django.db import models from django.utils.translation import ugettext_lazy as _ from model_utils import Choices @@ -8,6 +9,14 @@ from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, restringe_tipos_de_arquivo_txt, xstr) +def grupo_autor(): + try: + grupo = Group.objects.get(name='Autor') + except Group.DoesNotExist: + return None + return grupo.id + + class TipoMateriaLegislativa(models.Model): sigla = models.CharField(max_length=5, verbose_name=_('Sigla')) descricao = models.CharField(max_length=50, verbose_name=_('Descrição ')) @@ -199,6 +208,7 @@ class TipoAutor(models.Model): class Autor(models.Model): + user = models.ForeignKey(User) partido = models.ForeignKey(Partido, blank=True, null=True) comissao = models.ForeignKey(Comissao, blank=True, null=True) parlamentar = models.ForeignKey(Parlamentar, blank=True, null=True) @@ -206,18 +216,24 @@ class Autor(models.Model): nome = models.CharField( max_length=50, blank=True, verbose_name=_('Autor')) cargo = models.CharField(max_length=50, blank=True) - username = models.CharField(max_length=50, blank=True) + username = models.CharField( + max_length=50, + blank=True, + verbose_name=_('Nome de Usuário')) + email = models.EmailField( + verbose_name=_('Email')) + grupo_usuario = models.ForeignKey(Group, default=grupo_autor) class Meta: verbose_name = _('Autor') verbose_name_plural = _('Autores') def __str__(self): - if str(self.tipo) == 'Parlamentar': + if str(self.tipo) == 'Parlamentar' and self.parlamentar: return self.parlamentar.nome_parlamentar - elif str(self.tipo) == 'Comissao': + elif str(self.tipo) == 'Comissao' and self.comissao: return str(self.comissao) - elif str(self.tipo) == 'Partido': + elif str(self.tipo) == 'Partido' and self.partido: return str(self.partido) else: if str(self.cargo): diff --git a/sapl/materia/tests/test_materia.py b/sapl/materia/tests/test_materia.py index ce530185b..2bed11631 100644 --- a/sapl/materia/tests/test_materia.py +++ b/sapl/materia/tests/test_materia.py @@ -1,7 +1,9 @@ import pytest + +from django.contrib.auth.models import User from django.core.urlresolvers import reverse -from model_mommy import mommy +from model_mommy import mommy from sapl.comissoes.models import Comissao, TipoComissao from sapl.materia.models import (Anexada, Autor, Autoria, DespachoInicial, DocumentoAcessorio, MateriaLegislativa, @@ -118,12 +120,15 @@ def test_materia_anexada_submit(admin_client): @pytest.mark.django_db(transaction=False) def test_autoria_submit(admin_client): materia_principal = make_materia_principal() - # Cria um tipo de Autor tipo_autor = mommy.make(TipoAutor, descricao='Teste Tipo_Autor') # Cria um Autor - autor = mommy.make(Autor, tipo=tipo_autor, nome='Autor Teste') + autor = mommy.make( + Autor, + tipo=tipo_autor, + nome='Autor Teste', + grupo_usuario_id=8) # Testa POST response = admin_client.post(reverse('sapl.materia:autoria_create', @@ -200,7 +205,11 @@ def test_documento_acessorio_submit(admin_client): tipo_autor = mommy.make(TipoAutor, descricao='Teste Tipo_Autor') # Cria um Autor - autor = mommy.make(Autor, tipo=tipo_autor, nome='Autor Teste') + autor = mommy.make( + Autor, + tipo=tipo_autor, + nome='Autor Teste', + grupo_usuario_id=8) # Cria um tipo de documento tipo = mommy.make(TipoDocumento, @@ -424,10 +433,22 @@ def test_form_errors_relatoria(admin_client): @pytest.mark.django_db(transaction=False) def test_proposicao_submit(admin_client): + tipo_autor = mommy.make(TipoAutor, descricao='Teste Tipo_Autor') + user = User.objects.filter(is_active=True)[0] + + autor = mommy.make( + Autor, + user=user, + tipo=tipo_autor, + nome='Autor Teste', + grupo_usuario_id=8) + response = admin_client.post(reverse('sapl.materia:proposicao_create'), {'tipo': mommy.make(TipoProposicao, pk=3).pk, 'descricao': 'Teste proposição', - 'salvar': 'salvar'}, + 'autor': autor, + 'salvar': 'salvar', + }, follow=True) assert response.status_code == 200 @@ -439,9 +460,19 @@ def test_proposicao_submit(admin_client): @pytest.mark.django_db(transaction=False) def test_form_errors_proposicao(admin_client): + tipo_autor = mommy.make(TipoAutor, descricao='Teste Tipo_Autor') + user = User.objects.filter(is_active=True)[0] + + autor = mommy.make( + Autor, + user=user, + tipo=tipo_autor, + nome='Autor Teste', + grupo_usuario_id=8) response = admin_client.post(reverse('sapl.materia:proposicao_create'), - {'salvar': 'salvar'}, + {'autor': autor, + 'salvar': 'salvar'}, follow=True) assert (response.context_data['form'].errors['tipo'] == ['Este campo é obrigatório.']) diff --git a/sapl/materia/urls.py b/sapl/materia/urls.py index dbc6499fc..f2aa6d5c5 100644 --- a/sapl/materia/urls.py +++ b/sapl/materia/urls.py @@ -3,9 +3,9 @@ from django.conf.urls import include, url from sapl.materia.views import (AcompanhamentoConfirmarView, AcompanhamentoExcluirView, AcompanhamentoMateriaView, AnexadaCrud, - AutorCrud, AutoriaCrud, DespachoInicialCrud, - DocumentoAcessorioCrud, LegislacaoCitadaCrud, - MateriaLegislativaCrud, + AutorCrud, AutoriaCrud, ConfirmarEmailView, + DespachoInicialCrud, DocumentoAcessorioCrud, + LegislacaoCitadaCrud, MateriaLegislativaCrud, MateriaLegislativaPesquisaView, MateriaTaView, NumeracaoCrud, OrgaoCrud, OrigemCrud, ProposicaoCrud, ProposicaoTaView, @@ -30,6 +30,9 @@ urlpatterns = [ RelatoriaCrud.get_urls() + DocumentoAcessorioCrud.get_urls())), + url(r'^confirmar/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})$', + ConfirmarEmailView.as_view(), name='confirmar_email'), + url(r'^proposicao/', include(ProposicaoCrud.get_urls())), # Integração com Compilação diff --git a/sapl/materia/views.py b/sapl/materia/views.py index 21f7de316..de56bced6 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -4,13 +4,19 @@ from string import ascii_letters, digits from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Button +from django.conf import settings from django.contrib import messages from django.contrib.auth.mixins import PermissionRequiredMixin -from django.core.exceptions import ObjectDoesNotExist +from django.contrib.auth.models import User +from django.contrib.auth.tokens import default_token_generator +from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist from django.core.mail import send_mail from django.core.urlresolvers import reverse from django.http.response import HttpResponseRedirect +from django.shortcuts import redirect from django.template import Context, loader +from django.utils.encoding import force_bytes +from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode from django.utils.translation import ugettext_lazy as _ from django.views.generic import CreateView, TemplateView, UpdateView from django_filters.views import FilterView @@ -19,15 +25,15 @@ from sapl.base.models import CasaLegislativa from sapl.compilacao.views import IntegracaoTaView from sapl.crispy_layout_mixin import SaplFormLayout, form_actions, to_row from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView, - CrudDeleteView, CrudListView, CrudUpdateView, - make_pagination) + CrudDeleteView, CrudDetailView, CrudListView, + CrudUpdateView, make_pagination) from sapl.crud.masterdetail import MasterDetailCrud from sapl.norma.models import LegislacaoCitada from sapl.utils import (autor_label, autor_modal, get_base_url, - permissao_tb_aux, permissoes_materia) + permissao_tb_aux, permissoes_autor, permissoes_materia) -from .forms import (AcompanhamentoMateriaForm, AnexadaForm, AutoriaForm, - DespachoInicialForm, DocumentoAcessorioForm, +from .forms import (AcompanhamentoMateriaForm, AnexadaForm, AutorForm, + AutoriaForm, DespachoInicialForm, DocumentoAcessorioForm, LegislacaoCitadaForm, MateriaLegislativaFilterSet, NumeracaoForm, ProposicaoForm, RelatoriaForm, TramitacaoForm, UnidadeTramitacaoForm, @@ -103,9 +109,55 @@ class AutorCrud(Crud): help_path = 'autor' class BaseMixin(PermissionRequiredMixin, CrudBaseMixin): + list_field_names = ['tipo', 'nome', + 'username', 'cargo'] + def has_permission(self): return permissao_tb_aux(self) + class CreateView(CrudCreateView): + form_class = AutorForm + layout_key = 'AutorCreate' + + def get_success_url(self): + pk_autor = Autor.objects.get( + email=self.request.POST.get('email')).id + kwargs = {} + user = User.objects.get(email=self.request.POST.get('email')) + kwargs['token'] = default_token_generator.make_token(user) + kwargs['uidb64'] = urlsafe_base64_encode(force_bytes(user.pk)) + assunto = "SAPL - Confirmação de Conta" + full_url = self.request.get_raw_uri() + url_base = full_url[:full_url.find('sistema') - 1] + + mensagem = ("Este e-mail foi utilizado para fazer cadastro no " + + "SAPL com o perfil de Autor. Agora você pode " + + "criar/editar/enviar Proposições.\n" + + "Seu nome de usuário é: " + + self.request.POST['username'] + "\n" + "Caso você não tenha feito este cadastro, por favor " + + "ignore esta mensagem. Caso tenha, clique " + + "no link abaixo\n" + url_base + + reverse('sapl.materia:confirmar_email', kwargs=kwargs)) + remetente = settings.EMAIL_SEND_USER + destinatario = [self.request.POST.get('email')] + send_mail(assunto, mensagem, remetente, destinatario, + fail_silently=False) + return reverse('sapl.materia:autor_detail', + kwargs={'pk': pk_autor}) + + +class ConfirmarEmailView(TemplateView): + template_name = "confirma_email.html" + + def get(self, request, *args, **kwargs): + uid = urlsafe_base64_decode(self.kwargs['uidb64']) + user = User.objects.get(id=uid) + user.is_active = True + user.save() + context = self.get_context_data(**kwargs) + return self.render_to_response(context) + class OrgaoCrud(Crud): model = Orgao @@ -167,16 +219,66 @@ class ProposicaoCrud(Crud): def layout_key(self): return 'ProposicaoCreate' + def get_initial(self): + try: + autor_id = Autor.objects.get(user=self.request.user.id) + except MultipleObjectsReturned: + msg = _('Este usuário está relacionado a mais de um autor. ' + + 'Operação cancelada') + messages.add_message(self.request, messages.ERROR, msg) + return redirect(self.get_success_url()) + else: + return {'autor': autor_id} + class UpdateView(PermissionRequiredMixin, CrudUpdateView): form_class = ProposicaoForm - permission_required = permissoes_materia() + permission_required = permissoes_autor() + + @property + def layout_key(self): + return 'ProposicaoCreate' + + def has_permission(self): + perms = self.get_permission_required() + if self.request.user.has_perms(perms): + if (Proposicao.objects.filter( + id=self.kwargs['pk'], + autor__user_id=self.request.user.id).exists()): + proposicao = Proposicao.objects.get( + id=self.kwargs['pk'], + autor__user_id=self.request.user.id) + if not proposicao.data_recebimento: + return True + else: + msg = _('Essa proposição já foi recebida. ' + + 'Não pode mais ser editada') + messages.add_message(self.request, messages.ERROR, msg) + return False + else: + return False + + class DetailView(PermissionRequiredMixin, CrudDetailView): + permission_required = permissoes_autor() @property def layout_key(self): return 'ProposicaoCreate' - class ListView(CrudListView): + def has_permission(self): + perms = self.get_permission_required() + if self.request.user.has_perms(perms): + if (Proposicao.objects.filter( + id=self.kwargs['pk'], + autor__user_id=self.request.user.id).exists()): + return True + else: + return False + else: + return False + + class ListView(PermissionRequiredMixin, CrudListView): ordering = ['-data_envio', 'descricao'] + permission_required = permissoes_autor() def get_rows(self, object_list): @@ -186,6 +288,11 @@ class ProposicaoCrud(Crud): return [self._as_row(obj) for obj in object_list] + def get_queryset(self): + lista = Proposicao.objects.filter( + autor__user_id=self.request.user.id) + return lista + class DeleteView(PermissionRequiredMixin, CrudDeleteView): permission_required = permissoes_materia() diff --git a/sapl/parlamentares/forms.py b/sapl/parlamentares/forms.py index 9b636e882..fe21aeb2c 100644 --- a/sapl/parlamentares/forms.py +++ b/sapl/parlamentares/forms.py @@ -29,9 +29,9 @@ class LegislaturaForm(ModelForm): data_eleicao = cleaned_data['data_eleicao'] if data_inicio >= data_fim or data_eleicao >= data_inicio: - raise ValidationError(_('A data início deve ser menor que a data \ - fim, e a data eleição deve ser menor que\ - a data início')) + raise ValidationError(_('A data início deve ser menor que a ' + + 'data fim, e a data eleição deve ser ' + + 'menor que a data início')) return cleaned_data diff --git a/sapl/parlamentares/migrations/0022_auto_20160624_1124.py b/sapl/parlamentares/migrations/0022_auto_20160624_1124.py new file mode 100644 index 000000000..a395bc806 --- /dev/null +++ b/sapl/parlamentares/migrations/0022_auto_20160624_1124.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.5 on 2016-06-24 14:24 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import sapl.parlamentares.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('parlamentares', '0021_merge'), + ] + + operations = [ + migrations.AlterField( + model_name='sessaolegislativa', + name='legislatura', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='parlamentares.Legislatura', verbose_name=sapl.parlamentares.models.Legislatura), + ), + ] diff --git a/sapl/parlamentares/migrations/0023_auto_20160628_1247.py b/sapl/parlamentares/migrations/0023_auto_20160628_1247.py new file mode 100644 index 000000000..d40680e48 --- /dev/null +++ b/sapl/parlamentares/migrations/0023_auto_20160628_1247.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.5 on 2016-06-28 15:47 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('parlamentares', '0022_auto_20160624_1124'), + ] + + operations = [ + migrations.AlterField( + model_name='sessaolegislativa', + name='legislatura', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='parlamentares.Legislatura', verbose_name='Legislatura'), + ), + ] diff --git a/sapl/protocoloadm/migrations/0013_merge.py b/sapl/parlamentares/migrations/0024_merge.py similarity index 55% rename from sapl/protocoloadm/migrations/0013_merge.py rename to sapl/parlamentares/migrations/0024_merge.py index af5341f83..f8e63c317 100644 --- a/sapl/protocoloadm/migrations/0013_merge.py +++ b/sapl/parlamentares/migrations/0024_merge.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.9.5 on 2016-05-19 17:03 +# Generated by Django 1.9.7 on 2016-08-18 21:39 from __future__ import unicode_literals from django.db import migrations @@ -8,8 +8,8 @@ from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('protocoloadm', '0012_tipoinstituicao'), - ('protocoloadm', '0012_auto_20160503_0926'), + ('parlamentares', '0022_auto_20160702_1519'), + ('parlamentares', '0023_auto_20160628_1247'), ] operations = [ diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 90d684a36..1d86d9c57 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -1,16 +1,18 @@ +from datetime import datetime + import django_filters from crispy_forms.bootstrap import InlineRadios from crispy_forms.helper import FormHelper -from crispy_forms.layout import HTML, Button, Field, Fieldset, Layout, Submit +from crispy_forms.layout import HTML, Button, Fieldset, Layout, Submit from django import forms -from django.core.exceptions import ObjectDoesNotExist +from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.db import models from django.forms import ModelForm from django.utils.translation import ugettext_lazy as _ from sapl.crispy_layout_mixin import form_actions, to_row from sapl.materia.forms import RangeWidgetOverride -from sapl.materia.models import Autor +from sapl.materia.models import Autor, UnidadeTramitacao from sapl.utils import RANGE_ANOS, autor_label, autor_modal from .models import (DocumentoAcessorioAdministrativo, DocumentoAdministrativo, @@ -523,7 +525,6 @@ class TramitacaoAdmForm(ModelForm): 'data_encaminhamento', 'data_fim_prazo', 'texto', - 'documento', ] widgets = { @@ -532,22 +533,78 @@ class TramitacaoAdmForm(ModelForm): 'data_fim_prazo': forms.DateInput(format='%d/%m/%Y'), } - def __init__(self, *args, **kwargs): - self.helper = FormHelper() - self.helper.layout = Layout( - Fieldset(_('Incluir Tramitação'), - 'data_tramitacao', - 'unidade_tramitacao_local', - 'status', - 'unidade_tramitacao_destino', - 'data_encaminhamento', - 'data_fim_prazo', - 'texto'), - Field('documento', type="hidden"), - form_actions() - ) - super(TramitacaoAdmForm, self).__init__( - *args, **kwargs) + def clean(self): + data_enc_form = self.cleaned_data['data_encaminhamento'] + data_prazo_form = self.cleaned_data['data_fim_prazo'] + data_tram_form = self.cleaned_data['data_tramitacao'] + + if self.errors: + return self.errors + + ultima_tramitacao = TramitacaoAdministrativo.objects.filter( + documento_id=self.instance.documento_id).exclude( + id=self.instance.id).last() + + if not self.instance.data_tramitacao: + + if ultima_tramitacao: + destino = ultima_tramitacao.unidade_tramitacao_destino + if (destino != self.cleaned_data['unidade_tramitacao_local']): + msg = _('A origem da nova tramitação deve ser igual ao ' + 'destino da última adicionada!') + raise ValidationError(msg) + + if self.cleaned_data['data_tramitacao'] > datetime.now().date(): + msg = _( + 'A data de tramitação deve ser ' + + 'menor ou igual a data de hoje!') + raise ValidationError(msg) + + if (ultima_tramitacao and + data_tram_form < ultima_tramitacao.data_tramitacao): + msg = _('A data da nova tramitação deve ser ' + + 'maior que a data da última tramitação!') + raise ValidationError(msg) + + if data_enc_form < data_tram_form or data_prazo_form < data_tram_form: + msg = _('A data fim de prazo e encaminhamento devem ser ' + + 'maiores que a data de tramitação!') + raise ValidationError(msg) + + return self.cleaned_data + + +class TramitacaoAdmEditForm(TramitacaoAdmForm): + + unidade_tramitacao_local = forms.ModelChoiceField( + queryset=UnidadeTramitacao.objects.all(), + widget=forms.HiddenInput()) + + data_tramitacao = forms.DateField(widget=forms.HiddenInput()) + + class Meta: + model = TramitacaoAdministrativo + fields = ['data_tramitacao', + 'unidade_tramitacao_local', + 'status', + 'unidade_tramitacao_destino', + 'data_encaminhamento', + 'data_fim_prazo', + 'texto', + ] + + widgets = { + 'data_encaminhamento': forms.DateInput(format='%d/%m/%Y'), + 'data_fim_prazo': forms.DateInput(format='%d/%m/%Y'), + } + + def clean(self): + local = self.instance.unidade_tramitacao_local + data_tram = self.instance.data_tramitacao + + self.cleaned_data['data_tramitacao'] = data_tram + self.cleaned_data['unidade_tramitacao_local'] = local + return super(TramitacaoAdmEditForm, self).clean() class DocumentoAdministrativoForm(ModelForm): diff --git a/sapl/protocoloadm/migrations/0001_initial.py b/sapl/protocoloadm/migrations/0001_initial.py index a9f0277e4..5f9a851f8 100644 --- a/sapl/protocoloadm/migrations/0001_initial.py +++ b/sapl/protocoloadm/migrations/0001_initial.py @@ -1,147 +1,163 @@ # -*- coding: utf-8 -*- +# Generated by Django 1.9.5 on 2016-06-24 14:31 from __future__ import unicode_literals from django.db import migrations, models +import django.db.models.deletion +import sapl.protocoloadm.models class Migration(migrations.Migration): + initial = True + dependencies = [ - ('materia', '0001_initial'), + ('materia', '0038_auto_20160612_1506'), ] operations = [ migrations.CreateModel( name='DocumentoAcessorioAdministrativo', fields=[ - ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)), + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('nome', models.CharField(max_length=30, verbose_name='Nome')), - ('arquivo', models.CharField(max_length=100, verbose_name='Arquivo')), + ('arquivo', models.FileField(blank=True, null=True, upload_to=sapl.protocoloadm.models.texto_upload_path, verbose_name='Arquivo')), ('data', models.DateField(blank=True, null=True, verbose_name='Data')), - ('autor', models.CharField(blank=True, max_length=50, null=True, verbose_name='Autor')), - ('assunto', models.TextField(blank=True, null=True, verbose_name='Assunto')), - ('indexacao', models.TextField(blank=True, null=True)), + ('autor', models.CharField(blank=True, max_length=50, verbose_name='Autor')), + ('assunto', models.TextField(blank=True, verbose_name='Assunto')), + ('indexacao', models.TextField(blank=True)), ], options={ - 'verbose_name_plural': 'Documentos Acessórios', 'verbose_name': 'Documento Acessório', + 'verbose_name_plural': 'Documentos Acessórios', }, ), migrations.CreateModel( name='DocumentoAdministrativo', fields=[ - ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)), - ('numero', models.IntegerField(verbose_name='Número')), - ('ano', models.SmallIntegerField(verbose_name='Ano')), + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('numero', models.PositiveIntegerField(verbose_name='Número')), + ('ano', models.PositiveSmallIntegerField(choices=[(2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], verbose_name='Ano')), ('data', models.DateField(verbose_name='Data')), - ('numero_protocolo', models.IntegerField(blank=True, null=True, verbose_name='Núm. Protocolo')), - ('interessado', models.CharField(blank=True, max_length=50, null=True, verbose_name='Interessado')), - ('dias_prazo', models.IntegerField(blank=True, null=True, verbose_name='Dias Prazo')), + ('numero_protocolo', models.PositiveIntegerField(blank=True, null=True, verbose_name='Núm. Protocolo')), + ('interessado', models.CharField(blank=True, max_length=50, verbose_name='Interessado')), + ('dias_prazo', models.PositiveIntegerField(blank=True, null=True, verbose_name='Dias Prazo')), ('data_fim_prazo', models.DateField(blank=True, null=True, verbose_name='Data Fim Prazo')), - ('tramitacao', models.BooleanField(verbose_name='Em Tramitação?')), + ('tramitacao', models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], verbose_name='Em Tramitação?')), ('assunto', models.TextField(verbose_name='Assunto')), - ('observacao', models.TextField(blank=True, null=True, verbose_name='Observação')), - ('autor', models.ForeignKey(blank=True, null=True, to='materia.Autor')), + ('observacao', models.TextField(blank=True, verbose_name='Observação')), + ('texto_integral', models.FileField(blank=True, null=True, upload_to=sapl.protocoloadm.models.texto_upload_path, verbose_name='Texto Integral')), + ('autor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='materia.Autor')), ], options={ - 'verbose_name_plural': 'Documentos Administrativos', 'verbose_name': 'Documento Administrativo', + 'verbose_name_plural': 'Documentos Administrativos', }, ), migrations.CreateModel( name='Protocolo', fields=[ - ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)), - ('numero', models.IntegerField(blank=True, null=True, verbose_name='Número do Protocolo')), - ('ano', models.SmallIntegerField()), + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('numero', models.PositiveIntegerField(verbose_name='Número de Protocolo')), + ('ano', models.PositiveSmallIntegerField(choices=[(2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], verbose_name='Ano do Protocolo')), ('data', models.DateField()), ('hora', models.TimeField()), ('timestamp', models.DateTimeField()), - ('tipo_protocolo', models.IntegerField(verbose_name='Tipo de Protocolo')), - ('tipo_processo', models.IntegerField()), - ('interessado', models.CharField(blank=True, max_length=60, null=True, verbose_name='Interessado')), - ('assunto_ementa', models.TextField(blank=True, null=True)), - ('numero_paginas', models.IntegerField(blank=True, null=True, verbose_name='Número de Páginas')), - ('observacao', models.TextField(blank=True, null=True, verbose_name='Observação')), + ('tipo_protocolo', models.PositiveIntegerField(verbose_name='Tipo de Protocolo')), + ('tipo_processo', models.PositiveIntegerField()), + ('interessado', models.CharField(blank=True, max_length=60, verbose_name='Interessado')), + ('assunto_ementa', models.TextField(blank=True)), + ('numero_paginas', models.PositiveIntegerField(blank=True, null=True, verbose_name='Número de Páginas')), + ('observacao', models.TextField(blank=True, verbose_name='Observação')), ('anulado', models.BooleanField()), - ('user_anulacao', models.CharField(blank=True, max_length=20, null=True)), - ('ip_anulacao', models.CharField(blank=True, max_length=15, null=True)), - ('justificativa_anulacao', models.CharField(blank=True, max_length=60, null=True)), + ('user_anulacao', models.CharField(blank=True, max_length=20)), + ('ip_anulacao', models.CharField(blank=True, max_length=15)), + ('justificativa_anulacao', models.CharField(blank=True, max_length=60, verbose_name='Motivo')), ('timestamp_anulacao', models.DateTimeField(blank=True, null=True)), - ('autor', models.ForeignKey(blank=True, null=True, to='materia.Autor')), + ('autor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='materia.Autor')), ], options={ - 'verbose_name_plural': 'Protocolos', 'verbose_name': 'Protocolo', + 'verbose_name_plural': 'Protocolos', }, ), migrations.CreateModel( name='StatusTramitacaoAdministrativo', fields=[ - ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)), + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('sigla', models.CharField(max_length=10, verbose_name='Sigla')), ('descricao', models.CharField(max_length=60, verbose_name='Descrição')), ('indicador', models.CharField(choices=[('F', 'Fim'), ('R', 'Retorno')], max_length=1, verbose_name='Indicador da Tramitação')), ], options={ - 'verbose_name_plural': 'Status de Tramitação', 'verbose_name': 'Status de Tramitação', + 'verbose_name_plural': 'Status de Tramitação', }, ), migrations.CreateModel( name='TipoDocumentoAdministrativo', fields=[ - ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)), + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('sigla', models.CharField(max_length=5, verbose_name='Sigla')), ('descricao', models.CharField(max_length=50, verbose_name='Descrição')), ], options={ - 'verbose_name_plural': 'Tipos de Documento Administrativo', 'verbose_name': 'Tipo de Documento Administrativo', + 'verbose_name_plural': 'Tipos de Documento Administrativo', + }, + ), + migrations.CreateModel( + name='TipoInstituicao', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('descricao', models.CharField(max_length=50, verbose_name='Descrição')), + ], + options={ + 'verbose_name': 'Tipo de Instituição', + 'verbose_name_plural': 'Tipos de Instituições', }, ), migrations.CreateModel( name='TramitacaoAdministrativo', fields=[ - ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)), - ('data_tramitacao', models.DateField(blank=True, null=True, verbose_name='Data Tramitação')), + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('data_tramitacao', models.DateField(verbose_name='Data Tramitação')), ('data_encaminhamento', models.DateField(blank=True, null=True, verbose_name='Data Encaminhamento')), - ('ultima', models.BooleanField()), - ('texto', models.TextField(blank=True, null=True, verbose_name='Texto da Ação')), + ('texto', models.TextField(blank=True, verbose_name='Texto da Ação')), ('data_fim_prazo', models.DateField(blank=True, null=True, verbose_name='Data Fim do Prazo')), - ('documento', models.ForeignKey(to='protocoloadm.DocumentoAdministrativo')), - ('status', models.ForeignKey(blank=True, null=True, to='protocoloadm.StatusTramitacaoAdministrativo', verbose_name='Status')), - ('unidade_tramitacao_destino', models.ForeignKey(blank=True, null=True, to='materia.UnidadeTramitacao', verbose_name='Unidade Destino', related_name='+')), - ('unidade_tramitacao_local', models.ForeignKey(blank=True, null=True, to='materia.UnidadeTramitacao', verbose_name='Unidade Local', related_name='+')), + ('documento', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='protocoloadm.DocumentoAdministrativo')), + ('status', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='protocoloadm.StatusTramitacaoAdministrativo', verbose_name='Status')), + ('unidade_tramitacao_destino', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='adm_tramitacoes_destino', to='materia.UnidadeTramitacao', verbose_name='Unidade Destino')), + ('unidade_tramitacao_local', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='adm_tramitacoes_origem', to='materia.UnidadeTramitacao', verbose_name='Unidade Local')), ], options={ - 'verbose_name_plural': 'Tramitações de Documento Administrativo', 'verbose_name': 'Tramitação de Documento Administrativo', + 'verbose_name_plural': 'Tramitações de Documento Administrativo', }, ), migrations.AddField( model_name='protocolo', name='tipo_documento', - field=models.ForeignKey(blank=True, null=True, to='protocoloadm.TipoDocumentoAdministrativo', verbose_name='Tipo de documento'), + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='protocoloadm.TipoDocumentoAdministrativo', verbose_name='Tipo de documento'), ), migrations.AddField( model_name='protocolo', name='tipo_materia', - field=models.ForeignKey(blank=True, null=True, to='materia.TipoMateriaLegislativa', verbose_name='Tipo Matéria'), + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='materia.TipoMateriaLegislativa', verbose_name='Tipo Matéria'), ), migrations.AddField( model_name='documentoadministrativo', name='tipo', - field=models.ForeignKey(to='protocoloadm.TipoDocumentoAdministrativo', verbose_name='Tipo Documento'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='protocoloadm.TipoDocumentoAdministrativo', verbose_name='Tipo Documento'), ), migrations.AddField( model_name='documentoacessorioadministrativo', name='documento', - field=models.ForeignKey(to='protocoloadm.DocumentoAdministrativo'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='protocoloadm.DocumentoAdministrativo'), ), migrations.AddField( model_name='documentoacessorioadministrativo', name='tipo', - field=models.ForeignKey(to='protocoloadm.TipoDocumentoAdministrativo', verbose_name='Tipo'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='protocoloadm.TipoDocumentoAdministrativo', verbose_name='Tipo'), ), ] diff --git a/sapl/protocoloadm/migrations/0002_auto_20150729_1717.py b/sapl/protocoloadm/migrations/0002_auto_20150729_1717.py deleted file mode 100644 index 253bbb0eb..000000000 --- a/sapl/protocoloadm/migrations/0002_auto_20150729_1717.py +++ /dev/null @@ -1,59 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('protocoloadm', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='documentoadministrativo', - name='ano', - field=models.PositiveSmallIntegerField(verbose_name='Ano'), - ), - migrations.AlterField( - model_name='documentoadministrativo', - name='dias_prazo', - field=models.PositiveIntegerField(blank=True, verbose_name='Dias Prazo', null=True), - ), - migrations.AlterField( - model_name='documentoadministrativo', - name='numero', - field=models.PositiveIntegerField(verbose_name='Número'), - ), - migrations.AlterField( - model_name='documentoadministrativo', - name='numero_protocolo', - field=models.PositiveIntegerField(blank=True, verbose_name='Núm. Protocolo', null=True), - ), - migrations.AlterField( - model_name='protocolo', - name='ano', - field=models.PositiveSmallIntegerField(), - ), - migrations.AlterField( - model_name='protocolo', - name='numero', - field=models.PositiveIntegerField(blank=True, verbose_name='Número do Protocolo', null=True), - ), - migrations.AlterField( - model_name='protocolo', - name='numero_paginas', - field=models.PositiveIntegerField(blank=True, verbose_name='Número de Páginas', null=True), - ), - migrations.AlterField( - model_name='protocolo', - name='tipo_processo', - field=models.PositiveIntegerField(), - ), - migrations.AlterField( - model_name='protocolo', - name='tipo_protocolo', - field=models.PositiveIntegerField(verbose_name='Tipo de Protocolo'), - ), - ] diff --git a/sapl/protocoloadm/migrations/0003_documentoacessorioadministrativo_texto_integral.py b/sapl/protocoloadm/migrations/0003_documentoacessorioadministrativo_texto_integral.py deleted file mode 100644 index 24aa43a71..000000000 --- a/sapl/protocoloadm/migrations/0003_documentoacessorioadministrativo_texto_integral.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - -import sapl.protocoloadm.models - - -class Migration(migrations.Migration): - - dependencies = [ - ('protocoloadm', '0002_auto_20150729_1717'), - ] - - operations = [ - migrations.AddField( - model_name='documentoacessorioadministrativo', - name='texto_integral', - field=models.FileField(verbose_name='Texto Integral', blank=True, - null=True, upload_to=sapl.protocoloadm.models.texto_upload_path), - ), - ] diff --git a/sapl/protocoloadm/migrations/0004_auto_20151007_1035.py b/sapl/protocoloadm/migrations/0004_auto_20151007_1035.py deleted file mode 100644 index b5bb90d19..000000000 --- a/sapl/protocoloadm/migrations/0004_auto_20151007_1035.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - -import sapl.protocoloadm.models - - -class Migration(migrations.Migration): - - dependencies = [ - ('protocoloadm', - '0003_documentoacessorioadministrativo_texto_integral'), - ] - - operations = [ - migrations.RemoveField( - model_name='documentoacessorioadministrativo', - name='texto_integral', - ), - migrations.AddField( - model_name='documentoadministrativo', - name='texto_integral', - field=models.FileField( - blank=True, null=True, upload_to=sapl.protocoloadm.models.texto_upload_path, verbose_name='Texto Integral'), - ), - ] diff --git a/sapl/protocoloadm/migrations/0005_auto_20151008_0744.py b/sapl/protocoloadm/migrations/0005_auto_20151008_0744.py deleted file mode 100644 index b52937c7f..000000000 --- a/sapl/protocoloadm/migrations/0005_auto_20151008_0744.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - -import sapl.protocoloadm.models - - -class Migration(migrations.Migration): - - dependencies = [ - ('protocoloadm', '0004_auto_20151007_1035'), - ] - - operations = [ - migrations.AlterField( - model_name='documentoacessorioadministrativo', - name='arquivo', - field=models.FileField( - blank=True, null=True, upload_to=sapl.protocoloadm.models.texto_upload_path, verbose_name='Arquivo'), - ), - ] diff --git a/sapl/protocoloadm/migrations/0006_auto_20160216_1015.py b/sapl/protocoloadm/migrations/0006_auto_20160216_1015.py deleted file mode 100644 index 05791b6bd..000000000 --- a/sapl/protocoloadm/migrations/0006_auto_20160216_1015.py +++ /dev/null @@ -1,74 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('protocoloadm', '0005_auto_20151008_0744'), - ] - - operations = [ - migrations.AlterField( - model_name='documentoacessorioadministrativo', - name='assunto', - field=models.TextField(verbose_name='Assunto', blank=True), - ), - migrations.AlterField( - model_name='documentoacessorioadministrativo', - name='autor', - field=models.CharField(verbose_name='Autor', max_length=50, blank=True), - ), - migrations.AlterField( - model_name='documentoacessorioadministrativo', - name='indexacao', - field=models.TextField(blank=True), - ), - migrations.AlterField( - model_name='documentoadministrativo', - name='interessado', - field=models.CharField(verbose_name='Interessado', max_length=50, blank=True), - ), - migrations.AlterField( - model_name='documentoadministrativo', - name='observacao', - field=models.TextField(verbose_name='Observação', blank=True), - ), - migrations.AlterField( - model_name='protocolo', - name='assunto_ementa', - field=models.TextField(blank=True), - ), - migrations.AlterField( - model_name='protocolo', - name='interessado', - field=models.CharField(verbose_name='Interessado', max_length=60, blank=True), - ), - migrations.AlterField( - model_name='protocolo', - name='ip_anulacao', - field=models.CharField(max_length=15, blank=True), - ), - migrations.AlterField( - model_name='protocolo', - name='justificativa_anulacao', - field=models.CharField(max_length=60, blank=True), - ), - migrations.AlterField( - model_name='protocolo', - name='observacao', - field=models.TextField(verbose_name='Observação', blank=True), - ), - migrations.AlterField( - model_name='protocolo', - name='user_anulacao', - field=models.CharField(max_length=20, blank=True), - ), - migrations.AlterField( - model_name='tramitacaoadministrativo', - name='texto', - field=models.TextField(verbose_name='Texto da Ação', blank=True), - ), - ] diff --git a/sapl/protocoloadm/migrations/0007_auto_20160218_1429.py b/sapl/protocoloadm/migrations/0007_auto_20160218_1429.py deleted file mode 100644 index 51f753b83..000000000 --- a/sapl/protocoloadm/migrations/0007_auto_20160218_1429.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('protocoloadm', '0006_auto_20160216_1015'), - ] - - operations = [ - migrations.AlterField( - model_name='documentoadministrativo', - name='tramitacao', - field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], verbose_name='Em Tramitação?'), - ), - ] diff --git a/sapl/protocoloadm/migrations/0008_auto_20160308_1436.py b/sapl/protocoloadm/migrations/0008_auto_20160308_1436.py deleted file mode 100644 index 913921ac3..000000000 --- a/sapl/protocoloadm/migrations/0008_auto_20160308_1436.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-03-08 17:36 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('protocoloadm', '0007_auto_20160218_1429'), - ] - - operations = [ - migrations.AlterField( - model_name='protocolo', - name='ano', - field=models.PositiveSmallIntegerField(verbose_name='Ano do Protocolo'), - ), - ] diff --git a/sapl/protocoloadm/migrations/0009_auto_20160309_1323.py b/sapl/protocoloadm/migrations/0009_auto_20160309_1323.py deleted file mode 100644 index aa7760eca..000000000 --- a/sapl/protocoloadm/migrations/0009_auto_20160309_1323.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-03-09 16:23 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('protocoloadm', '0008_auto_20160308_1436'), - ] - - operations = [ - migrations.AlterField( - model_name='protocolo', - name='numero', - field=models.PositiveIntegerField(verbose_name='Número de Protocolo'), - ), - ] diff --git a/sapl/protocoloadm/migrations/0010_auto_20160309_1407.py b/sapl/protocoloadm/migrations/0010_auto_20160309_1407.py deleted file mode 100644 index b6e22f20c..000000000 --- a/sapl/protocoloadm/migrations/0010_auto_20160309_1407.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-03-09 17:07 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('protocoloadm', '0009_auto_20160309_1323'), - ] - - operations = [ - migrations.AlterField( - model_name='documentoadministrativo', - name='ano', - field=models.PositiveSmallIntegerField(choices=[(2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], verbose_name='Ano'), - ), - migrations.AlterField( - model_name='protocolo', - name='ano', - field=models.PositiveSmallIntegerField(choices=[(2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], verbose_name='Ano do Protocolo'), - ), - ] diff --git a/sapl/protocoloadm/migrations/0011_auto_20160318_1504.py b/sapl/protocoloadm/migrations/0011_auto_20160318_1504.py deleted file mode 100644 index e887fafb5..000000000 --- a/sapl/protocoloadm/migrations/0011_auto_20160318_1504.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-03-18 18:04 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('protocoloadm', '0010_auto_20160309_1407'), - ] - - operations = [ - migrations.AlterField( - model_name='protocolo', - name='justificativa_anulacao', - field=models.CharField(blank=True, max_length=60, verbose_name='Motivo'), - ), - ] diff --git a/sapl/protocoloadm/migrations/0012_auto_20160503_0926.py b/sapl/protocoloadm/migrations/0012_auto_20160503_0926.py deleted file mode 100644 index cc7da204c..000000000 --- a/sapl/protocoloadm/migrations/0012_auto_20160503_0926.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9.5 on 2016-05-03 12:26 -from __future__ import unicode_literals - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('protocoloadm', '0011_auto_20160318_1504'), - ] - - operations = [ - migrations.AlterField( - model_name='tramitacaoadministrativo', - name='unidade_tramitacao_destino', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='adm_tramitacoes_destino', to='materia.UnidadeTramitacao', verbose_name='Unidade Destino'), - ), - migrations.AlterField( - model_name='tramitacaoadministrativo', - name='unidade_tramitacao_local', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='adm_tramitacoes_origem', to='materia.UnidadeTramitacao', verbose_name='Unidade Local'), - ), - ] diff --git a/sapl/protocoloadm/migrations/0012_tipoinstituicao.py b/sapl/protocoloadm/migrations/0012_tipoinstituicao.py deleted file mode 100644 index 91884018a..000000000 --- a/sapl/protocoloadm/migrations/0012_tipoinstituicao.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9.5 on 2016-05-17 18:07 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('protocoloadm', '0011_auto_20160318_1504'), - ] - - operations = [ - migrations.CreateModel( - name='TipoInstituicao', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('descricao', models.CharField(max_length=50, verbose_name='Descrição')), - ], - options={ - 'verbose_name': 'Tipo de Instituição', - 'verbose_name_plural': 'Tipos de Instituições', - }, - ), - ] diff --git a/sapl/protocoloadm/models.py b/sapl/protocoloadm/models.py index 4d5c0b248..013ba89e2 100644 --- a/sapl/protocoloadm/models.py +++ b/sapl/protocoloadm/models.py @@ -167,16 +167,12 @@ class StatusTramitacaoAdministrativo(models.Model): class TramitacaoAdministrativo(models.Model): status = models.ForeignKey( StatusTramitacaoAdministrativo, - blank=True, - null=True, verbose_name=_('Status')) documento = models.ForeignKey(DocumentoAdministrativo) data_tramitacao = models.DateField( - blank=True, null=True, verbose_name=_('Data Tramitação')) + verbose_name=_('Data Tramitação')) unidade_tramitacao_local = models.ForeignKey( UnidadeTramitacao, - blank=True, - null=True, related_name='adm_tramitacoes_origem', verbose_name=_('Unidade Local')) data_encaminhamento = models.DateField( @@ -187,7 +183,6 @@ class TramitacaoAdministrativo(models.Model): null=True, related_name='adm_tramitacoes_destino', verbose_name=_('Unidade Destino')) - ultima = models.BooleanField() texto = models.TextField( blank=True, verbose_name=_('Texto da Ação')) data_fim_prazo = models.DateField( diff --git a/sapl/protocoloadm/urls.py b/sapl/protocoloadm/urls.py index 5f6feb538..ea978ba1b 100644 --- a/sapl/protocoloadm/urls.py +++ b/sapl/protocoloadm/urls.py @@ -22,13 +22,8 @@ from sapl.protocoloadm.views import (AnularProtocoloAdmView, ProtocoloPesquisaView, StatusTramitacaoAdministrativoCrud, TipoDocumentoAdministrativoCrud, - TipoInstituicaoCrud, - TramitacaoAdmDeleteView, - TramitacaoAdmEditView, - TramitacaoAdmIncluirView, - TramitacaoAdministrativoCrud, - TramitacaoAdmView, get_nome_autor, - pesquisa_autores) + TipoInstituicaoCrud, TramitacaoAdmCrud, + get_nome_autor, pesquisa_autores) from .apps import AppConfig @@ -36,7 +31,8 @@ app_name = AppConfig.name urlpatterns = [ url(r'^protocoloadm/docadm/', - include(DocumentoAdministrativoCrud.get_urls())), + include(DocumentoAdministrativoCrud.get_urls() + + TramitacaoAdmCrud.get_urls())), url(r'^protocoloadm/tipo-documento-adm/', include(TipoDocumentoAdministrativoCrud.get_urls())), url(r'^protocoloadm/doc-acessorio/', @@ -45,8 +41,6 @@ urlpatterns = [ include(StatusTramitacaoAdministrativoCrud.get_urls())), url(r'^protocoloadm/tipo-instituicao/', include(TipoInstituicaoCrud.get_urls())), - url(r'^protocoloadm/tramitacao-adm/', - include(TramitacaoAdministrativoCrud.get_urls())), url(r'^protocoloadm/protocolo-doc/', include(ProtocoloDocumentoCrud.get_urls())), url(r'^protocoloadm/protocolo-mat/', @@ -73,14 +67,6 @@ urlpatterns = [ DocumentoAcessorioAdministrativoEditView.as_view(), name='doc_ace_adm_edit'), - url(r'^protocoloadm/(?P\d+)/tramitacao$', - TramitacaoAdmView.as_view(), name='tramitacao_adm'), - url(r'^protocoloadm/(?P\d+)/tramitacao_incluir', - TramitacaoAdmIncluirView.as_view(), name='tramitacao_incluir'), - url(r'^protocoloadm/(?P\d+)/tramitacao_edit', - TramitacaoAdmEditView.as_view(), name='tramitacao_edit'), - url(r'^protocoloadm/(?P\d+)/tramitacao_delete/(?P\d+)', - TramitacaoAdmDeleteView.as_view(), name='tramitacao_delete'), url(r'^protocoloadm/(?P\d+)/(?P\d+)/comprovante$', ComprovanteProtocoloView.as_view(), name='comprovante_protocolo'), diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py index da00163c1..86fe97d93 100644 --- a/sapl/protocoloadm/views.py +++ b/sapl/protocoloadm/views.py @@ -13,9 +13,11 @@ from django.views.generic import CreateView, DetailView, FormView, ListView from django.views.generic.base import TemplateView from django_filters.views import FilterView +import sapl.crud.base from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView, CrudDeleteView, CrudListView, CrudUpdateView, make_pagination) +from sapl.crud.masterdetail import MasterDetailCrud from sapl.materia.models import Proposicao, TipoMateriaLegislativa from sapl.utils import (create_barcode, get_client_ip, permissoes_adm, permissoes_protocoloadm) @@ -24,7 +26,8 @@ from .forms import (AnularProcoloAdmForm, DocumentoAcessorioAdministrativoForm, DocumentoAdministrativoFilterSet, DocumentoAdministrativoForm, ProposicaoSimpleForm, ProtocoloDocumentForm, ProtocoloFilterSet, - ProtocoloMateriaForm, TramitacaoAdmForm) + ProtocoloMateriaForm, TramitacaoAdmEditForm, + TramitacaoAdmForm) from .models import (Autor, DocumentoAcessorioAdministrativo, DocumentoAdministrativo, Protocolo, StatusTramitacaoAdministrativo, @@ -32,16 +35,33 @@ from .models import (Autor, DocumentoAcessorioAdministrativo, TramitacaoAdministrativo) TipoDocumentoAdministrativoCrud = Crud.build(TipoDocumentoAdministrativo, '') -DocumentoAdministrativoCrud = Crud.build(DocumentoAdministrativo, '') DocumentoAcessorioAdministrativoCrud = Crud.build( DocumentoAcessorioAdministrativo, '') -TramitacaoAdministrativoCrud = Crud.build(TramitacaoAdministrativo, '') ProtocoloDocumentoCrud = Crud.build(Protocolo, '') # FIXME precisa de uma chave diferente para o layout ProtocoloMateriaCrud = Crud.build(Protocolo, '') TipoInstituicaoCrud = Crud.build(TipoInstituicao, '') +class DocumentoAdministrativoCrud(Crud): + model = DocumentoAdministrativo + help_path = '' + + class BaseMixin(sapl.crud.base.CrudBaseMixin): + list_field_names = ['tipo', 'numero', 'ano', 'data', + 'numero_protocolo', 'assunto', + 'interessado', 'tramitacao', 'texto_integral'] + + class CreateView(PermissionRequiredMixin, CrudCreateView): + permission_required = permissoes_adm() + + class UpdateView(PermissionRequiredMixin, CrudUpdateView): + permission_required = permissoes_adm() + + class DeleteView(PermissionRequiredMixin, CrudDeleteView): + permission_required = permissoes_adm() + + class StatusTramitacaoAdministrativoCrud(Crud): model = StatusTramitacaoAdministrativo help_path = '' @@ -582,94 +602,30 @@ class DocumentoAcessorioAdministrativoView(PermissionRequiredMixin, FormView): return reverse('sapl.protocoloadm:doc_ace_adm', kwargs={'pk': pk}) -class TramitacaoAdmView(PermissionRequiredMixin, FormView): - template_name = "protocoloadm/tramitacao.html" - permission_required = permissoes_adm() - - def get(self, request, *args, **kwargs): - - pk = kwargs['pk'] - documento = DocumentoAdministrativo.objects.get(id=pk) - tramitacoes = TramitacaoAdministrativo.objects.filter( - documento=documento).order_by('-data_tramitacao') - - return self.render_to_response({'documento': documento, - 'tramitacoes': tramitacoes}) - - -class TramitacaoAdmIncluirView(PermissionRequiredMixin, FormView): - template_name = "protocoloadm/tramitacao_incluir.html" - permission_required = permissoes_adm() - - def get(self, request, *args, **kwargs): - pk = kwargs['pk'] - documento = DocumentoAdministrativo.objects.get(id=pk) - data = {'documento': documento} - form = TramitacaoAdmForm(initial=data) - - return self.render_to_response({'documento': documento, 'form': form}) - - def post(self, request, *args, **kwargs): - pk = kwargs['pk'] - form = TramitacaoAdmForm(request.POST or None) - - if form.is_valid(): - tramitacao = form.save(commit=False) - tramitacao.ultima = False - tramitacao.save() - return HttpResponseRedirect(reverse( - 'sapl.protocoloadm:tramitacao_adm', kwargs={'pk': pk})) - else: - return self.form_invalid(form) - - -class TramitacaoAdmEditView(PermissionRequiredMixin, FormView): - - template_name = "protocoloadm/tramitacao_edit.html" - permission_required = permissoes_adm() - - def get(self, request, *args, **kwargs): - pk = kwargs['pk'] - tramitacao = TramitacaoAdministrativo.objects.get(id=pk) - documento = tramitacao.documento - form = TramitacaoAdmForm(instance=tramitacao) - - return self.render_to_response({'documento': documento, 'form': form}) - - def post(self, request, *args, **kwargs): - pk = kwargs['pk'] - tramitacao = TramitacaoAdministrativo.objects.get(id=pk) - form = TramitacaoAdmForm(request.POST, instance=tramitacao) - - if form.is_valid(): - tramitacao = form.save(commit=False) - tramitacao.ultima = False - tramitacao.save() - return HttpResponseRedirect( - reverse('sapl.protocoloadm:tramitacao_adm', - kwargs={'pk': tramitacao.documento.id})) - else: - return self.form_invalid(form) - - -class TramitacaoAdmDeleteView(PermissionRequiredMixin, DetailView): +class TramitacaoAdmCrud(MasterDetailCrud): + model = TramitacaoAdministrativo + parent_field = 'documento' + help_path = '' - template_name = "protocoloadm/tramitacao.html" - permission_required = permissoes_adm() + class BaseMixin(MasterDetailCrud.BaseMixin): + list_field_names = ['data_tramitacao', 'unidade_tramitacao_local', + 'unidade_tramitacao_destino', 'status'] - def get(self, request, *args, **kwargs): - pk = kwargs['pk'] - oid = kwargs['oid'] + class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView): + form_class = TramitacaoAdmForm + permission_required = permissoes_adm() - documento = DocumentoAdministrativo.objects.get(id=pk) + class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView): + form_class = TramitacaoAdmEditForm + permission_required = permissoes_adm() - tramitacao = TramitacaoAdministrativo.objects.get(id=oid) - tramitacao.delete() - tramitacoes = TramitacaoAdministrativo.objects.filter( - documento=documento) + class ListView(PermissionRequiredMixin, MasterDetailCrud.ListView): + permission_required = permissoes_adm() - return self.render_to_response({'documento': documento, - 'tramitacoes': tramitacoes}) + 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('-id') def get_nome_autor(request): diff --git a/sapl/settings.py b/sapl/settings.py index fb7fc4bb9..3c28078b3 100644 --- a/sapl/settings.py +++ b/sapl/settings.py @@ -130,6 +130,7 @@ EMAIL_PORT = config('EMAIL_PORT', cast=int, default=587) EMAIL_HOST_USER = config('EMAIL_HOST_USER', default='') EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD', default='') EMAIL_USE_TLS = config('EMAIL_USE_TLS', cast=bool, default=True) +EMAIL_SEND_USER = config('EMAIL_SEND_USER', cast=str, default='') MAX_DOC_UPLOAD_SIZE = 5 * 1024 * 1024 # 5MB MAX_IMAGE_UPLOAD_SIZE = 2 * 1024 * 1024 # 2MB diff --git a/sapl/templates/base.html b/sapl/templates/base.html index 05eba9d86..183ddab50 100644 --- a/sapl/templates/base.html +++ b/sapl/templates/base.html @@ -60,12 +60,20 @@ - + + + + +