diff --git a/materia/migrations/0004_materialegislativa_texto_original.py b/materia/migrations/0004_materialegislativa_texto_original.py new file mode 100644 index 000000000..163ae0ff2 --- /dev/null +++ b/materia/migrations/0004_materialegislativa_texto_original.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import materia.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0003_auto_20150729_1717'), + ] + + operations = [ + migrations.AddField( + model_name='materialegislativa', + name='texto_original', + field=models.FileField(null=True, blank=True, verbose_name='Texto original (PDF)', upload_to=materia.models.texto_upload_path), + ), + ] diff --git a/materia/models.py b/materia/models.py index 0fba3a6eb..a63c6e060 100644 --- a/materia/models.py +++ b/materia/models.py @@ -45,6 +45,14 @@ class Origem(models.Model): return self.nome +def get_materia_media_path(instance, subpath, filename): + return './materia/%s/%s/%s' % (instance.numero, subpath, filename) + + +def texto_upload_path(instance, filename): + return get_materia_media_path(instance, 'materia', filename) + + class MateriaLegislativa(models.Model): TIPO_APRESENTACAO_CHOICES, ORAL, ESCRITA = make_choices( 'O', _('Oral'), @@ -108,6 +116,11 @@ class MateriaLegislativa(models.Model): through_fields=( 'materia_principal', 'materia_anexada')) + texto_original = models.FileField( + blank=True, + null=True, + upload_to=texto_upload_path, + verbose_name=_('Texto original (PDF)')) class Meta: verbose_name = _('Matéria Legislativa') diff --git a/materia/urls.py b/materia/urls.py index 23350e944..b8a0aaf31 100644 --- a/materia/urls.py +++ b/materia/urls.py @@ -1,10 +1,11 @@ from django.conf.urls import include, url -from materia.views import (autor_crud, orgao_crud, origem_crud, - regime_tramitacao_crud, status_tramitacao_crud, - tipo_autor_crud, tipo_documento_crud, - tipo_fim_relatoria_crud, tipo_materia_crud, - tipo_proposicao_crud, unidade_tramitacao_crud) +from materia.views import (autor_crud, materia_legislativa_crud, orgao_crud, + origem_crud, regime_tramitacao_crud, + status_tramitacao_crud, tipo_autor_crud, + tipo_documento_crud, tipo_fim_relatoria_crud, + tipo_materia_crud, tipo_proposicao_crud, + unidade_tramitacao_crud) urlpatterns = [ url(r'^sistema/proposicoes/tipo/', include(tipo_proposicao_crud.urls)), @@ -25,4 +26,5 @@ urlpatterns = [ url(r'^sistema/materia/status-tramitacao/', include(status_tramitacao_crud.urls)), url(r'^sistema/materia/orgao/', include(orgao_crud.urls)), + url(r'^materia/', include(materia_legislativa_crud.urls)), ] diff --git a/materia/views.py b/materia/views.py index d931cc22c..0072362a3 100644 --- a/materia/views.py +++ b/materia/views.py @@ -49,19 +49,16 @@ materia_legislativa_crud = build_crud( [_('Identificação Básica'), [('tipo', 4), ('numero', 4), ('ano', 4)], [('data_apresentacao', 4), - ('num_protocolo_spdo_FIXME', 4), + ('numero_protocolo', 4), ('tipo_apresentacao', 4)], - [('nom_arquivo_FIXME', 6), ('modelo_FIXME', 6)]], - - [_('Proposição Eletrônica')], + [('texto_original', 12)]], [_('Outras Informações'), [('apelido', 4), ('dias_prazo', 4), ('polemica', 4)], [('objeto', 4), ('regime_tramitacao', 4), ('em_tramitacao', 4)], - [('data_fim_prazo', 3), - ('data_publicacao', 3), - ('complementar', 3), - ('txt_cep_FIXME', 3)]], + [('data_fim_prazo', 4), + ('data_publicacao', 4), + ('complementar', 4)]], [_('Origem Externa'), [('tipo_origem_externa', 4), diff --git a/sessao/urls.py b/sessao/urls.py index 531571a86..b63210bf3 100644 --- a/sessao/urls.py +++ b/sessao/urls.py @@ -1,10 +1,11 @@ from django.conf.urls import include, url -from sessao.views import (ExpedienteView, OradorExpedienteDelete, - OradorExpedienteEdit, OradorExpedienteView, - PainelView, PresencaOrdemDiaView, PresencaView, - sessao_crud, tipo_expediente_crud, - tipo_resultado_votacao_crud, tipo_sessao_crud) +from sessao.views import (ExpedienteView, MateriaOrdemDiaView, MesaView, + OradorExpedienteDelete, OradorExpedienteEdit, + OradorExpedienteView, PainelView, + PresencaOrdemDiaView, PresencaView, sessao_crud, + tipo_expediente_crud, tipo_resultado_votacao_crud, + tipo_sessao_crud) urlpatterns_sessao = sessao_crud.urlpatterns + [ url(r'^(?P\d+)/expediente$', @@ -22,6 +23,9 @@ urlpatterns_sessao = sessao_crud.urlpatterns + [ OradorExpedienteDelete.as_view(), name='oradorexcluir'), url(r'^(?P\d+)/oradorexpediente/editar/(?P\d+)$', OradorExpedienteEdit.as_view(), name='oradoreditar'), + url(r'^(?P\d+)/mesa$', MesaView.as_view(), name='mesa'), + url(r'^(?P\d+)/materiaordemdia$', + MateriaOrdemDiaView.as_view(), name='materiaordemdia') ] sessao_urls = urlpatterns_sessao, sessao_crud.namespace, sessao_crud.namespace diff --git a/sessao/views.py b/sessao/views.py index 6496a20cf..752d6759e 100644 --- a/sessao/views.py +++ b/sessao/views.py @@ -1,14 +1,21 @@ +from datetime import datetime +from re import sub + from django import forms +from django.core.urlresolvers import reverse +from django.utils.html import strip_tags from django.utils.translation import ugettext_lazy as _ from django.views.generic.edit import FormMixin from extra_views import InlineFormSetView +from materia.models import TipoMateriaLegislativa from parlamentares.models import Parlamentar from sapl.crud import build_crud -from .models import (ExpedienteMateria, ExpedienteSessao, OradorExpediente, - OrdemDia, PresencaOrdemDia, RegistroVotacao, - SessaoPlenaria, SessaoPlenariaPresenca, TipoExpediente, +from .models import (CargoMesa, ExpedienteMateria, ExpedienteSessao, + IntegranteMesa, OradorExpediente, OrdemDia, + PresencaOrdemDia, RegistroVotacao, SessaoPlenaria, + SessaoPlenariaPresenca, TipoExpediente, TipoResultadoVotacao, TipoSessaoPlenaria) tipo_sessao_crud = build_crud( @@ -93,6 +100,10 @@ class ExpedienteView(InlineFormSetView): can_delete = True extra = 1 + def get_success_url(self): + pk = self.kwargs['pk'] + return reverse('sessaoplenaria:expediente', kwargs={'pk': pk}) + class PresencaForm(forms.Form): presenca = forms.CharField(required=False, initial=False) @@ -132,7 +143,8 @@ class PresencaView(FormMixin, sessao_crud.CrudDetailView): return self.form_invalid(form) def get_success_url(self): - return self.detail_url + pk = self.kwargs['pk'] + return reverse('sessaoplenaria:presenca', kwargs={'pk': pk}) def get_parlamentares(self): self.object = self.get_object() @@ -192,7 +204,8 @@ class PresencaOrdemDiaView(FormMixin, sessao_crud.CrudDetailView): return self.form_invalid(form) def get_success_url(self): - return self.detail_url + pk = self.kwargs['pk'] + return reverse('sessaoplenaria:presencaordemdia', kwargs={'pk': pk}) def get_parlamentares(self): self.object = self.get_object() @@ -215,6 +228,78 @@ class PresencaOrdemDiaView(FormMixin, sessao_crud.CrudDetailView): yield (parlamentar, True) +class MateriaOrdemDiaForm(forms.Form): + data_sessao = forms.CharField(required=True) + numero_ordem = forms.IntegerField(required=True) + tipo_votacao = forms.IntegerField(required=True) + tipo_sessao = forms.IntegerField(required=True) + ano_materia = forms.IntegerField(required=True) + numero_materia = forms.IntegerField(required=True) + tipo_materia = forms.IntegerField(required=True) + observacao = forms.CharField(required=False) + + +class MateriaOrdemDiaView(FormMixin, sessao_crud.CrudDetailView): + template_name = 'sessao/materia_ordemdia.html' + form_class = MateriaOrdemDiaForm + + def get_success_url(self): + pk = self.kwargs['pk'] + return reverse('sessaoplenaria:materiaordemdia', kwargs={'pk': pk}) + + def get(self, request, *args, **kwargs): + self.object = self.get_object() + context = self.get_context_data(object=self.object) + + now = datetime.now() + + tipo_materia = TipoMateriaLegislativa.objects.all() + data_sessao = "%s/%s/%s" % (now.day, now.month, now.year) + tipo_sessao = TipoSessaoPlenaria.objects.all() + tipo_votacao = ExpedienteMateria.TIPO_VOTACAO_CHOICES + ano_materia = now.year + + context.update({'data_sessao': data_sessao, + 'tipo_sessao': tipo_sessao, + 'tipo_materia': tipo_materia, + 'tipo_votacao': tipo_votacao, + 'ano_materia': ano_materia, + 'error_message': '', }) + return self.render_to_response(context) + + def post(self, request, *args, **kwargs): + + self.object = self.get_object() + context = self.get_context_data(object=self.object) + form = MateriaOrdemDiaForm(request.POST) + + print(form) + + if form.is_valid(): + + # TODO: Pra que tipo_materia e tipo_sessao + # se já existem em seus respectivos objetos??? + # TODO: barrar matérias não existentes + # TODO: barrar criação de ordemdia para materias já incluídas + + ordemdia = OrdemDia() + ordemdia.sessao_plenaria_id = self.object.id + ordemdia.materia_id = request.POST['numero_materia'] + ordemdia.numero_ordem = request.POST['numero_ordem'] + ordemdia.data_ordem = datetime.now() + ordemdia.observacao = sub( + ' ', ' ', strip_tags(request.POST['observacao'])) + ordemdia.tipo_votacao = request.POST['tipo_votacao'] + + ordemdia.save() + + return self.form_valid(form) + else: + context.update( + {'error_message': "Não foi possível salvar formulário!"}) + return self.form_invalid(form) + + class OradorForm(forms.Form): numero_ordem = forms.IntegerField(required=True) parlamentar = forms.CharField(required=False, max_length=20) @@ -245,7 +330,8 @@ class OradorExpedienteDelete(FormMixin, sessao_crud.CrudDetailView): return self.form_invalid(form) def get_success_url(self): - return self.detail_url + pk = self.kwargs['pk'] + return reverse('sessaoplenaria:oradorexpediente', kwargs={'pk': pk}) class OradorExpedienteEdit(FormMixin, sessao_crud.CrudDetailView): @@ -253,7 +339,8 @@ class OradorExpedienteEdit(FormMixin, sessao_crud.CrudDetailView): form_class = OradorForm def get_success_url(self): - return self.detail_url + pk = self.kwargs['pk'] + return reverse('sessaoplenaria:oradorexpediente', kwargs={'pk': pk}) def post(self, request, *args, **kwargs): self.object = self.get_object() @@ -355,4 +442,100 @@ class OradorExpedienteView(FormMixin, sessao_crud.CrudDetailView): return self.form_invalid(form) def get_success_url(self): - return self.detail_url + pk = self.kwargs['pk'] + return reverse('sessaoplenaria:oradorexpediente', kwargs={'pk': pk}) + + +class MesaForm(forms.Form): + parlamentar = forms.IntegerField(required=True) + cargo = forms.IntegerField(required=True) + + +class MesaView(FormMixin, sessao_crud.CrudDetailView): + template_name = 'sessao/mesa.html' + form_class = MesaForm + + def get_success_url(self): + pk = self.kwargs['pk'] + return reverse('sessaoplenaria:mesa', kwargs={'pk': pk}) + + def post(self, request, *args, **kwargs): + self.object = self.get_object() + form = MesaForm(request.POST) + + if 'Incluir' in request.POST: + if form.is_valid(): + integrante = IntegranteMesa() + integrante.sessao_plenaria_id = self.object.id + integrante.parlamentar_id = request.POST['parlamentar'] + integrante.cargo_id = request.POST['cargo'] + integrante.save() + + return self.form_valid(form) + + else: + form.clean() + return self.form_valid(form) + elif 'Excluir' in request.POST: + ids = request.POST['composicao_mesa'].split(':') + IntegranteMesa.objects.get( + sessao_plenaria_id=self.object.id, + parlamentar_id=ids[0], + cargo_id=ids[1] + ).delete() + + return self.form_valid(form) + + def get(self, request, *args, **kwargs): + self.object = self.get_object() + context = self.get_context_data(object=self.object) + + mesa = IntegranteMesa.objects.filter( + sessao_plenaria=self.object) + + integrantes = [] + for m in mesa: + parlamentar = Parlamentar.objects.get( + id=m.parlamentar_id) + cargo = CargoMesa.objects.get( + id=m.cargo_id) + integrante = {'parlamentar': parlamentar, 'cargo': cargo} + integrantes.append(integrante) + + context.update({'integrantes': integrantes}) + + return self.render_to_response(context) + + def get_candidatos_mesa(self): + self.object = self.get_object() + lista_parlamentares = [] + lista_integrantes = [] + + for parlamentar in Parlamentar.objects.all(): + if parlamentar.ativo: + lista_parlamentares.append(parlamentar) + + for integrante in IntegranteMesa.objects.filter( + sessao_plenaria=self.object): + parlamentar = Parlamentar.objects.get( + id=integrante.parlamentar_id) + lista_integrantes.append(parlamentar) + + lista = list(set(lista_parlamentares) - set(lista_integrantes)) + lista.sort(key=lambda x: x.nome_parlamentar) + return lista + + def get_cargos_mesa(self): + self.object = self.get_object() + lista_cargos = CargoMesa.objects.all() + lista_cargos_ocupados = [] + + for integrante in IntegranteMesa.objects.filter( + sessao_plenaria=self.object): + cargo = CargoMesa.objects.get( + id=integrante.cargo_id) + lista_cargos_ocupados.append(cargo) + + lista = list(set(lista_cargos) - set(lista_cargos_ocupados)) + lista.sort(key=lambda x: x.descricao) + return lista diff --git a/templates/base.html b/templates/base.html index b68cd5754..507f8c602 100644 --- a/templates/base.html +++ b/templates/base.html @@ -12,7 +12,6 @@ {% block head_title %}{% trans 'SAPL - Sistema de Apoio ao Processo Legislativo' %}{% endblock %} {% block head_content %} - {# Styles #} @@ -27,8 +26,7 @@ - - + {% endblock %} diff --git a/templates/sessao/materia_ordemdia.html b/templates/sessao/materia_ordemdia.html new file mode 100644 index 000000000..7abaa6e11 --- /dev/null +++ b/templates/sessao/materia_ordemdia.html @@ -0,0 +1,46 @@ +{% extends "sessao/sessaoplenaria_detail.html" %} +{% load i18n %} + +{% block detail_content %} +
+ {{ error_message }} +
+
+ {% csrf_token %} + Data da Sessão: {{data_sessao}}
+ + Tipo da Sessão: + + Número Ordem: + +
+ Tipo Matéria: + + Número Matéria: + + Ano Matéria: + + + Tipo Votação: + +
+ Ementa: + + +
+{% endblock detail_content %} \ No newline at end of file diff --git a/templates/sessao/mesa.html b/templates/sessao/mesa.html new file mode 100644 index 000000000..77d395f92 --- /dev/null +++ b/templates/sessao/mesa.html @@ -0,0 +1,44 @@ +{% extends "sessao/sessaoplenaria_detail.html" %} +{% load i18n %} + +{% block detail_content %} +
+ Mesa Diretora da Sessão +
+ {% csrf_token %} + +
    +
  • + +
  • + +
  • + {% if view.get_cargos_mesa %}{% endif %} +
    +
    + +
  • + {% if view.get_cargos_mesa %} +
  • + + +
  • + {% endif %} +
+
+
+{% endblock detail_content %} diff --git a/templates/sessao/sessaoplenaria_detail.html b/templates/sessao/sessaoplenaria_detail.html index 70b8f5bb5..0c1bb18a2 100644 --- a/templates/sessao/sessaoplenaria_detail.html +++ b/templates/sessao/sessaoplenaria_detail.html @@ -8,6 +8,8 @@
{% trans 'Presença' %}
{% trans 'Presença Ordem do Dia' %}
{% trans 'Oradores do Expediente' %}
+
{% trans 'Mesa' %}
{% trans 'Painel Eletrônico' %}
+
{% trans 'Matérias' %}
{% endblock sections_nav %}