Browse Source

Merge pull request #440 from interlegis/312-crud-proposição

Fix #312 crud proposição
pull/445/head
Eduardo Edson Batista Cordeiro Alves 9 years ago
parent
commit
87d83484ea
  1. 64
      materia/forms.py
  2. 19
      materia/layouts.yaml
  3. 5
      materia/tests/test_materia.py
  4. 8
      materia/tests/test_materia_urls.py
  5. 11
      materia/urls.py
  6. 204
      materia/views.py
  7. 4
      parlamentares/views.py
  8. 2
      templates/base.html
  9. 40
      templates/materia/proposicao/proposicao_list.html
  10. 14
      templates/materia/proposicao_detail.html
  11. 0
      templates/materia/proposicao_form.html

64
materia/forms.py

@ -1,6 +1,8 @@
from datetime import datetime
import django_filters
from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML, Button, Column, Fieldset, Layout, Submit
from crispy_forms.layout import HTML, Button, Column, Fieldset, Layout
from django import forms
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.db import models
@ -52,43 +54,33 @@ class ProposicaoForm(ModelForm):
raise ValidationError("Arquivo muito grande. ( > 5mb )")
return texto_original
class Meta:
model = Proposicao
fields = ['tipo', 'data_envio', 'descricao', 'texto_original']
def clean_data_envio(self):
data_envio = self.cleaned_data.get('data_envio')
if (not data_envio) and bool(self.initial):
data_envio = datetime.now()
return data_envio
def __init__(self, excluir=False, *args, **kwargs):
more = []
if excluir:
more = [Submit('Excluir', 'Excluir')]
def clean(self):
cleaned_data = self.cleaned_data
if 'tipo' in cleaned_data:
if cleaned_data['tipo'].descricao == 'Parecer':
try:
materia = MateriaLegislativa.objects.get(
tipo_id=cleaned_data['tipo_materia'],
ano=cleaned_data['ano_materia'],
numero=cleaned_data['numero_materia'])
except ObjectDoesNotExist:
msg = _('Matéria adicionada não existe!')
raise ValidationError(msg)
else:
cleaned_data['materia'] = materia
cleaned_data['autor'] = materia.autoria_set.first().autor
row1 = crispy_layout_mixin.to_row(
[('tipo', 8), ('data_envio', 4)])
row2 = crispy_layout_mixin.to_row(
[('descricao', 12)])
row3 = crispy_layout_mixin.to_row(
[('tipo_materia', 4), ('numero_materia', 4), ('ano_materia', 4)])
row4 = crispy_layout_mixin.to_row(
[('texto_original', 12)])
return cleaned_data
self.helper = FormHelper()
self.helper.layout = Layout(
Fieldset(_('Incluir Proposição'),
row1, row2, row3, row4,
HTML("""
<div class="img-responsive" width="225" height="300"
src="{{ MEDIA_URL }}{{ form.texto_original.value }}">
<br /><br />
<input type="submit"
name="remover-texto"
id="remover-texto"
class="btn btn-warning"
value="Remover Texto"/>
<p></p>
""", ),
form_actions(more=more))
)
super(ProposicaoForm, self).__init__(
*args, **kwargs)
class Meta:
model = Proposicao
fields = ['tipo', 'data_envio', 'descricao', 'texto_original']
class AcompanhamentoMateriaForm(ModelForm):
@ -121,8 +113,6 @@ class DocumentoAcessorioForm(ModelForm):
fields = ['tipo', 'nome', 'data', 'autor', 'ementa', 'arquivo']
widgets = {'autor': forms.HiddenInput()}
widgets = {'autor': forms.HiddenInput()}
def clean_autor(self):
autor_field = self.cleaned_data['autor']
try:

19
materia/layouts.yaml

@ -87,12 +87,23 @@ TipoProposicao:
- materia_ou_documento tipo_documento
- modelo
ProposicaoCreate:
Proposição:
- tipo data_envio
- descricao
Materia:
- tipo_materia numero_materia ano_materia
Complemento:
- texto_original
Proposicao:
Proposição:
- tipo dat_criacao_FIXME data_recebimento
- descricao_FIXME
- tip_id_basica_FIXME num_ident_basica_FIXME ano_ident_basica_FIXME
- nom_arquivo_FIXME modelo_FIXME
- tipo data_envio
- descricao
Materia:
- materia
Complemento:
- texto_original
StatusTramitacao:
Status Tramitação:

5
materia/tests/test_materia.py

