mirror of https://github.com/interlegis/sapl.git
Browse Source
* Adicionando estrutura inicial de audiência * Corrige erro em test_urls.py * Modelo de dados inicial de audiência * Adições e correções * Nova adições em audiência Criação preliminar do form de audiência Correções na model Adição das urls do Crud Adição da view inicial de audiência * Correções para o funcionamento inicial de audiência * Corrige erros nos testes * Layout inicial de audiência * Pequenas correções * Modificação em Tipo Audiência e correções * Corrige o update, delete e list view. * Adição de valores padrão ao tipo no form * Adição de matéria por meio de dados chave * Corrige erro ao mostrar detalhes de audiênciapull/1807/head
João Pedro Sconetto
7 years ago
committed by
Edward
20 changed files with 513 additions and 1 deletions
@ -0,0 +1 @@ |
|||
default_app_config = 'sapl.audiencia.apps.AppConfig' |
@ -0,0 +1,3 @@ |
|||
from sapl.utils import register_all_models_in_admin |
|||
|
|||
register_all_models_in_admin(__name__) |
@ -0,0 +1,8 @@ |
|||
from django import apps |
|||
from django.utils.translation import ugettext_lazy as _ |
|||
|
|||
|
|||
class AppConfig(apps.AppConfig): |
|||
name = 'sapl.audiencia' |
|||
label = 'audiencia' |
|||
verbose_name = _('Audiência Pública') |
@ -0,0 +1,85 @@ |
|||
from django import forms |
|||
from django.core.exceptions import ObjectDoesNotExist, ValidationError |
|||
from django.db import transaction |
|||
from django.utils.translation import ugettext_lazy as _ |
|||
from sapl.audiencia.models import AudienciaPublica, TipoAudienciaPublica |
|||
from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa |
|||
from sapl.utils import timezone |
|||
|
|||
class AudienciaForm(forms.ModelForm): |
|||
|
|||
data_atual = timezone.now() |
|||
|
|||
tipo = forms.ModelChoiceField(required=True, |
|||
label='Tipo de Audiência Pública', |
|||
queryset=TipoAudienciaPublica.objects.all().order_by('nome')) |
|||
|
|||
tipo_materia = forms.ModelChoiceField( |
|||
label=_('Tipo Matéria'), |
|||
required=True, |
|||
queryset=TipoMateriaLegislativa.objects.all(), |
|||
empty_label='Selecione', |
|||
) |
|||
|
|||
numero_materia = forms.CharField( |
|||
label='Número Matéria', required=True) |
|||
|
|||
ano_materia = forms.CharField( |
|||
label='Ano Matéria', |
|||
initial=int(data_atual.year), |
|||
required=True) |
|||
|
|||
class Meta: |
|||
model = AudienciaPublica |
|||
fields = ['tipo', 'numero', 'nome', |
|||
'tema', 'data', 'hora_inicio', 'hora_fim', |
|||
'observacao', 'audiencia_cancelada', 'url_audio', |
|||
'url_video', 'upload_pauta', 'upload_ata', |
|||
'upload_anexo', 'tipo_materia', 'numero_materia', |
|||
'ano_materia'] |
|||
|
|||
|
|||
def __init__(self, **kwargs): |
|||
super(AudienciaForm, self).__init__(**kwargs) |
|||
|
|||
tipos = [] |
|||
|
|||
if not self.fields['tipo'].queryset: |
|||
tipos.append(TipoAudienciaPublica.objects.create(nome='Audiência Pública', tipo='A')) |
|||
tipos.append(TipoAudienciaPublica.objects.create(nome='Plebiscito', tipo='P')) |
|||
tipos.append(TipoAudienciaPublica.objects.create(nome='Referendo', tipo='R')) |
|||
tipos.append(TipoAudienciaPublica.objects.create(nome='Iniciativa Popular', tipo='I')) |
|||
|
|||
for t in tipos: |
|||
t.save() |
|||
|
|||
|
|||
def clean(self): |
|||
cleaned_data = super(AudienciaForm, self).clean() |
|||
if not self.is_valid(): |
|||
return cleaned_data |
|||
|
|||
try: |
|||
materia = MateriaLegislativa.objects.get( |
|||
numero=self.cleaned_data['numero_materia'], |
|||
ano=self.cleaned_data['ano_materia'], |
|||
tipo=self.cleaned_data['tipo_materia']) |
|||
except ObjectDoesNotExist: |
|||
msg = _('A matéria a ser inclusa não existe no cadastro' |
|||
' de matérias legislativas.') |
|||
raise ValidationError(msg) |
|||
else: |
|||
cleaned_data['materia'] = materia |
|||
|
|||
if self.cleaned_data['hora_inicio'] and self.cleaned_data['hora_fim']: |
|||
if (self.cleaned_data['hora_fim'] < |
|||
self.cleaned_data['hora_inicio']): |
|||
msg = _('A hora de fim não pode ser anterior a hora de ínicio') |
|||
raise ValidationError(msg) |
|||
|
|||
return self.cleaned_data |
|||
|
|||
@transaction.atomic() |
|||
def save(self, commit=True): |
|||
audiencia = super(AudienciaForm, self).save(commit) |
|||
return audiencia |
@ -0,0 +1,62 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.13 on 2018-03-01 17:01 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
import django.db.models.deletion |
|||
import sapl.audiencia.models |
|||
import sapl.utils |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
initial = True |
|||
|
|||
dependencies = [ |
|||
('materia', '0025_auto_20180221_1649'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.CreateModel( |
|||
name='AudienciaPublica', |
|||
fields=[ |
|||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
|||
('numero', models.PositiveIntegerField(blank=True, verbose_name='Número')), |
|||
('nome', models.CharField(max_length=100, verbose_name='Nome da Audiência Pública')), |
|||
('tema', models.CharField(max_length=100, verbose_name='Tema da Audiência Pública')), |
|||
('data', models.DateField(verbose_name='Data')), |
|||
('hora_inicio', models.CharField(max_length=5, verbose_name='Horário (hh:mm)')), |
|||
('hora_fim', models.CharField(max_length=5, verbose_name='Horário (hh:mm)')), |
|||
('observacao', models.CharField(blank=True, max_length=200, verbose_name='Observação')), |
|||
('audiencia_cancelada', models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=False, verbose_name='Audiência Cancela?')), |
|||
('url_audio', models.URLField(blank=True, max_length=150, verbose_name='URL Arquivo Áudio (Formatos MP3 / AAC)')), |
|||
('url_video', models.URLField(blank=True, max_length=150, verbose_name='URL Arquivo Vídeo (Formatos MP4 / FLV / WebM)')), |
|||
('upload_pauta', models.FileField(blank=True, null=True, upload_to=sapl.audiencia.models.pauta_upload_path, validators=[sapl.utils.restringe_tipos_de_arquivo_txt], verbose_name='Pauta da Audiência Pública')), |
|||
('upload_ata', models.FileField(blank=True, null=True, upload_to=sapl.audiencia.models.ata_upload_path, validators=[sapl.utils.restringe_tipos_de_arquivo_txt], verbose_name='Ata da Audiência Pública')), |
|||
('upload_anexo', models.FileField(blank=True, null=True, upload_to=sapl.audiencia.models.anexo_upload_path, verbose_name='Anexo da Audiência Pública')), |
|||
('materia', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='materia.MateriaLegislativa', verbose_name='Matéria Legislativa')), |
|||
], |
|||
options={ |
|||
'verbose_name': 'Audiência Pública', |
|||
'verbose_name_plural': 'Audiências Públicas', |
|||
'ordering': ['nome', 'numero', 'tipo'], |
|||
}, |
|||
), |
|||
migrations.CreateModel( |
|||
name='TipoAudienciaPublica', |
|||
fields=[ |
|||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
|||
('nome', models.CharField(choices=[('A', 'Audiência Pública'), ('P', 'Plebiscito'), ('R', 'Referendo'), ('I', 'Iniciativa Popular')], max_length=1, verbose_name='Tipo de Audiência Pública')), |
|||
], |
|||
options={ |
|||
'verbose_name': 'Tipo de Audiência Pública', |
|||
'verbose_name_plural': 'Tipos de Audiência Pública', |
|||
'ordering': ['nome'], |
|||
}, |
|||
), |
|||
migrations.AddField( |
|||
model_name='audienciapublica', |
|||
name='tipo', |
|||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='audiencia.TipoAudienciaPublica', verbose_name='Tipo'), |
|||
), |
|||
] |
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.13 on 2018-03-02 12:26 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('audiencia', '0001_initial'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='audienciapublica', |
|||
name='observacao', |
|||
field=models.TextField(blank=True, max_length=500, verbose_name='Observação'), |
|||
), |
|||
] |
@ -0,0 +1,36 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.13 on 2018-03-02 14:11 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
import django.db.models.deletion |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('audiencia', '0002_auto_20180302_0926'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='audienciapublica', |
|||
name='audiencia_cancelada', |
|||
field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=False, verbose_name='Audiência Cancelada?'), |
|||
), |
|||
migrations.AlterField( |
|||
model_name='audienciapublica', |
|||
name='hora_fim', |
|||
field=models.CharField(max_length=5, verbose_name='Horário Fim(hh:mm)'), |
|||
), |
|||
migrations.AlterField( |
|||
model_name='audienciapublica', |
|||
name='hora_inicio', |
|||
field=models.CharField(max_length=5, verbose_name='Horário Início(hh:mm)'), |
|||
), |
|||
migrations.AlterField( |
|||
model_name='audienciapublica', |
|||
name='materia', |
|||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='materia.MateriaLegislativa', verbose_name='Matéria Legislativa'), |
|||
), |
|||
] |
@ -0,0 +1,31 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.13 on 2018-03-05 13:06 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
import django.db.models.deletion |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('audiencia', '0003_auto_20180302_1111'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='tipoaudienciapublica', |
|||
name='tipo', |
|||
field=models.CharField(choices=[('A', 'Audiência Pública'), ('P', 'Plebiscito'), ('R', 'Referendo'), ('I', 'Iniciativa Popular')], default='A', max_length=1, verbose_name='Tipo de Audiência Pública'), |
|||
), |
|||
migrations.AlterField( |
|||
model_name='audienciapublica', |
|||
name='tipo', |
|||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='audiencia.TipoAudienciaPublica', verbose_name='Tipo de Audiência Pública'), |
|||
), |
|||
migrations.AlterField( |
|||
model_name='tipoaudienciapublica', |
|||
name='nome', |
|||
field=models.CharField(default='Audiência Pública', max_length=50, verbose_name='Nome do Tipo de Audiência Pública'), |
|||
), |
|||
] |
@ -0,0 +1,149 @@ |
|||
import reversion |
|||
from django.db import models |
|||
from django.utils.translation import ugettext_lazy as _ |
|||
from model_utils import Choices |
|||
from sapl.materia.models import MateriaLegislativa |
|||
from sapl.parlamentares.models import (CargoMesa, Parlamentar) |
|||
|
|||
from sapl.utils import (YES_NO_CHOICES, SaplGenericRelation, |
|||
restringe_tipos_de_arquivo_txt, texto_upload_path) |
|||
|
|||
|
|||
def get_audiencia_media_path(instance, subpath, filename): |
|||
return './sapl/audiencia/%s/%s/%s' % (instance.numero, subpath, filename) |
|||
|
|||
|
|||
def pauta_upload_path(instance, filename): |
|||
return texto_upload_path( |
|||
instance, filename, subpath='pauta', pk_first=True) |
|||
|
|||
|
|||
def ata_upload_path(instance, filename): |
|||
return texto_upload_path(instance, filename, subpath='ata', pk_first=True) |
|||
|
|||
|
|||
def anexo_upload_path(instance, filename): |
|||
return texto_upload_path( |
|||
instance, filename, subpath='anexo', pk_first=True) |
|||
|
|||
|
|||
@reversion.register() |
|||
class TipoAudienciaPublica(models.Model): |
|||
TIPO_AUDIENCIA_CHOICES = Choices(('A', 'audiencia', _('Audiência Pública')), |
|||
('P', 'plebiscito', _('Plebiscito')), |
|||
('R', 'referendo', _('Referendo')), |
|||
('I', 'iniciativa', _('Iniciativa Popular'))) |
|||
|
|||
nome = models.CharField( |
|||
max_length=50, verbose_name=_('Nome do Tipo de Audiência Pública'), default='Audiência Pública') |
|||
tipo = models.CharField( |
|||
max_length=1, verbose_name=_('Tipo de Audiência Pública'), choices=TIPO_AUDIENCIA_CHOICES, default='A') |
|||
|
|||
|
|||
class Meta: |
|||
verbose_name = _('Tipo de Audiência Pública') |
|||
verbose_name_plural = _('Tipos de Audiência Pública') |
|||
ordering = ['nome'] |
|||
|
|||
def __str__(self): |
|||
return self.nome |
|||
|
|||
|
|||
@reversion.register() |
|||
class AudienciaPublica(models.Model): |
|||
materia = models.ForeignKey( |
|||
MateriaLegislativa, |
|||
on_delete=models.PROTECT, |
|||
null=True, |
|||
blank=True, |
|||
verbose_name=_('Matéria Legislativa')) |
|||
tipo = models.ForeignKey(TipoAudienciaPublica, |
|||
on_delete=models.PROTECT, |
|||
null=True, |
|||
blank=True, |
|||
verbose_name=_('Tipo de Audiência Pública')) |
|||
numero = models.PositiveIntegerField(blank=True, verbose_name=_('Número')) |
|||
nome = models.CharField( |
|||
max_length=100, verbose_name=_('Nome da Audiência Pública')) |
|||
tema = models.CharField( |
|||
max_length=100, verbose_name=_('Tema da Audiência Pública')) |
|||
data = models.DateField(verbose_name=_('Data')) |
|||
hora_inicio = models.CharField( |
|||
max_length=5, verbose_name=_('Horário Início(hh:mm)')) |
|||
hora_fim = models.CharField( |
|||
max_length=5, verbose_name=_('Horário Fim(hh:mm)')) |
|||
observacao = models.TextField( |
|||
max_length=500, blank=True, verbose_name=_('Observação')) |
|||
audiencia_cancelada = models.BooleanField( |
|||
default=False, |
|||
choices=YES_NO_CHOICES, |
|||
verbose_name=_('Audiência Cancelada?')) |
|||
url_audio = models.URLField( |
|||
max_length=150, blank=True, |
|||
verbose_name=_('URL Arquivo Áudio (Formatos MP3 / AAC)')) |
|||
url_video = models.URLField( |
|||
max_length=150, blank=True, |
|||
verbose_name=_('URL Arquivo Vídeo (Formatos MP4 / FLV / WebM)')) |
|||
upload_pauta = models.FileField( |
|||
blank=True, |
|||
null=True, |
|||
upload_to=pauta_upload_path, |
|||
verbose_name=_('Pauta da Audiência Pública'), |
|||
validators=[restringe_tipos_de_arquivo_txt]) |
|||
upload_ata = models.FileField( |
|||
blank=True, |
|||
null=True, |
|||
upload_to=ata_upload_path, |
|||
verbose_name=_('Ata da Audiência Pública'), |
|||
validators=[restringe_tipos_de_arquivo_txt]) |
|||
upload_anexo = models.FileField( |
|||
blank=True, |
|||
null=True, |
|||
upload_to=anexo_upload_path, |
|||
verbose_name=_('Anexo da Audiência Pública')) |
|||
|
|||
class Meta: |
|||
verbose_name = _('Audiência Pública') |
|||
verbose_name_plural = _('Audiências Públicas') |
|||
ordering = ['nome', 'numero', 'tipo'] |
|||
|
|||
def __str__(self): |
|||
return self.nome |
|||
|
|||
def delete(self, using=None, keep_parents=False): |
|||
if self.upload_pauta: |
|||
self.upload_pauta.delete() |
|||
|
|||
if self.upload_ata: |
|||
self.upload_ata.delete() |
|||
|
|||
if self.upload_anexo: |
|||
self.upload_anexo.delete() |
|||
|
|||
return models.Model.delete( |
|||
self, using=using, keep_parents=keep_parents) |
|||
|
|||
def save(self, force_insert=False, force_update=False, using=None, |
|||
update_fields=None): |
|||
|
|||
if not self.pk and (self.upload_pauta or self.upload_ata or |
|||
self.upload_anexo): |
|||
upload_pauta = self.upload_pauta |
|||
upload_ata = self.upload_ata |
|||
upload_anexo = self.upload_anexo |
|||
self.upload_pauta = None |
|||
self.upload_ata = None |
|||
self.upload_anexo = None |
|||
models.Model.save(self, force_insert=force_insert, |
|||
force_update=force_update, |
|||
using=using, |
|||
update_fields=update_fields) |
|||
|
|||
self.upload_pauta = upload_pauta |
|||
self.upload_ata = upload_ata |
|||
self.upload_anexo = upload_anexo |
|||
|
|||
return models.Model.save(self, force_insert=force_insert, |
|||
force_update=force_update, |
|||
using=using, |
|||
update_fields=update_fields) |
@ -0,0 +1,3 @@ |
|||
from django.test import TestCase |
|||
|
|||
# Create your tests here. |
@ -0,0 +1,10 @@ |
|||
from django.conf.urls import include, url |
|||
from sapl.audiencia.views import (index, AudienciaCrud) |
|||
|
|||
from .apps import AppConfig |
|||
|
|||
app_name = AppConfig.name |
|||
|
|||
urlpatterns = [ |
|||
url(r'^audiencia/', include(AudienciaCrud.get_urls())), |
|||
] |
@ -0,0 +1,55 @@ |
|||
from django.shortcuts import render |
|||
from django.http import HttpResponse |
|||
from django.core.urlresolvers import reverse |
|||
from django.db.models import F |
|||
from django.views.decorators.clickjacking import xframe_options_exempt |
|||
from django.views.generic import ListView |
|||
from sapl.comissoes.forms import ParticipacaoCreateForm, ParticipacaoEditForm |
|||
from sapl.crud.base import RP_DETAIL, RP_LIST, Crud, CrudAux, MasterDetailCrud |
|||
from sapl.materia.models import MateriaLegislativa |
|||
|
|||
from .forms import AudienciaForm |
|||
from .models import (AudienciaPublica, TipoAudienciaPublica) |
|||
|
|||
def index(request): |
|||
return HttpResponse("Audiência Pública") |
|||
|
|||
class AudienciaCrud(Crud): |
|||
model = AudienciaPublica |
|||
public = [RP_LIST, RP_DETAIL, ] |
|||
|
|||
class BaseMixin(Crud.BaseMixin): |
|||
list_field_names = ['materia', 'tipo', 'numero', 'nome', |
|||
'data'] |
|||
ordering = 'nome', 'numero', 'tipo', 'data' |
|||
|
|||
class ListView(Crud.ListView): |
|||
paginate_by = 10 |
|||
|
|||
class CreateView(Crud.CreateView): |
|||
form_class = AudienciaForm |
|||
|
|||
def form_valid(self, form): |
|||
return super(Crud.CreateView, self).form_valid(form) |
|||
|
|||
class UpdateView(Crud.UpdateView): |
|||
form_class = AudienciaForm |
|||
|
|||
def get_initial(self): |
|||
self.initial['tipo_materia'] = self.object.materia.tipo.id |
|||
self.initial['numero_materia'] = self.object.materia.numero |
|||
self.initial['ano_materia'] = self.object.materia.ano |
|||
return self.initial |
|||
|
|||
class DeleteView(Crud.DeleteView): |
|||
pass |
|||
|
|||
class DetailView(Crud.DetailView): |
|||
|
|||
layout_key = 'AudienciaPublicaDetail' |
|||
|
|||
@xframe_options_exempt |
|||
def get(self, request, *args, **kwargs): |
|||
return super().get(request, *args, **kwargs) |
|||
|
|||
|
@ -0,0 +1,24 @@ |
|||
{% load i18n %} |
|||
AudienciaPublica: |
|||
{% trans 'Audiência Pública' %}: |
|||
- nome:10 numero |
|||
- tema |
|||
{% trans 'Dados' %}: |
|||
- tipo_materia numero_materia ano_materia |
|||
- tipo:4 data:2 hora_inicio:3 hora_fim:3 |
|||
- url_audio url_video |
|||
- upload_pauta upload_ata upload_anexo |
|||
- observacao |
|||
- audiencia_cancelada |
|||
|
|||
AudienciaPublicaDetail: |
|||
{% trans 'Audiência Pública' %}: |
|||
- nome:10 numero |
|||
- tema |
|||
{% trans 'Dados' %}: |
|||
- materia tipo |
|||
- data hora_inicio hora_fim |
|||
- url_audio url_video |
|||
- upload_pauta upload_ata upload_anexo |
|||
- observacao |
|||
- audiencia_cancelada |
Loading…
Reference in new issue