diff --git a/.gitignore b/.gitignore index 3bf1301ec..429873229 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,9 @@ __pycache__/ # C extensions *.so +# Nodejs +node_modules/ + # Distribution / packaging .Python env/ diff --git a/docker-compose.yml b/docker-compose.yml index 68218665d..3b388dc7d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,6 @@ sapldb: image: postgres + restart: always environment: POSTGRES_PASSWORD: sapl POSTGRES_USER: sapl @@ -8,9 +9,19 @@ sapldb: volumes: - sapldb_data:/var/lib/postgresql/data/ ports: - - "5532:5432" + - "5432:5432" sapl: image: interlegis/sapl:3.1.24-BETA + restart: always + environment: + ADMIN_PASSWORD: interlegis + ADMIN_EMAIL: email@dominio.net + DEBUG: 'False' + USE_TLS: 'False' + EMAIL_PORT: 587 + EMAIL_HOST: smtp.dominio.net + EMAIL_HOST_USER: usuariosmtp + EMAIL_HOST_PASSWORD: senhasmtp volumes: - sapl_data:/var/interlegis/sapl/data - sapl_media:/var/interlegis/sapl/media diff --git a/requirements/dev-requirements.txt b/requirements/dev-requirements.txt index 11d6a2509..674994ffa 100644 --- a/requirements/dev-requirements.txt +++ b/requirements/dev-requirements.txt @@ -6,4 +6,4 @@ ipdb==0.10.1 pip-review==0.4 pygraphviz==1.3.1 pytest-ipdb==0.1-prerelease2 -pipdeptree +pipdeptree==0.10.1 diff --git a/requirements/requirements.txt b/requirements/requirements.txt index e64eb97dc..f0f3573cc 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -16,8 +16,8 @@ django-filter==0.15.3 django-floppyforms==1.6.2 django-model-utils==2.5 django-sass-processor==0.5.4 -djangorestframework -drfdocs +djangorestframework==3.4.0 +drfdocs==0.0.11 easy-thumbnails==2.3 git+git://github.com/interlegis/trml2pdf.git libsass==0.11.1 diff --git a/requirements/test-requirements.txt b/requirements/test-requirements.txt index 7dd6def90..5599b6d80 100644 --- a/requirements/test-requirements.txt +++ b/requirements/test-requirements.txt @@ -1,6 +1,6 @@ -r requirements.txt coverage==4.1 -django-webtest +django-webtest==1.7.8 flake8==2.6.2 isort==4.2.5 model-mommy==1.2.6 diff --git a/sapl/base/forms.py b/sapl/base/forms.py index 992ce558b..7e64c33cd 100644 --- a/sapl/base/forms.py +++ b/sapl/base/forms.py @@ -231,7 +231,7 @@ class AutorForm(ModelForm): if 'status_user' in self.Meta.fields: if self.instance.pk and self.instance.user_id: if getattr( - self.instance.user.username, + self.instance.user, get_user_model().USERNAME_FIELD) != cd['username']: if 'status_user' not in cd or not cd['status_user']: raise ValidationError( diff --git a/sapl/legacy/migration.py b/sapl/legacy/migration.py index 8f3749d0c..e9d4f73b1 100644 --- a/sapl/legacy/migration.py +++ b/sapl/legacy/migration.py @@ -17,7 +17,8 @@ from django.db.models import Count, Max from django.db.models.base import ModelBase from sapl.base.models import AppConfig as AppConf -from sapl.base.models import Autor, ProblemaMigracao, TipoAutor +from sapl.base.models import (Autor, CasaLegislativa, ProblemaMigracao, + TipoAutor) from sapl.comissoes.models import Comissao, Composicao, Participacao from sapl.legacy.models import TipoNumeracaoProtocolo from sapl.materia.models import (AcompanhamentoMateria, Proposicao, @@ -208,7 +209,8 @@ def fill_vinculo_norma_juridica(): TipoVinculoNormaJuridica.objects.bulk_create(lista_objs) -def fill_tipo_numeracao_protocolo(): +def fill_dados_basicos(): + # Ajusta sequencia numérica e cria base.AppConfig letra = 'A' try: tipo = TipoNumeracaoProtocolo.objects.latest('dat_inicial_protocolo') @@ -223,6 +225,10 @@ def fill_tipo_numeracao_protocolo(): appconf = AppConf(sequencia_numeracao=letra) appconf.save() + # Cria instância de CasaLegislativa + casa = CasaLegislativa() + casa.save() + # Uma anomalia no sapl 2.5 causa a duplicação de registros de votação. # Essa duplicação deve ser eliminada para que não haja erro no sapl 3.1 @@ -253,6 +259,9 @@ def excluir_registrovotacao_duplicados(): def delete_old(legacy_model, cols_values): + # ajuste necessário por conta de cósigos html em txt_expediente + if legacy_model.__name__ == 'ExpedienteSessaoPlenaria': + cols_values.pop('txt_expediente') def eq_clause(col, value): if value is None: @@ -338,7 +347,7 @@ class DataMigrator: '--database=default', '--no-input'], stdout=PIPE) fill_vinculo_norma_juridica() - fill_tipo_numeracao_protocolo() + fill_dados_basicos() info('Começando migração: %s...' % obj) self._do_migrate(obj) diff --git a/sapl/painel/views.py b/sapl/painel/views.py index ec5426759..cc01cbf34 100644 --- a/sapl/painel/views.py +++ b/sapl/painel/views.py @@ -1,5 +1,4 @@ import json - from django.contrib import messages from django.contrib.auth.decorators import user_passes_test from django.core.exceptions import ObjectDoesNotExist @@ -9,6 +8,8 @@ from django.http import HttpResponse, JsonResponse from django.http.response import Http404, HttpResponseRedirect from django.shortcuts import render from django.utils.translation import ugettext_lazy as _ +from operator import itemgetter +from sapl.utils import sort_lista_chave from sapl.crud.base import Crud from sapl.painel.apps import AppConfig @@ -296,7 +297,7 @@ def get_presentes(pk, response, materia): filiacao = filiacao_data(p.parlamentar, data_sessao, data_sessao) if not filiacao: - partido = _('Sem Registro') + partido = 'Sem Registro' else: partido = filiacao @@ -324,6 +325,8 @@ def get_presentes(pk, response, materia): }) + presentes_list = sort_lista_chave(presentes_list, 'nome') + response.update({ 'presentes': presentes_list, 'num_presentes': num_presentes, diff --git a/sapl/parlamentares/migrations/0010_corrige_data_inicio_mandato.py b/sapl/parlamentares/migrations/0010_corrige_data_inicio_mandato.py index 9cc3cccaf..ae2e83d50 100644 --- a/sapl/parlamentares/migrations/0010_corrige_data_inicio_mandato.py +++ b/sapl/parlamentares/migrations/0010_corrige_data_inicio_mandato.py @@ -1,12 +1,8 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.db import migrations -import json -import os -from datetime import timedelta -from django.core.management import call_command +from django.db import migrations def altera_data_inicio_mandato(apps, schema_editor): @@ -16,7 +12,9 @@ def altera_data_inicio_mandato(apps, schema_editor): for mandato in mandatos: data_inicio = mandato.data_inicio_mandato data_inicio_legislatura = mandato.legislatura.data_inicio - days = abs((data_inicio - data_inicio_legislatura).days) + + days = abs((data_inicio - data_inicio_legislatura + ).days) if data_inicio else 60 if days >= 60: mandato.data_inicio_mandato = data_inicio_legislatura @@ -28,8 +26,8 @@ class Migration(migrations.Migration): dependencies = [ # A dependencia real desse script é o arquivo 0001_initial.py, mas # isso gera um erro (Conflicting migrations detected; multiple leaf - # nodes in the migration graph). para não ocasionar problemas de migração, - # vamos manter a ordem padrão do django. + # nodes in the migration graph). para não ocasionar problemas de migração, + # vamos manter a ordem padrão do django. ('parlamentares', '0009_auto_20170905_1617'), ] diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 692a2c4f2..e3874181f 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -4,7 +4,8 @@ from crispy_forms.bootstrap import InlineRadios from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Button, Fieldset, Layout from django import forms -from django.core.exceptions import ObjectDoesNotExist, ValidationError +from django.core.exceptions import (MultipleObjectsReturned, + ObjectDoesNotExist, ValidationError) from django.db import models from django.forms import ModelForm from django.utils import timezone @@ -153,7 +154,7 @@ class DocumentoAdministrativoFilterSet(django_filters.FilterSet): model = DocumentoAdministrativo fields = ['tipo', 'numero', - 'numero_protocolo', + 'protocolo__numero', 'data', 'tramitacaoadministrativo__unidade_tramitacao_destino', 'tramitacaoadministrativo__status'] @@ -172,7 +173,7 @@ class DocumentoAdministrativoFilterSet(django_filters.FilterSet): row2 = to_row( [('ano', 4), - ('numero_protocolo', 4), + ('protocolo__numero', 4), ('data', 4)]) row3 = to_row( @@ -549,6 +550,10 @@ class DocumentoAdministrativoForm(ModelForm): widget=forms.Select( attrs={'class': 'selector'})) + numero_protocolo = forms.IntegerField(required=False, + label=Protocolo._meta. + get_field('numero').verbose_name) + class Meta: model = DocumentoAdministrativo fields = ['tipo', @@ -577,8 +582,8 @@ class DocumentoAdministrativoForm(ModelForm): if not self.is_valid(): return cleaned_data - numero_protocolo = cleaned_data['numero_protocolo'] - ano_protocolo = cleaned_data['ano_protocolo'] + numero_protocolo = self.data['numero_protocolo'] + ano_protocolo = self.data['ano_protocolo'] # campos opcionais, mas que se informados devem ser válidos if numero_protocolo and ano_protocolo: @@ -590,6 +595,11 @@ class DocumentoAdministrativoForm(ModelForm): msg = _('Protocolo %s/%s inexistente.' % ( numero_protocolo, ano_protocolo)) raise ValidationError(msg) + except MultipleObjectsReturned: + msg = _( + 'Existe mais de um Protocolo com este ano e número.' % ( + numero_protocolo, ano_protocolo)) + raise ValidationError(msg) return self.cleaned_data diff --git a/sapl/protocoloadm/migrations/0002_remove_documentoadministrativo_numero_protocolo.py b/sapl/protocoloadm/migrations/0002_remove_documentoadministrativo_numero_protocolo.py new file mode 100644 index 000000000..de12f4139 --- /dev/null +++ b/sapl/protocoloadm/migrations/0002_remove_documentoadministrativo_numero_protocolo.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.3 on 2017-09-20 21:52 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('protocoloadm', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='documentoadministrativo', + name='numero_protocolo', + ), + ] diff --git a/sapl/protocoloadm/models.py b/sapl/protocoloadm/models.py index 6294399f8..d4d45b3ad 100644 --- a/sapl/protocoloadm/models.py +++ b/sapl/protocoloadm/models.py @@ -120,8 +120,7 @@ class DocumentoAdministrativo(models.Model): on_delete=models.PROTECT, verbose_name=_('Protocolo')) data = models.DateField(verbose_name=_('Data')) - numero_protocolo = models.PositiveIntegerField( - blank=True, null=True, verbose_name=_('Núm. Protocolo')) + interessado = models.CharField( max_length=50, blank=True, verbose_name=_('Interessado')) autor = models.ForeignKey(Autor, blank=True, null=True, diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py index 348f79229..3384e4934 100644 --- a/sapl/protocoloadm/views.py +++ b/sapl/protocoloadm/views.py @@ -88,7 +88,7 @@ class DocumentoAdministrativoCrud(Crud): class BaseMixin(Crud.BaseMixin): list_field_names = ['tipo', 'numero', 'ano', 'data', - 'numero_protocolo', 'assunto', + 'protocolo__numero', 'assunto', 'interessado', 'tramitacao', 'texto_integral'] @property diff --git a/sapl/relatorios/views.py b/sapl/relatorios/views.py index 01a3b06b2..7719e6d2d 100644 --- a/sapl/relatorios/views.py +++ b/sapl/relatorios/views.py @@ -956,7 +956,7 @@ def get_etiqueta_protocolos(prots): dic['num_documento'] = '' for documento in DocumentoAdministrativo.objects.filter( - numero_protocolo=p.numero): + protocolo=p): dic['num_documento'] = str(documento) dic['ident_processo'] = dic['num_materia'] or dic['num_documento'] diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index ee7b2f9de..f767cb5d4 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -116,6 +116,7 @@ class BancadaForm(ModelForm): class ExpedienteMateriaForm(ModelForm): _model = ExpedienteMateria + data_atual = timezone.now() tipo_materia = forms.ModelChoiceField( label=_('Tipo Matéria'), @@ -128,7 +129,9 @@ class ExpedienteMateriaForm(ModelForm): label='Número Matéria', required=True) ano_materia = forms.CharField( - label='Ano Matéria', required=True) + label='Ano Matéria', + initial=int(data_atual.year), + required=True) data_ordem = forms.CharField( label='Data Sessão', diff --git a/sapl/templates/materia/impressos/ficha_pdf.html b/sapl/templates/materia/impressos/ficha_pdf.html index 405d9a2f5..99ded497e 100644 --- a/sapl/templates/materia/impressos/ficha_pdf.html +++ b/sapl/templates/materia/impressos/ficha_pdf.html @@ -25,38 +25,23 @@ body #ementa_texto { font-family: Arial; - line-height: 175%; + line-height: 150%; border-style: none; text-align: justify; padding: 0pt 5pt 0pt 0pt; - line-height: 140%; + margin-right:100px; font-size: small; + height:130px; } -#ficha_menor - { - background-color: transparent; - margin: -2pt 20pt 0pt 0pt; - position: relative; - width: 285pt; - height: 370pt; - } #titulo { font-size: medium; + margin-right:100px; text-align: center; } -#ficha_maior - { - background-color: #9eddee; - margin:0pt; - position: relative; - width: 285pt; - height: 370pt; - } - #despacho_inicial { font-family: Arial; @@ -71,30 +56,38 @@ body - +
{% if materia.numeracao_set.first %} - PROCESSO Nº: {{ materia.numeracao_set.first.numero_materia }}

