diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index 65d89d984..523e1cede 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -1,6 +1,5 @@ from datetime import datetime -from sapl.crispy_layout_mixin import SaplFormHelper from crispy_forms.layout import HTML, Button, Fieldset, Layout from django import forms from django.contrib.contenttypes.models import ContentType @@ -13,6 +12,7 @@ from django.utils.translation import ugettext_lazy as _ import django_filters from sapl.base.models import Autor, TipoAutor +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, @@ -60,21 +60,11 @@ class SessaoPlenariaForm(FileFieldCheckMixin, ModelForm): "para a Legislatura, Sessão Legislativa e Tipo informados. " "Favor escolher um número distinto.") - sessoes = SessaoPlenaria.objects.filter(numero=num, - sessao_legislativa=sl, - legislatura=leg, - tipo=tipo, - data_inicio__year=abertura.year).\ - values_list('id', flat=True) - - qtd_sessoes = len(sessoes) + qs = tipo.queryset_tipo_numeracao(leg, sl, abertura) + qs &= Q(numero=num) - if qtd_sessoes > 0: - if instance.pk: # update - if instance.pk not in sessoes or qtd_sessoes > 1: - raise error - else: # create - raise error + if SessaoPlenaria.objects.filter(qs).exclude(pk=instance.pk).exists(): + raise error # Condições da verificação abertura_entre_leg = leg.data_inicio <= abertura <= leg.data_fim @@ -640,7 +630,7 @@ class OradorForm(ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['parlamentar'].queryset = \ - Parlamentar.objects.filter(ativo=True).order_by('nome_parlamentar') + Parlamentar.objects.filter(ativo=True).order_by('nome_parlamentar') def clean(self): super(OradorForm, self).clean() @@ -662,8 +652,8 @@ class OradorForm(ModelForm): "Já existe orador nesta posição de ordem de pronunciamento" )) - return self.cleaned_data + class Meta: model = Orador exclude = ['sessao_plenaria'] @@ -676,7 +666,7 @@ class OradorExpedienteForm(ModelForm): sessao = SessaoPlenaria.objects.get(id=id_sessao) legislatura_vigente = sessao.legislatura self.fields['parlamentar'].queryset = \ - Parlamentar.objects.filter(mandato__legislatura=legislatura_vigente, + Parlamentar.objects.filter(mandato__legislatura=legislatura_vigente, ativo=True).order_by('nome_parlamentar') def clean(self): @@ -711,7 +701,7 @@ class OradorOrdemDiaForm(ModelForm): sessao = SessaoPlenaria.objects.get(id=id_sessao) legislatura_vigente = sessao.legislatura self.fields['parlamentar'].queryset = \ - Parlamentar.objects.filter(mandato__legislatura=legislatura_vigente, + Parlamentar.objects.filter(mandato__legislatura=legislatura_vigente, ativo=True).order_by('nome_parlamentar') def clean(self): diff --git a/sapl/sessao/migrations/0041_auto_20190610_1300.py b/sapl/sessao/migrations/0041_auto_20190610_1300.py new file mode 100644 index 000000000..da25e64b3 --- /dev/null +++ b/sapl/sessao/migrations/0041_auto_20190610_1300.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-06-10 16:00 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('sessao', '0040_auto_20190523_1130'), + ] + + operations = [ + migrations.AddField( + model_name='tiposessaoplenaria', + name='tipo_numeracao', + field=models.PositiveIntegerField(choices=[(1, 'Quinzenal'), (2, 'Mensal'), (10, 'Anual'), (11, 'Sessão Legislativa'), ( + 12, 'Legislatura'), (99, 'Numeração Única')], default=11, verbose_name='Tipo de Numeração'), + ), + migrations.AlterField( + model_name='tiposessaoplenaria', + name='nome', + field=models.CharField( + max_length=30, verbose_name='Descrição do Tipo'), + ), + ] diff --git a/sapl/sessao/models.py b/sapl/sessao/models.py index 53721499b..8ab65ebfd 100644 --- a/sapl/sessao/models.py +++ b/sapl/sessao/models.py @@ -2,7 +2,8 @@ from operator import xor from django.core.exceptions import ValidationError from django.db import models -from django.utils import timezone +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 @@ -73,10 +74,24 @@ class Bancada(models.Model): @reversion.register() class TipoSessaoPlenaria(models.Model): - nome = models.CharField(max_length=30, verbose_name=_('Tipo')) + + TIPO_NUMERACAO_CHOICES = Choices( + (1, 'quizenal', 'Quinzenal'), + (2, 'mensal', 'Mensal'), + (10, 'anual', 'Anual'), + (11, 'sessao_legislativa', 'Sessão Legislativa'), + (12, 'legislatura', 'Legislatura'), + (99, 'unica', 'Numeração Única'), + ) + + nome = models.CharField(max_length=30, verbose_name=_('Descrição do Tipo')) quorum_minimo = models.PositiveIntegerField( verbose_name=_('Quórum mínimo')) + tipo_numeracao = models.PositiveIntegerField( + verbose_name=_('Tipo de Numeração'), + choices=TIPO_NUMERACAO_CHOICES, default=11) + class Meta: verbose_name = _('Tipo de Sessão Plenária') verbose_name_plural = _('Tipos de Sessão Plenária') @@ -85,6 +100,29 @@ class TipoSessaoPlenaria(models.Model): def __str__(self): return self.nome + def queryset_tipo_numeracao(self, legislatura, sessao_legislativa, data): + + qs = Q(tipo=self) + tnc = self.TIPO_NUMERACAO_CHOICES + + if self.tipo_numeracao == tnc.unica: + pass + elif self.tipo_numeracao == tnc.legislatura: + qs &= Q(legislatura=legislatura) + elif self.tipo_numeracao == tnc.sessao_legislativa: + qs &= Q(sessao_legislativa=sessao_legislativa) + elif self.tipo_numeracao == tnc.anual: + qs &= Q(data_inicio__year=data.year) + elif self.tipo_numeracao in (tnc.mensal, tnc.quizenal): + qs &= Q(data_inicio__year=data.year, data_inicio__month=data.month) + + if self.tipo_numeracao == tnc.quizenal: + if data.day <= 15: + qs &= Q(data_inicio__day__lte=15) + else: + qs &= Q(data_inicio__day__gt=15) + return qs + def get_sessao_media_path(instance, subpath, filename): return './sapl/sessao/%s/%s/%s' % (instance.numero, subpath, filename) @@ -176,7 +214,34 @@ class SessaoPlenaria(models.Model): verbose_name_plural = _('Sessões Plenárias') def __str__(self): - return _('%(numero)sª Sessão %(tipo_nome)s' + + tnc = self.tipo.TIPO_NUMERACAO_CHOICES + + base = '{}ª {}'.format(self.numero, self.tipo.nome) + + if self.tipo.tipo_numeracao == tnc.quizenal: + base += ' da {}ª Quinzena'.format( + 1 if self.data_inicio.day > 15 else 2) + + if self.tipo.tipo_numeracao <= tnc.mensal: + base += ' do mês de {}'.format( + formats.date_format(self.data_inicio, 'F') + ) + + if self.tipo.tipo_numeracao <= tnc.anual: + base += ' de {}'.format(self.data_inicio.year) + + if self.tipo.tipo_numeracao <= tnc.sessao_legislativa: + base += ' da {}ª Sessão Legislativa'.format( + self.sessao_legislativa.numero) + + if self.tipo.tipo_numeracao <= tnc.legislatura: + base += ' da {}ª Legislatura'.format( + self.legislatura.numero) + + return base + + """return _('%(numero)sª Sessão %(tipo_nome)s' ' da %(sessao_legislativa_numero)sª Sessão Legislativa' ' da %(legislatura_id)sª Legislatura') % { @@ -185,6 +250,7 @@ class SessaoPlenaria(models.Model): 'sessao_legislativa_numero': self.sessao_legislativa.numero, # XXX check if it shouldn't be legislatura.numero 'legislatura_id': self.legislatura.numero} + """ def delete(self, using=None, keep_parents=False): if self.upload_pauta: diff --git a/sapl/sessao/urls.py b/sapl/sessao/urls.py index d5d709967..c570dfde8 100644 --- a/sapl/sessao/urls.py +++ b/sapl/sessao/urls.py @@ -2,7 +2,7 @@ from django.conf.urls import include, url from sapl.sessao.views import (AdicionarVariasMateriasExpediente, AdicionarVariasMateriasOrdemDia, BancadaCrud, - CargoBancadaCrud, ExpedienteMateriaCrud, + CargoBancadaCrud, ExpedienteMateriaCrud, ExpedienteView, JustificativaAusenciaCrud, OcorrenciaSessaoView, MateriaOrdemDiaCrud, OradorOrdemDiaCrud, MesaView, OradorCrud, @@ -25,7 +25,7 @@ from sapl.sessao.views import (AdicionarVariasMateriasExpediente, VotacaoNominalView, VotacaoView, abrir_votacao, atualizar_mesa, insere_parlamentar_composicao, mudar_ordem_materia_sessao, recuperar_materia, - recuperar_numero_sessao, + recuperar_numero_sessao_view, remove_parlamentar_composicao, reordernar_materias_expediente, reordernar_materias_ordem, @@ -65,7 +65,7 @@ urlpatterns = [ url(r'^sessao/recuperar-materia/', recuperar_materia), url(r'^sessao/recuperar-numero-sessao/', - recuperar_numero_sessao, + recuperar_numero_sessao_view, name='recuperar_numero_sessao_view' ), url(r'^sessao/sessao-legislativa-legislatura-ajax/', diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index 3cf90b990..d5794f421 100755 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -93,6 +93,7 @@ def reordernar_materias_ordem(request, pk): return HttpResponseRedirect( reverse('sapl.sessao:ordemdia_list', kwargs={'pk': pk})) + def renumerar_materias_ordem(request, pk): ordens = OrdemDia.objects.filter(sessao_plenaria_id=pk) @@ -103,6 +104,7 @@ def renumerar_materias_ordem(request, pk): return HttpResponseRedirect( reverse('sapl.sessao:ordemdia_list', kwargs={'pk': pk})) + def renumerar_materias_expediente(request, pk): expedientes = ExpedienteMateria.objects.filter(sessao_plenaria_id=pk) @@ -113,6 +115,7 @@ def renumerar_materias_expediente(request, pk): return HttpResponseRedirect( reverse('sapl.sessao:expedientemateria_list', kwargs={'pk': pk})) + def verifica_presenca(request, model, spk): logger = logging.getLogger(__name__) if not model.objects.filter(sessao_plenaria_id=spk).exists(): @@ -595,7 +598,6 @@ class OradorCrud(MasterDetailCrud): class ListView(MasterDetailCrud.ListView): ordering = ['numero_ordem', 'parlamentar'] - class CreateView(MasterDetailCrud.CreateView): form_class = OradorForm @@ -607,7 +609,6 @@ class OradorCrud(MasterDetailCrud): return reverse('sapl.sessao:orador_list', kwargs={'pk': self.kwargs['pk']}) - class UpdateView(MasterDetailCrud.UpdateView): form_class = OradorForm @@ -615,7 +616,7 @@ class OradorCrud(MasterDetailCrud): def get_initial(self): initial = super(UpdateView, self).get_initial() initial.update({'id_sessao': self.object.sessao_plenaria.id}) - initial.update({'numero':self.object.numero_ordem}) + initial.update({'numero': self.object.numero_ordem}) return initial @@ -677,11 +678,24 @@ class BancadaCrud(CrudAux): return reverse('sapl.sessao:bancada_list') -def recuperar_numero_sessao(request): +def recuperar_numero_sessao_view(request): try: + tipo = TipoSessaoPlenaria.objects.get(pk=request.GET.get('tipo', '0')) + sl = request.GET.get('sessao_legislativa', '0') + l = request.GET.get('legislatura', '0') + data = request.GET.get('data_inicio', timezone.now()) + + if isinstance(data, str): + if data: + data = timezone.datetime.strptime(data, '%d/%m/%Y').date() + else: + data = timezone.now().date() + sessao = SessaoPlenaria.objects.filter( - tipo__pk=request.GET['tipo'], - sessao_legislativa=request.GET['sessao_legislativa']).last() + tipo.queryset_tipo_numeracao( + l, sl, data + )).last() + except ObjectDoesNotExist: numero = 1 else: @@ -1066,7 +1080,6 @@ class ListMateriaOrdemDiaView(FormMixin, DetailView): return self.get(self, request, args, kwargs) - class MesaView(FormMixin, DetailView): template_name = 'sessao/mesa.html' form_class = MesaForm @@ -1341,7 +1354,7 @@ def get_identificação_basica(sessao_plenaria): _('Encerramento: %(encerramento)s %(hora_fim)s') % { 'encerramento': encerramento, 'hora_fim': sessao_plenaria.hora_fim} ], - 'sessaoplenaria': sessao_plenaria}) + 'sessaoplenaria': sessao_plenaria}) def get_conteudo_multimidia(sessao_plenaria): @@ -1360,7 +1373,8 @@ def get_conteudo_multimidia(sessao_plenaria): def get_mesa_diretora(sessao_plenaria): - mesa = IntegranteMesa.objects.filter(sessao_plenaria=sessao_plenaria).order_by('cargo_id') + mesa = IntegranteMesa.objects.filter( + sessao_plenaria=sessao_plenaria).order_by('cargo_id') integrantes = [{'parlamentar': m.parlamentar, 'cargo': m.cargo} for m in mesa] return {'mesa': integrantes} @@ -1369,8 +1383,8 @@ def get_mesa_diretora(sessao_plenaria): def get_presenca_sessao(sessao_plenaria): parlamentares_sessao = [p.parlamentar for p in SessaoPlenariaPresenca.objects.filter( - sessao_plenaria_id=sessao_plenaria.id - ).order_by('parlamentar__nome_parlamentar')] + sessao_plenaria_id=sessao_plenaria.id + ).order_by('parlamentar__nome_parlamentar')] ausentes_sessao = JustificativaAusencia.objects.filter( sessao_plenaria_id=sessao_plenaria.id @@ -1404,7 +1418,8 @@ def get_materias_expediente(sessao_plenaria): numero = m.numero_ordem tramitacao = '' - tramitacoes = Tramitacao.objects.filter(materia=m.materia).order_by('-pk') + tramitacoes = Tramitacao.objects.filter( + materia=m.materia).order_by('-pk') for aux_tramitacao in tramitacoes: if aux_tramitacao.turno: tramitacao = aux_tramitacao @@ -1466,8 +1481,8 @@ def get_oradores_expediente(sessao_plenaria): def get_presenca_ordem_do_dia(sessao_plenaria): parlamentares_ordem = [p.parlamentar for p in PresencaOrdemDia.objects.filter( - sessao_plenaria_id=sessao_plenaria.id - ).order_by('parlamentar__nome_parlamentar')] + sessao_plenaria_id=sessao_plenaria.id + ).order_by('parlamentar__nome_parlamentar')] return {'presenca_ordem': parlamentares_ordem} @@ -1480,13 +1495,14 @@ def get_assinaturas(sessao_plenaria): '')] parlamentares_ordem = [p.parlamentar for p in PresencaOrdemDia.objects.filter( - sessao_plenaria_id=sessao_plenaria.id - ).order_by('parlamentar__nome_parlamentar')] + sessao_plenaria_id=sessao_plenaria.id + ).order_by('parlamentar__nome_parlamentar')] parlamentares_mesa = [m['parlamentar'] for m in mesa_dia] # filtra parlamentares retirando os que sao da mesa - parlamentares_ordem = [p for p in parlamentares_ordem if p not in parlamentares_mesa] + parlamentares_ordem = [ + p for p in parlamentares_ordem if p not in parlamentares_mesa] context = {} config_assinatura_ata = AppsAppConfig.attr('assinatura_ata') @@ -1517,7 +1533,8 @@ def get_materias_ordem_do_dia(sessao_plenaria): numero = o.numero_ordem tramitacao = '' - tramitacoes = Tramitacao.objects.filter(materia=o.materia).order_by('-pk') + tramitacoes = Tramitacao.objects.filter( + materia=o.materia).order_by('-pk') for aux_tramitacao in tramitacoes: if aux_tramitacao.turno: tramitacao = aux_tramitacao @@ -1600,7 +1617,7 @@ def get_oradores_ordemdia(sessao_plenaria): observacao = orador.observacao parlamentar = Parlamentar.objects.get( id=orador.parlamentar_id - ) + ) o = { 'numero_ordem': numero_ordem, 'url_discurso': url_discurso, @@ -1610,9 +1627,9 @@ def get_oradores_ordemdia(sessao_plenaria): oradores.append(o) context = {'oradores_ordemdia': oradores} - return context + return context + - def get_oradores_explicações_pessoais(sessao_plenaria): oradores_explicacoes = [] for orador in Orador.objects.filter( @@ -1729,7 +1746,7 @@ class ResumoView(DetailView): # ===================================================================== # Oradores Ordem do Dia context.update(get_oradores_ordemdia(self.object)) - # ===================================================================== + # ===================================================================== # Oradores nas Explicações Pessoais context.update(get_oradores_explicações_pessoais(self.object)) # ===================================================================== diff --git a/sapl/templates/sessao/layouts.yaml b/sapl/templates/sessao/layouts.yaml index 16e353910..f5356a829 100644 --- a/sapl/templates/sessao/layouts.yaml +++ b/sapl/templates/sessao/layouts.yaml @@ -1,11 +1,11 @@ {% load i18n %} TipoSessaoPlenaria: {% trans 'Tipo de Sessão Plenária' %}: - - nome quorum_minimo + - nome quorum_minimo tipo_numeracao SessaoPlenaria: {% trans 'Dados Básicos' %}: - - legislatura sessao_legislativa tipo:3 numero:1 + - legislatura sessao_legislativa tipo numero:2 - data_inicio:5 hora_inicio:5 iniciada - data_fim:5 hora_fim:5 finalizada - upload_pauta upload_ata upload_anexo diff --git a/sapl/templates/sessao/sessaoplenaria_form.html b/sapl/templates/sessao/sessaoplenaria_form.html index ee1bba4ac..aa18e0105 100644 --- a/sapl/templates/sessao/sessaoplenaria_form.html +++ b/sapl/templates/sessao/sessaoplenaria_form.html @@ -7,24 +7,35 @@