From 389bc037dbbf66665b88d80d8c9fea5f7e720a2b Mon Sep 17 00:00:00 2001 From: Talitha Pumar Date: Mon, 16 Apr 2018 11:30:59 -0300 Subject: [PATCH 01/25] Fix #1838 (#1847) --- sapl/relatorios/templates/pdf_etiqueta_protocolo_gerar.py | 6 +++++- sapl/relatorios/views.py | 5 +---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/sapl/relatorios/templates/pdf_etiqueta_protocolo_gerar.py b/sapl/relatorios/templates/pdf_etiqueta_protocolo_gerar.py index 142065450..38057791f 100755 --- a/sapl/relatorios/templates/pdf_etiqueta_protocolo_gerar.py +++ b/sapl/relatorios/templates/pdf_etiqueta_protocolo_gerar.py @@ -96,7 +96,11 @@ def protocolos(lst_protocolos, dic_cabecalho): tmp_data += '\t\t' + \ dic['data'] + '\n' tmp_data += '\t\t' + \ - dic['natureza'] + '\n' + dic['natureza'] + if dic['ident_processo']: + tmp_data += ' - ' + dic['ident_processo'] + '\n' + else: + tmp_data += '\n' tmp_data += '\t\n' return tmp_data diff --git a/sapl/relatorios/views.py b/sapl/relatorios/views.py index b38077309..adfdaec37 100644 --- a/sapl/relatorios/views.py +++ b/sapl/relatorios/views.py @@ -955,10 +955,7 @@ def get_etiqueta_protocolos(prots): if p.tipo_processo == 0: dic['natureza'] = 'Administrativo' if p.tipo_processo == 1: - if dic['num_materia']: - dic['natureza'] = dic['num_materia'] - else: - dic['natureza'] = 'Legislativo' + dic['natureza'] = 'Legislativo' dic['num_documento'] = '' for documento in DocumentoAdministrativo.objects.filter( From 1d3bddfd4610ab2128b6d650f13f0b9d74ff0531 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Tue, 17 Apr 2018 12:10:13 -0300 Subject: [PATCH 02/25] =?UTF-8?q?HOT-FIX:=20apaga=20ordem=20dia=20e=20expe?= =?UTF-8?q?diente=20ao=20apagar=20sess=C3=A3o=20plen=C3=A1ria?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0021_auto_20180417_1209.py | 26 +++++++++++++++++++ sapl/sessao/models.py | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 sapl/sessao/migrations/0021_auto_20180417_1209.py diff --git a/sapl/sessao/migrations/0021_auto_20180417_1209.py b/sapl/sessao/migrations/0021_auto_20180417_1209.py new file mode 100644 index 000000000..51993cfdc --- /dev/null +++ b/sapl/sessao/migrations/0021_auto_20180417_1209.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.11 on 2018-04-17 15:09 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('sessao', '0020_auto_20180416_1424'), + ] + + operations = [ + migrations.AlterField( + model_name='expedientemateria', + name='sessao_plenaria', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sessao.SessaoPlenaria'), + ), + migrations.AlterField( + model_name='ordemdia', + name='sessao_plenaria', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sessao.SessaoPlenaria'), + ), + ] diff --git a/sapl/sessao/models.py b/sapl/sessao/models.py index c10d3e03d..13e55aea7 100644 --- a/sapl/sessao/models.py +++ b/sapl/sessao/models.py @@ -231,7 +231,7 @@ class AbstractOrdemDia(models.Model): ) sessao_plenaria = models.ForeignKey(SessaoPlenaria, - on_delete=models.PROTECT) + on_delete=models.CASCADE) materia = models.ForeignKey(MateriaLegislativa, on_delete=models.PROTECT, verbose_name=_('Matéria')) From 42ca448d0a74ac3afe0da2de8ff5492d23b740e4 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Tue, 17 Apr 2018 12:13:22 -0300 Subject: [PATCH 03/25] HOT-FIX: adiciona uma mensagem mais elucidativa para AbstractOrdemDia --- sapl/sessao/models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sapl/sessao/models.py b/sapl/sessao/models.py index 13e55aea7..4c5e9e187 100644 --- a/sapl/sessao/models.py +++ b/sapl/sessao/models.py @@ -255,7 +255,8 @@ class AbstractOrdemDia(models.Model): abstract = True def __str__(self): - return '%s - %s' % (self.numero_ordem, self.sessao_plenaria) + return 'Ordem do Dia/Expediente: %s - %s em %s' % ( + self.numero_ordem, self.materia, self.sessao_plenaria) @reversion.register() From e6baff00c9c58a5d64358bdf21f7d5231255c09b Mon Sep 17 00:00:00 2001 From: Talitha Pumar Date: Tue, 17 Apr 2018 14:13:35 -0300 Subject: [PATCH 04/25] Fix #1893 (#1894) --- .../templates/pdf_sessao_plenaria_gerar.py | 7 +++++-- sapl/relatorios/views.py | 2 ++ sapl/sessao/views.py | 4 +++- .../sessao/blocos_resumo/oradores_expediente.html | 12 +++++++----- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py b/sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py index d9c8ed76e..1c01bfb08 100644 --- a/sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py +++ b/sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py @@ -215,8 +215,11 @@ def oradores_expediente(lst_oradores_expediente): tmp += '\t\t\t
\n' tmp += '\t\t\n' for orador_expediente in lst_oradores_expediente: - tmp += '\t\t' + str(orador_expediente['num_ordem']) + ' - ' + orador_expediente[ - 'nom_parlamentar'] + '/' + str(orador_expediente['sgl_partido']) + '\n' + tmp += '\t\t' + str(orador_expediente[ + 'num_ordem']) + ' - ' + orador_expediente[ + 'nom_parlamentar'] + '/' + str(orador_expediente[ + 'sgl_partido']) + ' - ' + str(orador_expediente[ + 'observacao']) + '\n' return tmp diff --git a/sapl/relatorios/views.py b/sapl/relatorios/views.py index adfdaec37..9f46450b8 100644 --- a/sapl/relatorios/views.py +++ b/sapl/relatorios/views.py @@ -617,6 +617,8 @@ def get_sessao_plenaria(sessao, casa): orador_expediente.numero_ordem) dic_oradores_expediente["nom_parlamentar"] = ( parlamentar.nome_parlamentar) + dic_oradores_expediente["observacao"] = ( + orador_expediente.observacao) partido_sigla = Filiacao.objects.filter( parlamentar=parlamentar).first() if not partido_sigla: diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index b876953fe..b256db879 100644 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -1306,11 +1306,13 @@ class ResumoView(DetailView): sessao_plenaria_id=self.object.id).order_by('numero_ordem'): numero_ordem = orador.numero_ordem url_discurso = orador.url_discurso + observacao = orador.observacao parlamentar = Parlamentar.objects.get( id=orador.parlamentar_id) ora = {'numero_ordem': numero_ordem, 'url_discurso': url_discurso, - 'parlamentar': parlamentar + 'parlamentar': parlamentar, + 'observacao' : observacao } oradores.append(ora) diff --git a/sapl/templates/sessao/blocos_resumo/oradores_expediente.html b/sapl/templates/sessao/blocos_resumo/oradores_expediente.html index 064b7d033..7d4b77390 100644 --- a/sapl/templates/sessao/blocos_resumo/oradores_expediente.html +++ b/sapl/templates/sessao/blocos_resumo/oradores_expediente.html @@ -1,14 +1,16 @@
Oradores do Expediente
-
Parlamentar
-
Discurso
+
Parlamentar
+
Discurso
+
Observação
{% for o in oradores %} -
{{o.numero_ordem}} - {{o.parlamentar}}
-
{{o.url_discurso}}
+
{{o.numero_ordem}} - {{o.parlamentar}}
+
{{o.url_discurso}}
+
{{o.observacao}}

