diff --git a/sapl/materia/migrations/0055_auto_20190702_1751.py b/sapl/materia/migrations/0055_auto_20190702_1751.py new file mode 100644 index 000000000..7ba7ad215 --- /dev/null +++ b/sapl/materia/migrations/0055_auto_20190702_1751.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.22 on 2019-07-02 20:51 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0054_merge_20190802_1117'), + ] + + operations = [ + migrations.AlterModelOptions( + name='tramitacao', + options={ + 'ordering': ['-id', '-timestamp', '-data_tramitacao'], + 'verbose_name': 'Tramitação', + 'verbose_name_plural': 'Tramitações' + }, + ), + ] diff --git a/sapl/materia/models.py b/sapl/materia/models.py index 219b38971..976ba6d50 100644 --- a/sapl/materia/models.py +++ b/sapl/materia/models.py @@ -1076,6 +1076,7 @@ class Tramitacao(models.Model): class Meta: verbose_name = _('Tramitação') verbose_name_plural = _('Tramitações') + ordering = ['-id', '-timestamp', '-data_tramitacao'] def __str__(self): return _('%(materia)s | %(status)s | %(data)s') % { diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index 570a706c4..a6865feb4 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -17,7 +17,7 @@ from sapl.crispy_layout_mixin import SaplFormHelper from sapl.crispy_layout_mixin import form_actions, to_row, SaplFormLayout from sapl.materia.forms import MateriaLegislativaFilterSet from sapl.materia.models import (MateriaLegislativa, StatusTramitacao, - TipoMateriaLegislativa) + TipoMateriaLegislativa, Tramitacao) from sapl.parlamentares.models import Parlamentar, Mandato from sapl.utils import (RANGE_DIAS_MES, RANGE_MESES, MateriaPesquisaOrderingFilter, autor_label, @@ -356,9 +356,13 @@ class ExpedienteMateriaForm(ModelForm): return cleaned_data def save(self, commit=False): - expediente = super(ExpedienteMateriaForm, self).save(commit) - expediente.materia = self.cleaned_data['materia'] + expediente = super().save(commit) + materia = self.cleaned_data['materia'] + + expediente.materia = materia + expediente.tramitacao = Tramitacao.objects.filter(materia=materia).first() expediente.save() + return expediente @@ -394,9 +398,13 @@ class OrdemDiaForm(ExpedienteMateriaForm): return self.cleaned_data def save(self, commit=False): - ordem = super(OrdemDiaForm, self).save(commit) - ordem.materia = self.cleaned_data['materia'] + ordem = super().save(commit) + materia = self.cleaned_data['materia'] + + ordem.materia = materia + ordem.tramitacao = Tramitacao.objects.filter(materia=materia).first() ordem.save() + return ordem diff --git a/sapl/sessao/migrations/0045_auto_20190626_1151.py b/sapl/sessao/migrations/0045_auto_20190626_1151.py new file mode 100644 index 000000000..290991cdd --- /dev/null +++ b/sapl/sessao/migrations/0045_auto_20190626_1151.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.21 on 2019-06-26 14:51 +from __future__ import unicode_literals + +import django.db.models.deletion +from django.db import migrations, models + + +def congirura_tramitacoes_pautas(apps, schema_editor): + ExpedienteMateria = apps.get_model('sessao', 'ExpedienteMateria') + OrdemDia = apps.get_model('sessao', 'OrdemDia') + + for expediente in ExpedienteMateria.objects.all(): + expediente.tramitacao = expediente.materia.tramitacao_set.first() + expediente.save() + + for ordemdia in OrdemDia.objects.all(): + ordemdia.tramitacao = ordemdia.materia.tramitacao_set.first() + ordemdia.save() + + +class Migration(migrations.Migration): + dependencies = [ + ('materia', '0051_auto_20190703_1414'), + ('sessao', '0044_merge_20190802_1117'), + ] + + operations = [ + migrations.AddField( + model_name='expedientemateria', + name='tramitacao', + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.PROTECT, + to='materia.Tramitacao'), + ), + migrations.AddField( + model_name='ordemdia', + name='tramitacao', + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.PROTECT, + to='materia.Tramitacao'), + ), + + migrations.RunPython(congirura_tramitacoes_pautas), + ] diff --git a/sapl/sessao/models.py b/sapl/sessao/models.py index e6016895f..8ad01f279 100644 --- a/sapl/sessao/models.py +++ b/sapl/sessao/models.py @@ -1,15 +1,15 @@ from operator import xor +import reversion from django.core.exceptions import ValidationError from django.db import models from django.db.models import Q from django.utils import timezone, formats from django.utils.translation import ugettext_lazy as _ from model_utils import Choices -import reversion from sapl.base.models import Autor -from sapl.materia.models import MateriaLegislativa +from sapl.materia.models import MateriaLegislativa, Tramitacao from sapl.parlamentares.models import (CargoMesa, Legislatura, Parlamentar, Partido, SessaoLegislativa) from sapl.utils import (YES_NO_CHOICES, SaplGenericRelation, @@ -247,21 +247,29 @@ class AbstractOrdemDia(models.Model): TIPO_VOTACAO_CHOICES = Choices( (1, 'simbolica', 'Simbólica'), (2, 'nominal', 'Nominal'), - (3, 'secreta', 'Secreta'), - ) + (3, 'secreta', 'Secreta'),) - sessao_plenaria = models.ForeignKey(SessaoPlenaria, - on_delete=models.CASCADE) - materia = models.ForeignKey(MateriaLegislativa, - on_delete=models.PROTECT, - verbose_name=_('Matéria')) - data_ordem = models.DateField(verbose_name=_('Data da Sessão')) + sessao_plenaria = models.ForeignKey( + SessaoPlenaria, + on_delete=models.CASCADE) + materia = models.ForeignKey( + MateriaLegislativa, + on_delete=models.PROTECT, + verbose_name=_('Matéria')) + data_ordem = models.DateField( + verbose_name=_('Data da Sessão')) observacao = models.TextField( - blank=True, verbose_name=_('Observação')) - numero_ordem = models.PositiveIntegerField(verbose_name=_('Nº Ordem')) - resultado = models.TextField(blank=True, verbose_name=_('Resultado')) + blank=True, + verbose_name=_('Observação')) + numero_ordem = models.PositiveIntegerField( + verbose_name=_('Nº Ordem')) + resultado = models.TextField( + blank=True, + verbose_name=_('Resultado')) tipo_votacao = models.PositiveIntegerField( - verbose_name=_('Tipo de votação'), choices=TIPO_VOTACAO_CHOICES, default=1) + verbose_name=_('Tipo de votação'), + choices=TIPO_VOTACAO_CHOICES, + default=1) votacao_aberta = models.NullBooleanField( blank=True, choices=YES_NO_CHOICES, @@ -270,6 +278,10 @@ class AbstractOrdemDia(models.Model): blank=True, choices=YES_NO_CHOICES, verbose_name=_('Registro de Votação Iniciado?')) + tramitacao = models.ForeignKey( + Tramitacao, + null=True, + on_delete=models.PROTECT) class Meta: abstract = True @@ -279,8 +291,7 @@ class AbstractOrdemDia(models.Model): return self.materia.ementa def __str__(self): - return 'Ordem do Dia/Expediente: %s - %s em %s' % ( - self.numero_ordem, self.materia, self.sessao_plenaria) + return 'Ordem do Dia/Expediente: %s - %s em %s' % (self.numero_ordem, self.materia, self.sessao_plenaria) @reversion.register() diff --git a/sapl/sessao/urls.py b/sapl/sessao/urls.py index 328c1da5e..f050ed15c 100644 --- a/sapl/sessao/urls.py +++ b/sapl/sessao/urls.py @@ -35,7 +35,7 @@ from sapl.sessao.views import (AdicionarVariasMateriasExpediente, VotacaoEmBlocoSimbolicaView, VotacaoEmBlocoNominalView, resumo_ordenacao, recuperar_nome_tipo_sessao, - voto_nominal_parlamentar) + voto_nominal_parlamentar, mostra_status_materia, atualiza_status_materia) from .apps import AppConfig @@ -116,6 +116,12 @@ urlpatterns = [ PesquisarPautaSessaoView.as_view(), name='pesquisar_pauta'), url(r'^sessao/pauta-sessao/(?P\d+)$', PautaSessaoDetailView.as_view(), name='pauta_sessao_detail'), + url(r'^sessao/pauta-sessao/(?P\d+)/mostra-situacao-(?P[\w-]+)/(?P\d+)/$', + mostra_status_materia, name='mostra_status_materia'), + url(r'^sessao/pauta-sessao/(?P\d+)/atualiza-situacao-(?P[\w-]+)/(?P\d+)/$', + atualiza_status_materia, name='atualiza_status_materia'), + + # Subnav sessão url(r'^sessao/(?P\d+)/expediente$', diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index 9560c66e1..98abf1312 100755 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -24,7 +24,6 @@ from django.views.generic.edit import FormMixin from django_filters.views import FilterView from django.shortcuts import render - from sapl.base.models import AppConfig as AppsAppConfig from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud, CrudAux, MasterDetailCrud, @@ -3246,21 +3245,15 @@ class PautaSessaoDetailView(DetailView): ]}) # ===================================================================== # Matérias Expediente - materias = ExpedienteMateria.objects.filter( - sessao_plenaria_id=self.object.id) + materias = ExpedienteMateria.objects.filter(sessao_plenaria_id=self.object.id) materias_expediente = [] for m in materias: ementa = m.materia.ementa titulo = m.materia numero = m.numero_ordem + situacao = m.tramitacao.status if m.tramitacao else _("Não informada") - ultima_tramitacao = m.materia.tramitacao_set.last() - - situacao = ultima_tramitacao.status if ultima_tramitacao else None - - if situacao is None: - situacao = _("Não informada") rv = m.registrovotacao_set.all() if rv: resultado = rv[0].tipo_resultado_votacao.nome @@ -3287,15 +3280,12 @@ class PautaSessaoDetailView(DetailView): context.update({'materia_expediente': materias_expediente}) # ===================================================================== # Expedientes - expediente = ExpedienteSessao.objects.filter( - sessao_plenaria_id=self.object.id) + expediente = ExpedienteSessao.objects.filter(sessao_plenaria_id=self.object.id) expedientes = [] for e in expediente: - tipo = TipoExpediente.objects.get( - id=e.tipo_id) - conteudo = sub( - ' ', ' ', strip_tags(e.conteudo.replace('
', '\n'))) + tipo = TipoExpediente.objects.get(id=e.tipo_id) + conteudo = sub(' ', ' ', strip_tags(e.conteudo.replace('
', '\n'))) ex = {'tipo': tipo, 'conteudo': conteudo} expedientes.append(ex) @@ -3303,26 +3293,19 @@ class PautaSessaoDetailView(DetailView): context.update({'expedientes': expedientes}) # ===================================================================== # Orador Expediente - oradores = OradorExpediente.objects.filter( - sessao_plenaria_id=self.object.id).order_by('numero_ordem') + oradores = OradorExpediente.objects.filter(sessao_plenaria_id=self.object.id).order_by('numero_ordem') context.update({'oradores': oradores}) # ===================================================================== # Matérias Ordem do Dia - ordem = OrdemDia.objects.filter( - sessao_plenaria_id=self.object.id) + ordem = OrdemDia.objects.filter(sessao_plenaria_id=self.object.id) materias_ordem = [] for o in ordem: ementa = o.materia.ementa titulo = o.materia numero = o.numero_ordem + situacao = o.tramitacao.status if o.tramitacao else _("Não informada") - ultima_tramitacao = o.materia.tramitacao_set.last() - - situacao = ultima_tramitacao.status if ultima_tramitacao else None - - if situacao is None: - situacao = _("Não informada") # Verificar resultado rv = o.registrovotacao_set.all() if rv: @@ -3332,8 +3315,7 @@ class PautaSessaoDetailView(DetailView): resultado = _('Matéria não votada') resultado_observacao = _(' ') - autoria = Autoria.objects.filter( - materia_id=o.materia_id) + autoria = Autoria.objects.filter(materia_id=o.materia_id) autor = [str(x.autor) for x in autoria] mat = {'id': o.materia_id, @@ -3354,6 +3336,46 @@ class PautaSessaoDetailView(DetailView): return self.render_to_response(context) +def pega_materia_exp_od(sessao_id, tipo, materia_id): + models = { + 'expediente': ExpedienteMateria, + 'ordemdia': OrdemDia + } + exp_od = models[tipo].objects.select_related('materia').get(sessao_plenaria=sessao_id, materia=materia_id) + + return exp_od + + +def mostra_status_materia(request, sessao_id, tipo, materia_id): + template_name = "sessao/pauta_sessao_situacao_materia.html" + exp_od = pega_materia_exp_od(sessao_id, tipo, materia_id) + autores = [a.autor.nome for a in exp_od.materia.autoria_set.all()] + + context = { + 'sessao_id': sessao_id, + 'materia_id': materia_id, + 'titulo': exp_od.materia, + 'exp_od_id': exp_od.id, + 'tipo': tipo, + 'autores': autores, + 'ementa': exp_od.materia.ementa, + 'tramitacao_id': exp_od.tramitacao.id, + 'status': exp_od.tramitacao.status, + 'nova_tramitacao_id': exp_od.materia.tramitacao_set.first().id, + 'novo_status': exp_od.materia.tramitacao_set.first().status + } + + return render(request, template_name, context) + + +def atualiza_status_materia(request, sessao_id, tipo, materia_id): + exp_od = pega_materia_exp_od(sessao_id, tipo, materia_id) + exp_od.tramitacao = exp_od.materia.tramitacao_set.first() + exp_od.save() + + return HttpResponseRedirect(reverse('sapl.sessao:pauta_sessao_detail', kwargs={'pk': sessao_id})) + + class PesquisarSessaoPlenariaView(FilterView): model = SessaoPlenaria filterset_class = SessaoPlenariaFilterSet @@ -3366,11 +3388,9 @@ class PesquisarSessaoPlenariaView(FilterView): kwargs = {'data': self.request.GET or None} - qs = self.get_queryset().select_related( - 'tipo', 'sessao_legislativa', 'legislatura') + qs = self.get_queryset().select_related('tipo', 'sessao_legislativa', 'legislatura') - qs = qs.distinct().order_by( - '-legislatura__numero', '-data_inicio', '-hora_inicio') + qs = qs.distinct().order_by('-legislatura__numero', '-data_inicio', '-hora_inicio') kwargs.update({ 'queryset': qs, diff --git a/sapl/templates/sessao/pauta_sessao_detail.html b/sapl/templates/sessao/pauta_sessao_detail.html index 6b2702f5f..a3fc6e15b 100644 --- a/sapl/templates/sessao/pauta_sessao_detail.html +++ b/sapl/templates/sessao/pauta_sessao_detail.html @@ -3,72 +3,75 @@ {% load crispy_forms_tags %} {% block base_content %} - -
- Identificação Básica - - - - {% for b in basica %} - - {% endfor %} - - -
{{b}}
-
-
- Matérias do Expediente - {% if materia_expediente %} - - - - - - - - - {% for m in materia_expediente %} - - - - - - {% endfor %} -
MatériaEmentaSituação
- {{m.numero}} - {{m.titulo}} -
- Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }} -
{{m.ementa|safe}}
{{m.observacao|linebreaksbr|safe}}
{{m.situacao}}
- {% else %} - Não existem Matérias de Expediente para essa Sessão Plenária - {% endif %} + +
+ Identificação Básica + + + + {% for b in basica %} + + {% endfor %} + + +
{{ b }}
+
+
+ Matérias do Expediente + {% if materia_expediente %} + + + + + + + + + {% for m in materia_expediente %} + + + + + + {% endfor %} +
MatériaEmentaSituação
+ {{ m.numero }} - {{ m.titulo }} +
+ Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }} +
{{ m.ementa|safe }}
{{ m.observacao|linebreaksbr|safe }}
{{ m.situacao }}
+ {% else %} + Não existem Matérias de Expediente para essa Sessão Plenária + {% endif %} -
-
- Matérias da Ordem do Dia - {% if materias_ordem %} - - - - - - - - - {% for m in materias_ordem %} - - - - - - {% endfor %} -
MatériaEmentaSituação
- {{m.numero}} - {{m.titulo}} -
- Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }} -
{{m.ementa|safe}}
{{m.observacao|linebreaksbr|safe}}
{{m.situacao}}
- {% else %} - Não existem Matérias de Ordem do Dia para essa Sessão Plenária - {% endif %} -
+
+
+ Matérias da Ordem do Dia + {% if materias_ordem %} + + + + + + + + + {% for m in materias_ordem %} + + + + + + {% endfor %} +
MatériaEmentaSituação
¡ + {{ m.numero }} - {{ m.titulo }} +
+ Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }} +
{{ m.ementa|safe }}
{{ m.observacao|linebreaksbr|safe }}
{{ m.situacao }}
+ {% else %} + Não existem Matérias de Ordem do Dia para essa Sessão Plenária + {% endif %} +
{% endblock base_content %} diff --git a/sapl/templates/sessao/pauta_sessao_situacao_materia.html b/sapl/templates/sessao/pauta_sessao_situacao_materia.html new file mode 100644 index 000000000..73b2e92df --- /dev/null +++ b/sapl/templates/sessao/pauta_sessao_situacao_materia.html @@ -0,0 +1,42 @@ +{% extends "crud/detail.html" %} +{% load i18n %} +{% load crispy_forms_tags %} + +{% block base_content %} +
+ Atualização da Situação da Matéria em Pauta + + + {% if tipo == expediente %} + + {% else %} + + {% endif %} + + + + + + + + + + + + + + + + + + +
Matéria do ExpedienteMatéria da Ordem Dia{{ titulo }}
Autor{{ autores|length|pluralize:"es" }}{{ autores|join:', ' }}
Ementa{{ ementa }}
Atual Situação{{ status }}
Nova Situação{{ novo_status }}
+
+
Ao apertar em 'Atualizar', não será possível reverter a alteração posteriormente.
+
+ Voltar +
+
+ Atualizar +
+{% endblock base_content %}