Browse Source

Fix #1566 (#1750)

* Adiciona a model, forms e views da reunião de comissão

* Adiciona a model, forms e views da reunião de comissão

* Adiciona a model, forms e views da reunião de comissão

* Adiciona telas de cadastro de reunião

* Adiciona telas de cadastro de reunião

* Adiciona layouts e legacy

* Adiciona template, modifica o subnav e o ListView

* Troca Crud por MasterCrudDetail

* Troca Crud por MasterCrudDetail

* Troca Crud por MasterCrudDetail

* Adiciona template de cadastro de reunião

* Corrige Createview e Listview

* Ajusta comissoes

* Corrige o deleteview e o detailview

* Muda o layout do create de reunião

* - Retira o campo tipo de cadastro de reunião
- Retira a obrigatoriedade do campo tema

* Corrige migração

* Adiciona Documento Acessorio em cadastro de reunião

* Adiciona migração

* Adiciona Documento Acessorio no Map Rules

* Corrige alguns erros e adiciona mais detalhes no template

* Pequena correção

* Fix #1566

* Adiciona migração e corrige list view

* Ajusta titulo de exibição do documento acessorio
pull/1759/head
Mariana Mendes 7 years ago
committed by Edward
parent
commit
29e94455e3
  1. 56
      sapl/comissoes/forms.py
  2. 1
      sapl/comissoes/legacy.yaml
  3. 29
      sapl/comissoes/migrations/0010_auto_20180307_1645.py
  4. 16
      sapl/comissoes/migrations/0011_merge.py
  5. 36
      sapl/comissoes/migrations/0012_documentoacessorio.py
  6. 20
      sapl/comissoes/migrations/0013_auto_20180312_1533.py
  7. 70
      sapl/comissoes/models.py
  8. 9
      sapl/comissoes/urls.py
  9. 98
      sapl/comissoes/views.py
  10. 1
      sapl/materia/forms.py
  11. 1
      sapl/rules/map_rules.py
  12. 7
      sapl/templates/comissoes/cadastro_reuniao.html
  13. 7
      sapl/templates/comissoes/cadastro_reuniao_edit.html
  14. 17
      sapl/templates/comissoes/layouts.yaml
  15. 1
      sapl/templates/comissoes/subnav.yaml

56
sapl/comissoes/forms.py

@ -7,7 +7,8 @@ from django.forms import ModelForm
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from sapl.base.models import Autor, TipoAutor from sapl.base.models import Autor, TipoAutor
from sapl.comissoes.models import Comissao, Composicao, Participacao, Reuniao from sapl.comissoes.models import (Comissao, Composicao, DocumentoAcessorio,
Participacao, Reuniao)
from sapl.parlamentares.models import Legislatura, Mandato, Parlamentar from sapl.parlamentares.models import Legislatura, Mandato, Parlamentar
@ -155,20 +156,53 @@ class ReuniaoForm(ModelForm):
class Meta: class Meta:
model = Reuniao model = Reuniao
exclude = ['cod_andamento_reuniao'] exclude = ['cod_andamento_reuniao']
widgets = {
'hora_fim': forms.TimeInput(format='%H:%M'),
'hora_inicio': forms.TimeInput(format='%H:%M'),
}
def clean(self): def clean(self):
super(ReuniaoForm, self).clean() super(ReuniaoForm, self).clean()
if self.errors: if self.cleaned_data['hora_fim']:
return 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')
raise ValidationError(msg)
return self.cleaned_data
class DocumentoAcessorioCreateForm(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'])
comissao = reuniao.comissao
comissao_pk = comissao.id
documentos = reuniao.documentoacessorio_set.all()
return self.create_documentoacessorio()
if self.cleaned_data['hora_fim'] < self.cleaned_data['hora_inicio']: def create_documentoacessorio(self):
msg = _('A hora de término da reunião não pode ' reuniao = Reuniao.objects.get(id=self.initial['parent_pk'])
'ser menor que a de início')
raise ValidationError(msg)
def clean(self):
super(DocumentoAcessorioCreateForm, self).clean()
return self.cleaned_data return self.cleaned_data
class DocumentoAcessorioEditForm(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)

1
sapl/comissoes/legacy.yaml

@ -47,7 +47,6 @@ Participacao (ComposicaoComissao):
Reuniao: Reuniao:
periodo: periodo_reuniao periodo: periodo_reuniao
comissao: cod_comissao comissao: cod_comissao
tipo: tipo_comissao
numero: num_comissao numero: num_comissao
nome: nom_reuniao nome: nom_reuniao
tema: tem_reuniao tema: tem_reuniao

29
sapl/comissoes/migrations/0010_auto_20180307_1645.py

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-03-07 19:45
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('comissoes', '0009_auto_20180301_1011'),
]
operations = [
migrations.RemoveField(
model_name='reuniao',
name='tipo',
),
migrations.AlterField(
model_name='reuniao',
name='nome',
field=models.CharField(max_length=150, verbose_name='Nome da Reunião'),
),
migrations.AlterField(
model_name='reuniao',
name='tema',
field=models.CharField(blank=True, max_length=150, verbose_name='Tema da Reunião'),
),
]

