diff --git a/sapl/base/tests/test_login.py b/sapl/base/tests/test_login.py index 73f9eac69..eaf25ac04 100755 --- a/sapl/base/tests/test_login.py +++ b/sapl/base/tests/test_login.py @@ -12,7 +12,8 @@ def user(): def test_login_aparece_na_barra_para_usuario_nao_logado(client): response = client.get('/') - assert 'Login' in str(response.content) + assert '' in str( + response.content) def test_username_do_usuario_logado_aparece_na_barra(client, user): diff --git a/sapl/base/urls.py b/sapl/base/urls.py index cc94d8b83..ee4a74d5e 100644 --- a/sapl/base/urls.py +++ b/sapl/base/urls.py @@ -10,7 +10,12 @@ app_name = AppConfig.name urlpatterns = [ +<<<<<<< HEAD url(r'^sistema/', SistemaView.as_view()), +======= + url(r'^sistema/', TemplateView.as_view(template_name='sistema.html')), + url(r'^ajuda/', TemplateView.as_view(template_name='ajuda.html')), +>>>>>>> master url(r'^ajuda/(?P\w+)$', HelpView.as_view(), name='help_topic'), url(r'^ajuda/', TemplateView.as_view(template_name='ajuda/index.html'), name='help_base'), diff --git a/sapl/comissoes/migrations/0005_comissao_ativa.py b/sapl/comissoes/migrations/0005_comissao_ativa.py new file mode 100644 index 000000000..930bf276c --- /dev/null +++ b/sapl/comissoes/migrations/0005_comissao_ativa.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.5 on 2016-08-05 18:36 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('comissoes', '0004_auto_20160307_0905'), + ] + + operations = [ + migrations.AddField( + model_name='comissao', + name='ativa', + field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=True, verbose_name='Comissão Ativa?'), + preserve_default=False, + ), + ] diff --git a/sapl/comissoes/models.py b/sapl/comissoes/models.py index b5ca44d31..304456c8f 100644 --- a/sapl/comissoes/models.py +++ b/sapl/comissoes/models.py @@ -73,6 +73,9 @@ class Comissao(models.Model): unidade_deliberativa = models.BooleanField( choices=YES_NO_CHOICES, verbose_name=_('Unidade Deliberativa')) + ativa = models.BooleanField( + choices=YES_NO_CHOICES, + verbose_name=_('Comissão Ativa?')) class Meta: verbose_name = _('Comissão') diff --git a/sapl/comissoes/views.py b/sapl/comissoes/views.py index 4a23a49aa..d4333f63d 100644 --- a/sapl/comissoes/views.py +++ b/sapl/comissoes/views.py @@ -138,7 +138,7 @@ class ComissaoCrud(Crud): permission_required = permissoes_comissoes() class BaseMixin(CrudBaseMixin): - list_field_names = ['nome', 'sigla', 'tipo', 'data_criacao'] + list_field_names = ['nome', 'sigla', 'tipo', 'data_criacao', 'ativa'] class MateriasTramitacaoListView(ListView): diff --git a/sapl/legacy/migration.py b/sapl/legacy/migration.py index bcf258129..b2d6bb3da 100644 --- a/sapl/legacy/migration.py +++ b/sapl/legacy/migration.py @@ -13,7 +13,7 @@ from model_mommy.mommy import foreign_key_required, make from sapl.base.models import ProblemaMigracao from sapl.comissoes.models import Composicao, Participacao -from sapl.materia.models import StatusTramitacao, Tramitacao +from sapl.materia.models import StatusTramitacao, TipoProposicao, Tramitacao from sapl.norma.models import AssuntoNormaRelationship, NormaJuridica from sapl.parlamentares.models import Parlamentar from sapl.protocoloadm.models import StatusTramitacaoAdministrativo @@ -377,7 +377,24 @@ def migrate(obj=appconfs): # MIGRATION_ADJUSTMENTS ##################################################### -def adjust_participacao(new_participacao, old): +def adjust_ordemdia(new, old): + # Prestar atenção + if not old.tip_votacao: + new.tipo_votacao = 1 + + +def adjust_parlamentar(new, old): + if old.ind_unid_deliberativa: + value = new.unidade_deliberativa + # Field is defined as not null in legacy db, + # but data includes null values + # => transform None to False + if value is None: + warn('nulo convertido para falso') + new.unidade_deliberativa = False + + +def adjust_participacao(new, old): composicao = Composicao() composicao.comissao, composicao.periodo = [ get_fk_related(Composicao._meta.get_field(name), value) @@ -391,33 +408,21 @@ def adjust_participacao(new_participacao, old): [composicao] = already_created else: composicao.save() - new_participacao.composicao = composicao - - -def adjust_parlamentar(new_parlamentar, old): - if old.ind_unid_deliberativa: - value = new_parlamentar.unidade_deliberativa - # Field is defined as not null in legacy db, - # but data includes null values - # => transform None to False - if value is None: - warn('nulo convertido para falso') - new_parlamentar.unidade_deliberativa = False + new.composicao = composicao -def adjust_normajuridica(new, old): - # O 'S' vem de 'Selecionar'. Na versão antiga do SAPL, quando uma opção do - # combobox era selecionada, o sistema pegava a primeira letra da seleção, - # sendo F para Federal, E para Estadual, M para Municipal e o S para - # Selecionar, que era a primeira opção quando nada era selecionado. - if old.tip_esfera_federacao == 'S': - new.esfera_federacao = '' +def adjust_sessaoplenaria(new, old): + assert not old.tip_expediente -def adjust_ordemdia(new, old): - # Prestar atenção - if not old.tip_votacao: - new.tipo_votacao = 1 +def adjust_tipoproposicao(new, old): + if new.materia_ou_documento == 'M': + field = TipoProposicao.tipo_materia.field + value = get_fk_related(field=field, value=old.tip_mat_ou_doc) + elif new.materia_ou_documento == 'D': + field = TipoProposicao.tipo_documento.field + value = get_fk_related(field=field, value=old.tip_mat_ou_doc) + setattr(new, field.name, value) def adjust_statustramitacao(new, old): @@ -438,11 +443,18 @@ def adjust_tramitacao(new, old): new.turno = 'U' -def adjust_sessaoplenaria(new, old): - assert not old.tip_expediente +def adjust_normajuridica_antes_salvar(new, old): + # Ajusta choice de esfera_federacao + # O 'S' vem de 'Selecionar'. Na versão antiga do SAPL, quando uma opção do + # combobox era selecionada, o sistema pegava a primeira letra da seleção, + # sendo F para Federal, E para Estadual, M para Municipal e o S para + # Selecionar, que era a primeira opção quando nada era selecionado. + if old.tip_esfera_federacao == 'S': + new.esfera_federacao = '' -def adjust_normajuridica(new, old): +def adjust_normajuridica_depois_salvar(new, old): + # Ajusta relação M2M lista_ids_assunto = old.cod_assunto.split(',') for id_assunto in lista_ids_assunto: relacao = AssuntoNormaRelationship() @@ -452,17 +464,19 @@ def adjust_normajuridica(new, old): AJUSTE_ANTES_SALVAR = { + NormaJuridica: adjust_normajuridica_antes_salvar, OrdemDia: adjust_ordemdia, - Participacao: adjust_participacao, Parlamentar: adjust_parlamentar, + Participacao: adjust_participacao, SessaoPlenaria: adjust_sessaoplenaria, + TipoProposicao: adjust_tipoproposicao, StatusTramitacao: adjust_statustramitacao, StatusTramitacaoAdministrativo: adjust_statustramitacaoadm, Tramitacao: adjust_tramitacao, } AJUSTE_DEPOIS_SALVAR = { - NormaJuridica: adjust_normajuridica, + NormaJuridica: adjust_normajuridica_depois_salvar, } # CHECKS #################################################################### diff --git a/sapl/legacy_migration_settings.py b/sapl/legacy_migration_settings.py index 4bc92976e..aef9cc90b 100644 --- a/sapl/legacy_migration_settings.py +++ b/sapl/legacy_migration_settings.py @@ -3,7 +3,7 @@ from .settings import * # flake8: noqa INSTALLED_APPS += ( - 'legacy', # legacy reversed model definitions + 'sapl.legacy', # legacy reversed model definitions ) DATABASES['legacy'] = { diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index 7c21c3ae6..054854e54 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -33,6 +33,31 @@ def em_tramitacao(): (False, 'Não')] +class ConfirmarProposicaoForm(ModelForm): + class Meta: + model = Proposicao + exclude = ['texto_original', 'descricao', 'tipo'] + + +class ReceberProposicaoForm(ModelForm): + cod_hash = forms.CharField(label='Código do Documento', required=True) + + class Meta: + model = Proposicao + exclude = ['texto_original', 'descricao', 'tipo'] + + def __init__(self, *args, **kwargs): + row1 = to_row([('cod_hash', 12)]) + self.helper = FormHelper() + self.helper.layout = Layout( + Fieldset( + _('Incorporar Proposição'), row1, + form_actions(save_label='Buscar Proposição') + ) + ) + super(ReceberProposicaoForm, self).__init__(*args, **kwargs) + + class UnidadeTramitacaoForm(ModelForm): class Meta: @@ -84,20 +109,33 @@ class ProposicaoForm(ModelForm): cleaned_data = self.cleaned_data if 'tipo' in cleaned_data: if cleaned_data['tipo'].descricao == 'Parecer': - try: - materia = MateriaLegislativa.objects.get( - tipo_id=cleaned_data['tipo_materia'], - ano=cleaned_data['ano_materia'], - numero=cleaned_data['numero_materia']) - except ObjectDoesNotExist: - msg = _('Matéria adicionada não existe!') - raise ValidationError(msg) + if self.instance.materia: + cleaned_data['materia'] = self.instance.materia + cleaned_data['autor'] = ( + self.instance.materia.autoria_set.first().autor) else: - cleaned_data['materia'] = materia - cleaned_data['autor'] = materia.autoria_set.first().autor + try: + materia = MateriaLegislativa.objects.get( + tipo_id=cleaned_data['tipo_materia'], + ano=cleaned_data['ano_materia'], + numero=cleaned_data['numero_materia']) + except ObjectDoesNotExist: + msg = _('Matéria adicionada não existe!') + raise ValidationError(msg) + else: + cleaned_data['materia'] = materia + cleaned_data['autor'] = materia.autoria_set.first( + ).autor return cleaned_data + def save(self, commit=False): + proposicao = super(ProposicaoForm, self).save(commit) + if 'materia' in self.cleaned_data: + proposicao.materia = self.cleaned_data['materia'] + proposicao.save() + return proposicao + class Meta: model = Proposicao fields = ['tipo', 'data_envio', 'descricao', 'texto_original', 'autor'] diff --git a/sapl/materia/legacy.yaml b/sapl/materia/legacy.yaml index 4e883c317..afcd1b70b 100644 --- a/sapl/materia/legacy.yaml +++ b/sapl/materia/legacy.yaml @@ -126,7 +126,8 @@ TipoProposicao: descricao: des_tipo_proposicao materia_ou_documento: ind_mat_ou_doc modelo: nom_modelo - tipo_materia: tip_mat_ou_doc + tipo_documento: + tipo_materia: Proposicao: autor: cod_autor diff --git a/sapl/materia/migrations/0039_auto_20160808_1753.py b/sapl/materia/migrations/0039_auto_20160808_1753.py new file mode 100644 index 000000000..a7473aa59 --- /dev/null +++ b/sapl/materia/migrations/0039_auto_20160808_1753.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.5 on 2016-08-08 20:53 +from __future__ import unicode_literals + +from django.db import migrations, models +import sapl.materia.models +import sapl.utils + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0038_auto_20160612_1506'), + ] + + operations = [ + migrations.RemoveField( + model_name='proposicao', + name='data_devolucao', + ), + migrations.AddField( + model_name='proposicao', + name='data_incorporação', + field=models.DateTimeField(blank=True, null=True, verbose_name='Data de Incorporação'), + ), + migrations.AlterField( + model_name='proposicao', + name='data_recebimento', + field=models.DateTimeField(blank=True, null=True, verbose_name='Data de Recebimento'), + ), + migrations.AlterField( + model_name='proposicao', + name='status', + field=models.CharField(blank=True, choices=[('E', 'Enviada'), ('R', 'Recebida'), ('I', 'Incorporada')], max_length=1, verbose_name='Status Proposição'), + ), + migrations.AlterField( + model_name='proposicao', + name='texto_original', + field=models.FileField(default='', upload_to=sapl.materia.models.texto_upload_path, validators=[sapl.utils.restringe_tipos_de_arquivo_txt], verbose_name='Texto Original'), + preserve_default=False, + ), + ] diff --git a/sapl/materia/migrations/0040_auto_20160810_1524.py b/sapl/materia/migrations/0040_auto_20160810_1524.py new file mode 100644 index 000000000..798bd8a64 --- /dev/null +++ b/sapl/materia/migrations/0040_auto_20160810_1524.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.5 on 2016-08-10 18:24 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0039_auto_20160808_1753'), + ] + + operations = [ + migrations.RemoveField( + model_name='proposicao', + name='documento', + ), + migrations.AddField( + model_name='proposicao', + name='documento_gerado', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='materia.DocumentoAcessorio'), + ), + migrations.AddField( + model_name='proposicao', + name='materia_gerada', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='materia_gerada', to='materia.MateriaLegislativa'), + ), + migrations.AlterField( + model_name='proposicao', + name='materia', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='materia_vinculada', to='materia.MateriaLegislativa', verbose_name='Matéria'), + ), + ] diff --git a/sapl/materia/migrations/0041_remove_proposicao_data_incorporação.py b/sapl/materia/migrations/0041_remove_proposicao_data_incorporação.py new file mode 100644 index 000000000..126ef1687 --- /dev/null +++ b/sapl/materia/migrations/0041_remove_proposicao_data_incorporação.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.5 on 2016-08-10 20:02 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0040_auto_20160810_1524'), + ] + + operations = [ + migrations.RemoveField( + model_name='proposicao', + name='data_incorporação', + ), + ] diff --git a/sapl/materia/migrations/0042_proposicao_data_devolução.py b/sapl/materia/migrations/0042_proposicao_data_devolução.py new file mode 100644 index 000000000..cb17864d6 --- /dev/null +++ b/sapl/materia/migrations/0042_proposicao_data_devolução.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.5 on 2016-08-10 20:37 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0041_remove_proposicao_data_incorporação'), + ] + + operations = [ + migrations.AddField( + model_name='proposicao', + name='data_devolução', + field=models.DateTimeField(blank=True, null=True, verbose_name='Data de Devolução'), + ), + ] diff --git a/sapl/materia/migrations/0043_auto_20160810_1738.py b/sapl/materia/migrations/0043_auto_20160810_1738.py new file mode 100644 index 000000000..4012d1162 --- /dev/null +++ b/sapl/materia/migrations/0043_auto_20160810_1738.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.5 on 2016-08-10 20:38 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0042_proposicao_data_devolução'), + ] + + operations = [ + migrations.RenameField( + model_name='proposicao', + old_name='data_devolução', + new_name='data_devolucao', + ), + ] diff --git a/sapl/materia/models.py b/sapl/materia/models.py index 741635e93..fb5153cb8 100644 --- a/sapl/materia/models.py +++ b/sapl/materia/models.py @@ -459,14 +459,16 @@ class TipoProposicao(models.Model): class Proposicao(models.Model): autor = models.ForeignKey(Autor, null=True, blank=True) tipo = models.ForeignKey(TipoProposicao, verbose_name=_('Tipo')) + # XXX data_envio was not null, but actual data said otherwise!!! data_envio = models.DateTimeField( - null=True, blank=True, verbose_name=_('Data de Envio')) + blank=True, null=True, verbose_name=_('Data de Envio')) data_recebimento = models.DateTimeField( - blank=True, null=True, verbose_name=_('Data de Incorporação')) - descricao = models.TextField(max_length=100, verbose_name=_('Descrição')) + blank=True, null=True, verbose_name=_('Data de Recebimento')) data_devolucao = models.DateTimeField( - blank=True, null=True, verbose_name=_('Data de devolução')) + blank=True, null=True, verbose_name=_('Data de Devolução')) + + descricao = models.TextField(max_length=100, verbose_name=_('Descrição')) justificativa_devolucao = models.CharField( max_length=200, blank=True, @@ -477,17 +479,23 @@ class Proposicao(models.Model): status = models.CharField(blank=True, max_length=1, choices=(('E', 'Enviada'), - ('D', 'Devolvida'), + ('R', 'Recebida'), ('I', 'Incorporada')), verbose_name=_('Status Proposição')) # mutually exclusive (depend on tipo.materia_ou_documento) materia = models.ForeignKey( - MateriaLegislativa, blank=True, null=True, verbose_name=_('Matéria')) - documento = models.ForeignKey( - DocumentoAcessorio, blank=True, null=True, verbose_name=_('Documento')) + MateriaLegislativa, blank=True, null=True, verbose_name=_('Matéria'), + related_name=_('materia_vinculada')) + + # Ao ser recebida, irá gerar uma nova matéria ou um documento acessorio + # de uma já existente + materia_gerada = models.ForeignKey( + MateriaLegislativa, blank=True, null=True, + related_name=_('materia_gerada')) + documento_gerado = models.ForeignKey( + DocumentoAcessorio, blank=True, null=True) + texto_original = models.FileField( - blank=True, - null=True, upload_to=texto_upload_path, verbose_name=_('Texto Original'), validators=[restringe_tipos_de_arquivo_txt]) diff --git a/sapl/materia/tests/test_materia.py b/sapl/materia/tests/test_materia.py index 2bed11631..152dd1fc5 100644 --- a/sapl/materia/tests/test_materia.py +++ b/sapl/materia/tests/test_materia.py @@ -7,10 +7,10 @@ from model_mommy import mommy from sapl.comissoes.models import Comissao, TipoComissao from sapl.materia.models import (Anexada, Autor, Autoria, DespachoInicial, DocumentoAcessorio, MateriaLegislativa, - Numeracao, Proposicao, RegimeTramitacao, - StatusTramitacao, TipoAutor, TipoDocumento, - TipoMateriaLegislativa, TipoProposicao, - Tramitacao, UnidadeTramitacao) + Numeracao, RegimeTramitacao, StatusTramitacao, + TipoAutor, TipoDocumento, + TipoMateriaLegislativa, Tramitacao, + UnidadeTramitacao) from sapl.norma.models import (LegislacaoCitada, NormaJuridica, TipoNormaJuridica) @@ -429,6 +429,7 @@ def test_form_errors_relatoria(admin_client): ['Este campo é obrigatório.']) assert (response.context_data['form'].errors['parlamentar'] == ['Este campo é obrigatório.']) +<<<<<<< HEAD @pytest.mark.django_db(transaction=False) @@ -478,3 +479,5 @@ def test_form_errors_proposicao(admin_client): ['Este campo é obrigatório.']) assert (response.context_data['form'].errors['descricao'] == ['Este campo é obrigatório.']) +======= +>>>>>>> master diff --git a/sapl/materia/urls.py b/sapl/materia/urls.py index f2aa6d5c5..0e2838d69 100644 --- a/sapl/materia/urls.py +++ b/sapl/materia/urls.py @@ -3,17 +3,24 @@ from django.conf.urls import include, url from sapl.materia.views import (AcompanhamentoConfirmarView, AcompanhamentoExcluirView, AcompanhamentoMateriaView, AnexadaCrud, +<<<<<<< HEAD AutorCrud, AutoriaCrud, ConfirmarEmailView, +======= + AutorCrud, AutoriaCrud, ConfirmarProposicao, +>>>>>>> master DespachoInicialCrud, DocumentoAcessorioCrud, LegislacaoCitadaCrud, MateriaLegislativaCrud, MateriaLegislativaPesquisaView, MateriaTaView, NumeracaoCrud, OrgaoCrud, OrigemCrud, - ProposicaoCrud, ProposicaoTaView, - RegimeTramitacaoCrud, RelatoriaCrud, - StatusTramitacaoCrud, TipoAutorCrud, - TipoDocumentoCrud, TipoFimRelatoriaCrud, - TipoMateriaCrud, TipoProposicaoCrud, - TramitacaoCrud, UnidadeTramitacaoCrud) + ProposicaoCrud, ProposicaoDevolvida, + ProposicaoPendente, ProposicaoRecebida, + ProposicaoTaView, ReceberProposicao, + ReciboProposicaoView, RegimeTramitacaoCrud, + RelatoriaCrud, StatusTramitacaoCrud, + TipoAutorCrud, TipoDocumentoCrud, + TipoFimRelatoriaCrud, TipoMateriaCrud, + TipoProposicaoCrud, TramitacaoCrud, + UnidadeTramitacaoCrud) from .apps import AppConfig @@ -34,6 +41,18 @@ urlpatterns = [ ConfirmarEmailView.as_view(), name='confirmar_email'), url(r'^proposicao/', include(ProposicaoCrud.get_urls())), + url(r'^proposicao/recibo/(?P\d+)', ReciboProposicaoView.as_view(), + name='recibo-proposicao'), + url(r'^proposicao/receber/', ReceberProposicao.as_view(), + name='receber-proposicao'), + url(r'^proposicao/pendente/', ProposicaoPendente.as_view(), + name='proposicao-pendente'), + url(r'^proposicao/recebida/', ProposicaoRecebida.as_view(), + name='proposicao-recebida'), + url(r'^proposicao/devolvida/', ProposicaoDevolvida.as_view(), + name='proposicao-devolvida'), + url(r'^proposicao/confirmar/(?P\d+)', ConfirmarProposicao.as_view(), + name='proposicao-confirmar'), # Integração com Compilação url(r'^materia/(?P[0-9]+)/ta$', diff --git a/sapl/materia/views.py b/sapl/materia/views.py index de56bced6..3aa3b7bf7 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -18,7 +18,7 @@ from django.template import Context, loader from django.utils.encoding import force_bytes from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode from django.utils.translation import ugettext_lazy as _ -from django.views.generic import CreateView, TemplateView, UpdateView +from django.views.generic import CreateView, ListView, TemplateView, UpdateView from django_filters.views import FilterView from sapl.base.models import CasaLegislativa @@ -29,6 +29,7 @@ from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView, CrudUpdateView, make_pagination) from sapl.crud.masterdetail import MasterDetailCrud from sapl.norma.models import LegislacaoCitada +<<<<<<< HEAD from sapl.utils import (autor_label, autor_modal, get_base_url, permissao_tb_aux, permissoes_autor, permissoes_materia) @@ -38,6 +39,17 @@ from .forms import (AcompanhamentoMateriaForm, AnexadaForm, AutorForm, NumeracaoForm, ProposicaoForm, RelatoriaForm, TramitacaoForm, UnidadeTramitacaoForm, filtra_tramitacao_destino, +======= +from sapl.utils import (autor_label, autor_modal, gerar_hash_arquivo, + get_base_url) + +from .forms import (AcompanhamentoMateriaForm, AnexadaForm, AutoriaForm, + ConfirmarProposicaoForm, DespachoInicialForm, + DocumentoAcessorioForm, LegislacaoCitadaForm, + MateriaLegislativaFilterSet, NumeracaoForm, ProposicaoForm, + ReceberProposicaoForm, RelatoriaForm, TramitacaoForm, + UnidadeTramitacaoForm, filtra_tramitacao_destino, +>>>>>>> master filtra_tramitacao_destino_and_status, filtra_tramitacao_status) from .models import (AcompanhamentoMateria, Anexada, Autor, Autoria, @@ -188,6 +200,43 @@ class StatusTramitacaoCrud(Crud): return permissao_tb_aux(self) +def criar_materia_proposicao(proposicao): + tipo_materia = TipoMateriaLegislativa.objects.get( + descricao=proposicao.tipo.descricao) + numero = MateriaLegislativa.objects.filter( + ano=datetime.now().year).order_by('numero').last().numero + 1 + regime = RegimeTramitacao.objects.get(descricao='Normal') + + return MateriaLegislativa.objects.create( + tipo=tipo_materia, + ano=datetime.now().year, + numero=numero, + data_apresentacao=datetime.now(), + regime_tramitacao=regime, + em_tramitacao=True, + ementa=proposicao.descricao, + texto_original=proposicao.texto_original + ) + + +def criar_doc_proposicao(proposicao): + tipo_doc = TipoDocumento.objects.get( + descricao=proposicao.tipo.descricao) + if proposicao.autor is None: + autor = 'Desconhecido' + else: + autor = proposicao.autor + + return DocumentoAcessorio.objects.create( + materia=proposicao.materia, + tipo=tipo_doc, + arquivo=proposicao.texto_original, + nome=proposicao.descricao, + data=proposicao.data_envio, + autor=autor + ) + + class UnidadeTramitacaoCrud(Crud): model = UnidadeTramitacao help_path = 'unidade_tramitacao' @@ -204,12 +253,149 @@ class UnidadeTramitacaoCrud(Crud): permission_required = permissoes_materia() +class ProposicaoDevolvida(ListView): + template_name = 'materia/prop_devolvidas_list.html' + model = Proposicao + ordering = ['data_envio'] + paginate_by = 10 + + def get_queryset(self): + return Proposicao.objects.filter( + data_envio__isnull=False, + data_recebimento__isnull=True, + data_devolucao__isnull=False) + + def get_context_data(self, **kwargs): + context = super(ProposicaoDevolvida, self).get_context_data(**kwargs) + paginator = context['paginator'] + page_obj = context['page_obj'] + context['page_range'] = make_pagination( + page_obj.number, paginator.num_pages) + context['NO_ENTRIES_MSG'] = 'Nenhuma proposição devolvida.' + return context + + +class ProposicaoPendente(ListView): + template_name = 'materia/prop_pendentes_list.html' + model = Proposicao + ordering = ['data_envio', 'autor', 'tipo', 'descricao'] + paginate_by = 10 + + def get_queryset(self): + return Proposicao.objects.filter( + data_envio__isnull=False, + data_recebimento__isnull=True, + data_devolucao__isnull=True) + + def get_context_data(self, **kwargs): + context = super(ProposicaoPendente, self).get_context_data(**kwargs) + paginator = context['paginator'] + page_obj = context['page_obj'] + context['page_range'] = make_pagination( + page_obj.number, paginator.num_pages) + context['NO_ENTRIES_MSG'] = 'Nenhuma proposição pendente.' + return context + + +class ProposicaoRecebida(ListView): + template_name = 'materia/prop_recebidas_list.html' + model = Proposicao + ordering = ['data_envio'] + paginate_by = 10 + + def get_queryset(self): + return Proposicao.objects.filter( + data_envio__isnull=False, + data_recebimento__isnull=False, + data_devolucao__isnull=True) + + def get_context_data(self, **kwargs): + context = super(ProposicaoRecebida, self).get_context_data(**kwargs) + paginator = context['paginator'] + page_obj = context['page_obj'] + context['page_range'] = make_pagination( + page_obj.number, paginator.num_pages) + context['NO_ENTRIES_MSG'] = 'Nenhuma proposição recebida.' + return context + + +class ReceberProposicao(CreateView): + template_name = "materia/receber_proposicao.html" + form_class = ReceberProposicaoForm + + def get_context_data(self, **kwargs): + context = super(ReceberProposicao, self).get_context_data(**kwargs) + context.update({'form': self.get_form()}) + return context + + def post(self, request, *args, **kwargs): + form = ReceberProposicaoForm(request.POST) + + if form.is_valid(): + proposicoes = Proposicao.objects.filter(data_envio__isnull=False) + + for proposicao in proposicoes: + hasher = gerar_hash_arquivo(proposicao.texto_original.path, + str(proposicao.pk)) + if hasher == form.cleaned_data['cod_hash']: + return HttpResponseRedirect( + reverse('sapl.materia:proposicao-confirmar', + kwargs={'pk': proposicao.pk})) + + msg = 'Proposição não encontrada!' + return self.render_to_response({'form': form, 'msg': msg}) + else: + return self.render_to_response({'form': form}) + + def get_success_url(self): + return reverse('sapl.materia:receber-proposicao') + + +class ConfirmarProposicao(CreateView): + template_name = "materia/confirmar_proposicao.html" + form_class = ConfirmarProposicaoForm + + def get_context_data(self, **kwargs): + context = super(ConfirmarProposicao, self).get_context_data(**kwargs) + proposicao = Proposicao.objects.get(pk=self.kwargs['pk']) + context.update({'form': self.get_form(), 'proposicao': proposicao}) + return context + + def post(self, request, *args, **kwargs): + form = ConfirmarProposicaoForm(request.POST) + proposicao = Proposicao.objects.get(pk=self.kwargs['pk']) + + if form.is_valid(): + if 'incorporar' in request.POST: + proposicao.data_recebimento = datetime.now() + if proposicao.tipo.descricao == 'Parecer': + documento = criar_doc_proposicao(proposicao) + proposicao.documento_gerado = documento + proposicao.save() + return HttpResponseRedirect( + reverse('sapl.materia:documentoacessorio_update', + kwargs={'pk': documento.pk})) + else: + materia = criar_materia_proposicao(proposicao) + proposicao.materia_gerada = materia + proposicao.save() + return HttpResponseRedirect( + reverse('sapl.materia:materialegislativa_update', + kwargs={'pk': materia.pk})) + else: + proposicao.data_devolucao = datetime.now() + proposicao.save() + return HttpResponseRedirect( + reverse('sapl.materia:proposicao-devolvida')) + + class ProposicaoCrud(Crud): model = Proposicao help_path = '' class BaseMixin(CrudBaseMixin): - list_field_names = ['data_envio', 'descricao', 'tipo'] + list_field_names = ['data_envio', 'descricao', + 'tipo', 'data_recebimento'] class CreateView(PermissionRequiredMixin, CrudCreateView): form_class = ProposicaoForm @@ -260,10 +446,22 @@ class ProposicaoCrud(Crud): class DetailView(PermissionRequiredMixin, CrudDetailView): permission_required = permissoes_autor() + def get_context_data(self, **kwargs): + context = super(UpdateView, self).get_context_data(**kwargs) + if self.object.materia: + context['form'].fields['tipo_materia'].initial = ( + self.object.materia.tipo.id) + context['form'].fields['numero_materia'].initial = ( + self.object.materia.numero) + context['form'].fields['ano_materia'].initial = ( + self.object.materia.ano) + return context + @property def layout_key(self): return 'ProposicaoCreate' +<<<<<<< HEAD def has_permission(self): perms = self.get_permission_required() if self.request.user.has_perms(perms): @@ -279,12 +477,23 @@ class ProposicaoCrud(Crud): class ListView(PermissionRequiredMixin, CrudListView): ordering = ['-data_envio', 'descricao'] permission_required = permissoes_autor() +======= + class ListView(CrudListView): + ordering = ['-data_envio', '-descricao'] +>>>>>>> master def get_rows(self, object_list): for obj in object_list: if obj.data_envio is None: obj.data_envio = 'Em elaboração...' + else: + obj.data_envio = obj.data_envio.strftime("%d/%m/%Y %H:%M") + if obj.data_recebimento is None: + obj.data_recebimento = 'Não recebida' + else: + obj.data_recebimento = obj.data_recebimento.strftime( + "%d/%m/%Y %H:%M") return [self._as_row(obj) for obj in object_list] @@ -311,6 +520,20 @@ class ProposicaoCrud(Crud): kwargs={'pk': proposicao.pk})) +class ReciboProposicaoView(TemplateView): + template_name = "materia/recibo_proposicao.html" + + def get_context_data(self, **kwargs): + context = super(ReciboProposicaoView, self).get_context_data( + **kwargs) + proposicao = Proposicao.objects.get(pk=self.kwargs['pk']) + context.update({'proposicao': proposicao, + 'hash': gerar_hash_arquivo( + proposicao.texto_original.path, + self.kwargs['pk'])}) + return context + + class RelatoriaCrud(MasterDetailCrud): model = Relatoria parent_field = 'materia' diff --git a/sapl/painel/views.py b/sapl/painel/views.py index a54881ced..4422c9445 100644 --- a/sapl/painel/views.py +++ b/sapl/painel/views.py @@ -153,7 +153,9 @@ def get_presentes(pk, response, materia): 'numero_votos_nao': 0, 'numero_abstencoes': 0, 'total_votos': 0, - 'tipo_resultado': tipo_votacao}) + 'tipo_resultado': tipo_votacao, + 'observacao_materia': materia.observacao, + 'materia_legislativa_texto': str(materia.materia)}) return response @@ -232,7 +234,9 @@ def get_presentes_expediente(pk, response, materia): 'numero_votos_nao': 0, 'numero_abstencoes': 0, 'total_votos': 0, - 'tipo_resultado': tipo_votacao}) + 'tipo_resultado': tipo_votacao, + 'observacao_materia': materia.observacao, + 'materia_legislativa_texto': str(materia.materia)}) return response @@ -267,7 +271,7 @@ def get_votos(response, materia): 'numero_abstencoes': registro.numero_abstencoes, 'total_votos': total, 'tipo_votacao': tipo_votacao, - 'tipo_resultado': registro.tipo_resultado_votacao.nome + 'tipo_resultado': registro.tipo_resultado_votacao.nome, }) return response diff --git a/sapl/parlamentares/views.py b/sapl/parlamentares/views.py index 71d778871..93e49f120 100644 --- a/sapl/parlamentares/views.py +++ b/sapl/parlamentares/views.py @@ -2,7 +2,7 @@ from django.contrib import messages from django.contrib.auth.mixins import PermissionRequiredMixin from django.contrib.auth.models import Permission from django.contrib.contenttypes.models import ContentType -from django.core.exceptions import ImproperlyConfigured +from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist from django.core.urlresolvers import reverse_lazy from django.shortcuts import redirect from django.utils.datastructures import MultiValueDictKeyError @@ -248,17 +248,21 @@ class ParlamentarCrud(Crud): legislaturas = Legislatura.objects.all().order_by( '-data_inicio', '-data_fim') - try: - legislatura_id = int(self.request.GET['periodo']) - except MultiValueDictKeyError: - legislatura_id = legislaturas.first().id - - return legislatura_id + if legislaturas: + try: + legislatura_id = int(self.request.GET['periodo']) + except MultiValueDictKeyError: + legislatura_id = legislaturas.first().id + return legislatura_id + else: + return 0 def get_queryset(self): - mandatos = Mandato.objects.filter( - legislatura_id=self.take_legislatura_id()) - return mandatos + if self.take_legislatura_id() != 0: + mandatos = Mandato.objects.filter( + legislatura_id=self.take_legislatura_id()) + return mandatos + return [] def get_rows(self, object_list): parlamentares = [] diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 1d86d9c57..3d9a0be7f 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -441,35 +441,6 @@ class ProtocoloMateriaForm(ModelForm): *args, **kwargs) -class ProposicaoSimpleForm(forms.Form): - - tipo = forms.CharField(label='Tipo', - widget=forms.TextInput( - attrs={'readonly': 'readonly'})) - materia = forms.CharField(label='Matéria', - widget=forms.TextInput( - attrs={'readonly': 'readonly'})) - data_envio = forms.DateField(label=_('Data Envio'), - widget=forms.DateInput( - format='%d/%m/%Y', - attrs={'readonly': 'readonly'})) - data_recebimento = forms.DateField(label=_('Data Recebimento'), - widget=forms.DateInput( - format='%d/%m/%Y', - attrs={'readonly': 'readonly'})) - - descricao = forms.CharField(label='Descrição', - widget=forms.TextInput( - attrs={'readonly': 'readonly'})) - - numero_proposicao = forms.CharField(label='Número', - widget=forms.TextInput( - attrs={'readonly': 'readonly'})) - # ano = forms.CharField(label='Ano', - # widget = forms.TextInput( - # attrs={'readonly':'readonly'})) - - class DocumentoAcessorioAdministrativoForm(ModelForm): class Meta: diff --git a/sapl/protocoloadm/urls.py b/sapl/protocoloadm/urls.py index ea978ba1b..1ab3f2cb1 100644 --- a/sapl/protocoloadm/urls.py +++ b/sapl/protocoloadm/urls.py @@ -9,11 +9,6 @@ from sapl.protocoloadm.views import (AnularProtocoloAdmView, DocumentoAcessorioAdministrativoView, DocumentoAdministrativoCrud, PesquisarDocumentoAdministrativoView, - ProposicaoDetailView, - ProposicaoReceberView, ProposicaoView, - ProposicoesIncorporadasView, - ProposicoesNaoIncorporadasView, - ProposicoesNaoRecebidasView, ProtocoloDocumentoCrud, ProtocoloDocumentoView, ProtocoloListView, ProtocoloMateriaCrud, @@ -22,8 +17,17 @@ from sapl.protocoloadm.views import (AnularProtocoloAdmView, ProtocoloPesquisaView, StatusTramitacaoAdministrativoCrud, TipoDocumentoAdministrativoCrud, +<<<<<<< HEAD TipoInstituicaoCrud, TramitacaoAdmCrud, get_nome_autor, pesquisa_autores) +======= + TipoInstituicaoCrud, + TramitacaoAdmDeleteView, + TramitacaoAdmEditView, + TramitacaoAdmIncluirView, + TramitacaoAdministrativoCrud, + TramitacaoAdmView) +>>>>>>> master from .apps import AppConfig @@ -72,26 +76,4 @@ urlpatterns = [ ComprovanteProtocoloView.as_view(), name='comprovante_protocolo'), url(r'^protocoloadm/(?P\d+)/(?P\d+)/criar_documento$', CriarDocumentoProtocolo.as_view(), name='criar_documento'), - - - # TODO: move to Proposicoes app - url(r'^proposicao$', - ProposicaoView.as_view(), name='proposicao'), - url(r'^proposicao/proposicao-receber', - ProposicaoReceberView.as_view(), name='proposicao_receber'), - url(r'^proposicao/proposicao-naorecebidas', - ProposicoesNaoRecebidasView.as_view(), - name='proposicao_naorecebidas'), - url(r'^proposicao/proposicao-naoincorporadas', - ProposicoesNaoIncorporadasView.as_view(), - name='proposicao_naoincorporadas'), - url(r'^proposicao/proposicao-incorporadas', - ProposicoesIncorporadasView.as_view(), - name='proposicao_incorporadas'), - url(r'^proposicao/(?P\d+)/proposicao', - ProposicaoDetailView.as_view(), name='proposicao_view'), - url(r'^proposicao/pesquisar_autor', - pesquisa_autores, name='pesquisar_autor'), - url(r'^proposicao/get_nome_autor', - get_nome_autor, name='get_nome_autor') ] diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py index 86fe97d93..a281ef599 100644 --- a/sapl/protocoloadm/views.py +++ b/sapl/protocoloadm/views.py @@ -13,6 +13,7 @@ from django.views.generic import CreateView, DetailView, FormView, ListView from django.views.generic.base import TemplateView from django_filters.views import FilterView +<<<<<<< HEAD import sapl.crud.base from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView, CrudDeleteView, CrudListView, CrudUpdateView, @@ -27,6 +28,16 @@ from .forms import (AnularProcoloAdmForm, DocumentoAcessorioAdministrativoForm, DocumentoAdministrativoForm, ProposicaoSimpleForm, ProtocoloDocumentForm, ProtocoloFilterSet, ProtocoloMateriaForm, TramitacaoAdmEditForm, +======= +from sapl.crud.base import Crud, CrudBaseMixin, CrudListView, make_pagination +from sapl.materia.models import TipoMateriaLegislativa +from sapl.utils import create_barcode, get_client_ip + +from .forms import (AnularProcoloAdmForm, DocumentoAcessorioAdministrativoForm, + DocumentoAdministrativoFilterSet, + DocumentoAdministrativoForm, ProtocoloDocumentForm, + ProtocoloFilterSet, ProtocoloMateriaForm, +>>>>>>> master TramitacaoAdmForm) from .models import (Autor, DocumentoAcessorioAdministrativo, DocumentoAdministrativo, Protocolo, @@ -349,6 +360,7 @@ class ProtocoloMateriaView(PermissionRequiredMixin, CreateView): return redirect(self.get_success_url()) +<<<<<<< HEAD # TODO: move to Proposicao app class ProposicaoReceberView(TemplateView): template_name = "protocoloadm/proposicao_receber.html" @@ -413,6 +425,9 @@ class ProposicaoDetailView(DetailView): class PesquisarDocumentoAdministrativoView(PermissionRequiredMixin, FilterView): +======= +class PesquisarDocumentoAdministrativoView(FilterView): +>>>>>>> master model = DocumentoAdministrativo filterset_class = DocumentoAdministrativoFilterSet paginate_by = 10 diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index 83af42eb8..6de9c622f 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -2,17 +2,18 @@ from datetime import datetime import django_filters from crispy_forms.helper import FormHelper -from crispy_forms.layout import Fieldset, Layout +from crispy_forms.layout import HTML, Button, Fieldset, Layout from django import forms from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.forms import ModelForm from django.utils.translation import ugettext_lazy as _ from sapl.crispy_layout_mixin import form_actions, to_row +from sapl.materia.forms import MateriaLegislativaFilterSet from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa -from sapl.utils import RANGE_DIAS_MES, RANGE_MESES +from sapl.utils import RANGE_DIAS_MES, RANGE_MESES, autor_label, autor_modal -from .models import Bancada, ExpedienteMateria, SessaoPlenaria +from .models import Bancada, ExpedienteMateria, SessaoPlenaria, OrdemDia def pega_anos(): @@ -94,6 +95,39 @@ class ExpedienteMateriaForm(ModelForm): return expediente +class OrdemDiaForm(ExpedienteMateriaForm): + + class Meta: + model = OrdemDia + fields = ['data_ordem', 'numero_ordem', 'tipo_materia', 'observacao', + 'numero_materia', 'ano_materia', 'tipo_votacao'] + + def clean_data_ordem(self): + return datetime.now() + + def clean(self): + cleaned_data = self.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 + + return cleaned_data + + def save(self, commit=False): + ordem = super(OrdemDiaForm, self).save(commit) + ordem.materia = self.cleaned_data['materia'] + ordem.save() + return ordem + + class PresencaForm(forms.Form): presenca = forms.CharField(required=False, initial=False) parlamentar = forms.CharField(required=False, max_length=20) @@ -107,19 +141,6 @@ class ListMateriaForm(forms.Form): error_message = forms.CharField(required=False, label='votacao_aberta') -class MateriaOrdemDiaForm(forms.Form): - data_sessao = forms.CharField(required=True, label=_('Data da Sessão')) - numero_ordem = forms.IntegerField(required=True, label=_('Número Ordem')) - tipo_votacao = forms.IntegerField(required=True, label=_('Tipo Votação')) - tipo_sessao = forms.IntegerField(required=True, label=_('Tipo da Sessão')) - ano_materia = forms.IntegerField(required=True, label=_('Ano Matéria')) - numero_materia = forms.IntegerField(required=True, - label=_('Número Matéria')) - tipo_materia = forms.IntegerField(required=True, label=_('Tipo Matéria')) - observacao = forms.CharField(required=False, label=_('Ementa')) - error_message = forms.CharField(required=False, label=_('Matéria')) - - class MesaForm(forms.Form): parlamentar = forms.IntegerField(required=True) cargo = forms.IntegerField(required=True) @@ -171,3 +192,76 @@ class SessaoPlenariaFilterSet(django_filters.FilterSet): row1, form_actions(save_label='Pesquisar')) ) + + +class AdicionarVariasMateriasFilterSet(MateriaLegislativaFilterSet): + class Meta: + model = MateriaLegislativa + fields = ['numero', + 'numero_protocolo', + 'ano', + 'tipo', + 'data_apresentacao', + 'data_publicacao', + 'autoria__autor__tipo', + 'autoria__partido', + 'relatoria__parlamentar_id', + 'local_origem_externa', + 'em_tramitacao', + ] + + order_by = ( + ('', 'Selecione'), + ('dataC', 'Data, Tipo, Ano, Numero - Ordem Crescente'), + ('dataD', 'Data, Tipo, Ano, Numero - Ordem Decrescente'), + ('tipoC', 'Tipo, Ano, Numero, Data - Ordem Crescente'), + ('tipoD', 'Tipo, Ano, Numero, Data - Ordem Decrescente') + ) + + def __init__(self, *args, **kwargs): + super(MateriaLegislativaFilterSet, self).__init__(*args, **kwargs) + + self.filters['tipo'].label = 'Tipo de Matéria' + self.filters['autoria__autor__tipo'].label = 'Tipo de Autor' + self.filters['autoria__partido'].label = 'Partido do Autor' + self.filters['relatoria__parlamentar_id'].label = 'Relatoria' + + row1 = to_row( + [('tipo', 12)]) + row2 = to_row( + [('numero', 4), + ('ano', 4), + ('numero_protocolo', 4)]) + row3 = to_row( + [('data_apresentacao', 6), + ('data_publicacao', 6)]) + row4 = to_row( + [('autoria__autor', 0), + (Button('pesquisar', + 'Pesquisar Autor', + css_class='btn btn-primary btn-sm'), 2), + (Button('limpar', + 'limpar Autor', + css_class='btn btn-primary btn-sm'), 10)]) + row5 = to_row( + [('autoria__autor__tipo', 6), + ('autoria__partido', 6)]) + row6 = to_row( + [('relatoria__parlamentar_id', 6), + ('local_origem_externa', 6)]) + row7 = to_row( + [('em_tramitacao', 6), + ('o', 6)]) + row8 = to_row( + [('ementa', 12)]) + + self.form.helper = FormHelper() + self.form.helper.form_method = 'GET' + self.form.helper.layout = Layout( + Fieldset(_('Pesquisa de Matéria'), + row1, row2, row3, + HTML(autor_label), + HTML(autor_modal), + row4, row5, row6, row7, row8, + form_actions(save_label='Pesquisar')) + ) diff --git a/sapl/sessao/migrations/0021_adicionamultiplasmaterias.py b/sapl/sessao/migrations/0021_adicionamultiplasmaterias.py new file mode 100644 index 000000000..7eb3dbd48 --- /dev/null +++ b/sapl/sessao/migrations/0021_adicionamultiplasmaterias.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-08-03 14:27 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0038_auto_20160612_1506'), + ('sessao', '0020_auto_20160517_1450'), + ] + + operations = [ + migrations.CreateModel( + name='AdicionaMultiplasMaterias', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('materia', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.MateriaLegislativa')), + ], + options={ + 'verbose_name_plural': 'Tabela de Adicionar Várias Matérias', + 'verbose_name': 'Tabela de Adicionar Várias Matérias', + }, + ), + ] diff --git a/sapl/sessao/migrations/0022_auto_20160805_0943.py b/sapl/sessao/migrations/0022_auto_20160805_0943.py new file mode 100644 index 000000000..51acbf4ef --- /dev/null +++ b/sapl/sessao/migrations/0022_auto_20160805_0943.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-08-05 12:43 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('sessao', '0021_adicionamultiplasmaterias'), + ] + + operations = [ + migrations.RemoveField( + model_name='adicionamultiplasmaterias', + name='materia', + ), + migrations.DeleteModel( + name='AdicionaMultiplasMaterias', + ), + ] diff --git a/sapl/sessao/urls.py b/sapl/sessao/urls.py index ef1a4c7be..a6b427628 100644 --- a/sapl/sessao/urls.py +++ b/sapl/sessao/urls.py @@ -1,9 +1,10 @@ from django.conf.urls import include, url -from sapl.sessao.views import (BancadaCrud, CargoBancadaCrud, - EditMateriaOrdemDiaView, ExpedienteMateriaCrud, - ExpedienteView, ListMateriaOrdemDiaView, - MateriaOrdemDiaView, MesaView, OradorCrud, +from sapl.sessao.views import (AdicionarVariasMateriasExpediente, + AdicionarVariasMateriasOrdemDia, + BancadaCrud, CargoBancadaCrud, + ExpedienteMateriaCrud, ExpedienteView, + MateriaOrdemDiaCrud, MesaView, OradorCrud, OradorExpedienteCrud, PainelView, PautaExpedienteDetail, PautaOrdemDetail, PautaSessaoDetailView, PautaSessaoListView, @@ -17,8 +18,10 @@ from sapl.sessao.views import (BancadaCrud, CargoBancadaCrud, VotacaoNominalExpedienteEditView, VotacaoNominalExpedienteView, VotacaoNominalView, VotacaoView, - abrir_votacao_view, - reordernar_materias_expediente) + abrir_votacao_expediente_view, + abrir_votacao_ordem_view, + reordernar_materias_expediente, + reordernar_materias_ordem) from .apps import AppConfig @@ -31,13 +34,19 @@ sessao_rest = [ urlpatterns = [ url(r'^sessao/', include(SessaoCrud.get_urls() + OradorCrud.get_urls() + OradorExpedienteCrud.get_urls() + - ExpedienteMateriaCrud.get_urls())), + ExpedienteMateriaCrud.get_urls() + + MateriaOrdemDiaCrud.get_urls())), - url(r'^(?P\d+)/(?P\d+)/abrir-votacao$', abrir_votacao_view, + url(r'^(?P\d+)/(?P\d+)/abrir-votacao-expediente$', + abrir_votacao_expediente_view, + name="abrir_votacao_exp"), + url(r'^(?P\d+)/(?P\d+)/abrir-votacao-ordem$', + abrir_votacao_ordem_view, name="abrir_votacao"), url(r'^(?P\d+)/reordenar-expediente$', reordernar_materias_expediente, name="reordenar_expediente"), - + url(r'^(?P\d+)/reordenar-ordem$', reordernar_materias_ordem, + name="reordenar_ordem"), url(r'^rest/', include(sessao_rest)), url(r'^sistema/sessao-plenaria/tipo/', include(TipoSessaoCrud.get_urls())), @@ -49,6 +58,12 @@ urlpatterns = [ include(BancadaCrud.get_urls())), url(r'^sistema/cargo-bancada/', include(CargoBancadaCrud.get_urls())), + url(r'^sessao/(?P\d+)/adicionar-varias-materias-expediente/', + AdicionarVariasMateriasExpediente.as_view(), + name='adicionar_varias_materias_expediente'), + url(r'^sessao/(?P\d+)/adicionar-varias-materias-ordem-dia/', + AdicionarVariasMateriasOrdemDia.as_view(), + name='adicionar_varias_materias_ordem_dia'), # PAUTA SESSÃO url(r'^pauta-sessao$', @@ -71,14 +86,6 @@ urlpatterns = [ PresencaOrdemDiaView.as_view(), name='presencaordemdia'), url(r'^(?P\d+)/mesa$', MesaView.as_view(), name='mesa'), - url(r'^(?P\d+)/materiaordemdia/list$', - ListMateriaOrdemDiaView.as_view(), name='materiaordemdia_list'), - url(r'^(?P\d+)/materiaordemdia/list$', - ListMateriaOrdemDiaView.as_view(), name='materiaordemdia_reorder'), - url(r'^(?P\d+)/materiaordemdia/edit/(?P\d+)$', - EditMateriaOrdemDiaView.as_view(), name='materiaordemdia_edit'), - url(r'^(?P\d+)/materiaordemdia/create$', - MateriaOrdemDiaView.as_view(), name='materiaordemdia_create'), url(r'^(?P\d+)/resumo$', ResumoView.as_view(), name='resumo'), url(r'^sessao/pesquisar-sessao$', @@ -100,7 +107,7 @@ urlpatterns = [ url(r'^(?P\d+)/matexp/votnom/edit/(?P\d+)/(?P\d+)$', VotacaoNominalExpedienteEditView.as_view(), name='votacaonominalexpedit'), - url(r'^(?P\d+)/matexp/votsec/(?P\d+)/(?P\d+)$', + url(r'^(?P\d+)/matexp/votsimb/(?P\d+)/(?P\d+)$', VotacaoExpedienteView.as_view(), name='votacaosimbolicaexp'), url(r'^(?P\d+)/matexp/votsec/view/(?P\d+)/(?P\d+)$', VotacaoExpedienteEditView.as_view(), name='votacaosimbolicaexpedit'), diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index 47b4aac4b..a78effc0d 100644 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -7,9 +7,10 @@ from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.core.urlresolvers import reverse from django.forms.utils import ErrorList from django.http.response import HttpResponseRedirect +from django.utils.datastructures import MultiValueDictKeyError from django.utils.html import strip_tags from django.utils.translation import ugettext_lazy as _ -from django.views.generic import ListView, TemplateView +from django.views.generic import FormView, ListView, TemplateView from django.views.generic.edit import FormMixin from django_filters.views import FilterView from rest_framework import generics @@ -18,17 +19,21 @@ from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView, CrudDeleteView, CrudDetailView, CrudListView, CrudUpdateView, make_pagination) from sapl.crud.masterdetail import MasterDetailCrud +from sapl.materia.forms import pega_ultima_tramitacao from sapl.materia.models import (Autoria, DocumentoAcessorio, TipoMateriaLegislativa, Tramitacao) +from sapl.materia.views import MateriaLegislativaPesquisaView from sapl.norma.models import NormaJuridica from sapl.parlamentares.models import Parlamentar from sapl.sessao.serializers import SessaoPlenariaSerializer from sapl.utils import permissao_tb_aux, permissoes_painel, permissoes_sessao -from .forms import (BancadaForm, ExpedienteForm, ExpedienteMateriaForm, - ListMateriaForm, MateriaOrdemDiaForm, MesaForm, - PresencaForm, SessaoPlenariaFilterSet, VotacaoEditForm, - VotacaoForm, VotacaoNominalForm) +from .forms import (AdicionarVariasMateriasFilterSet, + BancadaForm, ExpedienteForm, ExpedienteMateriaForm, + ListMateriaForm, MesaForm, + OrdemDiaForm, PresencaForm, + SessaoPlenariaFilterSet, VotacaoEditForm, VotacaoForm, + VotacaoNominalForm) from .models import (Bancada, CargoBancada, CargoMesa, ExpedienteMateria, ExpedienteSessao, IntegranteMesa, MateriaLegislativa, Orador, OradorExpediente, OrdemDia, PresencaOrdemDia, @@ -53,6 +58,19 @@ def reordernar_materias_expediente(request, pk): reverse('sapl.sessao:expedientemateria_list', kwargs={'pk': pk})) +def reordernar_materias_ordem(request, pk): + ordens = OrdemDia.objects.filter( + sessao_plenaria_id=pk) + ordem_num = 1 + for o in ordens: + o.numero_ordem = ordem_num + o.save() + ordem_num += 1 + + return HttpResponseRedirect( + reverse('sapl.sessao:ordemdia_list', kwargs={'pk': pk})) + + class BancadaCrud(Crud): model = Bancada help_path = '' @@ -73,6 +91,7 @@ class BancadaCrud(Crud): form_class = BancadaForm +<<<<<<< HEAD class TipoSessaoCrud(Crud): model = TipoSessaoPlenaria help_path = 'tipo_sessao_plenaria' @@ -109,7 +128,7 @@ class CargoBancadaCrud(Crud): return permissao_tb_aux(self) -def abrir_votacao_view(request, pk, spk): +def abrir_votacao_expediente_view(request, pk, spk): existe_votacao_aberta = ExpedienteMateria.objects.filter( sessao_plenaria_id=spk, votacao_aberta=True ).exists() @@ -125,6 +144,114 @@ def abrir_votacao_view(request, pk, spk): reverse('sapl.sessao:expedientemateria_list', kwargs={'pk': spk})) +def abrir_votacao_ordem_view(request, pk, spk): + existe_votacao_aberta = OrdemDia.objects.filter( + sessao_plenaria_id=spk, votacao_aberta=True + ).exists() + if existe_votacao_aberta: + msg = _('Já existe uma matéria com votação aberta. Para abrir ' + 'outra, termine ou feche a votação existente.') + raise ValidationError(msg) + else: + ordem = OrdemDia.objects.get(id=pk) + ordem.votacao_aberta = True + ordem.save() + return HttpResponseRedirect( + reverse('sapl.sessao:ordemdia_list', kwargs={'pk': spk})) + + +class MateriaOrdemDiaCrud(MasterDetailCrud): + model = OrdemDia + parent_field = 'sessao_plenaria' + help_path = '' + + class BaseMixin(MasterDetailCrud.BaseMixin): + list_field_names = ['numero_ordem', 'materia', 'observacao', + 'resultado'] + + class CreateView(MasterDetailCrud.CreateView): + form_class = OrdemDiaForm + + class UpdateView(MasterDetailCrud.UpdateView): + form_class = OrdemDiaForm + + 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 DetailView(MasterDetailCrud.DetailView): + @property + def layout_key(self): + return 'OrdemDiaDetail' + + class ListView(MasterDetailCrud.ListView): + ordering = ['numero_ordem', 'materia', 'resultado'] + + def get_rows(self, object_list): + for obj in object_list: + if not obj.resultado: + if obj.votacao_aberta: + url = '' + if obj.tipo_votacao == 1: + url = reverse('sapl.sessao:votacaosimbolica', + kwargs={ + 'pk': obj.sessao_plenaria_id, + 'oid': obj.materia_id, + 'mid': obj.pk}) + elif obj.tipo_votacao == 2: + url = reverse('sapl.sessao:votacaonominal', + kwargs={ + 'pk': obj.sessao_plenaria_id, + 'oid': obj.materia_id, + 'mid': obj.pk}) + elif obj.tipo_votacao == 3: + url = reverse('sapl.sessao:votacaosecreta', + kwargs={ + 'pk': obj.sessao_plenaria_id, + 'oid': obj.materia_id, + 'mid': obj.pk}) + + btn_registrar = ''' + Registrar Votação''' % (url) + obj.resultado = btn_registrar + else: + url = reverse('sapl.sessao:abrir_votacao', kwargs={ + 'pk': obj.pk, 'spk': obj.sessao_plenaria_id}) + btn_abrir = ''' + Matéria não votada
+ Abrir Votação''' % (url) + obj.resultado = btn_abrir + else: + url = '' + if obj.tipo_votacao == 1: + url = reverse('sapl.sessao:votacaosimbolicaedit', + kwargs={ + 'pk': obj.sessao_plenaria_id, + 'oid': obj.materia_id, + 'mid': obj.pk}) + elif obj.tipo_votacao == 2: + url = reverse('sapl.sessao:votacaonominaledit', + kwargs={ + 'pk': obj.sessao_plenaria_id, + 'oid': obj.materia_id, + 'mid': obj.pk}) + elif obj.tipo_votacao == 3: + url = reverse('sapl.sessao:votacaosecretaedit', + kwargs={ + 'pk': obj.sessao_plenaria_id, + 'oid': obj.materia_id, + 'mid': obj.pk}) + obj.resultado = '%s' % (url, + obj.resultado) + return [self._as_row(obj) for obj in object_list] + + class ExpedienteMateriaCrud(MasterDetailCrud): model = ExpedienteMateria parent_field = 'sessao_plenaria' @@ -167,7 +294,7 @@ class ExpedienteMateriaCrud(MasterDetailCrud): role="button">Registrar Votação''' % (url) obj.resultado = btn_registrar else: - url = reverse('sapl.sessao:abrir_votacao', kwargs={ + url = reverse('sapl.sessao:abrir_votacao_exp', kwargs={ 'pk': obj.pk, 'spk': obj.sessao_plenaria_id}) btn_abrir = ''' Matéria não votada
@@ -408,6 +535,7 @@ class PresencaOrdemDiaView(PermissionRequiredMixin, return reverse('sapl.sessao:presencaordemdia', kwargs={'pk': pk}) +<<<<<<< HEAD class ListMateriaOrdemDiaView(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/materia_ordemdia_list.html' form_class = ListMateriaForm @@ -1050,22 +1178,21 @@ class VotacaoEditView(PermissionRequiredMixin, ordem_id = kwargs['mid'] if(int(request.POST['anular_votacao']) == 1): - RegistroVotacao.objects.get( + RegistroVotacao.objects.filter( materia_id=materia_id, - ordem_id=ordem_id).delete() + ordem_id=ordem_id).last().delete() ordem = OrdemDia.objects.get( sessao_plenaria_id=self.object.id, materia_id=materia_id) ordem.votacao_aberta = False - ordem.resultado = None + ordem.resultado = '' ordem.save() return self.form_valid(form) def get(self, request, *args, **kwargs): - self.object = self.get_object() - context = self.get_context_data(object=self.object) + context = {} url = request.get_full_path() @@ -1084,15 +1211,16 @@ class VotacaoEditView(PermissionRequiredMixin, materia = {'materia': ordem.materia, 'ementa': ordem.observacao} context.update({'materia': materia}) - votacao = RegistroVotacao.objects.get( + votacao = RegistroVotacao.objects.filter( materia_id=materia_id, - ordem_id=ordem_id) + ordem_id=ordem_id).last() votacao_existente = {'observacao': sub( ' ', ' ', strip_tags(votacao.observacao)), 'tipo_resultado': votacao.tipo_resultado_votacao_id} context.update({'votacao_titulo': titulo, - 'votacao': votacao_existente}) + 'votacao': votacao_existente, + 'tipos': self.get_tipos_votacao()}) return self.render_to_response(context) @@ -1102,7 +1230,7 @@ class VotacaoEditView(PermissionRequiredMixin, def get_success_url(self): pk = self.kwargs['pk'] - return reverse('sapl.sessao:materiaordemdia_list', + return reverse('sapl.sessao:ordemdia_list', kwargs={'pk': pk}) @@ -1224,7 +1352,7 @@ class VotacaoView(PermissionRequiredMixin, def get_success_url(self): pk = self.kwargs['pk'] - return reverse('sapl.sessao:materiaordemdia_list', + return reverse('sapl.sessao:ordemdia_list', kwargs={'pk': pk}) @@ -1235,17 +1363,15 @@ class VotacaoNominalView(PermissionRequiredMixin, permission_required = permissoes_sessao() def get(self, request, *args, **kwargs): - self.object = self.get_object() - context = self.get_context_data(object=self.object) - ordem_id = kwargs['mid'] - ordem = OrdemDia.objects.get(id=ordem_id) materia = {'materia': ordem.materia, 'ementa': sub( ' ', ' ', strip_tags(ordem.observacao))} - context.update({'materia': materia}) + context = {'materia': materia, 'object': self.get_object(), + 'parlamentares': self.get_parlamentares(), + 'tipos': self.get_tipos_votacao()} return self.render_to_response(context) @@ -1354,7 +1480,7 @@ class VotacaoNominalView(PermissionRequiredMixin, def get_success_url(self): pk = self.kwargs['pk'] - return reverse('sapl.sessao:materiaordemdia_list', + return reverse('sapl.sessao:ordemdia_list', kwargs={'pk': pk}) @@ -1365,8 +1491,7 @@ class VotacaoNominalEditView(PermissionRequiredMixin, permission_required = permissoes_sessao() def get(self, request, *args, **kwargs): - self.object = self.get_object() - context = self.get_context_data(object=self.object) + context = {} materia_id = kwargs['oid'] ordem_id = kwargs['mid'] @@ -1393,7 +1518,8 @@ class VotacaoNominalEditView(PermissionRequiredMixin, ' ', ' ', strip_tags(votacao.observacao)), 'tipo_resultado': votacao.tipo_resultado_votacao_id} - context.update({'votacao': votacao_existente}) + context.update({'votacao': votacao_existente, + 'tipos': self.get_tipos_votacao()}) return self.render_to_response(context) @@ -1412,7 +1538,7 @@ class VotacaoNominalEditView(PermissionRequiredMixin, ordem = OrdemDia.objects.get( sessao_plenaria_id=self.object.id, materia_id=materia_id) - ordem.resultado = None + ordem.resultado = '' ordem.votacao_aberta = False ordem.save() @@ -1434,7 +1560,7 @@ class VotacaoNominalEditView(PermissionRequiredMixin, def get_success_url(self): pk = self.kwargs['pk'] - return reverse('sapl.sessao:materiaordemdia_list', + return reverse('sapl.sessao:ordemdia_list', kwargs={'pk': pk}) @@ -1445,17 +1571,15 @@ class VotacaoNominalExpedienteView(PermissionRequiredMixin, permission_required = permissoes_sessao() def get(self, request, *args, **kwargs): - self.object = self.get_object() - context = self.get_context_data(object=self.object) - expediente_id = kwargs['mid'] - expediente = ExpedienteMateria.objects.get(id=expediente_id) materia = {'materia': expediente.materia, 'ementa': sub( ' ', ' ', strip_tags(expediente.observacao))} - context.update({'materia': materia}) + context = {'materia': materia, 'object': self.get_object(), + 'parlamentares': self.get_parlamentares(), + 'tipos': self.get_tipos_votacao()} return self.render_to_response(context) @@ -1573,9 +1697,7 @@ class VotacaoNominalExpedienteEditView(PermissionRequiredMixin, permission_required = permissoes_sessao() def get(self, request, *args, **kwargs): - self.object = self.get_object() - context = self.get_context_data(object=self.object) - + context = {} materia_id = kwargs['oid'] expediente_id = kwargs['mid'] @@ -1601,7 +1723,8 @@ class VotacaoNominalExpedienteEditView(PermissionRequiredMixin, ' ', ' ', strip_tags(votacao.observacao)), 'tipo_resultado': votacao.tipo_resultado_votacao_id} - context.update({'votacao': votacao_existente}) + context.update({'votacao': votacao_existente, + 'tipos': self.get_tipos_votacao()}) return self.render_to_response(context) @@ -2076,3 +2199,154 @@ class PesquisarSessaoPlenariaView(FilterView): ) return self.render_to_response(context) + + +def filtra_tramitacao_ordem_dia(): + lista = pega_ultima_tramitacao() + return Tramitacao.objects.filter( + id__in=lista, + status__descricao='Ordem do Dia').distinct().values_list( + 'materia_id', flat=True) + + +def retira_materias_ja_adicionadas(id_sessao, model): + lista = model.objects.filter( + sessao_plenaria_id=id_sessao) + lista_id_materias = [l.materia_id for l in lista] + return lista_id_materias + + +class AdicionarVariasMateriasExpediente(MateriaLegislativaPesquisaView): + filterset_class = AdicionarVariasMateriasFilterSet + template_name = 'sessao/adicionar_varias_materias_expediente.html' + + def get_filterset_kwargs(self, filterset_class): + super(AdicionarVariasMateriasExpediente, + self).get_filterset_kwargs(filterset_class) + + kwargs = {'data': self.request.GET or None} + + qs = self.get_queryset() + + lista_ordem_dia = filtra_tramitacao_ordem_dia() + + lista_materias_adicionadas = retira_materias_ja_adicionadas( + self.kwargs['pk'], ExpedienteMateria) + + qs = qs.filter(id__in=lista_ordem_dia).exclude( + id__in=lista_materias_adicionadas).distinct() + + kwargs.update({ + 'queryset': qs, + }) + return kwargs + + def get_context_data(self, **kwargs): + # import ipdb; ipdb.set_trace() + context = super(MateriaLegislativaPesquisaView, + self).get_context_data(**kwargs) + + context['title'] = _('Pesquisar Matéria Legislativa') + + self.filterset.form.fields['o'].label = _('Ordenação') + + qr = self.request.GET.copy() + + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' + context['pk_sessao'] = self.kwargs['pk'] + + return context + + def post(self, request, *args, **kwargs): + marcadas = request.POST.getlist('materia_id') + + for m in marcadas: + try: + tipo_votacao = request.POST['tipo_votacao_%s' % m] + except MultiValueDictKeyError: + msg = _('Formulário Inválido. Você esqueceu de selecionar ' + + 'o tipo de votação de %s' % + MateriaLegislativa.objects.get(id=m)) + messages.add_message(request, messages.ERROR, msg) + return self.get(request, self.kwargs) + + if tipo_votacao: + lista_materias_expediente = ExpedienteMateria.objects.filter( + sessao_plenaria_id=self.kwargs[ + 'pk']) + + materia = MateriaLegislativa.objects.get(id=m) + + expediente = ExpedienteMateria() + expediente.sessao_plenaria_id = self.kwargs['pk'] + expediente.materia_id = materia.id + if lista_materias_expediente: + posicao = lista_materias_expediente.last().numero_ordem + 1 + expediente.numero_ordem = posicao + else: + expediente.numero_ordem = 1 + expediente.data_ordem = datetime.now() + expediente.tipo_votacao = request.POST['tipo_votacao_%s' % m] + expediente.save() + + return self.get(request, self.kwargs) + + +class AdicionarVariasMateriasOrdemDia(AdicionarVariasMateriasExpediente): + filterset_class = AdicionarVariasMateriasFilterSet + template_name = 'sessao/adicionar_varias_materias_ordem.html' + + def get_filterset_kwargs(self, filterset_class): + super(AdicionarVariasMateriasExpediente, + self).get_filterset_kwargs(filterset_class) + + kwargs = {'data': self.request.GET or None} + + qs = self.get_queryset() + + lista_ordem_dia = filtra_tramitacao_ordem_dia() + + lista_materias_adicionadas = retira_materias_ja_adicionadas( + self.kwargs['pk'], OrdemDia) + + qs = qs.filter(id__in=lista_ordem_dia).exclude( + id__in=lista_materias_adicionadas).distinct() + + kwargs.update({ + 'queryset': qs, + }) + return kwargs + + def post(self, request, *args, **kwargs): + marcadas = request.POST.getlist('materia_id') + + for m in marcadas: + try: + tipo_votacao = request.POST['tipo_votacao_%s' % m] + except MultiValueDictKeyError: + msg = _('Formulário Inválido. Você esqueceu de selecionar ' + + 'o tipo de votação de %s' % + MateriaLegislativa.objects.get(id=m)) + messages.add_message(request, messages.ERROR, msg) + return self.get(request, self.kwargs) + + if tipo_votacao: + lista_materias_ordem_dia = OrdemDia.objects.filter( + sessao_plenaria_id=self.kwargs[ + 'pk']) + + materia = MateriaLegislativa.objects.get(id=m) + + ordem_dia = OrdemDia() + ordem_dia.sessao_plenaria_id = self.kwargs['pk'] + ordem_dia.materia_id = materia.id + if lista_materias_ordem_dia: + posicao = lista_materias_ordem_dia.last().numero_ordem + 1 + ordem_dia.numero_ordem = posicao + else: + ordem_dia.numero_ordem = 1 + ordem_dia.data_ordem = datetime.now() + ordem_dia.tipo_votacao = tipo_votacao + ordem_dia.save() + + return self.get(request, self.kwargs) diff --git a/sapl/static/img/file.png b/sapl/static/img/file.png new file mode 100644 index 000000000..9bcae6c88 Binary files /dev/null and b/sapl/static/img/file.png differ diff --git a/sapl/static/img/icon_comissoes.png b/sapl/static/img/icon_comissoes.png new file mode 100644 index 000000000..8ec70e7e1 Binary files /dev/null and b/sapl/static/img/icon_comissoes.png differ diff --git a/sapl/static/img/icon_materia_legislativa.png b/sapl/static/img/icon_materia_legislativa.png new file mode 100644 index 000000000..18cdd81f9 Binary files /dev/null and b/sapl/static/img/icon_materia_legislativa.png differ diff --git a/sapl/static/img/icon_mesa_diretora.png b/sapl/static/img/icon_mesa_diretora.png new file mode 100644 index 000000000..12a1b9f13 Binary files /dev/null and b/sapl/static/img/icon_mesa_diretora.png differ diff --git a/sapl/static/img/icon_normas_juridicas.png b/sapl/static/img/icon_normas_juridicas.png new file mode 100644 index 000000000..147681ef8 Binary files /dev/null and b/sapl/static/img/icon_normas_juridicas.png differ diff --git a/sapl/static/img/icon_parlamentares.png b/sapl/static/img/icon_parlamentares.png new file mode 100644 index 000000000..fe9f91ac7 Binary files /dev/null and b/sapl/static/img/icon_parlamentares.png differ diff --git a/sapl/static/img/icon_pautas.png b/sapl/static/img/icon_pautas.png new file mode 100644 index 000000000..8d554f4e4 Binary files /dev/null and b/sapl/static/img/icon_pautas.png differ diff --git a/sapl/static/img/icon_plenarias.png b/sapl/static/img/icon_plenarias.png new file mode 100644 index 000000000..b5fdaa97d Binary files /dev/null and b/sapl/static/img/icon_plenarias.png differ diff --git a/sapl/static/img/icon_relatorios.png b/sapl/static/img/icon_relatorios.png new file mode 100644 index 000000000..3bd71c94d Binary files /dev/null and b/sapl/static/img/icon_relatorios.png differ diff --git a/sapl/static/styles/app.scss b/sapl/static/styles/app.scss index 901f7286c..1b2571e6f 100644 --- a/sapl/static/styles/app.scss +++ b/sapl/static/styles/app.scss @@ -139,3 +139,232 @@ fieldset { } } } + +.btn-primary, .btn-danger{ + font-size: 16px; + height: 40px !important; + display: inline-block; +} + +/* INDEX */ +#conteudo { + position: relative; + padding: 2em 1.5em 1.5em 1.5em; + overflow: hidden; + font-size: 100%; + text-align: left; + min-height: 350px; + max-width: 1000px; + margin: 0 auto; +} +#conteudo a:hover { + color: #444; + -webkit-transition: 0.3s ease-in; + -moz-transition: 0.3s ease-in; + -o-transition: 0.3s ease-in +} + +#homeIndex { + text-align: center; +} + +.homeBanner span { + color: white; + font-size: 32px; + font-weight: 600; + display: inline-block; + vertical-align: middle; + padding: 2px 45px 4px; + border: 2px solid; +} + +.homeBanner::after { + display: inline-block; + vertical-align: middle; + height: 100%; +} + +.homeBlock { + display: inline-block; + position: relative; + background-color: #F3F3F3; + width: 190px; + height: 260px; + margin: 3px; + text-align: center; + font-size: 0; + overflow: hidden; +} + +.homeBlock > a { + display: block; + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; +} + +.homeBlock::after { + content: ''; + display: inline-block; + vertical-align: middle; + height: 100%; + overflow: visible; + clear: none; + visibility: initial; +} + +.homeContent { + position: relative; + padding: 10px; + text-align: justify; + font-size: 14px; + color: #FFF; + opacity: 0; + transition: opacity 0.5s ease; + display: inline-block; + vertical-align: middle; +} + +.homeContent p { + display: block; + line-height: 13px; + font-size: 80%; + color: white; +} + +.homeIcon { + position: relative; + display: inline-block; + width: 105px; + height: 105px; + border-radius: 50%; + background: #364347; + z-index: 1; +} + +.homeIcon::before { + content: ''; + position: absolute; + width: 100%; + height: 100%; + border-radius: 50%; + background: #364347; + top: 0; + left: 0; + transform: scale(0.95); + transition: transform 0.6s ease; +} + +.homeIcon img { + position: absolute; + margin: auto; + top: 0; + bottom: 0; + right: 0; + left: 0; + transition: opacity 0.4s 0.4s ease; +} + +.homeFront { + position: absolute; + top: 46%; + width: 100%; + font-size: 0; + transform: translateY(-60%); + +} + +.homeFront h2 { + position: absolute; + margin-top: 18px; + font-size: 22px; + font-weight: 700; + color: #595959 !important; + width: 100%; + padding: 0 6%; + z-index: 0; +} + +.homeTitle { + display: block; + height: 32px; + text-align: center; + width: 100%; + opacity: 0; + transition: opacity 0.4s ease; +} + +.homeTitle::before { + content: ''; + display: inline-block; + vertical-align: middle; + height: 100%; +} + +.homeTitle h2 { + display: inline-block; + vertical-align: middle; + max-width: 110px; + font-size: 14px; + color: white !important; + line-height: 1em; +} + +.homeTitle img { + display: inline-block; + vertical-align: middle; + height: 30px; + margin-right: 5px; +} + +.homeBlock:hover .homeIcon::before { + transform: scale(3.6) translateY(7px); +} + +.homeBlock:hover .homeContent{ + opacity: 1; + transition-delay: 0.2s; +} + +.homeBlock:hover .homeIcon img { + opacity: 0; + transition-duration: 0.2s; + transition-delay: 0s; +} + +.homeBlock:hover .homeTitle { + opacity: 1; +} + +h1, h2, h3, h4, h5, h6, form, dl, dt, dd, p, div, img, a { + margin: 0; + padding: 0; +} + +p { + margin: 0.5em 0; +} +/* FIM INDEX */ + +/* TEMPLATE AJUDA */ +.manual li { + display: list-item; + line-height: 1.5em; + padding-right: 0; +} +.manual li a { + background-color: transparent; + border: none; + border-radius: none; + padding: 0; +} + +.manual, .manual ul { + padding-left: 1.5em; + list-style-type: none; + margin-top: 0; + font-size: 100%; +} +/* FIM TEMPLATE AJUDA */ diff --git a/sapl/templates/ajuda.html b/sapl/templates/ajuda.html new file mode 100644 index 000000000..b90f4db25 --- /dev/null +++ b/sapl/templates/ajuda.html @@ -0,0 +1,149 @@ +{% extends "base.html" %} +{% load i18n crispy_forms_tags %} + +{% block base_content %} +
+

Tópicos do Manual de Ajuda

+
+ +
+{% endblock base_content %} diff --git a/sapl/templates/base.html b/sapl/templates/base.html index 183ddab50..cec533fc0 100644 --- a/sapl/templates/base.html +++ b/sapl/templates/base.html @@ -28,7 +28,6 @@
- {% block navigation %}
{% endblock %} diff --git a/sapl/templates/materia/confirmar_proposicao.html b/sapl/templates/materia/confirmar_proposicao.html new file mode 100644 index 000000000..f81ad26dc --- /dev/null +++ b/sapl/templates/materia/confirmar_proposicao.html @@ -0,0 +1,32 @@ +{% extends "base.html" %} +{% load i18n crispy_forms_tags %} + +{% block base_content %} + +
+ Confirmar recebimento de Proposição + + + + + +
Tipo: {{proposicao.tipo}}
Autor: {{proposicao.autor}}
Descrição: {{proposicao.descricao}}
Data de Envio: {{proposicao.data_envio|date:'d/m/Y H:i:s'}}
+ + + {% csrf_token %} +
+ +               + +
+ +
+{% endblock %} diff --git a/sapl/templates/materia/formulario_cadastro.html b/sapl/templates/materia/formulario_cadastro.html deleted file mode 100644 index d71724b81..000000000 --- a/sapl/templates/materia/formulario_cadastro.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends "crud/detail.html" %} -{% load i18n %} -{% load crispy_forms_tags %} - -{% block detail_content %} - -
- {% csrf_token %} - {% crispy form %} -
-{% endblock %} \ No newline at end of file diff --git a/sapl/templates/materia/prop_devolvidas_list.html b/sapl/templates/materia/prop_devolvidas_list.html new file mode 100644 index 000000000..04089432e --- /dev/null +++ b/sapl/templates/materia/prop_devolvidas_list.html @@ -0,0 +1,43 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block sections_nav %} {% include 'materia/subnav_prop.html'%} {% endblock sections_nav %} + +{% block base_content %} +
+ Proposições Não Incorporadas + {% if not object_list %} +

{{ NO_ENTRIES_MSG }}

+ {% else %} + + + + + + + + + + + + {% for prop in object_list %} + + + + + + + + {% endfor %} + +
Data do DevoluçãoTipoDescriçãoAutorVínculo
{{ prop.data_devolucao|date:"d/m/Y H:i:s" }}{{ prop.tipo.descricao }}{{ prop.descricao }}{{ prop.autor }} + {% if prop.materia_gerada %} + {{ prop.materia_gerada.tipo.sigla }} {{ prop.materia_gerada.numero }}/{{ prop.materia_gerada.ano }} + {% elif prop.documento_gerado %} + {{ prop.documento_gerado.materia.tipo.sigla }} {{ prop.documento_gerado.materia.numero }}/{{ prop.documento_gerado.materia.ano }} + {% endif %} +
+ {% endif %} +
+ {% include 'paginacao.html'%} +{% endblock %} diff --git a/sapl/templates/materia/prop_pendentes_list.html b/sapl/templates/materia/prop_pendentes_list.html new file mode 100644 index 000000000..825b1fad9 --- /dev/null +++ b/sapl/templates/materia/prop_pendentes_list.html @@ -0,0 +1,35 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block sections_nav %} {% include 'materia/subnav_prop.html'%} {% endblock sections_nav %} + +{% block base_content %} +
+ Proposições Não Recebidas + {% if not object_list %} +

{{ NO_ENTRIES_MSG }}

+ {% else %} + + + + + + + + + + + {% for prop in object_list %} + + + + + + + {% endfor %} + +
Data de EnvioTipoDescriçãoAutor
{{ prop.data_envio|date:"d/m/Y H:i:s" }}{{ prop.tipo.descricao }}{{ prop.descricao }}{{ prop.autor }}
+ {% endif %} +
+ {% include 'paginacao.html'%} +{% endblock %} diff --git a/sapl/templates/materia/prop_recebidas_list.html b/sapl/templates/materia/prop_recebidas_list.html new file mode 100644 index 000000000..08ccfe473 --- /dev/null +++ b/sapl/templates/materia/prop_recebidas_list.html @@ -0,0 +1,43 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block sections_nav %} {% include 'materia/subnav_prop.html'%} {% endblock sections_nav %} + +{% block base_content %} +
+ Proposições Incorporadas + {% if not object_list %} +

{{ NO_ENTRIES_MSG }}

+ {% else %} + + + + + + + + + + + + {% for prop in object_list %} + + + + + + + + {% endfor %} + +
Data do RecebimentoTipoDescriçãoAutorVínculo
{{ prop.data_recebimento|date:"d/m/Y H:i:s" }}{{ prop.tipo.descricao }}{{ prop.descricao }}{{ prop.autor }} + {% if prop.materia_gerada %} + {{ prop.materia_gerada.tipo.sigla }} {{ prop.materia_gerada.numero }}/{{ prop.materia_gerada.ano }} + {% elif prop.documento_gerado %} + {{ prop.documento_gerado.materia.tipo.sigla }} {{ prop.documento_gerado.materia.numero }}/{{ prop.documento_gerado.materia.ano }} + {% endif %} +
+ {% endif %} +
+ {% include 'paginacao.html'%} +{% endblock %} diff --git a/sapl/templates/materia/proposicao_confirm_delete.html b/sapl/templates/materia/proposicao_confirm_delete.html new file mode 100644 index 000000000..be402a125 --- /dev/null +++ b/sapl/templates/materia/proposicao_confirm_delete.html @@ -0,0 +1,10 @@ +{% extends "crud/confirm_delete.html" %} +{% load i18n %} + +{% block msg %} + {% if proposicao.data_envio %} + Confirma o retorno de "{{ object }}"? + {% else %} + Confirma exclusão de "{{ object }}"? + {% endif %} +{% endblock msg %} diff --git a/sapl/templates/materia/proposicao_detail.html b/sapl/templates/materia/proposicao_detail.html index 2eb15c6c7..e2963f548 100644 --- a/sapl/templates/materia/proposicao_detail.html +++ b/sapl/templates/materia/proposicao_detail.html @@ -4,6 +4,7 @@ {% block actions %}
+<<<<<<< HEAD {% if proposicao.data_envio %} {% if perms|get_change_perm:view %} {% trans 'Editar Proposição' %} @@ -14,13 +15,18 @@ {% endif %} {% else %} - {% if perms|get_change_perm:view %} + {% if perms|get_change_perm:view %} {% trans 'Enviar/Editar Proposição' %} {% endif %} - {% if perms|get_delete_perm:view %} + {% if perms|get_delete_perm:view %} {% trans 'Excluir Proposição' %} {% endif %} {% endif %}
{% endblock actions %} +{% block extra_msg %} + {% if proposicao.data_envio and not proposicao.data_recebimento %} +

[Imprimir Recibo]

+ {% endif %} +{% endblock extra_msg %} diff --git a/sapl/templates/materia/proposicao_form.html b/sapl/templates/materia/proposicao_form.html index d71a27b12..610565250 100644 --- a/sapl/templates/materia/proposicao_form.html +++ b/sapl/templates/materia/proposicao_form.html @@ -7,18 +7,12 @@ $(document).ready(function(){ if($("#id_data_envio").val() != ''){ $("#submit-id-excluir").val('Retornar proposição enviada'); - $("#submit-id-salvar").val('Salvar proposição'); }else{ $("#submit-id-excluir").val('Excluir proposição'); - $("#submit-id-salvar").val('Enviar proposição'); } }); function disable_fields() { - $("#id_tipo_materia").val(""); - $("#id_numero_materia").val(""); - $("#id_ano_materia").val(""); - $("#id_tipo_materia").attr("disabled", "disabled"); $("#id_numero_materia").attr("disabled", "disabled"); $("#id_ano_materia").attr("disabled", "disabled"); @@ -34,7 +28,7 @@ $(function () { disable_fields(); $("#id_tipo").change(function() { - if ($("#id_tipo").val() == 9) { // parecer + if ($('#id_tipo option:selected').text() == 'Parecer') { // parecer enable_fields(); }else { disable_fields(); diff --git a/sapl/templates/materia/receber_proposicao.html b/sapl/templates/materia/receber_proposicao.html new file mode 100644 index 000000000..888820934 --- /dev/null +++ b/sapl/templates/materia/receber_proposicao.html @@ -0,0 +1,9 @@ +{% extends "crud/form.html" %} +{% load i18n %} + +{% block sections_nav %} {% include 'materia/subnav_prop.html'%} {% endblock sections_nav %} + +{% load crispy_forms_tags %} +{% block extra_msg %} +

{{msg}}

+{% endblock %} diff --git a/sapl/templates/materia/recibo_proposicao.html b/sapl/templates/materia/recibo_proposicao.html new file mode 100644 index 000000000..a8b15d2b7 --- /dev/null +++ b/sapl/templates/materia/recibo_proposicao.html @@ -0,0 +1,70 @@ +{% load i18n %} +{% load crispy_forms_tags %} +{% load static %} + +{% block detail_content %} + + +
+ +
+ +
+ + + + + + + +
+ Logotipo +
+
+ {% if nome %} + {{ nome }} {% trans 'de' %} {{ municipio }} - {{ uf }} + {% else %} + {% trans 'Sem Nome Cadastrado' %} + {% endif %} +
+ {% trans 'Sistema de Apoio ao Processo Legislativo' %} +
RECIBO DE ENVIO DE PROPOSIÇÃO
+ +

+ + + + + + + + + + + + + +
Código do Documento: {{hash}}Tipo de Proposição: {{proposicao.tipo.descricao}}
Autor: {{proposicao.autor}}Data de Envio: {{proposicao.data_envio|date:"d/m/Y H:i:s"}}
Descrição: {{proposicao.descricao}}
+ +

+ + + + + + + +
+ Declaro que o conteúdo do texto impresso em anexo é idêntico ao conteúdo enviado eletronicamente por meio do sistema SAPL para esta proposição. +



________________________________________________________________
{{proposicao.autor}}
+{% endblock detail_content %} diff --git a/sapl/templates/materia/subnav_prop.html b/sapl/templates/materia/subnav_prop.html new file mode 100644 index 000000000..0cf82c77e --- /dev/null +++ b/sapl/templates/materia/subnav_prop.html @@ -0,0 +1,6 @@ + diff --git a/sapl/templates/painel/index.html b/sapl/templates/painel/index.html index 941bc480a..7e01e9ba7 100644 --- a/sapl/templates/painel/index.html +++ b/sapl/templates/painel/index.html @@ -5,209 +5,220 @@ - - - - - {% block head_title %}{% trans 'SAPL - Sistema de Apoio ao Processo Legislativo' %}{% endblock %} - - - - - - - - - -

- -

-

-

-

-

-

- - - - - - - - - - - - - - - - - -
TEMPO DECORRIDO:
DISCURSO:
APARTE:
QUESTÃO DE ORDEM:
- - - - - -
-
    -
-
-
    -
-
-
-
- - - + }else{ + jQuery.each(presentes_ordem_dia, function(index, parlamentar) { + $('
  • ', {text: parlamentar.nome + ' - ' + parlamentar.partido}).appendTo(presentes); + }); + } + + //console.debug(presentes_ordem_dia) + + var votacao = $("#votacao") + + if (data["num_presentes_ordem_dia"] != null) { + num_presentes_ordem_dia = data["num_presentes_ordem_dia"]; + } + else if (data["num_presentes_expediente"] != null){ + num_presentes_ordem_dia = data["num_presentes_expediente"] + } + + votacao.children().remove() + votacao.append("
  • Sim: " + data["numero_votos_sim"] + "
  • ") + votacao.append("
  • Não: " + data["numero_votos_nao"] + "
  • ") + votacao.append("
  • Abstenções: " + data["numero_abstencoes"] + "
  • ") + votacao.append("
  • Presentes: " + num_presentes_ordem_dia + "
  • ") + votacao.append("
  • Total votos: " + data["total_votos"] + "
  • ") + + + var discurso_current = data["cronometro_discurso"]; + if (discurso_current != discurso_previous) { + $('#cronometro_discurso').runner(discurso_current); + discurso_previous = discurso_current; + } + + var aparte_current = data["cronometro_aparte"]; + if (aparte_current != aparte_previous) { + $('#cronometro_aparte').runner(aparte_current); + aparte_previous = aparte_current; + } + + var ordem_current = data["cronometro_ordem"]; + if (ordem_current != ordem_previous) { + $('#cronometro_ordem').runner(ordem_current); + ordem_previous = ordem_current; + } + + $("#materia_legislativa_texto").text(data["materia_legislativa_texto"]) + $("#observacao_materia").text(data["observacao_materia"]) + $("#resultado_votacao").text(data["tipo_resultado"]) + + }, + error: function(err) { + console.error(err); + }, + dataType: "json", + complete: setTimeout(function() {poll()}, 2000), + timeout: 20000 // TODO: decrease + }) + })(); + }); + diff --git a/sapl/templates/sessao/OrdemDia.html b/sapl/templates/sessao/OrdemDia.html deleted file mode 100644 index 322bbdcd6..000000000 --- a/sapl/templates/sessao/OrdemDia.html +++ /dev/null @@ -1,12 +0,0 @@ -{% extends "crud/detail.html" %} -{% load i18n %} -{% load crispy_forms_tags %} - -{% block detail_content %} -
    - {% csrf_token %} - {{formset}} -
    - -
    -{% endblock detail_content %} \ No newline at end of file diff --git a/sapl/templates/sessao/adicionar_varias_materias_expediente.html b/sapl/templates/sessao/adicionar_varias_materias_expediente.html new file mode 100644 index 000000000..eb224c8d6 --- /dev/null +++ b/sapl/templates/sessao/adicionar_varias_materias_expediente.html @@ -0,0 +1,96 @@ +{% extends "crud/detail.html" %} +{% load i18n %} +{% load crispy_forms_tags %} +{% block actions %}{% endblock %} + +{% block sections_nav %} +{% endblock %} + + + + + +{% block detail_content %} + {% block buttons %} + + {% if filter_url %} + + + + + {% endif %} + + {% endblock %} + + {% if not filter_url %} + {% crispy filter.form %} + {% endif %} + +

    + {% if filter_url %} + + + + + + + + {% if paginator.count %} + {% if paginator.count > 1 %} +

    {% blocktrans with paginator.count as total_materias %}Pesquisa concluída com sucesso! Foram encontradas {{total_materias}} matérias.{% endblocktrans %}

    + {% elif paginator.count == 1 %} +

    {% trans 'Pesquisa concluída com sucesso! Foi encontrada 1 matéria.'%}

    + {% endif %} + + + {% csrf_token %} + + {% for m in page_obj %} + + + + + {% endfor %} + + {% else %} + + + {% endif %} + +

    {% trans "Matérias" %}

    {% trans "Tipo de Votação" %}

    + + {{m.tipo.sigla}} {{m.numero}}/{{m.ano}} - {{m.tipo}}
    + Autores: + {% for a in m.autoria_set.all %} + {% if not forloop.first %} + ,    {{a.autor|default_if_none:"Não Informado"}} + {% else %} +  {{a.autor|default_if_none:"Não Informado"}} + {% endif %} + {% endfor %} +
    + Localização Atual:  {{m.tramitacao_set.last.unidade_tramitacao_destino|default_if_none:"Não Informada"}}
    + Status:  {{m.tramitacao_set.last.status|default_if_none:"Não Informada"}}
    + Data da última Tramitação:  {{m.tramitacao_set.last.data_tramitacao|default_if_none:"Não Informada"}}
    + Ementa: {{ m.ementa|safe }}
    +

    +
    + +
    + +
    + +
    +

    Nenhuma matéria encontrada com essas especificações

    +
    + + + + +{% endif %} + +{% endblock detail_content %} diff --git a/sapl/templates/sessao/adicionar_varias_materias_ordem.html b/sapl/templates/sessao/adicionar_varias_materias_ordem.html new file mode 100644 index 000000000..6cb555ee7 --- /dev/null +++ b/sapl/templates/sessao/adicionar_varias_materias_ordem.html @@ -0,0 +1,18 @@ +{% extends "sessao/adicionar_varias_materias_expediente.html" %} +{% load i18n %} +{% load crispy_forms_tags %} + +{% block buttons %} + + {% if filter_url %} + + + + + {% endif %} + + {% endblock %} \ No newline at end of file diff --git a/sapl/templates/sessao/expediente_ordemdia_list.html b/sapl/templates/sessao/expediente_ordemdia_list.html deleted file mode 100644 index 45529e447..000000000 --- a/sapl/templates/sessao/expediente_ordemdia_list.html +++ /dev/null @@ -1,85 +0,0 @@ -{% extends "crud/detail.html" %} -{% load i18n %} - -{% block detail_content %} - -{% if form.errors %} -
    -
      - {% for field in form %} - {% if field.errors %} - {% if field.label == 'votacao_aberta' %} -
    • Já existe uma matéria com a votação aberta!
      - Para abrir outra, termine ou feche a votação existente!
    • - {% endif %} - {% endif %} - {% endfor %} -
    -
    -{% endif %} - -Matérias do Expediente - - - - - - - - - {% for m in materias_ordem %} - - - - - - - - {% endfor %} -
    MatériaEmentaResultado da Votação
    - {{m.numero}} - {{m.titulo}} -   -
    - Autor{{m.autor|length|pluralize:"es"}}: {{m.autor|join:', '}} -
    {{m.ementa|safe}} - {% if m.resultado %} - {% if m.tipo_votacao == 1 %} - {{m.resultado}} - {% elif m.tipo_votacao == 2 %} - {{m.resultado}} - {% elif m.tipo_votacao == 3%} - {{m.resultado}} - {% endif %} - {% else %} - Matéria não votada
    - {% if m.votacao_aberta %} - {% if m.tipo_votacao == 1 %} - Registrar Votação - {% elif m.tipo_votacao == 2 %} - Registrar Votação - {% elif m.tipo_votacao == 3%} - Registrar Votação - {% endif %} - {% else %} -
    - {% csrf_token %} - - - -
    - {% endif %} - {% endif %} -
    -
    -
    - {% csrf_token %} - - {% trans 'Adicionar Matérias' %} -     - -     - -
    - - -{% endblock detail_content %} diff --git a/sapl/templates/sessao/expedientemateria_list.html b/sapl/templates/sessao/expedientemateria_list.html index 1844124e0..01cf53b61 100644 --- a/sapl/templates/sessao/expedientemateria_list.html +++ b/sapl/templates/sessao/expedientemateria_list.html @@ -6,4 +6,7 @@ {% blocktrans with verbose_name=view.verbose_name %} Reordenar Matérias {% endblocktrans %} + + {% blocktrans with verbose_name=view.verbose_name %} Adicionar Várias Matérias {% endblocktrans %} + {% endblock more_buttons %} diff --git a/sapl/templates/sessao/layouts.yaml b/sapl/templates/sessao/layouts.yaml index 981788a4e..a99e224f8 100644 --- a/sapl/templates/sessao/layouts.yaml +++ b/sapl/templates/sessao/layouts.yaml @@ -11,20 +11,6 @@ SessaoPlenaria: - upload_pauta upload_ata - url_audio url_video -ExpedienteMateria: - {% trans 'Cadastro de Matérias do Expediente' %}: - - data_ordem tip_sessao_FIXME numero_ordem - - tip_id_basica_FIXME num_ident_basica_FIXME ano_ident_basica_FIXME - - tipo_votacao - - observacao - -OrdemDia: - {% trans 'Cadastro de Matérias da Ordem do Dia' %}: - - data_ordem tip_sessao_FIXME numero_ordem - - tip_id_basica_FIXME num_ident_basica_FIXME ano_ident_basica_FIXME - - tipo_votacao - - observacao - TipoResultadoVotacao: {% trans 'Tipo de Resultado da Votação' %}: - nome @@ -55,12 +41,25 @@ ExpedienteMateria: - tipo_votacao - observacao +OrdemDia: + {% trans 'Matéria da Ordem do Dia' %}: + - data_ordem numero_ordem + - tipo_materia numero_materia ano_materia + - tipo_votacao + - observacao + ExpedienteMateriaDetail: {% trans 'Matérias do Expediente' %}: - materia - tipo_votacao - observacao +OrdemDiaDetail: + {% trans 'Matérias da Ordem do Dia' %}: + - materia + - tipo_votacao + - observacao + Bancada: {% trans 'Bancada' %}: - legislatura diff --git a/sapl/templates/sessao/materia_ordemdia.html b/sapl/templates/sessao/materia_ordemdia.html deleted file mode 100644 index e848827c3..000000000 --- a/sapl/templates/sessao/materia_ordemdia.html +++ /dev/null @@ -1,76 +0,0 @@ -{% extends "crud/detail.html" %} -{% load i18n %} - -{% block detail_content %} -
    - {{ error_message }} -
    - -{% if form.errors %} -
    -

    Os seguintes erros foram encontrados:

    -
      - {% for field in form %} - {% if field.errors %} - {% if field.label == 'Matéria' %} -
    • Matéria inexistente!
    • - {% else %} -
    • O campo {{field.label}} é obrigatório!
    • - {% endif %} - {% endif %} - {% endfor %} -
    -
    -{% endif %} - -
    - {% csrf_token %} - -
    -
    Data da Sessão:
    - -
    - Tipo da Sessão: -
    -
    Número Ordem:
    -
    - -
    -
    - Tipo Matéria: - -
    -
    Número Matéria:
    -
    Ano Matéria:
    -
    - -
    -
    - Tipo Votação: - -
    -
    - -
    -
    Ementa:
    -
    - - - -
    -{% endblock detail_content %} diff --git a/sapl/templates/sessao/materia_ordemdia_edit.html b/sapl/templates/sessao/materia_ordemdia_edit.html deleted file mode 100644 index ed9987dfe..000000000 --- a/sapl/templates/sessao/materia_ordemdia_edit.html +++ /dev/null @@ -1,74 +0,0 @@ -{% extends "crud/detail.html" %} -{% load i18n %} -{% load crispy_forms_tags %} -{% block detail_content %} -
    - {{ error_message }} -
    - -{% if form.errors %} -
    -

    Os seguintes erros foram encontrados:

    -
      - {% for field in form %} - {% if field.errors %} -
    • O campo {{field.label}} é obrigatório!
    • - {% endif %} - {% endfor %} -
    -
    -{% endif %} - -
    - {% csrf_token %} - -
    -
    Data da Sessão:
    - -
    - Tipo da Sessão: -
    -
    Número Ordem:
    -
    - -
    -
    - Tipo Matéria: - -
    -
    Número Matéria:
    -
    Ano Matéria:
    -
    - -
    -
    - Tipo Votação: - -
    -
    - -
    -
    Ementa:
    -
    -
    - - - - -
    -{% endblock detail_content %} diff --git a/sapl/templates/sessao/materia_ordemdia_list.html b/sapl/templates/sessao/materia_ordemdia_list.html deleted file mode 100644 index 4c4e9b9f5..000000000 --- a/sapl/templates/sessao/materia_ordemdia_list.html +++ /dev/null @@ -1,89 +0,0 @@ -{% extends "crud/detail.html" %} -{% load i18n %} -{% load common_tags %} - -{% block detail_content %} - -{% if form.errors %} -
    -
      - {% for field in form %} - {% if field.errors %} - {% if field.label == 'votacao_aberta' %} -
    • Já existe uma matéria com a votação aberta!
      - Para abrir outra, termine ou feche a votação existente!
    • - {% endif %} - {% endif %} - {% endfor %} -
    -
    -{% endif %} - -Matérias da Ordem do Dia - - - - - - - - - {% for m in materias_ordem %} - - - - - - - - {% endfor %} -
    MatériaEmentaResultado da Votação
    - {{m.numero}} - {{m.titulo}} -   -
    - Autor{{m.autor|length|pluralize:"es"}}: {{m.autor|join:', '}} -
    {{m.ementa|safe}} - {% if m.resultado %} - {% if m.tipo_votacao == 1 %} - {{m.resultado}} - {% elif m.tipo_votacao == 2 %} - {{m.resultado}} - {% elif m.tipo_votacao == 3%} - {{m.resultado}} - {% endif %} - {% else %} - Matéria não votada
    - {% if m.votacao_aberta %} - {% if m.tipo_votacao == 1 %} - Registrar Votação - {% elif m.tipo_votacao == 2 %} - Registrar Votação - {% elif m.tipo_votacao == 3%} - Registrar Votação - {% endif %} - {% else %} -
    - {% csrf_token %} - - -
    - {% endif %} - {% endif %} -
    -
    - -
    - {% csrf_token %} - - {% if perms|get_add_perm:view %} - {% trans 'Adicionar Matérias' %} -     - {% endif %} - -     - {% if perms|get_add_perm:view %} - - {% endif %} -
    - -{% endblock detail_content %} diff --git a/sapl/templates/sessao/painel.html b/sapl/templates/sessao/painel.html index 0ceb2af87..6221284e6 100644 --- a/sapl/templates/sessao/painel.html +++ b/sapl/templates/sessao/painel.html @@ -7,11 +7,11 @@

    Operação do Painel Eletrônico

    diff --git a/sapl/templates/sessao/pauta_sessao_detail.html b/sapl/templates/sessao/pauta_sessao_detail.html index 7dfef342e..0de9908d6 100644 --- a/sapl/templates/sessao/pauta_sessao_detail.html +++ b/sapl/templates/sessao/pauta_sessao_detail.html @@ -7,7 +7,7 @@
    Identificação Básica - +
    {% for b in basica %} @@ -20,12 +20,14 @@
    Expedientes -
    +
    {% for e in expedientes %} - - + {% endfor %} @@ -34,7 +36,7 @@
    Matérias do Expediente -
    {{e.tipo}}:{{e.conteudo|safe}} + {{e.tipo}}:
    +

    {{e.conteudo}}

    +
    +
    @@ -58,7 +60,7 @@
    Oradores do Expediente -
    Matéria
    +
    @@ -76,7 +78,7 @@
    Matérias da Ordem do Dia -
    Parlamentar
    +
    diff --git a/sapl/templates/sessao/pauta_sessao_list.html b/sapl/templates/sessao/pauta_sessao_list.html index ce716c82e..66566d20b 100644 --- a/sapl/templates/sessao/pauta_sessao_list.html +++ b/sapl/templates/sessao/pauta_sessao_list.html @@ -1,20 +1,34 @@ -{% extends "crud/list.html" %} -{% load i18n %} -{% load crispy_forms_tags %} +{% extends "base.html" %} +{% load i18n staticfiles %} {% block base_content %} - {% block detail_content %} -
    Matéria
    - {% for sessao in page_obj %} - - - - {% endfor %} -
    - {{sessao}} -
    - Data: {{sessao.data_inicio}} - Abertura {{sessao.hora_inicio}} -
    - {% include "paginacao.html" %} - {% endblock %} + + {% if not page_obj %} +

    Não há pautas.

    + {% else %} + + + + + + + + + + {% for sessao in page_obj %} + + + + + + {% endfor %} + +
    DataSessãoPDF
    + {{sessao.data_inicio}} - {{sessao.hora_inicio}} + {{sessao}} + +
    + {% endif %} + + {% include "paginacao.html" %} {% endblock %} diff --git a/sapl/templates/sessao/subnav.yaml b/sapl/templates/sessao/subnav.yaml index e6a32279d..cca959a10 100644 --- a/sapl/templates/sessao/subnav.yaml +++ b/sapl/templates/sessao/subnav.yaml @@ -22,7 +22,7 @@ - title: {% trans 'Ordem do Dia' %} children: - title: {% trans 'Matérias Ordem do Dia' %} - url: materiaordemdia_list + url: ordemdia_list - title: {% trans 'Presença Ordem do Dia' %} url: presencaordemdia diff --git a/sapl/templates/sessao/votacao/nominal.html b/sapl/templates/sessao/votacao/nominal.html index 6dcc7be78..9627b25ac 100644 --- a/sapl/templates/sessao/votacao/nominal.html +++ b/sapl/templates/sessao/votacao/nominal.html @@ -12,11 +12,11 @@
    Ementa: {{materia.ementa|safe}} - +
    Votos
    - {% for parlamentar in view.get_parlamentares %} + {% for parlamentar in parlamentares %}
    {{parlamentar.nome_parlamentar}}
    - {% for tipo in view.get_tipos_votacao %} + {% for tipo in tipos %} {% endfor %}
    +
    - Observações - + Observações
    +
    diff --git a/sapl/templates/sessao/votacao/nominal_edit.html b/sapl/templates/sessao/votacao/nominal_edit.html index 24daed1df..83d584a33 100644 --- a/sapl/templates/sessao/votacao/nominal_edit.html +++ b/sapl/templates/sessao/votacao/nominal_edit.html @@ -12,8 +12,8 @@
    Ementa: {{materia.ementa|safe}} -
    +
    Votos
    @@ -24,6 +24,7 @@
    +
    Anular Votação @@ -34,21 +35,23 @@
    +
    - Resultado da Votação: - {% for tipo in view.get_tipos_votacao %} + Resultado da Votação: + {% for tipo in tipos %} {% if votacao.tipo_resultado == tipo.id %} - {{ tipo.nome }} + {{ tipo.nome }} {% endif %} {% endfor %}
    +
    Observações - +
    diff --git a/sapl/utils.py b/sapl/utils.py index e2138b5dd..88038e6e4 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -1,3 +1,4 @@ +import hashlib from datetime import date from functools import wraps @@ -221,6 +222,7 @@ def intervalos_tem_intersecao(a_inicio, a_fim, b_inicio, b_fim): return maior_inicio <= menor_fim +<<<<<<< HEAD def permissoes_materia(): lista_permissoes = [] cts = ContentType.objects.filter(app_label='materia') @@ -308,3 +310,14 @@ def permissoes_autor(): for p in perms_autor: lista_permissoes.append('materia.' + p.codename) return set(lista_permissoes) + + +def gerar_hash_arquivo(arquivo, pk, block_size=2**20): + md5 = hashlib.md5() + arq = open(arquivo, 'rb') + while True: + data = arq.read(block_size) + if not data: + break + md5.update(data) + return 'P' + md5.hexdigest() + '/' + pk