diff --git a/comissoes/forms.py b/comissoes/forms.py index fcd23936a..a3e637e1a 100644 --- a/comissoes/forms.py +++ b/comissoes/forms.py @@ -8,100 +8,7 @@ import crispy_layout_mixin from crispy_layout_mixin import form_actions from parlamentares.models import Filiacao -from .models import Comissao, Participacao - - -class CadastrarComissaoForm(ModelForm): - - class Meta: - - model = Comissao - fields = ['nome', - 'tipo', - 'sigla', - 'data_criacao', - 'data_extincao', - 'unidade_deliberativa', - - 'local_reuniao', - 'agenda_reuniao', - 'telefone_reuniao', - 'endereco_secretaria', - 'telefone_secretaria', - 'fax_secretaria', - 'secretario', - 'email', - 'finalidade', - - 'apelido_temp', - 'data_instalacao_temp', - 'data_final_prevista_temp', - 'data_prorrogada_temp', - 'data_fim_comissao'] - - def __init__(self, *args, **kwargs): - - row1 = crispy_layout_mixin.to_row( - [('nome', 8), - ('sigla', 4)]) - - row2 = crispy_layout_mixin.to_row( - [('tipo', 3), - ('data_criacao', 3), - ('unidade_deliberativa', 3), - ('data_extincao', 3)]) - - row3 = crispy_layout_mixin.to_row( - [('local_reuniao', 4), - ('agenda_reuniao', 4), - ('telefone_reuniao', 4)]) - - row4 = crispy_layout_mixin.to_row( - [('endereco_secretaria', 4), - ('telefone_secretaria', 4), - ('fax_secretaria', 4)]) - - row5 = crispy_layout_mixin.to_row( - [('secretario', 6), - ('email', 6)]) - - row6 = crispy_layout_mixin.to_row( - [('finalidade', 12)]) - - row7 = crispy_layout_mixin.to_row( - [('apelido_temp', 9), - ('data_instalacao_temp', 3)]) - - row8 = crispy_layout_mixin.to_row( - [('data_final_prevista_temp', 4), - ('data_prorrogada_temp', 4), - ('data_fim_comissao', 4)]) - - self.helper = FormHelper() - self.helper.layout = Layout( - Fieldset( - _('Cadastrar Comissão'), - Fieldset( - _('Dados Básicos'), - row1, - row2 - ), - Fieldset( - _('Dados Complementares'), - row3, - row4, - row5, - row6 - ), - Fieldset( - 'Temporária', - row7, - row8 - ), - form_actions() - ) - ) - super(CadastrarComissaoForm, self).__init__(*args, **kwargs) +from .models import Participacao class ComposicaoForm(forms.Form): diff --git a/comissoes/layouts.yaml b/comissoes/layouts.yaml index 43d9b0068..3a2d38a08 100644 --- a/comissoes/layouts.yaml +++ b/comissoes/layouts.yaml @@ -14,12 +14,12 @@ TipoComissao: Comissao: Dados Básicos: - - nome:9 sigla - - tipo data_criacao unidade_deliberativa data_extincao + - nome:8 sigla + - tipo data_criacao unidade_deliberativa data_extincao Dados Complementares: - - local_reuniao agenda_reuniao telefone_reuniao + - local_reuniao agenda_reuniao telefone_reuniao - endereco_secretaria telefone_secretaria fax_secretaria - - secretario:4 email + - secretario email - finalidade Temporária: - apelido_temp:8 data_instalacao_temp diff --git a/comissoes/test_comissoes.py b/comissoes/test_comissoes.py index 5b4c60e76..665146d35 100644 --- a/comissoes/test_comissoes.py +++ b/comissoes/test_comissoes.py @@ -96,7 +96,7 @@ def test_incluir_comissao_submit(client): sigla='T', nome='Teste') - response = client.post(reverse('comissoes:cadastrar_comissao'), + response = client.post(reverse('comissoes:comissao_create'), {'tipo': tipo.pk, 'nome': 'Comissão Teste', 'sigla': 'CT', @@ -113,7 +113,7 @@ def test_incluir_comissao_submit(client): @pytest.mark.django_db(transaction=False) def test_incluir_comissao_errors(client): - response = client.post(reverse('comissoes:cadastrar_comissao'), + response = client.post(reverse('comissoes:comissao_create'), {'salvar': 'salvar'}, follow=True) diff --git a/comissoes/urls.py b/comissoes/urls.py index 6a7e44ef4..edefa5efd 100644 --- a/comissoes/urls.py +++ b/comissoes/urls.py @@ -1,42 +1,33 @@ from django.conf.urls import include, url -from comissoes.views import (CadastrarComissaoView, CargoCrud, ComissaoCrud, +from comissoes.views import (CargoCrud, ComissaoCrud, ComissaoParlamentarEditView, ComissaoParlamentarIncluirView, ComposicaoView, - MateriasTramitacaoListView, MateriasView, - PeriodoComposicaoCrud, ReunioesView, + MateriasTramitacaoListView, PeriodoComposicaoCrud, TipoComissaoCrud) from .apps import AppConfig app_name = AppConfig.name -comissao_url_patterns = ComissaoCrud.get_urls() + [ - url(r'^(?P\d+)/composicao$', +urlpatterns = [ + url(r'^comissao/', include(ComissaoCrud.get_urls())), + + url(r'^comissao/(?P\d+)/composicao$', ComposicaoView.as_view(), name='composicao'), - url(r'^(?P\d+)/materias-em-tramitacao$', + url(r'^comissao/(?P\d+)/materias-em-tramitacao$', MateriasTramitacaoListView.as_view(), name='materias_em_tramitacao'), - url(r'^(?P\d+)/composicao/(?P\d+)/parlamentar$', + + url(r'^comissao/(?P\d+)/composicao/(?P\d+)/parlamentar$', ComissaoParlamentarIncluirView.as_view(), name='comissao_parlamentar'), - url(r'^(?P\d+)/composicao/(?P\d+)/parlamentar/(?P\d+)/edit$', + url(r'''^comissao/(?P\d+)/composicao/(?P\d+)/ + parlamentar/(?P\d+)/edit$''', ComissaoParlamentarEditView.as_view(), name='comissao_parlamentar_edit'), - url(r'^(?P\d+)/materias$', - MateriasView.as_view(), name='materias'), - url(r'^(?P\d+)/reunioes$', - ReunioesView.as_view(), name='reunioes'), - url(r'^cadastrar-comissao$', - CadastrarComissaoView.as_view(), name='cadastrar_comissao'), -] - -app_name = AppConfig.name - -urlpatterns = [ - url(r'^comissoes/', include(comissao_url_patterns)), - url(r'^sistema/comissoes/cargo/', include(CargoCrud.get_urls())), - url(r'^sistema/comissoes/periodo-composicao/', + url(r'^sistema/comissao/cargo/', include(CargoCrud.get_urls())), + url(r'^sistema/comissao/periodo-composicao/', include(PeriodoComposicaoCrud.get_urls())), - url(r'^sistema/comissoes/tipo/', include(TipoComissaoCrud.get_urls())), + url(r'^sistema/comissao/tipo/', include(TipoComissaoCrud.get_urls())), ] diff --git a/comissoes/views.py b/comissoes/views.py index 5eefa208f..88ca097f0 100644 --- a/comissoes/views.py +++ b/comissoes/views.py @@ -1,27 +1,28 @@ from django.contrib import messages -from django.core.urlresolvers import reverse, reverse_lazy +from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ -from django.views.generic import CreateView, FormView, ListView +from django.views.generic import FormView, ListView +import crud.base from crud.base import Crud from materia.models import Tramitacao from parlamentares.models import Filiacao -from .forms import (CadastrarComissaoForm, ComposicaoForm, - ParticipacaoCadastroForm) +from .forms import ComposicaoForm, ParticipacaoCadastroForm from .models import (CargoComissao, Comissao, Composicao, Participacao, Periodo, TipoComissao) CargoCrud = Crud.build(CargoComissao, 'cargo_comissao') PeriodoComposicaoCrud = Crud.build(Periodo, 'periodo_composicao_comissao') TipoComissaoCrud = Crud.build(TipoComissao, 'tipo_comissao') -ComissaoCrud = Crud.build(Comissao, 'modulo_comissoes') -class CadastrarComissaoView(CreateView): - template_name = "comissoes/cadastrar_comissao.html" - form_class = CadastrarComissaoForm - success_url = reverse_lazy('comissoes:comissao_list') +class ComissaoCrud(Crud): + model = Comissao + help_path = 'modulo_comissoes' + + class BaseMixin(crud.base.BaseMixin): + list_field_names = ['nome', 'sigla', 'tipo', 'data_criacao'] class ComposicaoView(FormView): @@ -29,7 +30,6 @@ class ComposicaoView(FormView): def get(self, request, *args, **kwargs): form = ComposicaoForm() - composicoes = Composicao.objects.filter( comissao_id=self.kwargs['pk']).order_by('-periodo') participacoes = Participacao.objects.all().order_by('parlamentar') @@ -66,14 +66,6 @@ class ComposicaoView(FormView): 'object': Comissao.objects.get(id=self.kwargs['pk'])}) -class MateriasView(ComissaoCrud.CrudDetailView): - template_name = 'comissoes/materias.html' - - -class ReunioesView(ComissaoCrud.CrudDetailView): - template_name = 'comissoes/reunioes.html' - - class ComissaoParlamentarIncluirView(FormView): template_name = "comissoes/comissao_parlamentar.html" diff --git a/crispy_layout_mixin.py b/crispy_layout_mixin.py index ddff0283c..7971466ca 100644 --- a/crispy_layout_mixin.py +++ b/crispy_layout_mixin.py @@ -67,18 +67,28 @@ def get_field_display(obj, fieldname): class CrispyLayoutFormMixin: + @property + def layout_key(self): + if hasattr(super(CrispyLayoutFormMixin, self), 'layout_key'): + return super(CrispyLayoutFormMixin, self).layout_key + else: + return self.model.__name__ + def get_layout(self): filename = join( dirname(self.model._meta.app_config.models_module.__file__), 'layouts.yaml') - return read_layout_from_yaml(filename, self.model.__name__) + return read_layout_from_yaml(filename, self.layout_key) @property def fields(self): - '''Returns all fields in the layout''' - return [fieldname for legend_rows in self.get_layout() - for row in legend_rows[1:] - for fieldname, span in row] + if hasattr(self, 'form_class') and self.form_class: + return None + else: + '''Returns all fields in the layout''' + return [fieldname for legend_rows in self.get_layout() + for row in legend_rows[1:] + for fieldname, span in row] def get_form(self, form_class=None): try: diff --git a/crud/base.py b/crud/base.py index 48bcb1e62..ea9f9c109 100644 --- a/crud/base.py +++ b/crud/base.py @@ -107,6 +107,13 @@ class CrudListView(ListView): paginate_by = 10 no_entries_msg = _('Nenhum registro encontrado.') + def get_rows(self, object_list): + return [self._as_row(obj) for obj in object_list] + + def get_headers(self): + return [self.model._meta.get_field(fieldname).verbose_name + for fieldname in self.list_field_names] + def _as_row(self, obj): return [ (get_field_display(obj, name)[1], obj.pk if i == 0 else None) @@ -117,18 +124,17 @@ class CrudListView(ListView): context.setdefault('title', self.verbose_name_plural) # pagination - page_obj = context['page_obj'] - paginator = context['paginator'] - context['page_range'] = make_pagination( - page_obj.number, paginator.num_pages) + if self.paginate_by: + page_obj = context['page_obj'] + paginator = context['paginator'] + context['page_range'] = make_pagination( + page_obj.number, paginator.num_pages) # rows object_list = context['object_list'] - context['rows'] = [self._as_row(obj) for obj in object_list] + context['headers'] = self.get_headers() + context['rows'] = self.get_rows(object_list) - context['headers'] = [ - self.model._meta.get_field(fieldname).verbose_name - for fieldname in self.list_field_names] context['NO_ENTRIES_MSG'] = self.no_entries_msg return context @@ -214,11 +220,5 @@ class Crud: model = _model help_path = _help_path - # FIXME!!!! corrigir referencias no codigo e remover isso!!!!! - # fazer com #230 - class CrudDetailView(cls.BaseMixin, cls.DetailView): - model = _model - help_path = _help_path - ModelCrud.__name__ = '%sCrud' % _model.__name__ return ModelCrud diff --git a/crud/tests/stub_app/urls.py b/crud/tests/stub_app/urls.py index 66f7fed14..623f167bf 100644 --- a/crud/tests/stub_app/urls.py +++ b/crud/tests/stub_app/urls.py @@ -3,5 +3,5 @@ from django.conf.urls import include, url from .views import CountryCrud urlpatterns = [ - url(r'^countries/', include(CountryCrud.get_urls(), 'stub_app')), + url(r'^country/', include(CountryCrud.get_urls(), 'stub_app')), ] diff --git a/crud/tests/test_base.py b/crud/tests/test_base.py index f8379fb8a..824857a91 100644 --- a/crud/tests/test_base.py +++ b/crud/tests/test_base.py @@ -140,11 +140,11 @@ def test_layout_detail_fieldsets(monkeypatch): def test_reverse(): - assert '/countries/' == reverse('stub_app:country_list') - assert '/countries/create' == reverse('stub_app:country_create') - assert '/countries/2' == reverse('stub_app:country_detail', args=(2,)) - assert '/countries/2/edit' == reverse('stub_app:country_update', args=(2,)) - assert '/countries/2/delete' == reverse( + assert '/country/' == reverse('stub_app:country_list') + assert '/country/create' == reverse('stub_app:country_create') + assert '/country/2' == reverse('stub_app:country_detail', args=(2,)) + assert '/country/2/edit' == reverse('stub_app:country_update', args=(2,)) + assert '/country/2/delete' == reverse( 'stub_app:country_delete', args=(2,)) @@ -199,7 +199,7 @@ def test_flux_list_paginate_detail( CountryCrud.ListView.paginate_by = page_size - res = app.get('/countries/') + res = app.get('/country/') if num_entries == 0: assert_on_list_page(res) @@ -254,7 +254,7 @@ def test_flux_list_create_detail(app, cancel, make_invalid_submit): # to have a couple an option for continent field stub_continent = mommy.make(Continent) - res = app.get('/countries/') + res = app.get('/country/') # on list page assert_on_list_page(res) @@ -293,7 +293,7 @@ def test_flux_list_create_detail(app, cancel, make_invalid_submit): # on redirect to detail page created = Country.objects.get(name=stub_name) - assert res.url.endswith('/countries/%s' % created.id) + assert res.url.endswith('/country/%s' % created.id) res = res.follow() # on detail page @@ -305,7 +305,7 @@ def test_flux_list_create_detail(app, cancel, make_invalid_submit): def get_detail_page(app): stub = mommy.make(Country, name='Country Stub') - res = app.get('/countries/%s' % stub.id) + res = app.get('/country/%s' % stub.id) # on detail page assert_on_detail_page(res, stub.name) return stub, res @@ -333,7 +333,7 @@ def test_flux_detail_update_detail(app, cancel): res = form.submit() # on redirect to detail page - assert res.url.endswith('/countries/%s' % stub.id) + assert res.url.endswith('/country/%s' % stub.id) res = res.follow() # back to detail page @@ -362,7 +362,7 @@ def test_flux_detail_delete_list(app, cancel): res = res.form.submit() # on redirect to list page - assert res.url.endswith('/countries/') + assert res.url.endswith('/country/') res = res.follow() # on list page diff --git a/materia/forms.py b/materia/forms.py index dcd517752..9fea5b817 100644 --- a/materia/forms.py +++ b/materia/forms.py @@ -404,142 +404,6 @@ class MateriaAnexadaForm(ModelForm): *args, **kwargs) -class FormularioSimplificadoForm(ModelForm): - - class Meta: - model = MateriaLegislativa - fields = ['tipo', - 'numero', - 'ano', - 'data_apresentacao', - 'numero_protocolo', - 'regime_tramitacao', - 'em_tramitacao', - 'ementa', - 'texto_original'] - exclude = ['anexadas'] - widgets = { - 'data_apresentacao': forms.DateInput(attrs={'class': 'dateinput'}), - } - - def clean_texto_original(self): - texto_original = self.cleaned_data.get('texto_original', False) - if texto_original: - if texto_original.size > MAX_DOC_UPLOAD_SIZE: - raise ValidationError("Arquivo muito grande. ( > 5mb )") - return texto_original - else: - raise ValidationError("Não foi possível salvar o arquivo.") - - def __init__(self, *args, **kwargs): - - row1 = crispy_layout_mixin.to_row( - [('tipo', 4), - ('numero', 4), - ('ano', 4)]) - - row2 = crispy_layout_mixin.to_row( - [('data_apresentacao', 4), - ('numero_protocolo', 4), - ('regime_tramitacao', 4)]) - - row3 = crispy_layout_mixin.to_row( - [('texto_original', 9), - ('em_tramitacao', 3)]) - - row4 = crispy_layout_mixin.to_row( - [('ementa', 12)]) - - self.helper = FormHelper() - self.helper.layout = Layout( - Fieldset( - _('Formulário Simplificado'), - Fieldset( - _('Identificação Básica'), - row1, row2, row3, row4 - ), - form_actions() - ) - ) - super(FormularioSimplificadoForm, self).__init__(*args, **kwargs) - - -class FormularioCadastroForm(ModelForm): - - class Meta: - model = MateriaLegislativa - fields = ['tipo', - 'numero', - 'ano', - 'data_apresentacao', - 'numero_protocolo', - 'tipo_apresentacao', - 'texto_original', - 'apelido', - 'dias_prazo', - 'polemica', - 'objeto', - 'regime_tramitacao', - 'em_tramitacao', - 'data_fim_prazo', - 'data_publicacao', - 'complementar', - 'tipo_origem_externa', - 'numero_origem_externa', - 'ano_origem_externa', - 'local_origem_externa', - 'data_origem_externa', - 'ementa', - 'indexacao', - 'observacao'] - - def __init__(self, *args, **kwargs): - self.helper = FormHelper() - self.helper.layout = Layout( - Fieldset( - _('Formulário de Cadastro'), - Fieldset( - _('Identificação Básica'), - 'tipo', - 'numero', - 'ano', - 'data_apresentacao', - 'numero_protocolo', - 'tipo_apresentacao', - 'texto_original' - ), - Fieldset( - _('Outras Informações'), - 'apelido', - 'dias_prazo', - 'polemica', - 'objeto', - 'regime_tramitacao', - 'em_tramitacao', - 'data_fim_prazo', - 'data_publicacao', - 'complementar' - ), - Fieldset( - _('Origem Externa'), - 'tipo_origem_externa', - 'numero_origem_externa', - 'ano_origem_externa', - 'local_origem_externa', - 'data_origem_externa' - ), - Fieldset( - _('Dados Textuais'), - 'ementa', - 'indexacao', - 'observacao' - ), - form_actions() - ) - ) - super(FormularioCadastroForm, self).__init__(*args, **kwargs) - - class AutoriaForm(ModelForm): autor = forms.ModelChoiceField( label=_('Autor'), diff --git a/materia/urls.py b/materia/urls.py index 416f101b3..d39828694 100644 --- a/materia/urls.py +++ b/materia/urls.py @@ -6,7 +6,6 @@ from materia.views import (AcompanhamentoConfirmarView, AutoriaEditView, AutoriaView, DespachoInicialEditView, DespachoInicialView, DocumentoAcessorioEditView, DocumentoAcessorioView, - FormularioCadastroView, FormularioSimplificadoView, LegislacaoCitadaEditView, LegislacaoCitadaView, MateriaAnexadaEditView, MateriaAnexadaView, MateriaLegislativaCrud, @@ -35,9 +34,9 @@ urlpatterns = [ ProposicaoTaView.as_view(), name='proposicao_ta'), - url(r'^sistema/proposicoes/tipo/', + url(r'^sistema/proposicao/tipo/', include(TipoProposicaoCrud.get_urls())), - url(r'^sistema/proposicoes/autor/', include(AutorCrud.get_urls())), + url(r'^sistema/proposicao/autor/', include(AutorCrud.get_urls())), url(r'^sistema/materia/tipo/', include(TipoMateriaCrud.get_urls())), url(r'^sistema/materia/regime-tramitacao/', include(RegimeTramitacaoCrud.get_urls())), @@ -53,12 +52,6 @@ urlpatterns = [ url(r'^sistema/materia/status-tramitacao/', include(StatusTramitacaoCrud.get_urls())), url(r'^sistema/materia/orgao/', include(OrgaoCrud.get_urls())), - url(r'^materia/formulario-simplificado', - FormularioSimplificadoView.as_view(), - name='formulario_simplificado'), - url(r'^materia/formulario-cadastro', - FormularioCadastroView.as_view(), - name='formulario_cadastro'), url(r'^materia/(?P\d+)/materia-anexada$', MateriaAnexadaView.as_view(), name='materia_anexada'), url(r'^materia/(?P\d+)/materia-anexada/(?P\d+)/edit', diff --git a/materia/views.py b/materia/views.py index e920d134e..8ed12829a 100644 --- a/materia/views.py +++ b/materia/views.py @@ -6,7 +6,7 @@ from string import ascii_letters, digits from django.contrib import messages from django.core.exceptions import ObjectDoesNotExist from django.core.mail import send_mail -from django.core.urlresolvers import reverse, reverse_lazy +from django.core.urlresolvers import reverse from django.http.response import HttpResponseRedirect from django.shortcuts import redirect from django.template import Context, loader @@ -14,6 +14,7 @@ from django.utils.translation import ugettext_lazy as _ from django.views.generic import CreateView, FormView, ListView, TemplateView from django_filters.views import FilterView +import crud.base from base.models import CasaLegislativa from comissoes.models import Comissao, Composicao from compilacao.views import IntegracaoTaView @@ -24,7 +25,6 @@ from sapl.utils import get_base_url from .forms import (AcompanhamentoMateriaForm, AutoriaForm, DespachoInicialForm, DocumentoAcessorioForm, - FormularioCadastroForm, FormularioSimplificadoForm, LegislacaoCitadaForm, MateriaAnexadaForm, MateriaLegislativaFilterSet, NumeracaoForm, ProposicaoForm, RelatoriaForm, TramitacaoForm, filtra_tramitacao_destino, @@ -43,7 +43,6 @@ TipoMateriaCrud = Crud.build(TipoMateriaLegislativa, RegimeTramitacaoCrud = Crud.build(RegimeTramitacao, 'regime_tramitacao') TipoDocumentoCrud = Crud.build(TipoDocumento, 'tipo_documento') TipoFimRelatoriaCrud = Crud.build(TipoFimRelatoria, 'fim_relatoria') -MateriaLegislativaCrud = Crud.build(MateriaLegislativa, '') AnexadaCrud = Crud.build(Anexada, '') TipoAutorCrud = Crud.build(TipoAutor, 'tipo_autor') AutorCrud = Crud.build(Autor, 'autor') @@ -59,16 +58,12 @@ UnidadeTramitacaoCrud = Crud.build(UnidadeTramitacao, 'unidade_tramitacao') TramitacaoCrud = Crud.build(Tramitacao, '') -class FormularioSimplificadoView(CreateView): - template_name = "materia/formulario_simplificado.html" - form_class = FormularioSimplificadoForm - success_url = reverse_lazy('materia:materialegislativa_list') - +class MateriaLegislativaCrud(Crud): + model = MateriaLegislativa + help_path = 'materia_legislativa' -class FormularioCadastroView(CreateView): - template_name = "materia/formulario_cadastro.html" - form_class = FormularioCadastroForm - success_url = reverse_lazy('materia:formulario_cadastro') + class BaseMixin(crud.base.BaseMixin): + list_field_names = ['tipo', 'numero', 'ano', 'data_apresentacao'] class MateriaAnexadaView(FormView): @@ -1371,7 +1366,7 @@ class ProposicaoTaView(IntegracaoTaView): model_type_foreignkey = TipoProposicao -class AcompanhamentoMateriaView(MateriaLegislativaCrud.CrudDetailView): +class AcompanhamentoMateriaView(CreateView): template_name = "materia/acompanhamento_materia.html" def get_random_chars(self): diff --git a/painel/urls.py b/painel/urls.py index b210bff05..a6ca948d0 100644 --- a/painel/urls.py +++ b/painel/urls.py @@ -3,8 +3,7 @@ from django.conf.urls import url from .apps import AppConfig from .views import controlador_painel # CronometroPainelCrud, from .views import (cronometro_painel, get_dados_painel, painel_mensagem_view, - painel_parlamentares_view, painel_view, - painel_votacao_view) + painel_parlamentar_view, painel_view, painel_votacao_view) app_name = AppConfig.name @@ -14,8 +13,8 @@ urlpatterns = [ url(r'^painel/controlador$', controlador_painel, name='painel_controlador'), url(r'^painel/mensagem$', painel_mensagem_view, name="painel_mensagem"), - url(r'^painel/parlamentares$', painel_parlamentares_view, - name='painel_parlamentares'), + url(r'^painel/parlamentar$', painel_parlamentar_view, + name='painel_parlamentar'), url(r'^painel/votacao$', painel_votacao_view, name='painel_votacao'), url(r'^painel/cronometro$', cronometro_painel, name='cronometro_painel'), # url(r'^painel/cronometro$', include(CronometroPainelCrud.get_urls())), diff --git a/painel/views.py b/painel/views.py index 5a5398886..a84ffe514 100644 --- a/painel/views.py +++ b/painel/views.py @@ -46,7 +46,7 @@ def painel_mensagem_view(request): return render(request, 'painel/mensagem.html') -def painel_parlamentares_view(request): +def painel_parlamentar_view(request): return render(request, 'painel/parlamentares.html') diff --git a/parlamentares/forms.py b/parlamentares/forms.py index 43377bbe6..9a3c1ab3c 100644 --- a/parlamentares/forms.py +++ b/parlamentares/forms.py @@ -1,165 +1,44 @@ from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Fieldset, Layout, Submit from django import forms -from django.core.exceptions import ValidationError +from django.db import transaction from django.forms import ModelForm from django.utils.translation import ugettext_lazy as _ import crispy_layout_mixin from crispy_layout_mixin import form_actions -from sapl.settings import MAX_IMAGE_UPLOAD_SIZE from .models import Dependente, Filiacao, Legislatura, Mandato, Parlamentar -class ParlamentaresListForm(forms.Form): - periodo = forms.CharField() +class ParlamentarCreateForm(ModelForm): - -class ParlamentaresForm (ModelForm): - ativo = forms.TypedChoiceField( - coerce=lambda x: x == 'True', - choices=((True, 'Sim'), (False, 'Não')), + legislatura = forms.ModelChoiceField( + label=_('Legislatura'), + required=True, + queryset=Legislatura.objects.all().order_by('-data_inicio'), + empty_label='----------', ) - def clean_fotografia(self): - fotografia = self.cleaned_data.get('fotografia', False) - if fotografia: - if fotografia.size > MAX_IMAGE_UPLOAD_SIZE: - raise ValidationError('Imagem muito grande. ( > 2mb )') - return fotografia + data_expedicao_diploma = forms.DateField( + label=_('Expedição do Diploma'), + required=True, + ) class Meta: model = Parlamentar - fields = ['nome_parlamentar', - 'ativo', - 'nome_completo', - 'nivel_instrucao', - 'sexo', - 'cpf', - 'rg', - 'titulo_eleitor', - 'data_nascimento', - 'situacao_militar', - 'profissao', - 'endereco_web', - 'email', - 'numero_gab_parlamentar', - 'telefone', - 'fax', - 'endereco_residencia', - 'cep_residencia', - 'municipio_residencia', - 'telefone_residencia', - 'fax_residencia', - 'locais_atuacao', - 'fotografia', - 'biografia'] - - widgets = { - 'cpf': forms.TextInput(attrs={'class': 'cpf'}), - 'rg': forms.TextInput(attrs={'class': 'rg'}), - 'titulo_eleitor': forms.TextInput(attrs={ - 'class': 'titulo_eleitor'}), - 'telefone': forms.TextInput(attrs={'class': 'telefone'}), - 'fax': forms.TextInput(attrs={'class': 'telefone'}), - 'cep_residencia': forms.TextInput(attrs={'class': 'cep'}), - 'telefone_residencia': forms.TextInput(attrs={ - 'class': 'telefone'}), - 'fax_residencia': forms.TextInput(attrs={'class': 'telefone'}), - 'fotografia': forms.FileInput, - 'biografia': forms.Textarea(attrs={'id': 'biografia-parlamentar'}) - } - - def __init__(self, *args, **kwargs): - - row1 = crispy_layout_mixin.to_row( - [('nome_parlamentar', 8), ('ativo', 4)]) - - row2 = crispy_layout_mixin.to_row( - [('nome_completo', 12)]) - - row3 = crispy_layout_mixin.to_row( - [('nivel_instrucao', 4), - ('sexo', 4), - ('data_nascimento', 4)]) - - row4 = crispy_layout_mixin.to_row( - [('cpf', 4), - ('rg', 4), - ('titulo_eleitor', 4)]) - - row5 = crispy_layout_mixin.to_row( - [('situacao_militar', 6), - ('profissao', 6)]) - - row6 = crispy_layout_mixin.to_row( - [('endereco_web', 12)]) - - row7 = crispy_layout_mixin.to_row( - [('email', 12)]) - - row8 = crispy_layout_mixin.to_row( - [('numero_gab_parlamentar', 4), - ('telefone', 4), - ('fax', 4)]) - - row9 = crispy_layout_mixin.to_row( - [('endereco_residencia', 6), - ('cep_residencia', 6)]) - - row10 = crispy_layout_mixin.to_row( - [('municipio_residencia', 12)]) - - row11 = crispy_layout_mixin.to_row( - [('telefone_residencia', 6), - ('fax_residencia', 6)]) - - row12 = crispy_layout_mixin.to_row( - [('locais_atuacao', 12)]) - - row13 = crispy_layout_mixin.to_row( - [('fotografia', 12)]) - - row14 = crispy_layout_mixin.to_row( - [('biografia', 12)]) - - self.helper = FormHelper() - self.helper.layout = Layout( - Fieldset(_('Cadastro do Parlamentar'), - row1, row2, row3, row4, row5, - row6, row7, row8, row9, row10, - row11, row12, row13, - HTML("""
- {% if not form.fotografia.errors %} - {% if form.fotografia.value %} - -

- - {% endif %} - {% endif %} -
""", ), - row14, - form_actions()) - ) - super(ParlamentaresForm, self).__init__( - *args, **kwargs) - - -class ParlamentaresEditForm(ParlamentaresForm): - - def __init__(self, *args, **kwargs): - super(ParlamentaresEditForm, self).__init__( - *args, **kwargs) - self.helper.layout[0][-1:] = form_actions(more=[ - HTML(' '), - Submit('excluir', 'Excluir', - css_class='btn btn-primary')]) + exclude = [] + + @transaction.atomic + def save(self, commit=True): + parlamentar = super(ParlamentarCreateForm, self).save(commit) + legislatura = self.cleaned_data['legislatura'] + Mandato.objects.create( + parlamentar=parlamentar, + legislatura=legislatura, + data_fim_mandato=legislatura.data_fim, + data_expedicao_diploma=self.cleaned_data['data_expedicao_diploma']) + return parlamentar class MandatoForm(ModelForm): diff --git a/parlamentares/layouts.yaml b/parlamentares/layouts.yaml index 9a224a622..d4d342231 100644 --- a/parlamentares/layouts.yaml +++ b/parlamentares/layouts.yaml @@ -42,6 +42,26 @@ Parlamentar: - fotografia - biografia +ParlamentarCreate: + Dados do Mandato: + - legislatura data_expedicao_diploma + Cadastro do Parlamentar: + - nome_parlamentar:8 ativo + - nome_completo + - nivel_instrucao sexo data_nascimento + - cpf rg titulo_eleitor + - situacao_militar profissao + - endereco_web + - email + - numero_gab_parlamentar telefone fax + - endereco_residencia cep_residencia + - municipio_residencia + - telefone_residencia fax_residencia + - locais_atuacao + - fotografia + - biografia + + Filiacao: 'Filiações Partidárias ': - partido data data_desfiliacao diff --git a/parlamentares/models.py b/parlamentares/models.py index 7c9a6852a..6bca49e95 100644 --- a/parlamentares/models.py +++ b/parlamentares/models.py @@ -1,10 +1,11 @@ -import datetime +from datetime import datetime from django.db import models from django.utils.translation import ugettext_lazy as _ from model_utils import Choices -from sapl.utils import UF, YES_NO_CHOICES, restringe_tipos_de_arquivo_img +from sapl.utils import (UF, YES_NO_CHOICES, intervalos_tem_intersecao, + restringe_tipos_de_arquivo_img) class Legislatura(models.Model): @@ -18,7 +19,7 @@ class Legislatura(models.Model): def __str__(self): # XXX Usar id mesmo? Ou criar campo para nº legislatura? - current_date = datetime.datetime.now().year + current_date = datetime.now().year if(self.data_inicio.year <= current_date and self.data_fim.year >= current_date): current = ' (%s)' % _('Atual') @@ -354,6 +355,17 @@ class Mandato(models.Model): 'parlamentar': self.parlamentar, 'legislatura': self.legislatura } + def get_partidos(self): + filicacoes = Filiacao.objects.filter( + parlamentar=self.parlamentar).order_by('data') + return [f.partido.sigla + for f in filicacoes + if intervalos_tem_intersecao( + self.legislatura.data_inicio, + self.legislatura.data_fim, + f.data, + f.data_desfiliacao or datetime.max.date())] + class CargoMesa(models.Model): # TODO M2M ???? diff --git a/parlamentares/test_mandato.py b/parlamentares/test_mandato.py new file mode 100644 index 000000000..ce855450d --- /dev/null +++ b/parlamentares/test_mandato.py @@ -0,0 +1,33 @@ +from datetime import datetime + +import pytest +from model_mommy import mommy + +from .models import Filiacao, Legislatura, Mandato + +pytestmark = pytest.mark.django_db + + +def data(valor): + return datetime.strptime(valor, '%Y-%m-%d').date() + + +def test_filiacoes(): + legislatura = mommy.make(Legislatura, + data_inicio=data('2001-01-01'), + data_fim=data('2001-12-31'), + ) + mandato = mommy.make(Mandato, legislatura=legislatura) + f1_fora, f2, f3, f4 = [mommy.make(Filiacao, + parlamentar=mandato.parlamentar, + data=ini, + data_desfiliacao=fim) + for ini, fim in ( + (data('2000-01-01'), data('2000-12-31')), + (data('2000-01-01'), data('2001-03-01')), + (data('2001-03-02'), data('2001-10-01')), + (data('2001-10-02'), None), + )] + assert mandato.get_partidos() == [f2.partido.sigla, + f3.partido.sigla, + f4.partido.sigla] diff --git a/parlamentares/test_parlamentares.py b/parlamentares/test_parlamentares.py index 944985b95..81d9b35ed 100644 --- a/parlamentares/test_parlamentares.py +++ b/parlamentares/test_parlamentares.py @@ -6,26 +6,46 @@ from .models import (Dependente, Filiacao, Legislatura, Mandato, Parlamentar, Partido, TipoDependente) -# vamos refazer a funcionalidade adicionando os campos ogrigatórios de mandato @pytest.mark.django_db(transaction=False) -def TODO_DESLIGADO_RELIGAR_test_cadastro_parlamentar(client): - mommy.make(Legislatura, pk=5) +def test_cadastro_parlamentar(client): + legislatura = mommy.make(Legislatura) - response = client.get(reverse('parlamentares:parlamentares_cadastro', - kwargs={'pk': 5})) + url = reverse('parlamentares:parlamentar_create') + response = client.get(url) assert response.status_code == 200 - response = client.post(reverse('parlamentares:parlamentares_cadastro', - kwargs={'pk': 5}), - {'nome_completo': 'Teresa Barbosa', - 'nome_parlamentar': 'Terezinha', - 'sexo': 'F', - 'ativo': 'True'}, follow=True) + response = client.post(url, {'nome_completo': 'Teresa Barbosa', + 'nome_parlamentar': 'Terezinha', + 'sexo': 'F', + 'ativo': 'True', + 'legislatura': legislatura.id, + 'data_expedicao_diploma': '2001-01-01'}, + follow=True) + + [parlamentar] = Parlamentar.objects.all() + assert parlamentar.nome_parlamentar == 'Terezinha' + assert parlamentar.sexo == 'F' + assert parlamentar.ativo is True + # o primeiro mandato é criado + [mandato] = Mandato.objects.all() + assert mandato.parlamentar == parlamentar + assert str(mandato.data_expedicao_diploma) == '2001-01-01' + assert mandato.legislatura == legislatura + assert mandato.data_fim_mandato == legislatura.data_fim - parlamentar = Parlamentar.objects.first() - assert "Terezinha" == parlamentar.nome_parlamentar - if not parlamentar.ativo: - pytest.fail("Parlamentar deve estar ativo") + +@pytest.mark.django_db(transaction=False) +def test_incluir_parlamentar_errors(client): + url = reverse('parlamentares:parlamentar_create') + response = client.post(url) + erros_esperados = {campo: ['Este campo é obrigatório.'] + for campo in ['legislatura', + 'data_expedicao_diploma', + 'nome_parlamentar', + 'nome_completo', + 'sexo', + ]} + assert response.context_data['form'].errors == erros_esperados @pytest.mark.django_db(transaction=False) @@ -33,7 +53,7 @@ def test_filiacao_submit(client): mommy.make(Parlamentar, pk=14) mommy.make(Partido, pk=32) - client.post(reverse('parlamentares:parlamentares_filiacao', + client.post(reverse('parlamentares:parlamentar_filiacao', kwargs={'pk': 14}), {'partido': 32, 'data': '2016-03-22', @@ -50,7 +70,7 @@ def test_dependente_submit(client): mommy.make(Partido, pk=32) mommy.make(TipoDependente, pk=3) - client.post(reverse('parlamentares:parlamentares_dependentes', + client.post(reverse('parlamentares:parlamentar_dependente', kwargs={'pk': 14}), {'nome': 'Eduardo', 'tipo': 3, @@ -66,7 +86,7 @@ def test_dependente_submit(client): @pytest.mark.django_db(transaction=False) def test_form_errors_dependente(client): mommy.make(Parlamentar, pk=14) - response = client.post(reverse('parlamentares:parlamentares_dependentes', + response = client.post(reverse('parlamentares:parlamentar_dependente', kwargs={'pk': 14}), {'salvar': 'salvar'}, follow=True) @@ -83,7 +103,7 @@ def test_form_errors_dependente(client): def test_form_errors_filiacao(client): mommy.make(Parlamentar, pk=14) - response = client.post(reverse('parlamentares:parlamentares_filiacao', + response = client.post(reverse('parlamentares:parlamentar_filiacao', kwargs={'pk': 14}), {'partido': '', 'salvar': 'salvar'}, @@ -100,7 +120,7 @@ def test_mandato_submit(client): mommy.make(Parlamentar, pk=14) mommy.make(Legislatura, pk=5) - client.post(reverse('parlamentares:parlamentares_mandato', + client.post(reverse('parlamentares:parlamentar_mandato', kwargs={'pk': 14}), {'legislatura': 5, 'data_fim_mandato': '2016-01-01', @@ -116,7 +136,7 @@ def test_mandato_submit(client): @pytest.mark.django_db(transaction=False) def test_form_errors_mandato(client): mommy.make(Parlamentar, pk=14) - response = client.post(reverse('parlamentares:parlamentares_mandato', + response = client.post(reverse('parlamentares:parlamentar_mandato', kwargs={'pk': 14}), {'legislatura': '', 'salvar': 'salvar'}, @@ -128,22 +148,3 @@ def test_form_errors_mandato(client): ['Este campo é obrigatório.']) assert (response.context_data['form'].errors['data_expedicao_diploma'] == ['Este campo é obrigatório.']) - - -@pytest.mark.django_db(transaction=False) -def test_incluir_parlamentar_errors(client): - mommy.make(Legislatura, pk=5) - - response = client.post(reverse('parlamentares:parlamentares_cadastro', - kwargs={'pk': 5}), - {'salvar': 'salvar'}, - follow=True) - - assert (response.context_data['form'].errors['nome_parlamentar'] == - ['Este campo é obrigatório.']) - assert (response.context_data['form'].errors['nome_completo'] == - ['Este campo é obrigatório.']) - assert (response.context_data['form'].errors['sexo'] == - ['Este campo é obrigatório.']) - assert (response.context_data['form'].errors['ativo'] == - ['Este campo é obrigatório.']) diff --git a/parlamentares/urls.py b/parlamentares/urls.py index c7a9f922c..6ef8bdf59 100644 --- a/parlamentares/urls.py +++ b/parlamentares/urls.py @@ -4,63 +4,56 @@ from parlamentares.views import (CargoMesaCrud, ColigacaoCrud, FiliacaoEditView, FiliacaoView, LegislaturaCrud, MandatoEditView, MandatoView, MesaDiretoraView, NivelInstrucaoCrud, - ParlamentaresCadastroView, + ParlamentarCrud, ParlamentaresDependentesEditView, - ParlamentaresDependentesView, - ParlamentaresEditarView, ParlamentaresView, - PartidoCrud, SessaoLegislativaCrud, - TipoAfastamentoCrud, TipoDependenteCrud, - TipoMilitarCrud) + ParlamentaresDependentesView, PartidoCrud, + SessaoLegislativaCrud, TipoAfastamentoCrud, + TipoDependenteCrud, TipoMilitarCrud) from .apps import AppConfig app_name = AppConfig.name urlpatterns = [ - url(r'^sistema/parlamentares/legislatura/', + url(r'^parlamentar/', include(ParlamentarCrud.get_urls())), + + url(r'^sistema/parlamentar/legislatura/', include(LegislaturaCrud.get_urls())), - url(r'^sistema/parlamentares/tipo-dependente/', + url(r'^sistema/parlamentar/tipo-dependente/', include(TipoDependenteCrud.get_urls())), - url(r'^sistema/parlamentares/nivel-instrucao/', + url(r'^sistema/parlamentar/nivel-instrucao/', include(NivelInstrucaoCrud.get_urls())), - url(r'^sistema/parlamentares/coligacao/', + url(r'^sistema/parlamentar/coligacao/', include(ColigacaoCrud.get_urls())), - url(r'^sistema/parlamentares/tipo-afastamento/', + url(r'^sistema/parlamentar/tipo-afastamento/', include(TipoAfastamentoCrud.get_urls())), - url(r'^sistema/parlamentares/tipo-militar/', + url(r'^sistema/parlamentar/tipo-militar/', include(TipoMilitarCrud.get_urls())), - url(r'^sistema/parlamentares/partido/', include(PartidoCrud.get_urls())), + url(r'^sistema/parlamentar/partido/', include(PartidoCrud.get_urls())), url(r'^sistema/mesa-diretora/sessao-legislativa/', include(SessaoLegislativaCrud.get_urls())), url(r'^sistema/mesa-diretora/cargo-mesa/', include(CargoMesaCrud.get_urls())), - url(r'^parlamentares/$', - ParlamentaresView.as_view(), name='parlamentares'), - url(r'^parlamentares/(?P\d+)/cadastro$', - ParlamentaresCadastroView.as_view(), name='parlamentares_cadastro'), - url(r'^parlamentares/(?P\d+)/dependentes$', + url(r'^parlamentar/(?P\d+)/dependente$', ParlamentaresDependentesView.as_view(), - name='parlamentares_dependentes'), - url(r'^parlamentares/(?P\d+)/dependentes/(?P\d+)$', + name='parlamentar_dependente'), + url(r'^parlamentar/(?P\d+)/dependente/(?P\d+)$', ParlamentaresDependentesEditView.as_view(), - name='parlamentares_dependentes_edit'), - url(r'^parlamentares/(?P\d+)/filiacao$', + name='parlamentar_dependente_edit'), + url(r'^parlamentar/(?P\d+)/filiacao$', FiliacaoView.as_view(), - name='parlamentares_filiacao'), - url(r'^parlamentares/(?P\d+)/filiacao/(?P\d+)$', + name='parlamentar_filiacao'), + url(r'^parlamentar/(?P\d+)/filiacao/(?P\d+)$', FiliacaoEditView.as_view(), - name='parlamentares_filiacao_edit'), - url(r'^parlamentares/(?P\d+)/mandato$', + name='parlamentar_filiacao_edit'), + url(r'^parlamentar/(?P\d+)/mandato$', MandatoView.as_view(), - name='parlamentares_mandato'), - url(r'^parlamentares/(?P\d+)/mandato/(?P\d+)$', + name='parlamentar_mandato'), + url(r'^parlamentar/(?P\d+)/mandato/(?P\d+)$', MandatoEditView.as_view(), - name='parlamentares_mandato_edit'), - - url(r'^parlamentares/(?P\d+)/editar$', - ParlamentaresEditarView.as_view(), name='parlamentares_editar'), + name='parlamentar_mandato_edit'), url(r'^mesa-diretora/$', MesaDiretoraView.as_view(), name='mesa_diretora'), diff --git a/parlamentares/views.py b/parlamentares/views.py index f0e5ae54e..6caed3ec4 100644 --- a/parlamentares/views.py +++ b/parlamentares/views.py @@ -1,18 +1,17 @@ -import os - from django.contrib import messages from django.core.urlresolvers import reverse, reverse_lazy from django.http import HttpResponseRedirect from django.shortcuts import redirect +from django.utils.datastructures import MultiValueDictKeyError from django.utils.translation import ugettext_lazy as _ from django.views.generic import CreateView, FormView, UpdateView +import crud.base from crud.base import Crud from .forms import (DependenteEditForm, DependenteForm, FiliacaoEditForm, FiliacaoForm, MandatoEditForm, MandatoForm, - ParlamentaresEditForm, ParlamentaresForm, - ParlamentaresListForm) + ParlamentarCreateForm) from .models import (CargoMesa, Coligacao, ComposicaoMesa, Dependente, Filiacao, Legislatura, Mandato, NivelInstrucao, Parlamentar, Partido, SessaoLegislativa, SituacaoMilitar, @@ -24,7 +23,6 @@ ColigacaoCrud = Crud.build(Coligacao, 'coligacao') PartidoCrud = Crud.build(Partido, 'partidos') DependenteCrud = Crud.build(Dependente, '') SessaoLegislativaCrud = Crud.build(SessaoLegislativa, 'sessao_legislativa') -ParlamentarCrud = Crud.build(Parlamentar, '') FiliacaoCrud = Crud.build(Filiacao, '') MandatoCrud = Crud.build(Mandato, '') TipoDependenteCrud = Crud.build(TipoDependente, 'tipo_dependente') @@ -33,6 +31,70 @@ TipoAfastamentoCrud = Crud.build(TipoAfastamento, 'tipo_afastamento') TipoMilitarCrud = Crud.build(SituacaoMilitar, 'tipo_situa_militar') +class ParlamentarCrud(Crud): + model = Parlamentar + help_path = '' + + class CreateView(crud.base.CrudCreateView): + form_class = ParlamentarCreateForm + + @property + def layout_key(self): + return 'ParlamentarCreate' + + class ListView(crud.base.CrudListView): + template_name = "parlamentares/parlamentares_list.html" + paginate_by = None + + def take_legislatura_id(self): + legislaturas = Legislatura.objects.all().order_by( + '-data_inicio', '-data_fim') + + try: + legislatura_id = int(self.request.GET['periodo']) + except MultiValueDictKeyError: + legislatura_id = legislaturas.first().id + + return legislatura_id + + def get_queryset(self): + mandatos = Mandato.objects.filter( + legislatura_id=self.take_legislatura_id()) + return mandatos + + def get_rows(self, object_list): + parlamentares = [] + for m in object_list: + + if m.parlamentar.filiacao_set.last(): + partido = ', '.join(str(p) for p in m.get_partidos()) + else: + partido = _('Sem Registro') + + parlamentar = [ + (m.parlamentar.nome_parlamentar, m.parlamentar.id), + (partido, None), + ('Sim' if m.parlamentar.ativo else 'Não', None) + ] + parlamentares.append(parlamentar) + return parlamentares + + def get_headers(self): + return ['Parlamentar', 'Partido', 'Ativo?'] + + def get_context_data(self, **kwargs): + context = super(ParlamentarCrud.ListView, self + ).get_context_data(**kwargs) + context.setdefault('title', self.verbose_name_plural) + + # Adiciona legislatura para filtrar parlamentares + legislaturas = Legislatura.objects.all().order_by( + '-data_inicio', '-data_fim') + context['legislaturas'] = legislaturas + context['legislatura_id'] = self.take_legislatura_id() + return context + + def validate(form, parlamentar, filiacao, request): data_filiacao = form.cleaned_data['data'] data_desfiliacao = form.cleaned_data['data_desfiliacao'] @@ -95,131 +157,14 @@ def validate(form, parlamentar, filiacao, request): return True -class ParlamentaresView(FormView): - template_name = "parlamentares/parlamentares_list.html" - - def get(self, request, *args, **kwargs): - form = ParlamentaresListForm() - - if not Legislatura.objects.all(): - mensagem = _('Cadastre alguma Legislatura antes' - ' de cadastrar algum Parlamentar') - messages.add_message(request, messages.INFO, mensagem) - return self.render_to_response( - {'legislaturas': [], - 'legislatura_id': 0, - 'form': form, - }) - - legislaturas = Legislatura.objects.all().order_by( - '-data_inicio', '-data_fim') - - mandatos = Mandato.objects.filter( - legislatura_id=legislaturas.first().id) - - parlamentares = [] - dict_parlamentar = {} - for m in mandatos: - - if m.parlamentar.filiacao_set.last(): - partido = m.parlamentar.filiacao_set.last().partido.sigla - else: - partido = _('Sem Registro') - - dict_parlamentar = { - 'id': m.parlamentar.id, - 'nome': m.parlamentar.nome_parlamentar, - 'partido': partido, - 'ativo': m.parlamentar.ativo} - parlamentares.append(dict_parlamentar) - - return self.render_to_response( - {'legislaturas': legislaturas, - 'legislatura_id': legislaturas.first().id, - 'form': form, - 'parlamentares': parlamentares}) - - def post(self, request, *args, **kwargs): - form = ParlamentaresListForm(request.POST) - - mandatos = Mandato.objects.filter( - legislatura_id=int(form.data['periodo'])) - - parlamentares = [] - dict_parlamentar = {} - for m in mandatos: - - if m.parlamentar.filiacao_set.last(): - partido = m.parlamentar.filiacao_set.last().partido.sigla - else: - partido = _('Sem Registro') - - dict_parlamentar = { - 'id': m.parlamentar.id, - 'nome': m.parlamentar.nome_parlamentar, - 'partido': partido, - 'ativo': m.parlamentar.ativo} - parlamentares.append(dict_parlamentar) - - return self.render_to_response( - {'legislaturas': Legislatura.objects.all().order_by( - '-data_inicio', '-data_fim'), - 'legislatura_id': int(form.data['periodo']), - 'form': form, - 'parlamentares': parlamentares}) - - -class ParlamentaresCadastroView(CreateView): - template_name = "parlamentares/parlamentares_cadastro.html" - form_class = ParlamentaresForm - model = Parlamentar - - def get_success_url(self): - return reverse('parlamentares:parlamentares') - - def get_context_data(self, **kwargs): - context = super(ParlamentaresCadastroView, self).get_context_data( - **kwargs) - legislatura_id = self.kwargs['pk'] - context.update({'legislatura_id': legislatura_id}) - return context - - def form_valid(self, form): - form.save() - return redirect(self.get_success_url()) - - -class ParlamentaresEditarView(UpdateView): - template_name = "parlamentares/parlamentares_cadastro.html" - form_class = ParlamentaresEditForm - model = Parlamentar - success_url = reverse_lazy('parlamentares:parlamentares') - - def form_valid(self, form): - parlamentar = form.instance - if 'salvar' in self.request.POST: - form.save() - elif 'excluir' in self.request.POST: - Mandato.objects.get(parlamentar=parlamentar).delete() - parlamentar.delete() - elif "remover-foto" in self.request.POST: - try: - os.unlink(parlamentar.fotografia.path) - except OSError: - pass # Should log this error!!!!! - parlamentar.fotografia = None - parlamentar.save() - return HttpResponseRedirect(self.get_success_url()) - - class ParlamentaresDependentesView(CreateView): - template_name = "parlamentares/parlamentares_dependentes.html" + template_name = "parlamentares/parlamentar_dependente.html" form_class = DependenteForm model = Dependente def get_success_url(self): pk = self.kwargs['pk'] - return reverse('parlamentares:parlamentares_dependentes', + return reverse('parlamentares:parlamentar_dependente', kwargs={'pk': pk}) def get_context_data(self, **kwargs): @@ -251,14 +196,14 @@ class ParlamentaresDependentesView(CreateView): class ParlamentaresDependentesEditView(UpdateView): - template_name = "parlamentares/parlamentares_dependentes_edit.html" + template_name = "parlamentares/parlamentar_dependente_edit.html" form_class = DependenteEditForm model = Dependente pk_url_kwarg = 'dk' def get_success_url(self): pk = self.kwargs['pk'] - return reverse('parlamentares:parlamentares_dependentes', + return reverse('parlamentares:parlamentar_dependente', kwargs={'pk': pk}) def get_context_data(self, **kwargs): @@ -395,13 +340,13 @@ class MesaDiretoraView(FormView): class FiliacaoView(CreateView): - template_name = "parlamentares/parlamentares_filiacao.html" + template_name = "parlamentares/parlamentar_filiacao.html" form_class = FiliacaoForm model = Filiacao def get_success_url(self): pk = self.kwargs['pk'] - return reverse('parlamentares:parlamentares_filiacao', + return reverse('parlamentares:parlamentar_filiacao', kwargs={'pk': pk}) def get_context_data(self, **kwargs): @@ -435,14 +380,14 @@ class FiliacaoView(CreateView): class FiliacaoEditView(UpdateView): - template_name = "parlamentares/parlamentares_filiacao_edit.html" + template_name = "parlamentares/parlamentar_filiacao_edit.html" form_class = FiliacaoEditForm model = Filiacao pk_url_kwarg = 'dk' def get_success_url(self): pk = self.kwargs['pk'] - return reverse('parlamentares:parlamentares_filiacao', + return reverse('parlamentares:parlamentar_filiacao', kwargs={'pk': pk}) def get_context_data(self, **kwargs): @@ -470,13 +415,13 @@ class FiliacaoEditView(UpdateView): class MandatoView(CreateView): - template_name = "parlamentares/parlamentares_mandato.html" + template_name = "parlamentares/parlamentar_mandato.html" model = Mandato form_class = MandatoForm def get_success_url(self): pk = self.kwargs['pk'] - return reverse('parlamentares:parlamentares_mandato', + return reverse('parlamentares:parlamentar_mandato', kwargs={'pk': pk}) def get_context_data(self, **kwargs): @@ -508,14 +453,14 @@ class MandatoView(CreateView): class MandatoEditView(UpdateView): - template_name = "parlamentares/parlamentares_mandato_edit.html" + template_name = "parlamentares/parlamentar_mandato_edit.html" model = Mandato form_class = MandatoEditForm pk_url_kwarg = 'dk' def get_success_url(self): pk = self.kwargs['pk'] - return reverse('parlamentares:parlamentares_mandato', + return reverse('parlamentares:parlamentar_mandato', kwargs={'pk': pk}) def get_context_data(self, **kwargs): diff --git a/protocoloadm/urls.py b/protocoloadm/urls.py index 6e2103ac0..e69decff5 100644 --- a/protocoloadm/urls.py +++ b/protocoloadm/urls.py @@ -81,21 +81,21 @@ urlpatterns = [ # TODO: move to Proposicoes app - url(r'^proposicoes$', + url(r'^proposicao$', ProposicaoView.as_view(), name='proposicao'), - url(r'^proposicoes/proposicao-receber', + url(r'^proposicao/proposicao-receber', ProposicaoReceberView.as_view(), name='proposicao_receber'), - url(r'^proposicoes/proposicoes-naorecebidas', + url(r'^proposicao/proposicao-naorecebidas', ProposicoesNaoRecebidasView.as_view(), - name='proposicoes_naorecebidas'), - url(r'^proposicoes/proposicoes-naoincorporadas', + name='proposicao_naorecebidas'), + url(r'^proposicao/proposicao-naoincorporadas', ProposicoesNaoIncorporadasView.as_view(), - name='proposicoes_naoincorporadas'), - url(r'^proposicoes/proposicoes-incorporadas', + name='proposicao_naoincorporadas'), + url(r'^proposicao/proposicao-incorporadas', ProposicoesIncorporadasView.as_view(), - name='proposicoes_incorporadas'), - url(r'^proposicoes/(?P\d+)/proposicao', + name='proposicao_incorporadas'), + url(r'^proposicao/(?P\d+)/proposicao', ProposicaoDetailView.as_view(), name='proposicao_view'), - url(r'^proposicoes/pesquisar_autores', - pesquisa_autores, name='pesquisar_autores') + url(r'^proposicao/pesquisar_autor', + pesquisa_autores, name='pesquisar_autor') ] diff --git a/protocoloadm/views.py b/protocoloadm/views.py index 74c1c1f5d..c4b3e8b2a 100644 --- a/protocoloadm/views.py +++ b/protocoloadm/views.py @@ -293,7 +293,7 @@ class ProposicaoReceberView(TemplateView): class ProposicoesNaoRecebidasView(ListView): - template_name = "protocoloadm/proposicoes_naorecebidas.html" + template_name = "protocoloadm/proposicao_naorecebidas.html" model = Proposicao paginate_by = 10 @@ -302,7 +302,7 @@ class ProposicoesNaoRecebidasView(ListView): class ProposicoesNaoIncorporadasView(ListView): - template_name = "protocoloadm/proposicoes_naoincorporadas.html" + template_name = "protocoloadm/proposicao_naoincorporadas.html" model = Proposicao paginate_by = 10 @@ -313,7 +313,7 @@ class ProposicoesNaoIncorporadasView(ListView): class ProposicoesIncorporadasView(ListView): - template_name = "protocoloadm/proposicoes_incorporadas.html" + template_name = "protocoloadm/proposicao_incorporadas.html" model = Proposicao paginate_by = 10 diff --git a/relatorios/urls.py b/relatorios/urls.py index 9dbcbbec0..a2837818b 100644 --- a/relatorios/urls.py +++ b/relatorios/urls.py @@ -10,22 +10,22 @@ from .views import (relatorio_capa_processo, app_name = AppConfig.name urlpatterns = [ - url(r'^relatorios/materia$', relatorio_materia, name='relatorio_materia'), - url(r'^relatorios/capa_processo$', + url(r'^relatorio/materia$', relatorio_materia, name='relatorio_materia'), + url(r'^relatorio/capa_processo$', relatorio_capa_processo, name='relatorio_capa_processo'), - url(r'^relatorios/ordem_dia$', relatorio_ordem_dia, + url(r'^relatorio/ordem_dia$', relatorio_ordem_dia, name='relatorio_ordem_dia'), - url(r'^relatorios/relatorio_documento_administrativo$', + url(r'^relatorio/relatorio_documento_administrativo$', relatorio_documento_administrativo, name='relatorio_documento_administrativo'), - url(r'^relatorios/espelho$', relatorio_espelho, + url(r'^relatorio/espelho$', relatorio_espelho, name='relatorio_espelho'), - url(r'^relatorios/(?P\d+)/sessao_plenaria$', + url(r'^relatorio/(?P\d+)/sessao_plenaria$', relatorio_sessao_plenaria, name='relatorio_sessao_plenaria'), - url(r'^relatorios/protocolo$', + url(r'^relatorio/protocolo$', relatorio_protocolo, name='relatorio_protocolo'), - url(r'^relatorios/(?P\d+)/(?P\d+)/etiqueta_protocolo$', + url(r'^relatorio/(?P\d+)/(?P\d+)/etiqueta_protocolo$', relatorio_etiqueta_protocolo, name='relatorio_etiqueta_protocolo'), - url(r'^relatorios/pauta_sessao$', + url(r'^relatorio/pauta_sessao$', relatorio_pauta_sessao, name='relatorio_pauta_sessao'), ] diff --git a/sapl/urls.py b/sapl/urls.py index 2afef0e3c..72facc767 100644 --- a/sapl/urls.py +++ b/sapl/urls.py @@ -17,22 +17,34 @@ from django.conf.urls import include, url from django.contrib import admin from django.views.generic.base import TemplateView +import base.urls +import comissoes.urls +import compilacao.urls +import lexml.urls +import materia.urls +import norma.urls +import painel.urls +import parlamentares.urls +import protocoloadm.urls +import relatorios.urls +import sessao.urls + urlpatterns = [ url(r'^$', TemplateView.as_view(template_name='index.html')), url(r'^admin/', include(admin.site.urls)), - url(r'', include('comissoes.urls')), - url(r'', include('sessao.urls')), - url(r'', include('parlamentares.urls')), - url(r'', include('materia.urls')), - url(r'', include('norma.urls')), - url(r'', include('lexml.urls')), - url(r'', include('painel.urls')), - url(r'', include('protocoloadm.urls')), - url(r'', include('compilacao.urls')), - url(r'', include('relatorios.urls')), + url(r'', include(comissoes.urls)), + url(r'', include(sessao.urls)), + url(r'', include(parlamentares.urls)), + url(r'', include(materia.urls)), + url(r'', include(norma.urls)), + url(r'', include(lexml.urls)), + url(r'', include(painel.urls)), + url(r'', include(protocoloadm.urls)), + url(r'', include(compilacao.urls)), + url(r'', include(relatorios.urls)), # must come at the end # so that base /sistema/ url doesn't capture its children - url(r'', include('base.urls')), + url(r'', include(base.urls)), ] diff --git a/sapl/utils.py b/sapl/utils.py index 6f7004c67..c2a7c5f68 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -184,3 +184,9 @@ restringe_tipos_de_arquivo_txt = fabrica_validador_de_tipos_de_arquivo( TIPOS_TEXTO_PERMITIDOS, 'restringe_tipos_de_arquivo_txt') restringe_tipos_de_arquivo_img = fabrica_validador_de_tipos_de_arquivo( TIPOS_IMG_PERMITIDOS, 'restringe_tipos_de_arquivo_img') + + +def intervalos_tem_intersecao(a_inicio, a_fim, b_inicio, b_fim): + maior_inicio = max(a_inicio, b_inicio) + menor_fim = min(a_fim, b_fim) + return maior_inicio <= menor_fim diff --git a/sessao/forms.py b/sessao/forms.py index 4b2367e52..d62af30c7 100644 --- a/sessao/forms.py +++ b/sessao/forms.py @@ -1,14 +1,6 @@ -from crispy_forms.helper import FormHelper -from crispy_forms.layout import Fieldset, Layout from django import forms -from django.forms import ModelForm from django.utils.translation import ugettext_lazy as _ -import crispy_layout_mixin -from crispy_layout_mixin import form_actions - -from .models import SessaoPlenaria - class PresencaForm(forms.Form): presenca = forms.CharField(required=False, initial=False) @@ -66,68 +58,3 @@ class VotacaoForm(forms.Form): class VotacaoEditForm(forms.Form): pass - - -class SessaoForm(ModelForm): - - class Meta: - model = SessaoPlenaria - fields = ['numero', - 'tipo', - 'legislatura', - 'sessao_legislativa', - 'data_inicio', - 'hora_inicio', - 'iniciada', - 'data_fim', - 'hora_fim', - 'finalizada', - 'upload_pauta', - 'upload_ata', - 'url_audio', - 'url_video'] - - widgets = { - 'hora_inicio': forms.TextInput(attrs={'class': 'hora'}), - 'hora_fim': forms.TextInput(attrs={'class': 'hora'}), - } - - def __init__(self, *args, **kwargs): - - row1 = crispy_layout_mixin.to_row( - [('numero', 3), - ('tipo', 3), - ('legislatura', 3), - ('sessao_legislativa', 3)]) - - row2 = crispy_layout_mixin.to_row( - [('data_inicio', 4), - ('hora_inicio', 4), - ('iniciada', 4)]) - - row3 = crispy_layout_mixin.to_row( - [('data_fim', 4), - ('hora_fim', 4), - ('finalizada', 4)]) - - row4 = crispy_layout_mixin.to_row( - [('upload_pauta', 6), - ('upload_ata', 6)]) - - row5 = crispy_layout_mixin.to_row( - [('url_audio', 6), - ('url_video', 6)]) - - self.helper = FormHelper() - self.helper.layout = Layout( - Fieldset( - _('Dados Básicos'), - row1, - row2, - row3, - row4, - row5, - form_actions() - ) - ) - super(SessaoForm, self).__init__(*args, **kwargs) diff --git a/sessao/urls.py b/sessao/urls.py index 0710e74b9..4a50be674 100644 --- a/sessao/urls.py +++ b/sessao/urls.py @@ -12,8 +12,7 @@ from sessao.views import (EditExpedienteOrdemDiaView, EditMateriaOrdemDiaView, PautaExpedienteDetail, PautaOrdemDetail, PautaSessaoDetailView, PautaSessaoListView, PresencaOrdemDiaView, PresencaView, ResumoView, - SessaoCadastroView, SessaoCrud, SessaoListView, - SessaoPlenariaView, TipoExpedienteCrud, + SessaoCrud, SessaoPlenariaView, TipoExpedienteCrud, TipoResultadoVotacaoCrud, TipoSessaoCrud, VotacaoEditView, VotacaoExpedienteEditView, VotacaoExpedienteView, VotacaoNominalEditView, @@ -25,7 +24,34 @@ from .apps import AppConfig app_name = AppConfig.name -urlpatterns_sessao = SessaoCrud.get_urls() + [ +sessao_rest = [ + url(r'^sessao$', SessaoPlenariaView.as_view(), name='sessao_rest') +] + +urlpatterns = [ + url(r'^sessao/', include(SessaoCrud.get_urls())), + + url(r'^media/(?P.*)$', serve, + {'document_root': settings.MEDIA_ROOT}), + url(r'^rest/', include(sessao_rest)), + url(r'^sistema/sessao-plenaria/tipo/', + include(TipoSessaoCrud.get_urls())), + url(r'^sistema/sessao-plenaria/tipo-resultado-votacao/', + include(TipoResultadoVotacaoCrud.get_urls())), + url(r'^sistema/sessao-plenaria/tipo-expediente/', + include(TipoExpedienteCrud.get_urls())), + + # PAUTA SESSÃO + url(r'^pauta-sessao$', + PautaSessaoListView.as_view(), name='list_pauta_sessao'), + url(r'^pauta-sessao/(?P\d+)$', + PautaSessaoDetailView.as_view(), name='pauta_sessao_detail'), + url(r'^pauta-sessao/(?P\d+)/expediente/$', + PautaExpedienteDetail.as_view(), name='pauta_expediente_detail'), + url(r'^pauta-sessao/(?P\d+)/ordem/$', + PautaOrdemDetail.as_view(), name='pauta_ordem_detail'), + + # Subnav sessão url(r'^(?P\d+)/expediente$', ExpedienteView.as_view(), name='expediente'), url(r'^(?P\d+)/presenca$', @@ -89,32 +115,4 @@ urlpatterns_sessao = SessaoCrud.get_urls() + [ VotacaoExpedienteView.as_view(), name='votacaosecretaexp'), url(r'^(?P\d+)/matexp/votsec/view/(?P\d+)/(?P\d+)$', VotacaoExpedienteEditView.as_view(), name='votacaosecretaexpedit'), - url(r'^sessao-list$', - SessaoListView.as_view(), name='list_sessao'), - url(r'^pauta-sessao-list$', - PautaSessaoListView.as_view(), name='list_pauta_sessao'), - url(r'^(?P\d+)/pauta-sessao-detail$', - PautaSessaoDetailView.as_view(), name='pauta_sessao_detail'), - url(r'^cadastro$', SessaoCadastroView.as_view(), name='sessao_cadastro'), - url(r'^pauta-sessao/(?P\d+)/expediente/$', - PautaExpedienteDetail.as_view(), name='pauta_expediente_detail'), - url(r'^pauta-sessao/(?P\d+)/ordem/$', - PautaOrdemDetail.as_view(), name='pauta_ordem_detail'), -] - -sessao_rest = [ - url(r'^sessao$', SessaoPlenariaView.as_view(), name='sessao_rest') -] - -urlpatterns = [ - url(r'^sessao/', include(urlpatterns_sessao)), - url(r'^media/(?P.*)$', serve, - {'document_root': settings.MEDIA_ROOT}), - url(r'^rest/', include(sessao_rest)), - url(r'^sistema/sessao-plenaria/tipo/', - include(TipoSessaoCrud.get_urls())), - url(r'^sistema/sessao-plenaria/tipo-resultado-votacao/', - include(TipoResultadoVotacaoCrud.get_urls())), - url(r'^sistema/sessao-plenaria/tipo-expediente/', - include(TipoExpedienteCrud.get_urls())) ] diff --git a/sessao/views.py b/sessao/views.py index 95be1199c..a8fbbb002 100644 --- a/sessao/views.py +++ b/sessao/views.py @@ -3,14 +3,15 @@ from re import sub from django.contrib import messages from django.core.exceptions import ObjectDoesNotExist -from django.core.urlresolvers import reverse, reverse_lazy +from django.core.urlresolvers import reverse from django.forms.utils import ErrorList from django.utils.html import strip_tags from django.utils.translation import ugettext_lazy as _ -from django.views.generic import CreateView, ListView +from django.views.generic import ListView, TemplateView from django.views.generic.edit import FormMixin from rest_framework import generics +import crud.base from crud.base import Crud, make_pagination from materia.models import (Autoria, DocumentoAcessorio, TipoMateriaLegislativa, Tramitacao) @@ -20,8 +21,7 @@ from sessao.serializers import SessaoPlenariaSerializer from .forms import (ExpedienteForm, ListMateriaForm, MateriaOrdemDiaForm, MesaForm, OradorDeleteForm, OradorForm, PresencaForm, - SessaoForm, VotacaoEditForm, VotacaoForm, - VotacaoNominalForm) + VotacaoEditForm, VotacaoForm, VotacaoNominalForm) from .models import (CargoMesa, ExpedienteMateria, ExpedienteSessao, IntegranteMesa, MateriaLegislativa, Orador, OradorExpediente, OrdemDia, PresencaOrdemDia, @@ -30,7 +30,6 @@ from .models import (CargoMesa, ExpedienteMateria, ExpedienteSessao, VotoParlamentar) TipoSessaoCrud = Crud.build(TipoSessaoPlenaria, 'tipo_sessao_plenaria') -SessaoCrud = Crud.build(SessaoPlenaria, '') ExpedienteMateriaCrud = Crud.build(ExpedienteMateria, '') OrdemDiaCrud = Crud.build(OrdemDia, '') TipoResultadoVotacaoCrud = Crud.build( @@ -39,6 +38,21 @@ TipoExpedienteCrud = Crud.build(TipoExpediente, 'tipo_expediente') RegistroVotacaoCrud = Crud.build(RegistroVotacao, '') +class SessaoCrud(Crud): + model = SessaoPlenaria + help_path = 'sessao_plenaria' + + class BaseMixin(crud.base.BaseMixin): + list_field_names = ['numero', 'tipo', 'legislatura', + 'sessao_legislativa', 'data_inicio', 'hora_inicio'] + + # FIXME!!!! corrigir referencias no codigo e remover isso!!!!! + # fazer com #230 + class CrudDetailView(crud.base.BaseMixin, crud.base.DetailView): + model = SessaoPlenaria + help_path = 'sessao_plenaria' + + class PresencaMixin: def get_parlamentares(self): @@ -56,9 +70,10 @@ class PresencaMixin: yield (parlamentar, False) -class PresencaView(FormMixin, PresencaMixin, SessaoCrud.CrudDetailView): +class PresencaView(FormMixin, PresencaMixin, SessaoCrud.DetailView): template_name = 'sessao/presenca.html' form_class = PresencaForm + model = SessaoPlenaria def post(self, request, *args, **kwargs): self.object = self.get_object() @@ -96,7 +111,7 @@ class PresencaView(FormMixin, PresencaMixin, SessaoCrud.CrudDetailView): return reverse('sessao:presenca', kwargs={'pk': pk}) -class PainelView(SessaoCrud.CrudDetailView): +class PainelView(TemplateView): template_name = 'sessao/painel.html' @@ -2238,12 +2253,6 @@ class PautaSessaoDetailView(SessaoCrud.CrudDetailView): return self.render_to_response(context) -class SessaoCadastroView(CreateView): - template_name = "sessao/sessao_cadastro.html" - form_class = SessaoForm - success_url = reverse_lazy('sessao:list_sessao') - - class SessaoPlenariaView(generics.ListAPIView): queryset = SessaoPlenaria.objects.all() serializer_class = SessaoPlenariaSerializer diff --git a/static/js/app.js b/static/js/app.js index a029fa6a6..3e210a17a 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -74,7 +74,7 @@ function autorModal() { $( "#pesquisar" ).click(function() { var query = $("#q").val() - $.get("/proposicoes/pesquisar_autores?q="+ query, function( + $.get("/proposicao/pesquisar_autor?q="+ query, function( data, status){ $("#div-resultado").children().remove(); diff --git a/templates/base.html b/templates/base.html index 85f491306..e14cb7d89 100644 --- a/templates/base.html +++ b/templates/base.html @@ -49,7 +49,7 @@ - + @@ -68,7 +68,7 @@