16
sapl/comissoes/migrations/0011_merge.py

@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-03-09 10:27
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('comissoes', '0010_auto_20180307_1645'),
('comissoes', '0010_auto_20180306_0918'),
]
operations = [
]

36
sapl/comissoes/migrations/0012_documentoacessorio.py

@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-03-09 12:38
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import sapl.comissoes.models
import sapl.utils
class Migration(migrations.Migration):
dependencies = [
('comissoes', '0011_merge'),
]
operations = [
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(blank=True, max_length=50, verbose_name='Autor')),
('ementa', models.TextField(blank=True, verbose_name='Ementa')),
('indexacao', models.TextField(blank=True)),
('arquivo', models.FileField(blank=True, null=True, upload_to=sapl.comissoes.models.anexo_upload_path, validators=[sapl.utils.restringe_tipos_de_arquivo_txt], 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='comissoes.Reuniao')),
],
options={
'verbose_name': 'Documento Acessório',
'verbose_name_plural': 'Documentos Acessórios',
},
),
]

20
sapl/comissoes/migrations/0013_auto_20180312_1533.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-03-12 18:33
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('comissoes', '0012_documentoacessorio'),
]
operations = [
migrations.AlterField(
model_name='documentoacessorio',
name='autor',
field=models.CharField(max_length=100, verbose_name='Autor'),
),
]

70
sapl/comissoes/models.py