@ -416,7 +416,7 @@ def test_form_errors_relatoria(client):
@pytest.mark.django_db(transaction=False)
def test_proposicao_submit(client):
response = client.post(reverse('materia:adicionar_proposicao'),
response = client.post(reverse('materia:proposicao_create'),
{'tipo': mommy.make(TipoProposicao, pk=3).pk,
'descricao': 'Teste proposição',
'salvar': 'salvar'},
@ -432,10 +432,9 @@ def test_proposicao_submit(client):
@pytest.mark.django_db(transaction=False)
def test_form_errors_proposicao(client):
response = client.post(reverse('materia:adicionar_proposicao'),
response = client.post(reverse('materia:proposicao_create'),
{'salvar': 'salvar'},
follow=True)
assert (response.context_data['form'].errors['tipo'] ==
['Este campo é obrigatório.'])
assert (response.context_data['form'].errors['descricao'] ==

8
materia/tests/test_materia_urls.py

@ -9,11 +9,11 @@ from django.core.urlresolvers import reverse
('materia:tramitacao_update',
{'pk': '8'},
'/materia/tramitacao/8/edit'),
('materia:adicionar_proposicao', {}, '/materia/proposicao'),
('materia:editar_proposicao',
('materia:proposicao_create', {}, '/proposicao/create'),
('materia:proposicao_update',
{'pk': '3'},
'/materia/proposicao/3/edit'),
('materia:list_proposicao', {}, '/materia/proposicao_list'),
'/proposicao/3/edit'),
('materia:proposicao_list', {}, '/proposicao/'),
])
def test_reverse(test_input, kwargs, expected):
assert reverse(test_input, kwargs=kwargs) == expected

11
materia/urls.py

@ -8,8 +8,7 @@ from materia.views import (AcompanhamentoConfirmarView,
MateriaLegislativaCrud,
MateriaLegislativaPesquisaView, MateriaTaView,
NumeracaoCrud, OrgaoCrud, OrigemCrud,
ProposicaoEditView, ProposicaoListView,
ProposicaoTaView, ProposicaoView,
ProposicaoCrud, ProposicaoTaView,
RegimeTramitacaoCrud, RelatoriaCrud,
StatusTramitacaoCrud, TipoAutorCrud,
TipoDocumentoCrud, TipoFimRelatoriaCrud,
@ -31,6 +30,8 @@ urlpatterns = [
RelatoriaCrud.get_urls() +
DocumentoAcessorioCrud.get_urls())),
url(r'proposicao/', include(ProposicaoCrud.get_urls())),
# Integração com Compilação
url(r'^materia/(?P<pk>[0-9]+)/ta$',
MateriaTaView.as_view(), name='materia_ta'),
@ -55,12 +56,6 @@ urlpatterns = [
url(r'^sistema/materia/status-tramitacao/',
include(StatusTramitacaoCrud.get_urls())),
url(r'^sistema/materia/orgao/', include(OrgaoCrud.get_urls())),
url(r'^materia/proposicao$',
ProposicaoView.as_view(), name='adicionar_proposicao'),
url(r'^materia/proposicao_list$',
ProposicaoListView.as_view(), name='list_proposicao'),
url(r'^materia/proposicao/(?P<pk>[0-9]+)/edit$',
ProposicaoEditView.as_view(), name='editar_proposicao'),
url(r'^materia/pesquisar-materia$',
MateriaLegislativaPesquisaView.as_view(), name='pesquisar_materia'),
url(r'^materia/(?P<pk>\d+)/acompanhar-materia/$',

204
materia/views.py

@ -1,7 +1,7 @@
import os
from datetime import datetime
from random import choice
from string import ascii_letters, digits
from crispy_layout_mixin import form_actions
from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML, Button
@ -10,10 +10,9 @@ from django.core.exceptions import 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.translation import ugettext_lazy as _
from django.views.generic import CreateView, ListView, TemplateView, UpdateView
from django.views.generic import CreateView, TemplateView, UpdateView
from django_filters.views import FilterView
import crispy_layout_mixin
@ -53,11 +52,58 @@ TipoAutorCrud = Crud.build(TipoAutor, 'tipo_autor')
AutorCrud = Crud.build(Autor, 'autor')
OrgaoCrud = Crud.build(Orgao, 'orgao')
TipoProposicaoCrud = Crud.build(TipoProposicao, 'tipo_proposicao')
ProposicaoCrud = Crud.build(Proposicao, '')
StatusTramitacaoCrud = Crud.build(StatusTramitacao, 'status_tramitacao')
UnidadeTramitacaoCrud = Crud.build(UnidadeTramitacao, 'unidade_tramitacao')
class ProposicaoCrud(Crud):
model = Proposicao
help_path = ''
class BaseMixin(crud.base.CrudBaseMixin):
list_field_names = ['data_envio', 'descricao', 'tipo']
class CreateView(crud.base.CrudCreateView):
form_class = ProposicaoForm
@property
def layout_key(self):
return 'ProposicaoCreate'
class UpdateView(crud.base.CrudUpdateView):
form_class = ProposicaoForm
@property
def layout_key(self):
return 'ProposicaoCreate'
class ListView(crud.base.CrudListView):
ordering = ['-data_envio', 'descricao']
def get_rows(self, object_list):
for obj in object_list:
if obj.data_envio is None:
obj.data_envio = 'Em elaboração...'
return [self._as_row(obj) for obj in object_list]
class DeleteView(MasterDetailCrud.DeleteView):
def delete(self, request, *args, **kwargs):
proposicao = Proposicao.objects.get(id=self.kwargs['pk'])
if not proposicao.data_envio:
proposicao.delete()
return HttpResponseRedirect(reverse('materia:proposicao_list'))
else:
proposicao.data_envio = None
proposicao.save()
return HttpResponseRedirect(
reverse('materia:proposicao_detail',
kwargs={'pk': proposicao.pk}))
class RelatoriaCrud(MasterDetailCrud):
model = Relatoria
parent_field = 'materia'
@ -325,6 +371,42 @@ class MateriaLegislativaCrud(Crud):
list_field_names = ['tipo', 'numero', 'ano', 'data_apresentacao']
class DocumentoAcessorioView(CreateView):
template_name = "materia/documento_acessorio.html"
form_class = DocumentoAcessorioForm
def get(self, request, *args, **kwargs):
materia = MateriaLegislativa.objects.get(id=kwargs['pk'])
docs = DocumentoAcessorio.objects.filter(
materia_id=kwargs['pk']).order_by('data')
form = DocumentoAcessorioForm()
return self.render_to_response(
{'object': materia,
'form': form,
'docs': docs})
def post(self, request, *args, **kwargs):
form = self.get_form()
materia = MateriaLegislativa.objects.get(id=kwargs['pk'])
docs_list = DocumentoAcessorio.objects.filter(
materia_id=kwargs['pk'])
if form.is_valid():
documento_acessorio = form.save(commit=False)
documento_acessorio.materia = materia
documento_acessorio.save()
return self.form_valid(form)
else:
return self.render_to_response({'form': form,
'object': materia,
'docs': docs_list})
def get_success_url(self):
pk = self.kwargs['pk']
return reverse('materia:documento_acessorio', kwargs={'pk': pk})
class AcompanhamentoConfirmarView(TemplateView):
def get_redirect_url(self):
@ -556,27 +638,6 @@ def do_envia_email_tramitacao(request, materia):
return None
class ProposicaoListView(ListView):
template_name = "materia/proposicao/proposicao_list.html"
paginate_by = 10
model = Proposicao
def get_queryset(self):
return Proposicao.objects.all().order_by('data_envio',
'tipo',
'descricao')
def get_context_data(self, **kwargs):
context = super(ProposicaoListView, self).get_context_data(**kwargs)
paginator = context['paginator']
page_obj = context['page_obj']
context['page_range'] = make_pagination(
page_obj.number, paginator.num_pages)
return context
class MateriaLegislativaPesquisaView(FilterView):
model = MateriaLegislativa
filterset_class = MateriaLegislativaFilterSet
@ -651,99 +712,6 @@ class MateriaLegislativaPesquisaView(FilterView):
return self.render_to_response(context)
class ProposicaoView(CreateView):
template_name = "materia/proposicao/proposicao.html"
form_class = ProposicaoForm
def get_success_url(self):
return reverse('materia:list_proposicao')
def get(self, request, *args, **kwargs):
return self.render_to_response({'form': self.get_form()})
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
proposicao = form.save(commit=False)
tipo = TipoProposicao.objects.get(id=form.data['tipo'])
if tipo.descricao == 'Parecer':
try:
materia = MateriaLegislativa.objects.get(
tipo_id=int(form.data['tipo_materia']),
ano=int(form.data['ano_materia']),
numero=int(form.data['numero_materia']))
except ObjectDoesNotExist:
msg = _('Matéria adicionada não existe!')
messages.add_message(request, messages.INFO, msg)
return self.render_to_response({'form': form})
else:
proposicao.autor = materia.autoria_set.first().autor
proposicao.materia = materia
proposicao.save()
return redirect(self.get_success_url())
else:
return self.render_to_response({'form': form})
class ProposicaoEditView(CreateView):
template_name = "materia/proposicao/proposicao.html"
form_class = ProposicaoForm
def get_success_url(self):
return reverse('materia:list_proposicao')
def get(self, request, *args, **kwargs):
proposicao = Proposicao.objects.get(id=kwargs['pk'])
return self.render_to_response({'form': ProposicaoForm(
excluir=True,
instance=proposicao)})
def post(self, request, *args, **kwargs):
form = self.get_form()
proposicao = Proposicao.objects.get(id=kwargs['pk'])
if form.is_valid():
if 'Excluir' in request.POST:
if proposicao.data_envio:
proposicao.data_envio = None
proposicao.save()
else:
proposicao.delete()
if 'salvar' or "remover-foto" in request.POST:
if 'texto_original' in request.FILES:
# if os.unlink(proposicao.texto_original.path):
# proposicao.texto_original = None
proposicao.texto_original = request.FILES['texto_original']
tipo = TipoProposicao.objects.get(id=form.data['tipo'])
proposicao.tipo = tipo
proposicao.descricao = form.data['descricao']
if tipo.descricao == 'Parecer':
try:
materia = MateriaLegislativa.objects.get(
tipo_id=int(form.data['tipo_materia']),
ano=int(form.data['ano_materia']),
numero=int(form.data['numero_materia']))
except ObjectDoesNotExist:
msg = _('Matéria adicionada não existe!')
messages.add_message(request, messages.INFO, msg)
return self.render_to_response({'form': form})
else:
proposicao.autor = materia.autoria_set.first().autor
proposicao.materia = materia
if not proposicao.data_envio:
proposicao.data_envio = datetime.now()
if "remover-texto" in request.POST:
try:
os.unlink(proposicao.texto_original.path)
except OSError:
pass # Should log this error!!!!!
proposicao.texto_original = None
proposicao.save()
return redirect(self.get_success_url())
else:
return self.render_to_response({'form': form})
class MateriaTaView(IntegracaoTaView):
model = MateriaLegislativa
model_type_foreignkey = TipoMateriaLegislativa

4
parlamentares/views.py

@ -88,8 +88,8 @@ class ParlamentarCrud(Crud):
def get_rows(self, object_list):
parlamentares = []
for m in object_list:
ultima_filiacao = m.parlamentar.filiacao_set.\
order_by('-data').first()
ultima_filiacao = m.parlamentar.filiacao_set.order_by(
'-data').first()
if ultima_filiacao and not ultima_filiacao.data_desfiliacao:
partido = ultima_filiacao.partido.sigla
else:

2
templates/base.html

@ -67,7 +67,7 @@
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Atividade Legislativa <span class="caret"></span></a>
<ul class="dropdown-menu">
<li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'materia:list_proposicao' %}">Proposições</a></li>
<li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'materia:proposicao_list' %}">Proposições</a></li>
<li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'materia:materialegislativa_list' %}">Matérias Legislativas</a></li>
<li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'sessao:sessaoplenaria_list' %}">Sessões Plenárias</a></li>
<li class="nav__sub-item"><a class="nav__sub-link" href="{% url 'sessao:list_pauta_sessao' %}">Pautas das Sessões</a></li>

