From 44db00165521530d6439bc9e06ceb71eb8088590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pedro=20Sconetto?= Date: Tue, 27 Mar 2018 15:15:17 -0300 Subject: [PATCH] =?UTF-8?q?1413-Audi=C3=AAncia=20P=C3=BAblica=20(#1743)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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ência --- sapl/audiencia/__init__.py | 1 + sapl/audiencia/admin.py | 3 + sapl/audiencia/apps.py | 8 + sapl/audiencia/forms.py | 85 ++++++++++ sapl/audiencia/migrations/0001_initial.py | 62 ++++++++ .../migrations/0002_auto_20180302_0926.py | 20 +++ .../migrations/0003_auto_20180302_1111.py | 36 +++++ .../migrations/0004_auto_20180305_1006.py | 31 ++++ sapl/audiencia/migrations/__init__.py | 0 sapl/audiencia/models.py | 149 ++++++++++++++++++ sapl/audiencia/tests/test_audiencia.py | 3 + sapl/audiencia/urls.py | 10 ++ sapl/audiencia/views.py | 55 +++++++ sapl/redireciona_urls/views.py | 3 + sapl/rules/map_rules.py | 15 +- sapl/settings.py | 1 + sapl/templates/audiencia/layouts.yaml | 24 +++ sapl/templates/navbar.yaml | 2 + sapl/test_urls.py | 4 + sapl/urls.py | 2 + 20 files changed, 513 insertions(+), 1 deletion(-) create mode 100644 sapl/audiencia/__init__.py create mode 100644 sapl/audiencia/admin.py create mode 100644 sapl/audiencia/apps.py create mode 100644 sapl/audiencia/forms.py create mode 100644 sapl/audiencia/migrations/0001_initial.py create mode 100644 sapl/audiencia/migrations/0002_auto_20180302_0926.py create mode 100644 sapl/audiencia/migrations/0003_auto_20180302_1111.py create mode 100644 sapl/audiencia/migrations/0004_auto_20180305_1006.py create mode 100644 sapl/audiencia/migrations/__init__.py create mode 100644 sapl/audiencia/models.py create mode 100644 sapl/audiencia/tests/test_audiencia.py create mode 100644 sapl/audiencia/urls.py create mode 100644 sapl/audiencia/views.py create mode 100644 sapl/templates/audiencia/layouts.yaml diff --git a/sapl/audiencia/__init__.py b/sapl/audiencia/__init__.py new file mode 100644 index 000000000..e70131873 --- /dev/null +++ b/sapl/audiencia/__init__.py @@ -0,0 +1 @@ +default_app_config = 'sapl.audiencia.apps.AppConfig' \ No newline at end of file diff --git a/sapl/audiencia/admin.py b/sapl/audiencia/admin.py new file mode 100644 index 000000000..5c02ebd40 --- /dev/null +++ b/sapl/audiencia/admin.py @@ -0,0 +1,3 @@ +from sapl.utils import register_all_models_in_admin + +register_all_models_in_admin(__name__) diff --git a/sapl/audiencia/apps.py b/sapl/audiencia/apps.py new file mode 100644 index 000000000..e9b3c890f --- /dev/null +++ b/sapl/audiencia/apps.py @@ -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') \ No newline at end of file diff --git a/sapl/audiencia/forms.py b/sapl/audiencia/forms.py new file mode 100644 index 000000000..3ad74cca9 --- /dev/null +++ b/sapl/audiencia/forms.py @@ -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 \ No newline at end of file diff --git a/sapl/audiencia/migrations/0001_initial.py b/sapl/audiencia/migrations/0001_initial.py new file mode 100644 index 000000000..0e7bc7800 --- /dev/null +++ b/sapl/audiencia/migrations/0001_initial.py @@ -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'), + ), + ] diff --git a/sapl/audiencia/migrations/0002_auto_20180302_0926.py b/sapl/audiencia/migrations/0002_auto_20180302_0926.py new file mode 100644 index 000000000..7d32c24ec --- /dev/null +++ b/sapl/audiencia/migrations/0002_auto_20180302_0926.py @@ -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'), + ), + ] diff --git a/sapl/audiencia/migrations/0003_auto_20180302_1111.py b/sapl/audiencia/migrations/0003_auto_20180302_1111.py new file mode 100644 index 000000000..4f6e0bdec --- /dev/null +++ b/sapl/audiencia/migrations/0003_auto_20180302_1111.py @@ -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'), + ), + ] diff --git a/sapl/audiencia/migrations/0004_auto_20180305_1006.py b/sapl/audiencia/migrations/0004_auto_20180305_1006.py new file mode 100644 index 000000000..4208be958 --- /dev/null +++ b/sapl/audiencia/migrations/0004_auto_20180305_1006.py @@ -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'), + ), + ] diff --git a/sapl/audiencia/migrations/__init__.py b/sapl/audiencia/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/sapl/audiencia/models.py b/sapl/audiencia/models.py new file mode 100644 index 000000000..96ad8272a --- /dev/null +++ b/sapl/audiencia/models.py @@ -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) \ No newline at end of file diff --git a/sapl/audiencia/tests/test_audiencia.py b/sapl/audiencia/tests/test_audiencia.py new file mode 100644 index 000000000..7ce503c2d --- /dev/null +++ b/sapl/audiencia/tests/test_audiencia.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/sapl/audiencia/urls.py b/sapl/audiencia/urls.py new file mode 100644 index 000000000..ece3bf1fb --- /dev/null +++ b/sapl/audiencia/urls.py @@ -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())), +] \ No newline at end of file diff --git a/sapl/audiencia/views.py b/sapl/audiencia/views.py new file mode 100644 index 000000000..c0e353139 --- /dev/null +++ b/sapl/audiencia/views.py @@ -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) + + \ No newline at end of file diff --git a/sapl/redireciona_urls/views.py b/sapl/redireciona_urls/views.py index 64e03e36c..369ff7518 100644 --- a/sapl/redireciona_urls/views.py +++ b/sapl/redireciona_urls/views.py @@ -7,6 +7,7 @@ from sapl.materia.apps import AppConfig as materiaConfig from sapl.norma.apps import AppConfig as normaConfig from sapl.parlamentares.apps import AppConfig as parlamentaresConfig from sapl.sessao.apps import AppConfig as sessaoConfig +from sapl.audiencia.apps import AppConfig as audienciaConfig from .exceptions import UnknownUrlNameError @@ -22,6 +23,7 @@ app_materia = materiaConfig.name app_sessao = sessaoConfig.name app_norma = normaConfig.name app_relatorios = relatoriosConfig.name +app_audiencia = audienciaConfig.name pesquisar_atas = (app_atas + ':atas') presenca_sessao = (app_presenca_sessao + ':presenca_sessao') @@ -32,6 +34,7 @@ parlamentar_mesa_diretora = (app_parlamentares + ':mesa_diretora') comissao_list = (app_comissoes + ':comissao_list') comissao_detail = (app_comissoes + ':comissao_detail') +audiencia = (app_audiencia + ':audiencia') reuniao_detail = (app_comissoes + ':reuniao_detail') materialegislativa_detail = (app_materia + ':materialegislativa_detail') diff --git a/sapl/rules/map_rules.py b/sapl/rules/map_rules.py index c7589eecf..f98da8c0e 100644 --- a/sapl/rules/map_rules.py +++ b/sapl/rules/map_rules.py @@ -7,6 +7,7 @@ from sapl.norma import models as norma from sapl.painel import models as painel from sapl.parlamentares import models as parlamentares from sapl.protocoloadm import models as protocoloadm +from sapl.audiencia import models as audiencia from sapl.rules import (RP_ADD, RP_CHANGE, RP_DELETE, RP_DETAIL, RP_LIST, SAPL_GROUP_ADMINISTRATIVO, SAPL_GROUP_ANONYMOUS, SAPL_GROUP_AUTOR, SAPL_GROUP_COMISSOES, @@ -60,6 +61,15 @@ rules_group_administrativo = { ] } +rules_group_audiencia = { + 'group': SAPL_GROUP_GERAL, + 'rules': [ + (audiencia.AudienciaPublica, __base__), + (audiencia.TipoAudienciaPublica, __base__), + ] +} + + rules_group_protocolo = { 'group': SAPL_GROUP_PROTOCOLO, 'rules': [ @@ -272,7 +282,8 @@ rules_group_geral = { (compilacao.TipoDispositivoRelationship, []), (compilacao.PerfilEstruturalTextoArticulado, []), - + (audiencia.AudienciaPublica, __base__), + (audiencia.TipoAudienciaPublica, __base__), @@ -299,6 +310,7 @@ rules_group_geral['rules'] = (rules_group_geral['rules'] + rules_group_administrativo['rules'] + rules_group_protocolo['rules'] + rules_group_comissoes['rules'] + + rules_group_audiencia['rules'] + rules_group_materia['rules'] + rules_group_norma['rules'] + rules_group_sessao['rules'] + @@ -307,6 +319,7 @@ rules_group_geral['rules'] = (rules_group_geral['rules'] + rules_patterns = [ + rules_group_audiencia, rules_group_administrativo, rules_group_protocolo, rules_group_comissoes, diff --git a/sapl/settings.py b/sapl/settings.py index 2e6b7c7ff..41e7015ae 100644 --- a/sapl/settings.py +++ b/sapl/settings.py @@ -47,6 +47,7 @@ else: # SAPL business apps in dependency order SAPL_APPS = ( + 'sapl.audiencia', 'sapl.base', 'sapl.crud', 'sapl.parlamentares', diff --git a/sapl/templates/audiencia/layouts.yaml b/sapl/templates/audiencia/layouts.yaml new file mode 100644 index 000000000..90433db63 --- /dev/null +++ b/sapl/templates/audiencia/layouts.yaml @@ -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 \ No newline at end of file diff --git a/sapl/templates/navbar.yaml b/sapl/templates/navbar.yaml index 934557aea..80d220fb3 100644 --- a/sapl/templates/navbar.yaml +++ b/sapl/templates/navbar.yaml @@ -13,6 +13,8 @@ url: sapl.parlamentares:frente_list - title: {% trans 'Parlamentares' %} url: sapl.parlamentares:parlamentar_list + - title: {% trans 'Audiências Públicas' %} + url: sapl.audiencia:audienciapublica_list - title: {% trans 'Protocolo' %} check_permission: protocoloadm.list_protocolo diff --git a/sapl/test_urls.py b/sapl/test_urls.py index ebc88da2b..8423a98ed 100644 --- a/sapl/test_urls.py +++ b/sapl/test_urls.py @@ -148,6 +148,10 @@ def test_crudaux_list_do_crud_esta_na_pagina_sistema(url_item, admin_client): apps_url_patterns_prefixs_and_users = { + 'audiencia': { + 'prefixs': [ + '/audiencia', + ]}, 'api': { 'prefixs': [ '/api/', diff --git a/sapl/urls.py b/sapl/urls.py index 38667b4e7..b6a5af3e4 100644 --- a/sapl/urls.py +++ b/sapl/urls.py @@ -33,6 +33,7 @@ import sapl.protocoloadm.urls import sapl.redireciona_urls.urls import sapl.relatorios.urls import sapl.sessao.urls +import sapl.audiencia.urls urlpatterns = [ url(r'^$', TemplateView.as_view(template_name='index.html'), @@ -50,6 +51,7 @@ urlpatterns = [ url(r'', include(sapl.protocoloadm.urls)), url(r'', include(sapl.compilacao.urls)), url(r'', include(sapl.relatorios.urls)), + url(r'', include(sapl.audiencia.urls)), # must come at the end # so that base /sistema/ url doesn't capture its children