@ -182,15 +182,13 @@ class Participacao(models.Model): # ComposicaoComissao
def get_comissao_media_path(instance, subpath, filename): def get_comissao_media_path(instance, subpath, filename):
return './sapl/comissao/%s/%s/%s' % (instance.numero, subpath, filename) return './sapl/comissao/%s/%s/%s' % (instance.numero, subpath, filename)
def pauta_upload_path(instance, filename): def pauta_upload_path(instance, filename):
return texto_upload_path(instance, filename, subpath='pauta', pk_first=True)
return texto_upload_path(instance, filename, subpath='pauta', pk_first=True)
def ata_upload_path(instance, filename): def ata_upload_path(instance, filename):
return texto_upload_path(instance, filename, subpath='ata', pk_first=True) return texto_upload_path(instance, filename, subpath='ata', pk_first=True)
def anexo_upload_path(instance, filename): def anexo_upload_path(instance, filename):
return texto_upload_path(instance, filename, subpath='anexo', pk_first=True) return texto_upload_path(instance, filename, subpath='anexo', pk_first=True)
@ -204,15 +202,11 @@ class Reuniao(models.Model):
Comissao, Comissao,
on_delete=models.PROTECT, on_delete=models.PROTECT,
verbose_name=_('Comissão')) verbose_name=_('Comissão'))
tipo = models.ForeignKey(
TipoComissao,
on_delete=models.PROTECT,
verbose_name=_('Tipo de Comissão'))
numero = models.PositiveIntegerField(verbose_name=_('Número')) numero = models.PositiveIntegerField(verbose_name=_('Número'))
nome = models.CharField( nome = models.CharField(
max_length=100, verbose_name=_('Nome da Reunião')) max_length=150, verbose_name=_('Nome da Reunião'))
tema = models.CharField( tema = models.CharField(
max_length=100, verbose_name=_('Tema da Reunião')) max_length=150, blank=True, verbose_name=_('Tema da Reunião'))
data = models.DateField(verbose_name=_('Data')) data = models.DateField(verbose_name=_('Data'))
hora_inicio = models.TimeField( hora_inicio = models.TimeField(
verbose_name=_('Horário de Início (hh:mm)')) verbose_name=_('Horário de Início (hh:mm)'))
@ -287,3 +281,61 @@ class Reuniao(models.Model):
force_update=force_update, force_update=force_update,
using=using, using=using,
update_fields=update_fields) update_fields=update_fields)
@reversion.register()
class DocumentoAcessorio(models.Model):
reuniao = models.ForeignKey(Reuniao,
related_name='documentoacessorio_set',
on_delete=models.PROTECT)
nome = models.CharField(max_length=50, verbose_name=_('Nome'))
data = models.DateField(blank=True, null=True, default=None, verbose_name=_('Data'))
autor = models.CharField(
max_length=100, verbose_name=_('Autor'))
ementa = models.TextField(blank=True, verbose_name=_('Ementa'))
indexacao = models.TextField(blank=True)
arquivo = models.FileField(
blank=True,
null=True,
upload_to=anexo_upload_path,
verbose_name=_('Texto Integral'),
validators=[restringe_tipos_de_arquivo_txt])
data_ultima_atualizacao = models.DateTimeField(
blank=True, null=True,
auto_now=True,
verbose_name=_('Data'))
class Meta:
verbose_name = _('Documento Acessório')
verbose_name_plural = _('Documentos Acessórios')
def __str__(self):
return _('%(nome)s por %(autor)s') % {
'nome': self.nome,
'autor': self.autor}
def delete(self, using=None, keep_parents=False):
if self.arquivo:
self.arquivo.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.arquivo:
arquivo = self.arquivo
self.arquivo = None
models.Model.save(self, force_insert=force_insert,
force_update=force_update,
using=using,
update_fields=update_fields)
self.arquivo = arquivo
return models.Model.save(self, force_insert=force_insert,
force_update=force_update,
using=using,
update_fields=update_fields)

9
sapl/comissoes/urls.py