+ PROCESSO Nº {{ materia.numeracao_set.first.numero_materia }} / {{ materia.numeracao_set.first.ano_materia }}
  {% else %} - PROCESSO Nº: {{ materia.numero }}

+ PROCESSO Nº: {{ materia.numero }}
  {% endif %}
- - - {{materia.tipo}}: {{materia.numero}}/{{materia.ano}}
- - - Data de entrada: {{materia.data_apresentacao}}
+ + +
+ + {{materia.tipo}}: {{materia.numero}} / {{materia.ano}}
+
+ + + +
+ + Data de entrada: {{materia.data_apresentacao}}
+
-
+
+ {% if materia.autoria_set.all %} Autor: @@ -111,18 +104,16 @@ body
- -


-
+
Ementa: {{materia.ementa}}
-


+
@@ -134,8 +125,8 @@ body

-
- ________________NORMA JURIDICA_________________

+ + ________________NORMA JURIDICA_________________


_________________________________________________
diff --git a/sapl/templates/materia/materialegislativa_filter.html b/sapl/templates/materia/materialegislativa_filter.html index 5fe9fd04a..391de56c7 100644 --- a/sapl/templates/materia/materialegislativa_filter.html +++ b/sapl/templates/materia/materialegislativa_filter.html @@ -8,7 +8,7 @@ Pesquisa Textual - {% if perms.materia %} + {% if perms.materia.add_materialegislativa %} {% blocktrans with verbose_name=view.verbose_name %} Adicionar Matéria Legislativa {% endblocktrans %} diff --git a/sapl/templates/protocoloadm/documentoadministrativo_filter.html b/sapl/templates/protocoloadm/documentoadministrativo_filter.html index 354565c28..a69b27073 100644 --- a/sapl/templates/protocoloadm/documentoadministrativo_filter.html +++ b/sapl/templates/protocoloadm/documentoadministrativo_filter.html @@ -7,7 +7,7 @@ {% block actions %}
- {% if perms.protocoloadm %} + {% if perms.protocoloadm.add_documentoadministrativo %} {% blocktrans with verbose_name=view.verbose_name %} Adicionar Documento Administrativo {% endblocktrans %} diff --git a/sapl/templates/protocoloadm/protocolo_filter.html b/sapl/templates/protocoloadm/protocolo_filter.html index d50439ae8..6d9150fa6 100644 --- a/sapl/templates/protocoloadm/protocolo_filter.html +++ b/sapl/templates/protocoloadm/protocolo_filter.html @@ -44,7 +44,6 @@ {% if p.anulado %}  ** NULO **{% endif %}
Assunto: {{ p.assunto_ementa|default_if_none:"Não informado"}}
- Data Protocolo: {{ p.data|date:"d/m/Y"|default_if_none:"Não informado" }} - Horário: {{ p.hora|date:"G:i:s" }}
Data Protocolo: {{ p.data|date:"d/m/Y"|default_if_none:"Não informado" }} - Horário: {{ p.timestamp|localtime|date:"G:i:s" }}
{% if p.tipo_processo == 0 %} diff --git a/sapl/utils.py b/sapl/utils.py index 7afa00d1a..37e5711d3 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -4,6 +4,7 @@ import os import re from functools import wraps from unicodedata import normalize as unicodedata_normalize +from operator import itemgetter import django_filters import magic @@ -651,3 +652,14 @@ def show_results_filter_set(qr): return False return True + + +def sort_lista_chave(lista, chave): + """ + :param lista: Uma list a ser ordenada . + :param chave: Algum atributo (chave) que está presente na lista e qual deve ser usado para a ordenação da nova + lista. + :return: A lista ordenada pela chave passada. + """ + lista_ordenada = sorted(lista, key=itemgetter(chave)) + return lista_ordenada diff --git a/setup.py b/setup.py index e123f703f..8fa9eef5c 100644 --- a/setup.py +++ b/setup.py @@ -10,6 +10,13 @@ os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir))) install_requires = [ 'dj-database-url==0.4.1', + 'django-haystack==2.6.0', + 'django>=1.9,<1.10', + # TODO O django-admin-bootstrapped 2.5.7 não inseriu a mudança que permite + # a compatibilidade com Django 1.9+. A linha abaixo será mudada quando uma + # nova versão do django-admin-bootstrapped for lançada + # 'git+git://github.com/django-admin-bootstrapped/ + # django-admin-bootstrapped.git', 'django-bootstrap3==7.0.1', 'django-bower==5.1.0', 'django-braces==1.9.0', @@ -20,24 +27,29 @@ install_requires = [ 'django-filter==0.15.3', 'django-floppyforms==1.6.2', 'django-model-utils==2.5', - 'django-sass-processor==0.4.6', - 'django>=1.9,<1.10', + 'django-sass-processor==0.5.4', 'djangorestframework', + 'drfdocs', 'easy-thumbnails==2.3', + # 'git+git://github.com/interlegis/trml2pdf.git', 'libsass==0.11.1', 'psycopg2==2.6.2', 'python-decouple==3.0', 'pytz==2016.4', 'pyyaml==3.11', 'rtyaml==0.0.3', + 'textract==1.5.0', 'unipath==1.1', + 'pysolr==3.6.0', 'python-magic==0.4.12', 'gunicorn==19.6.0', - # git+git://github.com/interlegis/trml2pdf.git + 'django-reversion==2.0.8', + 'WeasyPrint==0.30', + 'whoosh==2.7.4' ] setup( name='interlegis-sapl', - version='3.1.1-alpha', + version='3.1.24-BETA', packages=find_packages(), include_package_data=True, license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007',