Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reunião para frente parlamentar #3441

Draft
wants to merge 1 commit into
base: 3.1.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions sapl/materia/migrations/0080_pautareuniaofrente.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 2.2.20 on 2021-08-17 23:29

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('parlamentares', '0039_documentoacessorio_reuniao'),
('materia', '0079_auto_20210311_1711'),
]

operations = [
migrations.CreateModel(
name='PautaReuniaoFrente',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('materia', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='materia.MateriaLegislativa', verbose_name='Matéria')),
('reuniao', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='parlamentares.Reuniao', verbose_name='Reunião')),
],
options={
'verbose_name': 'Matéria da Pauta',
'verbose_name_plural': 'Matérias da Pauta',
'ordering': ('id',),
},
),
]
26 changes: 26 additions & 0 deletions sapl/materia/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from model_utils import Choices
import reversion

from sapl.parlamentares.models import Reuniao as ReuniaoFrente
from sapl.base.models import SEQUENCIA_NUMERACAO_PROTOCOLO, Autor
from sapl.comissoes.models import Comissao, Reuniao
from sapl.compilacao.models import (PerfilEstruturalTextoArticulado,
Expand Down Expand Up @@ -462,6 +463,31 @@ def __str__(self):
}


class PautaReuniaoFrente(models.Model):
reuniao = models.ForeignKey(
ReuniaoFrente,
on_delete=models.CASCADE,
verbose_name=_('Reunião')
)
materia = models.ForeignKey(
MateriaLegislativa,
on_delete=models.PROTECT,
verbose_name=_('Matéria')
)

class Meta:
verbose_name = _('Matéria da Pauta')
verbose_name_plural = ('Matérias da Pauta')
ordering = ('id',)

def __str__(self):
return _('Reunião: %(reuniao)s'
' - Matéria: %(materia)s') % {
'reuniao': self.reuniao,
'materia': self.materia
}