@ -1,9 +1,7 @@
from django.conf.urls import include, url from django.conf.urls import include, url
from sapl.comissoes.views import (CargoCrud, ComissaoCrud, ComposicaoCrud, from sapl.comissoes.views import (CargoCrud, ComissaoCrud, ComposicaoCrud,
MateriasTramitacaoListView, ParticipacaoCrud, DocumentoAcessorioCrud, MateriasTramitacaoListView, ParticipacaoCrud,
PeriodoComposicaoCrud, ReuniaoCrud, PeriodoComposicaoCrud, ReuniaoCrud, TipoComissaoCrud)
TipoComissaoCrud)
from .apps import AppConfig from .apps import AppConfig
@ -13,7 +11,8 @@ urlpatterns = [
url(r'^comissao/', include(ComissaoCrud.get_urls() + url(r'^comissao/', include(ComissaoCrud.get_urls() +
ComposicaoCrud.get_urls() + ComposicaoCrud.get_urls() +
ReuniaoCrud.get_urls() + ReuniaoCrud.get_urls() +
ParticipacaoCrud.get_urls())), ParticipacaoCrud.get_urls() +
DocumentoAcessorioCrud.get_urls())),
url(r'^comissao/(?P<pk>\d+)/materias-em-tramitacao$', url(r'^comissao/(?P<pk>\d+)/materias-em-tramitacao$',
MateriasTramitacaoListView.as_view(), name='materias_em_tramitacao'), MateriasTramitacaoListView.as_view(), name='materias_em_tramitacao'),

98
sapl/comissoes/views.py

@ -1,23 +1,27 @@
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db.models import F from django.db.models import F
from django.http.response import HttpResponseRedirect
from django.views.decorators.clickjacking import xframe_options_exempt from django.views.decorators.clickjacking import xframe_options_exempt
from django.views.generic import ListView from django.views.generic import ListView
from django.views.generic.base import RedirectView from django.views.generic.base import RedirectView
from django.views.generic.detail import DetailView from django.views.generic.detail import DetailView
from django.views.generic.edit import FormMixin from django.views.generic.edit import FormMixin
from sapl.base.models import AppConfig as AppsAppConfig from sapl.base.models import AppConfig as AppsAppConfig
from sapl.comissoes.apps import AppConfig from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud,
from sapl.comissoes.forms import ParticipacaoCreateForm, ParticipacaoEditForm CrudAux, MasterDetailCrud,
from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud, CrudAux, PermissionRequiredForAppCrudMixin)
MasterDetailCrud, from sapl.comissoes.forms import (ComissaoForm, DocumentoAcessorioCreateForm,
PermissionRequiredForAppCrudMixin) DocumentoAcessorioEditForm, ParticipacaoCreateForm,
ParticipacaoEditForm, ReuniaoForm)
from sapl.materia.models import MateriaLegislativa, Tramitacao from sapl.materia.models import MateriaLegislativa, Tramitacao
from .forms import ComissaoForm, ReuniaoForm
from .models import (CargoComissao, Comissao, Composicao, Participacao, from .models import (CargoComissao, Comissao, Composicao, DocumentoAcessorio,
Periodo, Reuniao, TipoComissao) Participacao, Periodo, TipoComissao, Reuniao)
from sapl.comissoes.apps import AppConfig
def pegar_url_composicao(pk): def pegar_url_composicao(pk):
@ -26,6 +30,11 @@ def pegar_url_composicao(pk):
url = reverse('sapl.comissoes:composicao_detail', kwargs={'pk': comp_pk}) url = reverse('sapl.comissoes:composicao_detail', kwargs={'pk': comp_pk})
return url return url
def pegar_url_reuniao(pk):
documentoacessorio = DocumentoAcessorio.objects.get(id=pk)
r_pk = documentoacessorio.reuniao.pk
url = reverse('sapl.comissoes:reuniao_detail', kwargs={'pk': r_pk})
return url
CargoCrud = CrudAux.build(CargoComissao, 'cargo_comissao') CargoCrud = CrudAux.build(CargoComissao, 'cargo_comissao')
PeriodoComposicaoCrud = CrudAux.build(Periodo, 'periodo_composicao_comissao') PeriodoComposicaoCrud = CrudAux.build(Periodo, 'periodo_composicao_comissao')
@ -58,7 +67,6 @@ class ParticipacaoCrud(MasterDetailCrud):
form_class = ParticipacaoEditForm form_class = ParticipacaoEditForm
class DeleteView(MasterDetailCrud.DeleteView): class DeleteView(MasterDetailCrud.DeleteView):
def get_success_url(self): def get_success_url(self):
composicao_comissao_pk = self.object.composicao.comissao.pk composicao_comissao_pk = self.object.composicao.comissao.pk
composicao_pk = self.object.composicao.pk composicao_pk = self.object.composicao.pk
@ -146,22 +154,44 @@ class MateriasTramitacaoListView(ListView):
context['object'] = Comissao.objects.get(id=self.kwargs['pk']) context['object'] = Comissao.objects.get(id=self.kwargs['pk'])
return context return context
class ReuniaoCrud(MasterDetailCrud): class ReuniaoCrud(MasterDetailCrud):
model = Reuniao model = Reuniao
parent_field = 'comissao' parent_field = 'comissao'
model_set = 'documentoacessorio_set'
public = [RP_LIST, RP_DETAIL, ] public = [RP_LIST, RP_DETAIL, ]
class BaseMixin(MasterDetailCrud.BaseMixin): class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['nome', 'tema', 'comissao'] list_field_names = [ 'nome', 'tema', 'data']
@property
def list_url(self):
return ''
class ListView(MasterDetailCrud.ListView): class ListView(MasterDetailCrud.ListView):
paginate_by = 10 paginate_by = 10
def take_reuniao_pk(self):
try:
return int(self.request.GET['pk'])
except:
return 0
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
reuniao_pk = self.take_reuniao_pk()
if reuniao_pk == 0:
ultima_reuniao = list(context['reuniao_list'])
if len(ultima_reuniao) > 0:
ultimo = ultima_reuniao[-1]
context['reuniao_pk'] = ultimo.pk
else:
context['reuniao_pk'] = 0
else:
context['reuniao_pk'] = reuniao_pk
context['documentoacessorio_set'] = DocumentoAcessorio.objects.filter(
reuniao__pk=context['reuniao_pk']
).order_by('id')
return context
class UpdateView(MasterDetailCrud.UpdateView): class UpdateView(MasterDetailCrud.UpdateView):
form_class = ReuniaoForm form_class = ReuniaoForm
@ -172,15 +202,37 @@ class ReuniaoCrud(MasterDetailCrud):
form_class = ReuniaoForm form_class = ReuniaoForm
def get_initial(self): def get_initial(self):
comissao = Comissao.objects.get(id=self.kwargs['pk']) comissao = Comissao.objects.get(id=self.kwargs['pk'])
return {'comissao': comissao} return {'comissao': comissao}
class DeleteView(MasterDetailCrud.DeleteView):
pass
class DetailView(MasterDetailCrud.DetailView): class DocumentoAcessorioCrud(MasterDetailCrud):
model = DocumentoAcessorio
parent_field = 'reuniao__comissao'
public = [RP_DETAIL, ]
ListView = None
link_return_to_parent_field = True
class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['nome', 'tipo', 'data', 'autor', 'arquivo']
@xframe_options_exempt class CreateView(MasterDetailCrud.CreateView):
def get(self, request, *args, **kwargs): form_class = DocumentoAcessorioCreateForm
return super().get(request, *args, **kwargs)
def get_initial(self):
initial = super().get_initial()
initial['parent_pk'] = self.kwargs['pk']
return initial
class UpdateView(MasterDetailCrud.UpdateView):
layout_key = 'DocumentoAcessorioEdit'
form_class = DocumentoAcessorioEditForm
class DeleteView(MasterDetailCrud.DeleteView):
def delete(self, *args, **kwargs):
obj = self.get_object()
obj.delete()
return HttpResponseRedirect(
reverse('sapl.comissoes:reuniao_detail',
kwargs={'pk': obj.reuniao.pk}))