{% endfor %}
-
\ No newline at end of file + From f5a5aac0f887981e05e4c2c0f39e3e11fd186bd7 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Wed, 18 Apr 2018 12:00:01 -0300 Subject: [PATCH 05/25] HOT-FIX: Fix #1872 --- sapl/sessao/forms.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index f05209229..aea3c5dbb 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -464,14 +464,13 @@ class OradorExpedienteForm(ModelForm): def __init__(self, *args, **kwargs): super(OradorExpedienteForm, self).__init__(*args, **kwargs) - legislatura_atual = [l for l in Legislatura.objects.all() if l.atual] + legislatura_vigente = SessaoPlenaria.objects.get(pk=kwargs['initial']['id_sessao']).legislatura - if legislatura_atual: - legislatura_atual = legislatura_atual[0] + if legislatura_vigente: self.fields['parlamentar'].queryset = \ Parlamentar.objects.filter(ativo=True, - mandato__legislatura=legislatura_atual - ).order_by('nome_parlamentar') + mandato__legislatura=legislatura_vigente + ).order_by('nome_parlamentar') class Meta: model = OradorExpediente From 054f6e41ca2e6f1bc6492dd08b6716276cf772ae Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Wed, 18 Apr 2018 12:13:33 -0300 Subject: [PATCH 06/25] Fixes #1897 --- sapl/sessao/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index b256db879..9f8f8aaa2 100644 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -2596,7 +2596,7 @@ class PesquisarSessaoPlenariaView(FilterView): 'tipo', 'sessao_legislativa', 'legislatura') qs = qs.distinct().order_by( - '-legislatura__numero', '-data_inicio', '-numero') + '-legislatura__numero', '-data_inicio', '-hora_inicio') kwargs.update({ 'queryset': qs, From 5fe3653f83751ac4d15bad0a6cd9274cbf2c4324 Mon Sep 17 00:00:00 2001 From: Victor Fabre Date: Wed, 18 Apr 2018 12:15:58 -0300 Subject: [PATCH 07/25] Fix #1899 (#1900) --- sapl/sessao/views.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index 9f8f8aaa2..889f0ab8c 100644 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -978,13 +978,12 @@ class MesaView(FormMixin, DetailView): return self.render_to_response(context) mesa = sessao.integrantemesa_set.all() if sessao else [] - cargos_ocupados = [m.cargo for m in mesa] cargos = CargoMesa.objects.all() cargos_vagos = list(set(cargos) - set(cargos_ocupados)) # FIX-ME: tem formas melhores de fazer isso, poupando linhas. - parlamentares = Legislatura.objects.first().mandato_set.all() + parlamentares = Legislatura.objects.get(id=sessao.legislatura_id).mandato_set.all() parlamentares_ocupados = [m.parlamentar for m in mesa] parlamentares_vagos = list( set( From a2961c1d01059f44d8e228963fb529e7ab10bdf6 Mon Sep 17 00:00:00 2001 From: Talitha Pumar Date: Wed, 18 Apr 2018 12:15:40 -0300 Subject: [PATCH 08/25] Fix #1895 (#1901) --- sapl/sessao/forms.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index aea3c5dbb..219e5b69b 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -472,6 +472,25 @@ class OradorExpedienteForm(ModelForm): mandato__legislatura=legislatura_vigente ).order_by('nome_parlamentar') + def clean(self): + super(OradorExpedienteForm, self).clean() + cleaned_data = self.cleaned_data + + if not self.is_valid(): + return self.cleaned_data + + sessao_id = self.initial['id_sessao'] + ordem = OradorExpediente.objects.filter( + sessao_plenaria_id=sessao_id, + numero_ordem=cleaned_data['numero_ordem'] + ).exists() + if ordem: + raise ValidationError(_( + 'Já existe orador nesta posição da ordem de pronunciamento')) + + return self.cleaned_data + + class Meta: model = OradorExpediente exclude = ['sessao_plenaria'] From 000a48b7080196049cadc1927f0e989f327dfa6b Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Thu, 19 Apr 2018 11:09:59 -0300 Subject: [PATCH 09/25] Fixes #1904 --- sapl/protocoloadm/forms.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index dc3d5280c..36baa8f3e 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -668,11 +668,12 @@ class DocumentoAdministrativoForm(ModelForm): numero_documento = self.cleaned_data['numero'] tipo_documento = self.data['tipo'] - documento = DocumentoAdministrativo.objects.filter(numero=numero_documento, - tipo=tipo_documento, ano=ano_protocolo) - - if documento: - raise ValidationError('Documento já existente') + if not self.instance.pk: + documento = DocumentoAdministrativo.objects.filter(numero=numero_documento, + tipo=tipo_documento, + ano=ano_protocolo) + if documento: + raise ValidationError('Documento já existente') # campos opcionais, mas que se informados devem ser válidos if numero_protocolo and ano_protocolo: From edd132196790f5551ce6e343a0ff78efcccbcb76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pedro=20Sconetto?= Date: Fri, 20 Apr 2018 15:27:18 -0300 Subject: [PATCH 10/25] Fix #1785 --- sapl/materia/models.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sapl/materia/models.py b/sapl/materia/models.py index ce4690c39..4a38a3813 100644 --- a/sapl/materia/models.py +++ b/sapl/materia/models.py @@ -325,9 +325,11 @@ class AcompanhamentoMateria(models.Model): verbose_name_plural = _('Acompanhamentos de Matéria') def __str__(self): - # FIXME str should be human readable, using hash is very strange - return _('%(materia)s - #%(hash)s') % { - 'materia': self.materia, 'hash': self.hash} + return _('%(materia)s - %(email)s - Registrado em: %(data)s') % { + 'materia': self.materia, + 'email': self.email, + 'data': str(self.data_cadastro.strftime('%d/%m/%Y')) + } @reversion.register() From e7795002b14f23a53d4485565aa580b8953466e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pedro=20Sconetto?= Date: Fri, 20 Apr 2018 15:38:07 -0300 Subject: [PATCH 11/25] Fixing Travis Error --- sapl/materia/models.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/sapl/materia/models.py b/sapl/materia/models.py index 4a38a3813..98a045d01 100644 --- a/sapl/materia/models.py +++ b/sapl/materia/models.py @@ -325,11 +325,17 @@ class AcompanhamentoMateria(models.Model): verbose_name_plural = _('Acompanhamentos de Matéria') def __str__(self): - return _('%(materia)s - %(email)s - Registrado em: %(data)s') % { - 'materia': self.materia, - 'email': self.email, - 'data': str(self.data_cadastro.strftime('%d/%m/%Y')) - } + if self.data_cadastro is None: + return _('%(materia)s - %(email)s') % { + 'materia': self.materia, + 'email': self.email + } + else: + return _('%(materia)s - %(email)s - Registrado em: %(data)s') % { + 'materia': self.materia, + 'email': self.email, + 'data': str(self.data_cadastro.strftime('%d/%m/%Y')) + } @reversion.register() From e4866c09f0749fdd02e5cff73b4dd16cd3e7cf80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pedro=20Sconetto?= Date: Mon, 23 Apr 2018 09:57:51 -0300 Subject: [PATCH 12/25] Fix #1908 (#1909) --- sapl/sessao/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index 219e5b69b..c35abf306 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -452,7 +452,7 @@ class OradorForm(ModelForm): sessao_plenaria_id=id_sessao)] self.fields['parlamentar'].queryset = Parlamentar.objects.filter( - id__in=ids).order_by('nome_completo') + id__in=ids).order_by('nome_parlamentar') class Meta: model = Orador From 42dd49ba2c960254e6e9506e4c8970153c80af98 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Thu, 19 Apr 2018 11:23:36 -0300 Subject: [PATCH 13/25] HOT-FIX: retira checagem duplicada --- sapl/protocoloadm/forms.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 36baa8f3e..b51b5facd 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -655,9 +655,6 @@ class DocumentoAdministrativoForm(ModelForm): def clean(self): super(DocumentoAdministrativoForm, self).clean() - if not self.is_valid(): - return self.cleaned_data - cleaned_data = self.cleaned_data if not self.is_valid(): From 005131282d733aa3f64f8ed943ba323a6cafa83f Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Thu, 19 Apr 2018 11:38:54 -0300 Subject: [PATCH 14/25] =?UTF-8?q?N=C3=A3o=20permite=20atualizar=20doc=20ad?= =?UTF-8?q?m=20para=20tipo-n=C3=BAmero-ano=20existente?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/protocoloadm/forms.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index b51b5facd..1d5e84133 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -662,10 +662,17 @@ class DocumentoAdministrativoForm(ModelForm): numero_protocolo = self.data['numero_protocolo'] ano_protocolo = self.data['ano_protocolo'] - numero_documento = self.cleaned_data['numero'] - tipo_documento = self.data['tipo'] + numero_documento = int(self.cleaned_data['numero']) + tipo_documento = int(self.data['tipo']) + ano_documento = int(self.data['ano']) - if not self.instance.pk: + # não permite atualizar para numero/ano/tipo existente + if self.instance.pk: + mudanca_doc = numero_documento != self.instance.numero \ + or ano_documento != self.instance.ano \ + or tipo_documento != self.instance.tipo.pk + + if not self.instance.pk or mudanca_doc: documento = DocumentoAdministrativo.objects.filter(numero=numero_documento, tipo=tipo_documento, ano=ano_protocolo) From ce32268154e8c268139b90025e7bfd07ce5d1de2 Mon Sep 17 00:00:00 2001 From: Edward Date: Mon, 23 Apr 2018 13:32:35 -0300 Subject: [PATCH 15/25] Fix #1898 (#1910) --- sapl/sessao/views.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index 889f0ab8c..4ad6178ab 100644 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -393,6 +393,8 @@ def get_presencas_generic(model, sessao, legislatura): presentes = [p.parlamentar for p in presencas] + presentes = sorted(presentes, key=lambda x: x.nome_parlamentar) + mandato = Mandato.objects.filter( legislatura=legislatura).order_by('parlamentar__nome_parlamentar') From 742783379412b36941102e3a607afc38d76f5754 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Mon, 23 Apr 2018 13:08:08 -0300 Subject: [PATCH 16/25] Remove volumes pendentes --- scripts_docker/remove-all-containers.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts_docker/remove-all-containers.sh b/scripts_docker/remove-all-containers.sh index 64d41cd5c..a3d8fc624 100755 --- a/scripts_docker/remove-all-containers.sh +++ b/scripts_docker/remove-all-containers.sh @@ -1,4 +1,5 @@ #!/bin/bash -sudo docker stop $(docker ps -a -q) # Parar containers -sudo docker rm $(sudo docker ps -a -q) # Remover containers -sudo docker rmi -f $( sudo docker images -q ) # Remover imagens +sudo docker stop $(docker ps -a -q) # Para containers +sudo docker rm $(sudo docker ps -a -q) # Remove containers +sudo docker rmi -f $( sudo docker images -q ) # Remove imagens +sudo docker volume rm $(sudo docker volume ls -q -f dangling=true) # Remove volumes From ea62aeec3f493406f82007eb0b8c38f0a7666644 Mon Sep 17 00:00:00 2001 From: Edward Date: Wed, 25 Apr 2018 14:16:32 -0300 Subject: [PATCH 17/25] Fix #1913 (#1914) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix #1913 * Remove import não utilizado --- sapl/sessao/views.py | 73 +++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 45 deletions(-) diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index 4ad6178ab..d7844b3ce 100644 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -30,7 +30,6 @@ from sapl.materia.forms import filtra_tramitacao_status 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 (Filiacao, Legislatura, Mandato, Parlamentar, SessaoLegislativa) from sapl.sessao.apps import AppConfig @@ -1114,15 +1113,13 @@ def remove_parlamentar_composicao(request): if 'composicao_mesa' in request.POST: try: - composicao = IntegranteMesa.objects.get( - id=int(request.POST['composicao_mesa'])) + IntegranteMesa.objects.get( + id=int(request.POST['composicao_mesa'])).delete() except ObjectDoesNotExist: return JsonResponse( {'msg': ( 'Composição da Mesa não pôde ser removida!', 0)}) - composicao.delete() - return JsonResponse( {'msg': ( 'Parlamentar excluido com sucesso!', 1)}) @@ -1526,8 +1523,7 @@ class VotacaoEditView(SessaoPermissionMixin): ordem_id = kwargs['oid'] if(int(request.POST['anular_votacao']) == 1): - for r in RegistroVotacao.objects.filter(ordem_id=ordem_id): - r.delete() + RegistroVotacao.objects.filter(ordem_id=ordem_id).delete() ordem = OrdemDia.objects.get( sessao_plenaria_id=self.object.id, @@ -1558,9 +1554,8 @@ class VotacaoEditView(SessaoPermissionMixin): materia = {'materia': ordem.materia, 'ementa': ordem.materia.ementa} context.update({'materia': materia}) - votacao = RegistroVotacao.objects.filter( - materia_id=materia_id, - ordem_id=ordem_id).last() + votacao = RegistroVotacao.objects.filter(materia_id=materia_id, + ordem_id=ordem_id).last() votacao_existente = {'observacao': sub( ' ', ' ', strip_tags(votacao.observacao)), 'resultado': votacao.tipo_resultado_votacao.nome, @@ -1707,8 +1702,7 @@ def fechar_votacao_materia(materia): VotoParlamentar.objects.filter(ordem=materia).delete() elif type(materia) == ExpedienteMateria: - RegistroVotacao.objects.filter( - expediente=materia).delete() + RegistroVotacao.objects.filter(expediente=materia).delete() VotoParlamentar.objects.filter(expediente=materia).delete() if materia.resultado: @@ -1756,7 +1750,7 @@ class VotacaoNominalAbstract(SessaoPermissionMixin): elif self.expediente: expediente_id = kwargs['oid'] if (RegistroVotacao.objects.filter( - expediente_id=expediente_id).exists()): + expediente_id=expediente_id).exists()): msg = _('Esta matéria já foi votada!') messages.add_message(request, messages.ERROR, msg) return HttpResponseRedirect(reverse( @@ -1843,8 +1837,7 @@ class VotacaoNominalAbstract(SessaoPermissionMixin): return self.form_invalid(form) # Remove todas as votação desta matéria, caso existam if self.ordem: - RegistroVotacao.objects.filter( - ordem_id=ordem_id).delete() + RegistroVotacao.objects.filter(ordem_id=ordem_id).delete() elif self.expediente: RegistroVotacao.objects.filter( expediente_id=expediente_id).delete() @@ -1972,11 +1965,10 @@ class VotacaoNominalEditAbstract(SessaoPermissionMixin): if self.ordem: ordem_id = kwargs['oid'] - try: - ordem = OrdemDia.objects.get(id=ordem_id) - votacao = RegistroVotacao.objects.get( - ordem_id=ordem_id) - except ObjectDoesNotExist: + ordem = OrdemDia.objects.filter(id=ordem_id).last() + votacao = RegistroVotacao.objects.filter(ordem_id=ordem_id).last() + + if not ordem or not votacao: raise Http404() materia = ordem.materia @@ -1985,11 +1977,10 @@ class VotacaoNominalEditAbstract(SessaoPermissionMixin): elif self.expediente: expediente_id = kwargs['oid'] - try: - expediente = ExpedienteMateria.objects.get(id=expediente_id) - votacao = RegistroVotacao.objects.get( - expediente_id=expediente_id) - except ObjectDoesNotExist: + expediente = ExpedienteMateria.objects.filter(id=expediente_id).last() + votacao = RegistroVotacao.objects.filter(expediente_id=expediente_id).last() + + if not expediente or not votacao: raise Http404() materia = expediente.materia @@ -2106,9 +2097,9 @@ class VotacaoNominalTransparenciaDetailView(TemplateView): materia_votacao = self.request.GET.get('materia', None) if materia_votacao == 'ordem': - votacao = RegistroVotacao.objects.get(ordem=self.kwargs['oid']) + votacao = RegistroVotacao.objects.filter(ordem=self.kwargs['oid']).last() elif materia_votacao == 'expediente': - votacao = RegistroVotacao.objects.get(expediente=self.kwargs['oid']) + votacao = RegistroVotacao.objects.filter(expediente=self.kwargs['oid']).last() else: raise Http404() @@ -2142,10 +2133,9 @@ class VotacaoNominalExpedienteDetailView(DetailView): materia_id = kwargs['mid'] expediente_id = kwargs['oid'] - votacao = RegistroVotacao.objects.get( - materia_id=materia_id, - expediente_id=expediente_id) - expediente = ExpedienteMateria.objects.get(id=expediente_id) + votacao = RegistroVotacao.objects.filter(materia_id=materia_id, + expediente_id=expediente_id).last() + expediente = ExpedienteMateria.objects.filter(id=expediente_id).last() votos = VotoParlamentar.objects.filter(votacao_id=votacao.id) list_votos = [] @@ -2190,9 +2180,9 @@ class VotacaoSimbolicaTransparenciaDetailView(TemplateView): materia_votacao = self.request.GET.get('materia', None) if materia_votacao == 'ordem': - votacao = RegistroVotacao.objects.get(ordem=self.kwargs['oid']) + votacao = RegistroVotacao.objects.filter(ordem=self.kwargs['oid']).last() elif materia_votacao == 'expediente': - votacao = RegistroVotacao.objects.get(expediente=self.kwargs['oid']) + votacao = RegistroVotacao.objects.filter(expediente=self.kwargs['oid']).last() else: raise Http404() @@ -2378,14 +2368,9 @@ class VotacaoExpedienteEditView(SessaoPermissionMixin): 'ementa': expediente.materia.ementa} context.update({'materia': materia}) - try: - votacao = RegistroVotacao.objects.get( - materia_id=materia_id, - expediente_id=expediente_id) - except MultipleObjectsReturned: - votacao = RegistroVotacao.objects.filter( - materia_id=materia_id, - expediente_id=expediente_id).last() + votacao = RegistroVotacao.objects.filter(materia_id=materia_id, + expediente_id=expediente_id + ).last() votacao_existente = {'observacao': sub( ' ', ' ', strip_tags(votacao.observacao)), 'resultado': votacao.tipo_resultado_votacao.nome, @@ -2404,10 +2389,8 @@ class VotacaoExpedienteEditView(SessaoPermissionMixin): materia_id = kwargs['mid'] expediente_id = kwargs['oid'] - if(int(request.POST['anular_votacao']) == 1): - for r in RegistroVotacao.objects.filter( - expediente_id=expediente_id): - r.delete() + if int(request.POST['anular_votacao']) == 1: + RegistroVotacao.objects.filter(expediente_id=expediente_id).delete() expediente = ExpedienteMateria.objects.get( sessao_plenaria_id=self.object.id, From 1acf71395399a3ba54235e73150c51b80c3f36ce Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Wed, 25 Apr 2018 15:53:00 -0300 Subject: [PATCH 18/25] =?UTF-8?q?Adiciona=20campo=20n=C3=BAmero=20externo?= =?UTF-8?q?=20(opcional)=20para=20docs=20adm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/protocoloadm/forms.py | 15 ++++++++------ ..._documentoadministrativo_numero_externo.py | 20 +++++++++++++++++++ sapl/protocoloadm/models.py | 4 ++++ sapl/templates/protocoloadm/layouts.yaml | 1 + 4 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 sapl/protocoloadm/migrations/0004_documentoadministrativo_numero_externo.py diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 1d5e84133..06a2f7854 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -155,6 +155,7 @@ class DocumentoAdministrativoFilterSet(django_filters.FilterSet): fields = ['tipo', 'numero', 'protocolo__numero', + 'numero_externo', 'data', 'tramitacaoadministrativo__unidade_tramitacao_destino', 'tramitacaoadministrativo__status'] @@ -173,7 +174,8 @@ class DocumentoAdministrativoFilterSet(django_filters.FilterSet): row2 = to_row( [('ano', 4), - ('protocolo__numero', 4), + ('protocolo__numero', 2), + ('numero_externo', 2), ('data', 4)]) row3 = to_row( @@ -645,6 +647,7 @@ class DocumentoAdministrativoForm(ModelForm): 'tramitacao', 'dias_prazo', 'data_fim_prazo', + 'numero_externo', 'observacao', 'texto_integral', 'protocolo', @@ -673,10 +676,10 @@ class DocumentoAdministrativoForm(ModelForm): or tipo_documento != self.instance.tipo.pk if not self.instance.pk or mudanca_doc: - documento = DocumentoAdministrativo.objects.filter(numero=numero_documento, - tipo=tipo_documento, - ano=ano_protocolo) - if documento: + doc_exists = DocumentoAdministrativo.objects.filter(numero=numero_documento, + tipo=tipo_documento, + ano=ano_protocolo).exists() + if doc_exists: raise ValidationError('Documento já existente') # campos opcionais, mas que se informados devem ser válidos @@ -725,7 +728,7 @@ class DocumentoAdministrativoForm(ModelForm): [('texto_integral', 12)]) row6 = to_row( - [('dias_prazo', 6), ('data_fim_prazo', 6)]) + [('numero_externo', 4), ('dias_prazo', 6), ('data_fim_prazo', 2)]) row7 = to_row( [('observacao', 12)]) diff --git a/sapl/protocoloadm/migrations/0004_documentoadministrativo_numero_externo.py b/sapl/protocoloadm/migrations/0004_documentoadministrativo_numero_externo.py new file mode 100644 index 000000000..b3659efbb --- /dev/null +++ b/sapl/protocoloadm/migrations/0004_documentoadministrativo_numero_externo.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.11 on 2018-04-25 18:40 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('protocoloadm', '0003_auto_20180103_1343'), + ] + + operations = [ + migrations.AddField( + model_name='documentoadministrativo', + name='numero_externo', + field=models.PositiveIntegerField(blank=True, null=True, verbose_name='Número Externo'), + ), + ] diff --git a/sapl/protocoloadm/models.py b/sapl/protocoloadm/models.py index d4d45b3ad..cf7616d7a 100644 --- a/sapl/protocoloadm/models.py +++ b/sapl/protocoloadm/models.py @@ -133,6 +133,10 @@ class DocumentoAdministrativo(models.Model): verbose_name=_('Em Tramitação?'), choices=YES_NO_CHOICES) assunto = models.TextField(verbose_name=_('Assunto')) + numero_externo = models.PositiveIntegerField( + blank=True, + null=True, + verbose_name=_('Número Externo')) observacao = models.TextField( blank=True, verbose_name=_('Observação')) texto_integral = models.FileField( diff --git a/sapl/templates/protocoloadm/layouts.yaml b/sapl/templates/protocoloadm/layouts.yaml index 76b80da18..b1bb2f31b 100644 --- a/sapl/templates/protocoloadm/layouts.yaml +++ b/sapl/templates/protocoloadm/layouts.yaml @@ -11,6 +11,7 @@ DocumentoAdministrativo: - interessado tramitacao - texto_integral {% trans 'Outras Informações' %}: + - numero_externo - dias_prazo data_fim_prazo - observacao From e7e57c4e55be256075fd03e0667b73017502ae13 Mon Sep 17 00:00:00 2001 From: Edward Date: Fri, 27 Apr 2018 13:08:03 -0300 Subject: [PATCH 19/25] Fixes #1915 (#1916) --- sapl/materia/forms.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index 3d455ea29..e083e7fec 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -582,8 +582,18 @@ class AnexadaForm(ModelForm): msg = _('A matéria a ser anexada não existe no cadastro' ' de matérias legislativas.') raise ValidationError(msg) - else: - cleaned_data['materia_anexada'] = materia_anexada + + materia_principal = self.instance.materia_principal + if materia_principal == materia_anexada: + raise ValidationError(_('Matéria não pode ser anexada a si mesma')) + + is_anexada = Anexada.objects.filter(materia_principal=materia_principal, + materia_anexada=materia_anexada + ).exists() + if is_anexada: + raise ValidationError(_('Materia já se encontra anexada')) + + cleaned_data['materia_anexada'] = materia_anexada return cleaned_data From ff1c86b119acd64456d4a79f8f6aaaeca7b602fe Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Fri, 27 Apr 2018 14:53:31 -0300 Subject: [PATCH 20/25] =?UTF-8?q?HOT-FIX:=20melhora=20o=20desempenho=20de?= =?UTF-8?q?=20pesquisas=20na=20tela=20de=20relat=C3=B3rios?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/base/forms.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sapl/base/forms.py b/sapl/base/forms.py index 1a0637a22..513c3a7ca 100644 --- a/sapl/base/forms.py +++ b/sapl/base/forms.py @@ -525,6 +525,11 @@ class RelatorioAtasFilterSet(django_filters.FilterSet): model = SessaoPlenaria fields = ['data_inicio'] + @property + def qs(self): + parent = super(RelatorioAtasFilterSet, self).qs + return parent.distinct().prefetch_related('tipo').order_by('-ano', 'tipo', 'numero') + def __init__(self, *args, **kwargs): super(RelatorioAtasFilterSet, self).__init__( *args, **kwargs) @@ -588,7 +593,7 @@ class RelatorioHistoricoTramitacaoFilterSet(django_filters.FilterSet): @property def qs(self): parent = super(RelatorioHistoricoTramitacaoFilterSet, self).qs - return parent.distinct().order_by('-ano', 'tipo', 'numero') + return parent.distinct().prefetch_related('tipo').order_by('-ano', 'tipo', 'numero') class Meta: model = MateriaLegislativa @@ -628,7 +633,7 @@ class RelatorioDataFimPrazoTramitacaoFilterSet(django_filters.FilterSet): @property def qs(self): parent = super(RelatorioDataFimPrazoTramitacaoFilterSet, self).qs - return parent.distinct().order_by('-ano', 'tipo', 'numero') + return parent.distinct().prefetch_related('tipo').order_by('-ano', 'tipo', 'numero') class Meta: model = MateriaLegislativa From dd6e7cc964fb2484cc855f8739d92e641df6f5bf Mon Sep 17 00:00:00 2001 From: Mariana Mendes Date: Wed, 2 May 2018 14:17:40 -0300 Subject: [PATCH 21/25] fix #1898 (#1917) * Fix #1898 * Fix #1898 * Add "remover_acentos" to the sapl utils * Remove the import unicodedata --- sapl/sessao/views.py | 6 +++--- sapl/utils.py | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index d7844b3ce..5beec02ad 100644 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -34,7 +34,7 @@ from sapl.parlamentares.models import (Filiacao, Legislatura, Mandato, Parlamentar, SessaoLegislativa) from sapl.sessao.apps import AppConfig from sapl.sessao.forms import ExpedienteMateriaForm, OrdemDiaForm -from sapl.utils import show_results_filter_set +from sapl.utils import show_results_filter_set, remover_acentos from .forms import (AdicionarVariasMateriasFilterSet, BancadaForm, BlocoForm, ExpedienteForm, ListMateriaForm, MesaForm, @@ -385,14 +385,14 @@ def customize_link_materia(context, pk, has_permission, is_expediente): context['rows'][i][3] = (resultado, None) return context - + def get_presencas_generic(model, sessao, legislatura): presencas = model.objects.filter( sessao_plenaria=sessao) presentes = [p.parlamentar for p in presencas] - presentes = sorted(presentes, key=lambda x: x.nome_parlamentar) + presentes = sorted(presentes, key=lambda x: remover_acentos(x.nome_parlamentar)) mandato = Mandato.objects.filter( legislatura=legislatura).order_by('parlamentar__nome_parlamentar') diff --git a/sapl/utils.py b/sapl/utils.py index 0fa20f706..8045f0e0b 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -2,6 +2,7 @@ import hashlib import logging import os import re +import unicodedata from functools import wraps from operator import itemgetter from unicodedata import normalize as unicodedata_normalize @@ -732,3 +733,7 @@ def RemoveTag(texto): i += 1 return textoSaida + +def remover_acentos(string): + return ''.join([c for c in unicodedata.normalize('NFD', string) + if unicodedata.category(c) != 'Mn']) \ No newline at end of file From 2520ed2f82f3e095fba7eaf3e8eeacd6404c50d6 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Wed, 2 May 2018 15:34:37 -0300 Subject: [PATCH 22/25] =?UTF-8?q?Adiciona=20um=20script=20simples=20para?= =?UTF-8?q?=20gerar=20vers=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- release.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100755 release.sh diff --git a/release.sh b/release.sh new file mode 100755 index 000000000..78fee9187 --- /dev/null +++ b/release.sh @@ -0,0 +1,19 @@ +#/bin/bash + +VERSION=`git describe --tags --abbrev=0` +LAST_DIGIT=`echo $VERSION | cut -f 3 -d '.'` +MAIN_REV=`echo $VERSION | cut -f 1,2 -d '.'` +NEXT_NUMBER=$(($LAST_DIGIT + 1)) +NEXT_VERSION=$MAIN_REV'.'$NEXT_NUMBER + +sed -e s/$VERSION/$NEXT_VERSION/g docker-compose.yml > tmp1 +mv tmp1 docker-compose.yml + +sed -e s/$VERSION/$NEXT_VERSION/g setup.py > tmp2 +mv tmp2 setup.py + +git add docker-compose.yml setup.py +git commit -m "Release: $NEXT_VERSION" +git tag $NEXT_VERSION +git push origin $NEXT_VERSION +git push origin From eca5f280618159d049016be0db7ee62884643a81 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Thu, 3 May 2018 10:31:46 -0300 Subject: [PATCH 23/25] Fix #1921 --- sapl/parlamentares/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapl/parlamentares/views.py b/sapl/parlamentares/views.py index b56215648..093bb83bd 100644 --- a/sapl/parlamentares/views.py +++ b/sapl/parlamentares/views.py @@ -192,7 +192,7 @@ class ColigacaoCrud(CrudAux): help_topic = 'coligacao' class ListView(CrudAux.ListView): - ordering = ('-numero_votos', 'nome') + ordering = ('legislatura', '-nome') def get_context_data(self, **kwargs): context = super(ColigacaoCrud.ListView, self).get_context_data( From 32f4c23853350b660f1fb266d52df34d26d916cd Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Thu, 3 May 2018 10:56:15 -0300 Subject: [PATCH 24/25] Fixes #1920 --- .../migrations/0014_auto_20180503_1055.py | 23 +++++++++++++++++++ sapl/comissoes/models.py | 2 ++ sapl/comissoes/views.py | 7 +++++- 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 sapl/comissoes/migrations/0014_auto_20180503_1055.py diff --git a/sapl/comissoes/migrations/0014_auto_20180503_1055.py b/sapl/comissoes/migrations/0014_auto_20180503_1055.py new file mode 100644 index 000000000..7a2524fed --- /dev/null +++ b/sapl/comissoes/migrations/0014_auto_20180503_1055.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.11 on 2018-05-03 13:55 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('comissoes', '0013_auto_20180312_1533'), + ] + + operations = [ + migrations.AlterModelOptions( + name='composicao', + options={'ordering': ['periodo'], 'verbose_name': 'Composição de Comissão', 'verbose_name_plural': 'Composições de Comissão'}, + ), + migrations.AlterModelOptions( + name='periodo', + options={'ordering': ['-data_inicio', '-data_fim'], 'verbose_name': 'Período de composição de Comissão', 'verbose_name_plural': 'Períodos de composição de Comissão'}, + ), + ] diff --git a/sapl/comissoes/models.py b/sapl/comissoes/models.py index f0b1b8d8b..0c3240fc6 100644 --- a/sapl/comissoes/models.py +++ b/sapl/comissoes/models.py @@ -105,6 +105,7 @@ class Periodo(models.Model): # PeriodoCompComissao class Meta: verbose_name = _('Período de composição de Comissão') verbose_name_plural = _('Períodos de composição de Comissão') + ordering = ['-data_inicio', '-data_fim'] def __str__(self): if self.data_inicio and self.data_fim: @@ -140,6 +141,7 @@ class Composicao(models.Model): # IGNORE class Meta: verbose_name = _('Composição de Comissão') verbose_name_plural = _('Composições de Comissão') + ordering = ['periodo'] def __str__(self): return '%s: %s' % (self.comissao.sigla, self.periodo) diff --git a/sapl/comissoes/views.py b/sapl/comissoes/views.py index 82c3a79c1..c5870389e 100644 --- a/sapl/comissoes/views.py +++ b/sapl/comissoes/views.py @@ -51,6 +51,9 @@ class PeriodoComposicaoCrud(CrudAux): class UpdateView(CrudAux.UpdateView): form_class = PeriodoForm + # class ListView(CrudAux.ListView): + + class ParticipacaoCrud(MasterDetailCrud): model = Participacao parent_field = 'composicao__comissao' @@ -112,7 +115,9 @@ class ComposicaoCrud(MasterDetailCrud): composicao_pk = self.take_composicao_pk() if composicao_pk == 0: - ultima_composicao = context['composicao_list'].last() + # Composicao eh ordenada por Periodo, que por sua vez esta em + # ordem descrescente de data de inicio (issue #1920) + ultima_composicao = context['composicao_list'].first() if ultima_composicao: context['composicao_pk'] = ultima_composicao.pk else: From 16a73815b6542614e6185448469bd338fc5c236c Mon Sep 17 00:00:00 2001 From: cristian-longhi Date: Fri, 8 Jun 2018 09:15:01 -0300 Subject: [PATCH 25/25] =?UTF-8?q?Vota=C3=A7=C3=A3o=20simb=C3=B3lica=20defa?= =?UTF-8?q?ult=20em=20Mat=C3=A9rias=20do=20Expediente=20e=20Ordem=20do=20D?= =?UTF-8?q?ia?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/sessao/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapl/sessao/models.py b/sapl/sessao/models.py index 4c5e9e187..6af5f490f 100644 --- a/sapl/sessao/models.py +++ b/sapl/sessao/models.py @@ -241,7 +241,7 @@ class AbstractOrdemDia(models.Model): numero_ordem = models.PositiveIntegerField(verbose_name=_('Nº Ordem')) resultado = models.TextField(blank=True, verbose_name=_('Resultado')) tipo_votacao = models.PositiveIntegerField( - verbose_name=_('Tipo de votação'), choices=TIPO_VOTACAO_CHOICES) + verbose_name=_('Tipo de votação'), choices=TIPO_VOTACAO_CHOICES, default=1) votacao_aberta = models.NullBooleanField( blank=True, choices=YES_NO_CHOICES,