@reversion.register()
class Anexada(models.Model):
materia_principal = models.ForeignKey(
Expand Down
192 changes: 179 additions & 13 deletions sapl/parlamentares/forms.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from datetime import timedelta
import logging
from sapl.materia.models import MateriaEmTramitacao, PautaReuniaoFrente

from sapl.crispy_layout_mixin import SaplFormHelper
from crispy_forms.layout import Fieldset, Layout
Expand All @@ -15,15 +16,15 @@
from django.utils.translation import ugettext_lazy as _
from floppyforms.widgets import ClearableFileInput
from image_cropping.widgets import CropWidget, ImageCropWidget
from sapl.utils import FileFieldCheckMixin
from sapl.utils import FileFieldCheckMixin, FilterOverridesMetaMixin, validar_arquivo

from sapl.base.models import Autor, TipoAutor
from sapl.crispy_layout_mixin import form_actions, to_row
from sapl.rules import SAPL_GROUP_VOTANTE
import django_filters

from .models import (Coligacao, ComposicaoColigacao, Filiacao, Frente, Legislatura,
Mandato, Parlamentar, Partido, Votante, Bloco, FrenteParlamentar, BlocoMembro)
from .models import (Coligacao, ComposicaoColigacao, DocumentoAcessorio, Filiacao, Frente, Legislatura,
Mandato, Parlamentar, Partido, Reuniao, Votante, Bloco, FrenteParlamentar, BlocoMembro)


class ImageThumbnailFileInput(ClearableFileInput):
Expand Down Expand Up @@ -253,7 +254,8 @@ def __init__(self, *args, **kwargs):


class ColigacaoFilterSet(django_filters.FilterSet):
nome = django_filters.CharFilter(label=_('Nome da Coligação'), lookup_expr='icontains')
nome = django_filters.CharFilter(
label=_('Nome da Coligação'), lookup_expr='icontains')

class Meta:
model = Coligacao
Expand Down Expand Up @@ -316,7 +318,8 @@ def clean(self):
return self.cleaned_data

cleaned_data = self.cleaned_data
parlamentar = Parlamentar.objects.filter(nome_parlamentar=cleaned_data['nome_parlamentar']).exists()
parlamentar = Parlamentar.objects.filter(nome_parlamentar=cleaned_data[
'nome_parlamentar']).exists()

if parlamentar:
self.logger.error('Parlamentar já cadastrado.')
Expand Down Expand Up @@ -537,9 +540,11 @@ def clean(self):
return self.cleaned_data

if cd['cargo'].cargo_unico:
frente_parlamentar = FrenteParlamentar.objects.filter(frente=cd['frente'], cargo=cd['cargo'])
frente_parlamentar = FrenteParlamentar.objects.filter(
frente=cd['frente'], cargo=cd['cargo'])
if frente_parlamentar and not frente_parlamentar[0].parlamentar == cd['parlamentar']:
raise ValidationError(_("Cargo único já ocupado por outro parlamentar."))
raise ValidationError(
_("Cargo único já ocupado por outro parlamentar."))

return cd

Expand Down Expand Up @@ -669,11 +674,15 @@ def clean(self):
data_expedicao_diploma = cleaned_data['data_expedicao_diploma']

if parlamentar.mandato_set.filter(legislatura=legislatura):
self.logger.error('Parlamentar já está vinculado a legislatura informada.')
raise ValidationError(_('Parlamentar já está vinculado a legislatura informada.'))
self.logger.error(
'Parlamentar já está vinculado a legislatura informada.')
raise ValidationError(
_('Parlamentar já está vinculado a legislatura informada.'))
elif data_expedicao_diploma and legislatura.data_inicio <= data_expedicao_diploma:
self.logger.error('Data da Expedição do Diploma deve ser anterior a data de início da Legislatura.')
raise ValidationError(_('Data da Expedição do Diploma deve ser anterior a data de início da Legislatura.'))
self.logger.error(
'Data da Expedição do Diploma deve ser anterior a data de início da Legislatura.')
raise ValidationError(
_('Data da Expedição do Diploma deve ser anterior a data de início da Legislatura.'))

return cleaned_data

Expand Down Expand Up @@ -736,8 +745,165 @@ def clean(self):
if cd['cargo'].cargo_unico \
and BlocoMembro.objects.filter(bloco=cd['bloco'], cargo=cd['cargo'], data_saida__isnull=True)\
.exclude(pk=self.instance.pk).exists():
raise ValidationError(_("Cargo único já ocupado por outro membro."))
raise ValidationError(
_("Cargo único já ocupado por outro membro."))
elif not cd['data_saida'] and BlocoMembro.objects.filter(parlamentar=cd['parlamentar'], data_saida__isnull=True).exists():
raise ValidationError(_("Parlamentar já é membro do bloco parlamentar."))
raise ValidationError(
_("Parlamentar já é membro do bloco parlamentar."))

return cd


class ReuniaoForm(ModelForm):

logger = logging.getLogger(__name__)
frente = forms.ModelChoiceField(queryset=Frente.objects.all(),
widget=forms.HiddenInput())

class Meta:
model = Reuniao
exclude = ['cod_andamento_reuniao']

def clean(self):
super(ReuniaoForm, self).clean()

if not self.is_valid():
return self.cleaned_data

if self.cleaned_data['hora_fim']:
if (self.cleaned_data['hora_fim'] <
self.cleaned_data['hora_inicio']):
msg = _(
'A hora de término da reunião não pode ser menor que a de início')
self.logger.warning(
"A hora de término da reunião ({}) não pode ser menor que a de início ({}).".format(
self.cleaned_data[
'hora_fim'], self.cleaned_data['hora_inicio']
)
)
raise ValidationError(msg)

upload_pauta = self.cleaned_data.get('upload_pauta', False)
upload_ata = self.cleaned_data.get('upload_ata', False)
upload_anexo = self.cleaned_data.get('upload_anexo', False)

if upload_pauta:
validar_arquivo(upload_pauta, "Pauta da Reunião")

if upload_ata:
validar_arquivo(upload_ata, "Ata da Reunião")

if upload_anexo:
validar_arquivo(upload_anexo, "Anexo da Reunião")

return self.cleaned_data


class PautaReuniaoFilterSet(django_filters.FilterSet):

class Meta(FilterOverridesMetaMixin):
model = MateriaEmTramitacao
fields = ['materia__tipo', 'materia__ano',
'materia__numero', 'materia__data_apresentacao']

def __init__(self, *args, **kwargs):
super(PautaReuniaoFilterSet, self).__init__(*args, **kwargs)

self.filters['materia__tipo'].label = "Tipo da Matéria"
self.filters['materia__ano'].label = "Ano da Matéria"
self.filters['materia__numero'].label = "Número da Matéria"
self.filters[
'materia__data_apresentacao'].label = "Data (Inicial - Final)"

row1 = to_row(
[('materia__tipo', 4), ('materia__ano', 4), ('materia__numero', 4)])
row2 = to_row([('materia__data_apresentacao', 12)])

self.form.helper = SaplFormHelper()
self.form.helper.form_method = "GET"
self.form.helper.layout = Layout(
Fieldset(
_("Pesquisa de Matérias"), row1, row2,
form_actions(label="Pesquisar")
)
)


class PautaReuniaoForm(forms.ModelForm):

class Meta:
model = PautaReuniaoFrente
exclude = ['reuniao']


class DocumentoAcessorioCreateForm(FileFieldCheckMixin, forms.ModelForm):

parent_pk = forms.CharField(required=False) # widget=forms.HiddenInput())

class Meta:
model = DocumentoAcessorio
exclude = ['reuniao']

def __init__(self, user=None, **kwargs):
super(DocumentoAcessorioCreateForm, self).__init__(**kwargs)

if self.instance:
reuniao = Reuniao.objects.get(id=self.initial['parent_pk'])
frente = reuniao.frente
frente_pk = frente.id
documentos = reuniao.documentoacessorio_set.all()
return self.create_documentoacessorio()

def create_documentoacessorio(self):
reuniao = Reuniao.objects.get(id=self.initial['parent_pk'])

def clean(self):
super(DocumentoAcessorioCreateForm, self).clean()

if not self.is_valid():
return self.cleaned_data

arquivo = self.cleaned_data.get('arquivo')

if arquivo:
validar_arquivo(arquivo, "Texto Integral")
# else:
# ## TODO: definir arquivo no form e preservar o nome do campo
# ## que gerou a mensagem de erro.
# ## arquivo = forms.FileField(required=True, label="Texto Integral")
# nome_arquivo = self.fields['arquivo'].label
# raise ValidationError(f'Favor anexar arquivo em {nome_arquivo}')

return self.cleaned_data


class DocumentoAcessorioEditForm(FileFieldCheckMixin, forms.ModelForm):

parent_pk = forms.CharField(required=False) # widget=forms.HiddenInput())

class Meta:
model = DocumentoAcessorio
fields = ['nome', 'data', 'autor', 'ementa',
'indexacao', 'arquivo']

def __init__(self, user=None, **kwargs):
super(DocumentoAcessorioEditForm, self).__init__(**kwargs)

def clean(self):
super(DocumentoAcessorioEditForm, self).clean()

if not self.is_valid():
return self.cleaned_data

arquivo = self.cleaned_data.get('arquivo')

if arquivo:
validar_arquivo(arquivo, "Texto Integral")
# else:
# ## TODO: definir arquivo no form e preservar o nome do campo
# ## que gerou a mensagem de erro.
# ## arquivo = forms.FileField(required=True, label="Texto Integral")
# nome_arquivo = self.fields['arquivo'].label
# raise ValidationError(f'Favor anexar arquivo em {nome_arquivo}')

return self.cleaned_data
60 changes: 60 additions & 0 deletions sapl/parlamentares/migrations/0039_documentoacessorio_reuniao.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Generated by Django 2.2.20 on 2021-08-17 23:26

from django.db import migrations, models
import django.db.models.deletion
import sapl.parlamentares.models
import sapl.utils


class Migration(migrations.Migration):

dependencies = [
('parlamentares', '0038_sessao_legislativa_redundante'),
]

operations = [
migrations.CreateModel(
name='Reuniao',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('numero', models.PositiveIntegerField(verbose_name='Número')),
('nome', models.CharField(max_length=150, verbose_name='Nome da Reunião')),
('tema', models.CharField(blank=True, max_length=150, verbose_name='Tema da Reunião')),
('data', models.DateField(verbose_name='Data')),
('hora_inicio', models.TimeField(null=True, verbose_name='Horário de Início (hh:mm)')),
('hora_fim', models.TimeField(blank=True, null=True, verbose_name='Horário de Término (hh:mm)')),
('local_reuniao', models.CharField(blank=True, max_length=100, verbose_name='Local da Reunião')),
('observacao', models.TextField(blank=True, verbose_name='Observação')),
('url_audio', models.URLField(blank=True, max_length=150, verbose_name='URL do Arquivo de Áudio (Formatos MP3 / AAC)')),
('url_video', models.URLField(blank=True, max_length=150, verbose_name='URL do Arquivo de Vídeo (Formatos MP4 / FLV / WebM)')),
('upload_pauta', models.FileField(blank=True, max_length=300, null=True, storage=sapl.utils.OverwriteStorage(), upload_to=sapl.parlamentares.models.pauta_upload_path, verbose_name='Pauta da Reunião')),
('upload_ata', models.FileField(blank=True, max_length=300, null=True, storage=sapl.utils.OverwriteStorage(), upload_to=sapl.parlamentares.models.ata_upload_path, verbose_name='Ata da Reunião')),
('upload_anexo', models.FileField(blank=True, max_length=300, null=True, storage=sapl.utils.OverwriteStorage(), upload_to=sapl.parlamentares.models.anexo_upload_path, verbose_name='Anexo da Reunião')),
('frente', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='parlamentares.Frente', verbose_name='Frente Parlamentar')),
],
options={
'verbose_name': 'Reunião de Frente Parlamentar',
'verbose_name_plural': 'Reuniões de Frentes Parlamentares',
'ordering': ('numero', 'frente'),
},
),
migrations.CreateModel(
name='DocumentoAcessorio',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('nome', models.CharField(max_length=50, verbose_name='Nome')),
('data', models.DateField(blank=True, default=None, null=True, verbose_name='Data')),
('autor', models.CharField(max_length=200, verbose_name='Autor')),
('ementa', models.TextField(blank=True, verbose_name='Ementa')),
('indexacao', models.TextField(blank=True)),
('arquivo', models.FileField(blank=True, max_length=300, null=True, storage=sapl.utils.OverwriteStorage(), upload_to=sapl.parlamentares.models.anexo_upload_path, verbose_name='Texto Integral')),
('data_ultima_atualizacao', models.DateTimeField(auto_now=True, null=True, verbose_name='Data')),
('reuniao', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='documentoacessorio_set', to='parlamentares.Reuniao')),
],
options={
'verbose_name': 'Documento Acessório',
'verbose_name_plural': 'Documentos Acessórios',
'ordering': ('data', 'id'),
},
),
]
Loading