1
sapl/materia/forms.py

@ -1266,6 +1266,7 @@ class ProposicaoForm(forms.ModelForm):
inst.texto_original.delete() inst.texto_original.delete()
self.gerar_hash(inst, receber_recibo) self.gerar_hash(inst, receber_recibo)
return super().save(commit) return super().save(commit)
inst.ano = timezone.now().year inst.ano = timezone.now().year

1
sapl/rules/map_rules.py

@ -90,6 +90,7 @@ rules_group_comissoes = {
(comissoes.Participacao, __base__), (comissoes.Participacao, __base__),
(materia.Relatoria, __base__), (materia.Relatoria, __base__),
(comissoes.Reuniao, __base__), (comissoes.Reuniao, __base__),
(comissoes.DocumentoAcessorio, __base__),
] ]
} }

7
sapl/templates/comissoes/cadastro_reuniao.html

@ -0,0 +1,7 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block actions %}{% endblock %}
{% block detail_content %}
{% crispy form %}
{% endblock detail_content %}

7
sapl/templates/comissoes/cadastro_reuniao_edit.html

@ -0,0 +1,7 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block actions %}{% endblock %}
{% block detail_content %}
{% crispy form %}
{% endblock detail_content %}

17
sapl/templates/comissoes/layouts.yaml

@ -46,7 +46,7 @@ ParticipacaoEdit:
Reuniao: Reuniao:
{% trans 'Reunião' %}: {% trans 'Reunião' %}:
- periodo numero tipo - periodo numero
- nome tema local_reuniao - nome tema local_reuniao
- data hora_inicio hora_fim - data hora_inicio hora_fim
- url_video url_audio - url_video url_audio
@ -54,3 +54,18 @@ Reuniao:
- upload_pauta upload_ata upload_anexo - upload_pauta upload_ata upload_anexo
- comissao - comissao
DocumentoAcessorio:
{% trans 'Documento Acessório' %}:
- nome data
- autor arquivo
- indexacao
- ementa
DocumentoAcessorioEdit:
{% trans 'Documento Acessório' %}:
- nome data
- autor arquivo
- indexacao
- ementa

1
sapl/templates/comissoes/subnav.yaml

@ -8,3 +8,4 @@
url: materias_em_tramitacao url: materias_em_tramitacao
- title: {% trans 'Reunião' %} - title: {% trans 'Reunião' %}
url: reuniao_list url: reuniao_list

Loading…
Cancel
Save