40
templates/materia/proposicao/proposicao_list.html

@ -1,40 +0,0 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block actions %}<!-- Remvoer botões 'Editar' e 'Excluir' -->{% endblock %}
{% block sections_nav %}
{% endblock %}
{% block detail_content %}
<h2><b>Proposições</b></h2>
<div class="actions btn-group pull-right" role="group">
<a href="{% url 'materia:adicionar_proposicao' %}" class="btn btn-default">Nova Proposição</a>
</div>
<table class="table table-striped table-bordered">
<thead class="thead-default">
<tr>
<th>Enviada em</th>
<th>Tipo</th>
<th>Descrição</th>
<th>Incorporada?</th>
</tr>
</thead>
{% for proposicao in page_obj %}
<tr>
{% if proposicao.data_envio %}
<td><a href="{% url 'materia:editar_proposicao' proposicao.id %}"><b>{{ proposicao.data_envio|date:'d/m/Y H:i' }}</b></a></td>
{% else %}
<td><a href="{% url 'materia:editar_proposicao' proposicao.id %}"><b>Em elaboração...</b></a></td>
{% endif %}
<td>{{ proposicao.tipo }}</td>
<td>{{ proposicao.descricao|safe }}</td>
<td>{% if proposicao.materia %} Sim {% else %} Não {% endif %}</td>
</tr>
{% endfor %}
</table>
{% include "paginacao.html" %}
{% endblock %}

14
templates/materia/proposicao_detail.html

@ -0,0 +1,14 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% block actions %}
<div class="actions btn-group pull-right" role="group">
{% if proposicao.data_envio %}
<a href="{{ view.update_url }}" class="btn btn-default">{% trans 'Editar Proposição' %}</a>
<a href="{{ view.delete_url }}" class="btn btn-default">{% trans 'Retornar Proposição Enviada' %}</a>
{% else %}
<a href="{{ view.update_url }}" class="btn btn-default">{% trans 'Enviar/Editar Proposição' %}</a>
<a href="{{ view.delete_url }}" class="btn btn-default">{% trans 'Excluir Proposição' %}</a>
{% endif %}
</div>
{% endblock actions %}

0
templates/materia/proposicao/proposicao.html → templates/materia/proposicao_form.html

Loading…
Cancel
Save