Browse Source

Merge pull request #2 from VictorArnaud/static_analysis

Static analysis
pull/1120/head
Victor Arnaud 9 years ago
committed by GitHub
parent
commit
44bf5b3791
  1. 6
      .travis.yml
  2. 40
      Dockerfile
  3. 2
      config/env-sample
  4. 8
      config/env_dockerfile
  5. 31
      config/nginx/nginx.conf
  6. 25
      docker-compose.yml
  7. 3
      requirements/requirements.txt
  8. 4
      sapl/legacy/migration.py
  9. 4
      sapl/legacy/scripts/fix_tables.sql
  10. 32
      sapl/materia/migrations/0004_auto_20170504_1751.py
  11. 4
      sapl/norma/models.py
  12. 25
      sapl/parlamentares/migrations/0002_auto_20170504_1751.py
  13. 17
      sapl/parlamentares/urls.py
  14. 222
      sapl/parlamentares/views.py
  15. 4
      sapl/sessao/urls.py
  16. 79
      sapl/sessao/views.py
  17. 17
      sapl/static/js/app.js
  18. 1
      sapl/static/styles/app.css
  19. 1
      sapl/static/styles/compilacao.css
  20. 8
      sapl/static/styles/style_tinymce.css
  21. 251
      sapl/templates/parlamentares/composicaomesa_form.html
  22. 2
      sapl/templates/sessao/resumo.html
  23. 54
      sapl/templates/sessao/votacao/nominal_detail.html
  24. 11
      start.sh

6
.travis.yml

@ -18,9 +18,11 @@ before_script:
script:
- ./manage.py migrate
- ./manage.py bower install
- py.test --create-db
# - ./test_and_check_qa.sh
- py.test --create-db --cov . --cov-report term
addons:
hosts:
- 127.0.0.1 sapldb
after_sucess:
- CODECLIMATE_REPO_TOKEN=4d19e43ef9a92ca21314499fc1cc4e127cc5a4dea7fcc5b8e36e03780ada43c9 codeclimate-test-reporter

40
Dockerfile

@ -4,31 +4,43 @@ ENV BUILD_PACKAGES postgresql-dev graphviz-dev graphviz build-base git pkgconfig
python3-dev libxml2-dev jpeg-dev libressl-dev libffi-dev libxslt-dev nodejs py3-lxml \
py3-magic postgresql-client vim
RUN apk add --no-cache python3 && \
RUN apk add --no-cache python3 nginx && \
python3 -m ensurepip && \
rm -r /usr/lib/python*/ensurepip && \
pip3 install --upgrade pip setuptools && \
rm -r /root/.cache
rm -r /root/.cache && \
rm -f /etc/nginx/conf.d/*
RUN mkdir -p /var/interlegis/sapl &&\
RUN mkdir -p /var/interlegis/sapl && \
apk add --update --no-cache $BUILD_PACKAGES && \
npm install -g bower
# Bower aceitar root
RUN touch /root/.bowerrc \
&& chmod 751 /root/.bowerrc \
&& echo "{ \"allow_root\": true }" >> /root/.bowerrc \
&& npm cache clean
npm install -g bower && \
npm cache clean
WORKDIR /var/interlegis/sapl/
ADD . /var/interlegis/sapl/
COPY start.sh /var/interlegis/sapl/
COPY config/nginx/sapl.conf /etc/nginx/conf.d
COPY config/nginx/nginx.conf /etc/nginx/nginx.conf
RUN pip install -r /var/interlegis/sapl/requirements/dev-requirements.txt --upgrade setuptools && \
rm -r /root/.cache && \
rm -r /tmp/*
COPY config/env_dockerfile /var/interlegis/sapl/sapl/.env
# manage.py bower install bug: https://github.com/nvbn/django-bower/issues/51
RUN python3 manage.py bower_install -- --allow-root --no-input && \
python3 manage.py collectstatic --no-input && \
rm -rf /var/interlegis/sapl/sapl/.env && \
rm -rf /var/interlegis/sapl/sapl.db
RUN chmod +x /var/interlegis/sapl/start.sh
RUN chmod +x /var/interlegis/sapl/start.sh && \
ln -sf /dev/stdout /var/log/nginx/access.log && \
ln -sf /dev/stderr /var/log/nginx/error.log
RUN pip install -r /var/interlegis/sapl/requirements/requirements.txt --upgrade setuptools
VOLUME ["/var/interlegis/sapl/data", "/var/interlegis/sapl/media"]
VOLUME ["/var/interlegis/sapl/data", "/var/interlegis/sapl/media", "/var/interlegis/sapl/collected_static"]
ENTRYPOINT ["/var/interlegis/sapl/start.sh"]
CMD ["/var/interlegis/sapl/start.sh"]

2
config/env-sample

@ -1,6 +1,6 @@
DATABASE_URL = postgresql://postgres:@sapldb:/sapl
KEY
DEBUG = False
DEBUG = True
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST = ''

8
config/env_dockerfile

@ -0,0 +1,8 @@
DATABASE_URL = sqlite:///sapl.db
SECRET_KEY = 'Dockerfile_Key'
DEBUG = True
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST = ''
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''

31
config/nginx/nginx.conf

@ -0,0 +1,31 @@
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile off;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}

25
docker-compose.yml

@ -1,13 +1,3 @@
server:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./config/nginx:/etc/nginx/conf.d
- ./collected_static:/var/interlegis/sapl/collected_static
- ./media:/var/interlegis/sapl/media
volumes_from:
- web
sapldb:
image: postgres
environment:
@ -16,16 +6,15 @@ sapldb:
POSTGRES_DB: sapl
PGDATA : /var/lib/postgresql/data/
volumes:
- ./postgres-data/data/:/var/lib/postgresql/data/
- ./data:/data-import
- sapldb_data:/var/lib/postgresql/data/
ports:
- "5532:5432"
web:
build: .
sapl:
image: interlegis/sapl:latest
volumes:
- .:/var/interlegis/sapl/
- ./data:/var/interlegis/sapl/data
- ./media:/var/interlegis/sapl/media
- ./collected_static:/var/interlegis/sapl/collected_static
- sapl_data:/var/interlegis/sapl/data
- sapl_media:/var/interlegis/sapl/media
links:
- sapldb
ports:
- "80:80"

3
requirements/requirements.txt

@ -15,7 +15,7 @@ django-extra-views==0.8.0
django-filter==0.15.3
django-floppyforms==1.6.2
django-model-utils==2.5
django-sass-processor==0.4.6
django-sass-processor==0.5.4
djangorestframework
drfdocs
easy-thumbnails==2.3
@ -32,3 +32,4 @@ python-magic==0.4.12
gunicorn==19.6.0
django-reversion==2.0.8
whoosh==2.7.4
codeclimate-test-reporter

4
sapl/legacy/migration.py

@ -130,9 +130,7 @@ def get_fk_related(field, value, label=None):
if not field.null:
fields_dict = get_fields_dict(field.related_model)
# Cria stub ao final da tabela para evitar erros
pk = 1
if hasattr(field.related_model.objects.last(), 'pk'):
pk = field.related_model.objects.last().pk
pk = get_last_value(field.related_model)
with reversion.create_revision():
reversion.set_comment('Stub criado pela migração')
value = mommy.make(

4
sapl/legacy/scripts/fix_tables.sql

@ -2,15 +2,19 @@
SELECT REPLACE(@@sql_mode,'STRICT_TRANS_TABLES,','');
-- Exclui procedures caso já existam
DROP PROCEDURE IF EXISTS verifica_campos_proposicao;
DROP PROCEDURE IF EXISTS verifica_campos_tipo_materia_legislativa;
DROP PROCEDURE IF EXISTS verifica_campos_sessao_plenaria_presenca;
DROP PROCEDURE IF EXISTS cria_lexml_registro_provedor_e_publicador;
-- Procedure para criar campo num_proposicao em proposicao
CREATE PROCEDURE verifica_campos_proposicao() BEGIN IF NOT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='proposicao' AND column_name='num_proposicao') THEN ALTER TABLE proposicao ADD COLUMN num_proposicao INT(11) NULL after txt_justif_devolucao; END IF; END;
-- Procedure para criar campo iind_num_automatica em tipo_materia_legislativa
CREATE PROCEDURE verifica_campos_tipo_materia_legislativa() BEGIN IF NOT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='tipo_materia_legislativa' AND column_name='ind_num_automatica') THEN ALTER TABLE tipo_materia_legislativa ADD COLUMN ind_num_automatica BOOLEAN NULL DEFAULT FALSE after des_tipo_materia; END IF; IF NOT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='tipo_materia_legislativa' AND column_name='quorum_minimo_votacao') THEN ALTER TABLE tipo_materia_legislativa ADD COLUMN quorum_minimo_votacao INT(11) NULL after ind_num_automatica; END IF; END;
-- Procedure para criar campos cod_presenca_sessao (sendo a nova PK da tabela) e dat_sessao em sessao_plenaria_presenca
CREATE PROCEDURE verifica_campos_sessao_plenaria_presenca() BEGIN IF NOT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='sessao_plenaria_presenca' AND column_name='cod_presenca_sessao') THEN ALTER TABLE sessao_plenaria_presenca DROP PRIMARY KEY, ADD cod_presenca_sessao INT AUTO_INCREMENT PRIMARY KEY FIRST; END IF; IF NOT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='sessao_plenaria_presenca' AND column_name='dat_sessao') THEN ALTER TABLE sessao_plenaria_presenca ADD COLUMN dat_sessao DATE NULL after cod_parlamentar; END IF; END;
-- Procedure para criar tabela lexml_registro_provedor e lexml_registro_publicador
CREATE PROCEDURE cria_lexml_registro_provedor_e_publicador() BEGIN IF NOT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='lexml_registro_publicador') THEN CREATE TABLE lexml_registro_publicador (cod_publicador INT AUTO_INCREMENT NOT NULL, id_publicador INT, nom_publicador VARCHAR(255), adm_email VARCHAR(50), sigla VARCHAR(255), nom_responsavel VARCHAR(255), tipo VARCHAR(50), id_responsavel INT, PRIMARY KEY (cod_publicador)); END IF; IF NOT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='lexml_registro_provedor') THEN CREATE TABLE lexml_registro_provedor (cod_provedor INT AUTO_INCREMENT NOT NULL, id_provedor INT, nom_provedor VARCHAR(255), sgl_provedor VARCHAR(15), adm_email VARCHAR(50), nom_responsavel VARCHAR(255), tipo VARCHAR(50), id_responsavel INT, xml_provedor LONGTEXT, PRIMARY KEY (cod_provedor)); END IF; END;
-- Executa as procedures criadas acima
CALL verifica_campos_proposicao;
CALL verifica_campos_tipo_materia_legislativa;
CALL verifica_campos_sessao_plenaria_presenca;
CALL cria_lexml_registro_provedor_e_publicador;

32
sapl/materia/migrations/0004_auto_20170504_1751.py

@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.11 on 2017-05-04 17:51
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('materia', '0003_auto_20170403_1505'),
]
operations = [
migrations.AlterField(
model_name='assuntomateria',
name='dispositivo',
field=models.CharField(blank=True, default='', max_length=200, verbose_name='Descrição do Dispositivo Legal'),
preserve_default=False,
),
migrations.AlterField(
model_name='materiaassunto',
name='assunto',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='materia.AssuntoMateria', verbose_name='Assunto'),
),
migrations.AlterField(
model_name='materiaassunto',
name='materia',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='materia.MateriaLegislativa', verbose_name='Matéria'),
),
]

4
sapl/norma/models.py

@ -18,8 +18,8 @@ class AssuntoNorma(models.Model):
max_length=250, blank=True, verbose_name=_('Descrição'))
class Meta:
verbose_name = _('Assunto de Norma')
verbose_name_plural = _('Assuntos de Norma')
verbose_name = _('Assunto de Norma Jurídica')
verbose_name_plural = _('Assuntos de Normas Jurídicas')
def __str__(self):
return self.assunto

25
sapl/parlamentares/migrations/0002_auto_20170504_1751.py

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.11 on 2017-05-04 17:51
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('parlamentares', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='coligacao',
name='numero_votos',
field=models.PositiveIntegerField(blank=True, null=True, verbose_name='Nº Votos Recebidos (Coligação)'),
),
migrations.AlterField(
model_name='mandato',
name='votos_recebidos',
field=models.PositiveIntegerField(blank=True, null=True, verbose_name='Votos Recebidos (Mandato)'),
),
]

17
sapl/parlamentares/urls.py

@ -1,14 +1,18 @@
from django.conf.urls import include, url
from sapl.parlamentares.views import (CargoMesaCrud, ColigacaoCrud,
from sapl.parlamentares.views import (altera_field_mesa,
CargoMesaCrud, ColigacaoCrud,
ComposicaoColigacaoCrud, DependenteCrud,
FiliacaoCrud, FrenteCrud, FrenteList,
LegislaturaCrud, MandatoCrud,
LegislaturaCrud,
insere_parlamentar_composicao,
MandatoCrud,
MesaDiretoraView, NivelInstrucaoCrud,
ParlamentarCrud,
ParticipacaoParlamentarCrud, PartidoCrud,
ProposicaoParlamentarCrud,
RelatoriaParlamentarCrud,
remove_parlamentar_composicao,
SessaoLegislativaCrud,
TipoAfastamentoCrud, TipoDependenteCrud,
TipoMilitarCrud, VotanteView)
@ -51,4 +55,13 @@ urlpatterns = [
url(r'^mesa-diretora/$',
MesaDiretoraView.as_view(), name='mesa_diretora'),
url(r'^mesa-diretora/altera-field-mesa/$',
altera_field_mesa, name='altera_field_mesa'),
url(r'^mesa-diretora/insere-parlamentar-composicao/$',
insere_parlamentar_composicao, name='insere_parlamentar_composicao'),
url(r'^mesa-diretora/remove-parlamentar-composicao/$',
remove_parlamentar_composicao, name='remove_parlamentar_composicao'),
]

222
sapl/parlamentares/views.py

@ -1,7 +1,8 @@
from django.contrib import messages
from django.core.exceptions import ObjectDoesNotExist
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.core.urlresolvers import reverse, reverse_lazy
from django.db.models import F
from django.db.models import F, Q
from django.http import JsonResponse
from django.http.response import HttpResponseRedirect
from django.utils.datastructures import MultiValueDictKeyError
from django.utils.translation import ugettext_lazy as _
@ -344,8 +345,47 @@ class ParlamentarCrud(Crud):
# Tira Link do avatar_html e coloca no nome
for row in context['rows']:
# Coloca a filiação atual ao invés da última
if row[0][1]:
# Pega o Parlamentar por meio da pk
parlamentar = Parlamentar.objects.get(
id=(row[0][1].split('/')[-1]))
# Pega a Legislatura
legislatura = Legislatura.objects.get(
id=context['legislatura_id'])
# As condições para mostrar a filiação são:
# A data de filiacao deve ser menor que a data de fim
# da legislatura e data de desfiliação deve nula, ou maior,
# ou igual a data de fim da legislatura
try:
filiacao = parlamentar.filiacao_set.get(Q(
data__lte=legislatura.data_fim,
data_desfiliacao__gte=legislatura.data_fim) | Q(
data__lte=legislatura.data_fim,
data_desfiliacao__isnull=True))
# Caso não exista filiação com essas condições
except ObjectDoesNotExist:
row[2] = ('Não possui filiação', None)
# Caso exista mais de uma filiação nesse intervalo
# Entretanto, NÃO DEVE OCORRER
except MultipleObjectsReturned:
filiacao = parlamentar.filiacao_set.filter(Q(
data__lte=legislatura.data_fim,
data_desfiliacao__gte=legislatura.data_fim) | Q(
data__lte=legislatura.data_fim,
data_desfiliacao__isnull=True)).last()
# Caso encontre UMA filiação nessas condições
else:
row[2] = (filiacao.partido.sigla, None)
row[1] = (row[1][0], row[0][1])
row[0] = (row[0][0], None)
return context
@ -395,6 +435,11 @@ class MesaDiretoraView(FormView):
[p.parlamentar for p in parlamentares]) - set(
parlamentares_ocupados))
# Se todos os cargos estiverem ocupados, a listagem de parlamentares
# deve ser renderizada vazia
if not cargos_vagos:
parlamentares_vagos = []
return self.render_to_response(
{'legislaturas': Legislatura.objects.all(
).order_by('-numero'),
@ -408,20 +453,73 @@ class MesaDiretoraView(FormView):
'cargos_vagos': cargos_vagos
})
def existe_membro_mesa(self, sessao_plenaria, cargo):
return ComposicaoMesa.objects.filter(
sessao_legislativa_id=sessao_plenaria.id,
# parlamentar_id = integrante.parlamentar_id,
cargo_id=cargo.id
).exists()
def post(self, request, *args, **kwargs):
def altera_field_mesa(request):
"""
Essa função lida com qualquer alteração nos campos
da Mesa Diretora, após qualquer
operação (Legislatura/Sessão/Inclusão/Remoção),
atualizando os campos após cada alteração
"""
if (not Legislatura.objects.exists() or
not SessaoLegislativa.objects.exists()):
return self.validation(request)
legislatura = request.GET['legislatura']
sessoes = SessaoLegislativa.objects.filter(
legislatura=legislatura).order_by('-data_inicio')
if not sessoes:
return JsonResponse({'msg': ('Nenhuma sessão encontrada!', 0)})
# Verifica se já tem uma sessão selecionada. Ocorre quando
# é alterado o campo de sessão ou feita alguma operação
# de inclusão/remoção.
if request.GET['sessao']:
sessao_selecionada = request.GET['sessao']
# Caso a mudança tenha sido no campo legislatura, a sessão
# atual deve ser a primeira daquela legislatura
else:
sessao_selecionada = SessaoLegislativa.objects.filter(
legislatura=legislatura).order_by(
'-data_inicio').first().id
# Atualiza os componentes da view após a mudança
composicao_mesa = ComposicaoMesa.objects.filter(
sessao_legislativa=sessao_selecionada)
cargos_ocupados = [m.cargo for m in composicao_mesa]
cargos = CargoMesa.objects.all()
cargos_vagos = list(set(cargos) - set(cargos_ocupados))
parlamentares = Legislatura.objects.get(
id=legislatura).mandato_set.all()
parlamentares_ocupados = [m.parlamentar for m in composicao_mesa]
parlamentares_vagos = list(
set(
[p.parlamentar for p in parlamentares]) - set(
parlamentares_ocupados))
lista_sessoes = [(s.id, s.__str__()) for s in sessoes]
lista_composicao = [(c.id, c.parlamentar.__str__(),
c.cargo.__str__()) for c in composicao_mesa]
lista_parlamentares = [(
p.id, p.__str__()) for p in parlamentares_vagos]
lista_cargos = [(c.id, c.__str__()) for c in cargos_vagos]
if 'Incluir' in request.POST and request.user.has_perm(
return JsonResponse(
{'lista_sessoes': lista_sessoes,
'lista_composicao': lista_composicao,
'lista_parlamentares': lista_parlamentares,
'lista_cargos': lista_cargos,
'sessao_selecionada': sessao_selecionada,
'msg': ('', 1)})
def insere_parlamentar_composicao(request):
"""
Essa função lida com qualquer operação de inserção
na composição da Mesa Diretora
"""
if request.user.has_perm(
'%s.add_%s' % (
AppConfig.label, ComposicaoMesa._meta.model_name)):
@ -431,84 +529,62 @@ class MesaDiretoraView(FormView):
composicao.sessao_legislativa = SessaoLegislativa.objects.get(
id=int(request.POST['sessao']))
except MultiValueDictKeyError:
messages.error(request, _(
'Nenhuma sessão foi inserida!'))
return self.get(request)
return JsonResponse({'msg': ('Nenhuma sessão foi inserida!', 0)})
try:
composicao.parlamentar = Parlamentar.objects.get(
id=int(request.POST['parlamentar']))
except MultiValueDictKeyError:
messages.error(request, _(
'Nenhum parlamentar foi inserido!'))
return self.get(request)
return JsonResponse({
'msg': ('Nenhum parlamentar foi inserido!', 0)})
try:
composicao.cargo = CargoMesa.objects.get(
id=int(request.POST['cargo']))
if self.existe_membro_mesa(composicao.sessao_legislativa,
composicao.cargo):
messages.error(request, _('Parlamentar já inserido!'))
return self.get(request)
parlamentar_ja_inserido = ComposicaoMesa.objects.filter(
sessao_legislativa_id=composicao.sessao_legislativa.id,
cargo_id=composicao.cargo.id).exists()
if parlamentar_ja_inserido:
return JsonResponse({'msg': ('Parlamentar já inserido!', 0)})
composicao.save()
except MultiValueDictKeyError:
messages.error(request, _(
'Nenhum cargo foi inserido!'))
return self.get(request)
messages.success(request, _(
'Parlamentar adicionado com sucesso!'))
except MultiValueDictKeyError:
return JsonResponse({'msg': ('Nenhum cargo foi inserido!', 0)})
elif 'Excluir' in request.POST and request.user.has_perm(
'%s.delete_%s' % (
AppConfig.label, ComposicaoMesa._meta.model_name)):
return JsonResponse({'msg': ('Parlamentar inserido com sucesso!', 1)})
if 'composicao_mesa' in request.POST:
ids = request.POST['composicao_mesa'].split(':')
composicao = ComposicaoMesa.objects.get(
sessao_legislativa_id=int(request.POST['sessao']),
parlamentar_id=int(ids[0]),
cargo_id=int(ids[1])
)
composicao.delete()
messages.success(request, _(
'Parlamentar excluido com sucesso!'))
else:
messages.error(request, _(
'Selecione um parlamentar para ser excluido!'))
return JsonResponse(
{'msg': ('Você não tem permissão para esta operação!', 0)})
mesa = ComposicaoMesa.objects.filter(
sessao_legislativa=request.POST['sessao'])
cargos_ocupados = [m.cargo for m in mesa]
cargos = CargoMesa.objects.all()
cargos_vagos = list(set(cargos) - set(cargos_ocupados))
def remove_parlamentar_composicao(request):
"""
Essa função lida com qualquer operação de remoção
na composição da Mesa Diretora
"""
parlamentares = Legislatura.objects.get(
id=int(request.POST['legislatura'])).mandato_set.all()
parlamentares_ocupados = [m.parlamentar for m in mesa]
parlamentares_vagos = list(
set(
[p.parlamentar for p in parlamentares]) - set(
parlamentares_ocupados))
if request.POST and request.user.has_perm(
'%s.delete_%s' % (
AppConfig.label, ComposicaoMesa._meta.model_name)):
sessao_sel = SessaoLegislativa.objects.get(
id=int(request.POST['sessao']))
if 'composicao_mesa' in request.POST:
try:
composicao = ComposicaoMesa.objects.get(
id=request.POST['composicao_mesa'])
except ObjectDoesNotExist:
return JsonResponse(
{'msg': (
'Composição da Mesa não pôde ser removida!', 0)})
if str(sessao_sel.legislatura_id) != request.POST['legislatura']:
sessao_sel = SessaoLegislativa.objects.filter(
legislatura=Legislatura.objects.first()).first()
composicao.delete()
return self.render_to_response(
{'legislaturas': Legislatura.objects.all(
).order_by('-numero'),
'legislatura_selecionada': Legislatura.objects.get(
id=int(request.POST['legislatura'])),
'sessoes': SessaoLegislativa.objects.filter(
legislatura_id=int(request.POST['legislatura'])),
'sessao_selecionada': sessao_sel,
'composicao_mesa': mesa,
'parlamentares': parlamentares_vagos,
'cargos_vagos': cargos_vagos
})
return JsonResponse(
{'msg': (
'Parlamentar excluido com sucesso!', 1)})
else:
return JsonResponse(
{'msg': (
'Selecione algum parlamentar para ser excluido!', 0)})

4
sapl/sessao/urls.py

@ -16,6 +16,7 @@ from sapl.sessao.views import (AdicionarVariasMateriasExpediente,
VotacaoEditView, VotacaoExpedienteEditView,
VotacaoExpedienteView, VotacaoNominalEditView,
VotacaoNominalExpedienteEditView,
VotacaoNominalExpedienteDetailView,
VotacaoNominalExpedienteView,
VotacaoNominalView, VotacaoView,
abrir_votacao_expediente_view,
@ -120,6 +121,9 @@ urlpatterns = [
url(r'^sessao/(?P<pk>\d+)/matexp/votnom/edit/(?P<oid>\d+)/(?P<mid>\d+)$',
VotacaoNominalExpedienteEditView.as_view(),
name='votacaonominalexpedit'),
url(r'^sessao/(?P<pk>\d+)/matexp/votnom/detail/(?P<oid>\d+)/(?P<mid>\d+)$',
VotacaoNominalExpedienteDetailView.as_view(),
name='votacaonominalexpdetail'),
url(r'^sessao/(?P<pk>\d+)/matexp/votsimb/(?P<oid>\d+)/(?P<mid>\d+)$',
VotacaoExpedienteView.as_view(), name='votacaosimbolicaexp'),
url(r'^sessao/(?P<pk>\d+)/matexp/votsec/view/(?P<oid>\d+)/(?P<mid>\d+)$',

79
sapl/sessao/views.py

@ -353,6 +353,17 @@ class ExpedienteMateriaCrud(MasterDetailCrud):
(url,
resultado_descricao,
resultado_observacao))
else:
if obj.tipo_votacao == 2:
url = reverse('sapl.sessao:votacaonominalexpdetail',
kwargs={
'pk': obj.sessao_plenaria_id,
'oid': obj.materia_id,
'mid': obj.pk})
obj.resultado = ('<a href="%s">%s</a><br/>%s' %
(url,
resultado_descricao,
resultado_observacao))
else:
obj.resultado = ('%s<br/>%s' %
(resultado_descricao,
@ -1072,11 +1083,13 @@ class ResumoView(DetailView):
numero = o.numero_ordem
# Verificar resultado
resultado = o.registrovotacao_set.filter(materia=o.materia)
if resultado:
resultado = resultado[0].tipo_resultado_votacao.nome
rv = o.registrovotacao_set.filter(materia=o.materia).first()
if rv:
resultado = rv.tipo_resultado_votacao.nome
resultado_observacao = rv.observacao
else:
resultado = _('Matéria não votada')
resultado_observacao = _(' ')
autoria = Autoria.objects.filter(
materia_id=o.materia_id)
@ -1086,6 +1099,7 @@ class ResumoView(DetailView):
'titulo': titulo,
'numero': numero,
'resultado': resultado,
'resultado_observacao': resultado_observacao,
'autor': autor
}
materias_ordem.append(mat)
@ -1847,6 +1861,51 @@ class VotacaoNominalExpedienteEditView(SessaoPermissionMixin):
return reverse('sapl.sessao:expedientemateria_list',
kwargs={'pk': pk})
class VotacaoNominalExpedienteDetailView(DetailView):
template_name = 'sessao/votacao/nominal_detail.html'
def get(self, request, *args, **kwargs):
context = {}
materia_id = kwargs['oid']
expediente_id = kwargs['mid']
votacao = RegistroVotacao.objects.get(
materia_id=materia_id,
expediente_id=expediente_id)
expediente = ExpedienteMateria.objects.get(id=expediente_id)
votos = VotoParlamentar.objects.filter(votacao_id=votacao.id)
list_votos = []
for v in votos:
parlamentar = Parlamentar.objects.get(id=v.parlamentar_id)
list_votos.append({'parlamentar': parlamentar, 'voto': v.voto})
context.update({'votos': list_votos})
materia = {'materia': expediente.materia,
'ementa': sub(
'&nbsp;', ' ', strip_tags(expediente.observacao))}
context.update({'materia': materia})
votacao_existente = {'observacao': sub(
'&nbsp;', ' ', strip_tags(votacao.observacao)),
'resultado': votacao.tipo_resultado_votacao.nome,
'tipo_resultado':
votacao.tipo_resultado_votacao_id}
context.update({'votacao': votacao_existente,
'tipos': self.get_tipos_votacao()})
return self.render_to_response(context)
def get_tipos_votacao(self):
for tipo in TipoResultadoVotacao.objects.all():
yield tipo
def get_success_url(self):
pk = self.kwargs['pk']
return reverse('sapl.sessao:expedientemateria_list',
kwargs={'pk': pk})
class VotacaoExpedienteView(SessaoPermissionMixin):
@ -2019,7 +2078,7 @@ class VotacaoExpedienteEditView(SessaoPermissionMixin):
expediente_id=expediente_id).last()
votacao_existente = {'observacao': sub(
'&nbsp;', ' ', strip_tags(votacao.observacao)),
'resultado': votacao.tipo_resultado.nome,
'resultado': votacao.tipo_resultado_votacao.nome,
'tipo_resultado':
votacao.tipo_resultado_votacao_id}
context.update({'votacao_titulo': titulo,
@ -2113,11 +2172,13 @@ class PautaSessaoDetailView(DetailView):
situacao = m.materia.tramitacao_set.last().status
if situacao is None:
situacao = _("Não informada")
resultado = m.registrovotacao_set.all()
if resultado:
resultado = resultado[0].tipo_resultado_votacao.nome
rv = m.registrovotacao_set.all()
if rv:
resultado = rv[0].tipo_resultado_votacao.nome
resultado_observacao = rv[0].observacao
else:
resultado = _('Matéria não votada')
resultado_observacao = _(' ')
autoria = Autoria.objects.filter(materia_id=m.materia_id)
autor = [str(x.autor) for x in autoria]
@ -2127,6 +2188,7 @@ class PautaSessaoDetailView(DetailView):
'titulo': titulo,
'numero': numero,
'resultado': resultado,
'resultado_observacao': resultado_observacao,
'situacao': situacao,
'autor': autor
}
@ -2462,12 +2524,13 @@ class AdicionarVariasMateriasOrdemDia(AdicionarVariasMateriasExpediente):
@csrf_exempt
@permission_required('sessao.change_expedientemateria',
'sessao.change_ordemdia')
def mudar_ordem_materia_sessao(request):
# Pega os dados vindos da requisição
posicao_inicial = int(request.POST['pos_ini']) + 1
posicao_final = int(request.POST['pos_fim']) + 1
pk_sessao = int(request.POST['pk_sessao'])
pk_list = request.POST.getlist('pk_list[]')
materia = request.POST['materia']

17
sapl/static/js/app.js

@ -217,3 +217,20 @@ $(document).ready(function(){
OptionalCustomFrontEnd();
});
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}

1
sapl/static/styles/app.css

File diff suppressed because one or more lines are too long

1
sapl/static/styles/compilacao.css

File diff suppressed because one or more lines are too long

8
sapl/static/styles/style_tinymce.css

@ -1,8 +0,0 @@
.mce-content-body {
font-family: "Open Sans" "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif;
font-style: normal;
font-weight: normal;
line-height: 1.5;
font-size: 1em;
color: #444444;
}

251
sapl/templates/parlamentares/composicaomesa_form.html

@ -8,15 +8,28 @@
<b>{{legislatura_selecionada}}</b> não possui nenhuma Sessão Legislativa cadastrada.<br />
Clique <a href="{% url 'sapl.parlamentares:sessaolegislativa_create' %}">aqui</a> para cadastrar uma nova.
</div>
{% else %}
<form method="POST">
{% csrf_token %}
<div class="alert alert-danger alert-dismissible fade in" id="div-error" role="alert" style="display: none">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
</button>
<b><span id="error-message"></span></b>
</div>
<div class="alert alert-success alert-dismissible fade in" id="div-success" style="display: none" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
</button>
<b><span id="success-message"></span></b>
</div>
<fieldset class="form-group">
<legend>Escolha da Legislatura e da Sessão Legislativa</legend>
<div class="row">
<div class="col-md-6">
<label>Escolha uma Legislatura</label>
<select name="legislatura" class="form-control" onChange="form.submit();">
<select name="legislatura" id="id_legislatura" class="form-control">
{% for l in legislaturas %}
<option value="{{l.id}}" {% if l == legislatura_selecionada %} selected {% endif %}>
{{l}}
@ -26,7 +39,7 @@
</div>
<div class="col-md-6">
<label>Escolha uma Sessão Legislativa</label>
<select name="sessao" class="form-control" onChange="form.submit();">
<select name="sessao" id="id_sessao_legislativa" class="form-control">
{% for s in sessoes %}
<option value="{{s.id}}" {% if s == sessao_selecionada %} selected {% endif %}>
{{s}}
@ -42,9 +55,9 @@
<div class="row">
<div class="col-md-4">
<label>Composição da Mesa Diretora</label>
<select multiple size="5" class="form-control" name="composicao_mesa">
<select multiple size="5" class="form-control" id="id_composicao_mesa" name="composicao_mesa">
{% for p in composicao_mesa %}
<option value="{{p.parlamentar.id}}:{{p.cargo.id}}">
<option value="{{p.id}}">
{{p.parlamentar}} || {{p.cargo}}
</option>
{% endfor %}
@ -53,37 +66,243 @@
<div class="col-md-4" align="center">
<br /><br />
{% if cargos_vagos %}
{% if perms.parlamentares.add_cargomesa %}
<input type="submit" name="Incluir" Value="Incluir" class="btn btn-primary" />
{% endif %}
<input type="submit" style="display: none" name="Incluir" id="id_incluir" Value="Incluir" class="btn btn-primary" />
{% endif %}
<br />
<br />
{% if perms.parlamentares.add_composicaomesa %}
<input type="submit" name="Excluir" Value="Excluir" class="btn btn-danger" />
<input type="submit" style="display: none" name="Excluir" id="id_excluir" Value="Excluir" class="btn btn-danger" />
{% endif %}
</div>
{% if cargos_vagos %}
<div class="col-md-4">
<label>Parlamentare | Cargo</label>
<select class="form-control" name="parlamentar" id="parlamentar">
<label id='parlamentar-cargo-title' style="display: none">Parlamentar | Cargo</label>
<select class="form-control" name="parlamentar" id="id_parlamentar" style="display: none">
{% for p in parlamentares %}
<option value="{{p.id}}">{{p.nome_completo}}</option>
{% endfor %}
</select>
<br />
<select class="form-control" name="cargo" id="cargo">
<select class="form-control" name="cargo" id="id_cargo" style="display: none">
{% for c in cargos_vagos %}
<option value="{{c.id}}">{{c}}</option>
{% endfor %}
</select>
</div>
{% endif %}
</div>
</fieldset>
</form>
{% endif %}
{% endblock detail_content %}
{% block extra_js %}
<script language="Javascript">
//##############################################################
// Inicialização da View #
//##############################################################
// Se a composicao estiver completa, deve-se esconder o botão e os
// campos de inserção
$(document).ready(function(){
if($("#id_parlamentar").val() == null || $("#id_cargo").val() == null){
$("#id_parlamentar").hide();
$("#id_cargo").hide();
$("#parlamentar-cargo-title").hide();
$('#id_incluir').hide();
}
else{
$("#id_parlamentar").show();
$("#id_cargo").show();
$("#parlamentar-cargo-title").show();
$('#id_incluir').show();
}
// Se a composição estiver vazia, deve-se esconder
// de Excluir
if (!$("#id_composicao_mesa option").val()){
$("#id_excluir").hide()
}
else{
$("#id_excluir").show()
}
});
//##############################################################
//# EVENT HANDLERS #
//##############################################################
function errors_handler(msg){
if (msg == null){
$("#div-success").hide()
$("#div-error").hide()
$("#success-message").html('')
$("#error-message").html('')
}
else{
if (msg[1] == 0){
$("#div-error").show()
$("#error-message").html(msg[0])
}
else{
$("#div-success").show()
$("#success-message").html(msg[0])
}
}
}
// Atualiza os campos após alguma operação de mudança da Legislatura/Sessao ou
// Inserção/Remoção
function altera_field(id_legislatura, id_sessao=null, msg=null){
// Pega o novo valor do campo que foi modificado (Sessao/Legislatura) ou utiliza
// o valor da Legislatura, por conveniência, quando há alguma inserção ou remoção
var sessao_value = id_sessao
var legislatura_value = id_legislatura
// Limpa os campos que serão atualizados
$("#id_sessao_legislativa option").remove();
$("#id_composicao_mesa option").remove();
$("#id_parlamentar option").remove();
$("#id_cargo option").remove();
$.get("/mesa-diretora/altera-field-mesa",
{legislatura: legislatura_value, sessao: sessao_value},
function(data) {
// Caso não venha nenhum dado da requisição, retorna null
if ($.isEmptyObject(data)){
return null
}
lista_sessoes = data['lista_sessoes'];
lista_composicao = data['lista_composicao'];
lista_parlamentares = data['lista_parlamentares'];
lista_cargos = data['lista_cargos'];
// Atualiza a listagem dos campos
for (i = 0; i < lista_sessoes.length; i++) {
$('#id_sessao_legislativa').append('<option value="' + lista_sessoes[i][0] + '">' + lista_sessoes[i][1] + '</option>');
}
for (i = 0; i < lista_composicao.length; i++) {
$('#id_composicao_mesa').append('<option value="' + lista_composicao[i][0] + '">' + lista_composicao[i][1] + ' || ' + lista_composicao[i][2] + '</option>');
}
// Caso ainda tenha parlamentares/cargos a serem inseridos, preenche a listagem com
// os disponíveis e garante que as ferramentas de inserção estejam disponíveis
if (lista_parlamentares.length != 0 && lista_cargos.length != 0){
$('#id_incluir').show()
$('#id_cargo').show();
$('#id_parlamentar').show();
$("#parlamentar-cargo-title").show();
for (i = 0; i < lista_parlamentares.length; i++) {
$('#id_parlamentar').append('<option value="' + lista_parlamentares[i][0] + '">' + lista_parlamentares[i][1] + '</option>');
}
for (i = 0; i < lista_cargos.length; i++) {
$('#id_cargo').append('<option value="' + lista_cargos[i][0] + '">' + lista_cargos[i][1] + '</option>');
}
}
// Caso contrário, esconde do usuário essas opções
else{
$('#id_incluir').hide();
$('#id_cargo').hide();
$('#id_parlamentar').hide();
$("#parlamentar-cargo-title").hide();
}
// Garante que o botão de remoção aparecerá, caso tenha
// algum parlamentar na composição
if (lista_composicao.length != 0){
$("#id_excluir").show()
}
else{
$("#id_excluir").hide()
}
// Garante que a Sessão atual será a selecionada previamente e, no caso em que
// o campo modificado seja o de Legislatura, que a Sessão seja a última daquela
// legislatura
$("#id_sessao_legislativa").val(data['sessao_selecionada'])
// Caso haja algum erro que venha após a alteração da legislatura/sessao
// Essa mensagem de erro é prioridade
if (data['msg'][1] == 0){
msg = data['msg']
}
errors_handler(msg)
});
}
//#############################################################
//# EVENTS CATCH #
//#############################################################
$("#id_legislatura").change(function(){
legislatura = $("#id_legislatura").val();
altera_field(legislatura);
});
$("#id_sessao_legislativa").change(function(){
legislatura = $("#id_legislatura").val();
sessao = $("#id_sessao_legislativa").val();
altera_field(legislatura, sessao);
});
$('#id_incluir').click(function(){
$.ajax({
data: {sessao: $("#id_sessao_legislativa").val(),
parlamentar: $("#id_parlamentar").val(),
cargo: $("#id_cargo").val()},
type: 'POST',
url: "{% url 'sapl.parlamentares:insere_parlamentar_composicao' %}",
headers: {
'X-CSRFToken': getCookie('csrftoken')
},
success: function(data){
var msg = data['msg'];
legislatura = $("#id_legislatura").val();
sessao = $("#id_sessao_legislativa").val();
setTimeout(function(data){
// Atualiza os campos após a inserção
altera_field(legislatura, sessao, msg)
}, 500)
},
});
})
$('#id_excluir').click(function(){
// Pega o id do parlamentar que foi selecionado
selecionado = $("#id_composicao_mesa option:selected").val()
if (selecionado){
$.ajax({
data: {composicao_mesa: selecionado},
type: 'POST',
url: "{% url 'sapl.parlamentares:remove_parlamentar_composicao' %}",
headers: {
'X-CSRFToken': getCookie('csrftoken')
},
success: function(data){
var msg = data['msg'];
legislatura = $("#id_legislatura").val();
sessao = $("#id_sessao_legislativa").val();
setTimeout(function(data){
// Atualiza os campos após a remoção
altera_field(legislatura, sessao, msg)
}, 500)
},
});
}
});
</script>
{% endblock %}

2
sapl/templates/sessao/resumo.html

@ -139,6 +139,7 @@
<th>Matéria</th>
<th>Ementa</th>
<th>Resultado da Votação</th>
<th>Observação da Votação</th>
</tr>
</thead>
<tbody>
@ -151,6 +152,7 @@
</td>
<td>{{m.ementa|safe}}</td>
<td>{{m.resultado}}</td>
<td>{{m.resultado_observacao}}</td>
</tr>
{% endfor %}
</tbody>

54
sapl/templates/sessao/votacao/nominal_detail.html

@ -0,0 +1,54 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% block detail_content %}
<form method="post">
{% csrf_token %}
<fieldset>
<legend>Votação Nominal</legend>
<div>
Matéria: {{materia.materia|safe}}
<br />
Ementa: {{materia.ementa|safe}}
</div>
<br />
<fieldset>
<legend>Votos</legend>
<div class="row">
{% for v in votos %}
<div class="col-md-6">{{v.parlamentar}}</div>
<div class="col-md-6">{{v.voto}}</div>
{% endfor %}
</div>
</fieldset>
<br />
<br />
<div class="row">
<div class="col-md-12">
<b>Resultado da Votação: </b>
{% for tipo in tipos %}
{% if votacao.tipo_resultado == tipo.id %}
{{ tipo.nome }}
{% endif %}
{% endfor %}
</div>
</div>
<br />
<div class="row">
<div class="col-md-12">
Observações
<textarea id="observacao" name="observacao" style="width:100%;" rows="7" class="form-control">{{votacao.observacao|safe}}</textarea>
</div>
</div>
</fieldset>
</form>
{% endblock detail_content %}
{% block foot_js %}
<script language="JavaScript">
document.getElementById("observacao").disabled = true;
</script>
{% endblock %}

11
start.sh

@ -1,3 +1,5 @@
#!/bin/sh
create_env() {
echo "[ENV FILE] creating .env file..."
# check if file exists
@ -25,7 +27,7 @@ create_env() {
echo "SECRET_KEY="$KEY > $FILENAME
# now only appends
echo "DATABASE_URL = "$DATABASE_URL >> $FILENAME
echo "DEBUG = ""${DEBUG-False}" >> $FILENAME
echo "DEBUG = ""${DEBUG-True}" >> $FILENAME
echo "EMAIL_USE_TLS = ""${USE_TLS-True}" >> $FILENAME
echo "EMAIL_PORT = ""${EMAIL_PORT-587}" >> $FILENAME
echo "EMAIL_HOST = ""${EMAIL_HOST-''}" >> $FILENAME
@ -37,12 +39,12 @@ create_env() {
create_env
python3 manage.py bower install
#python3 manage.py bower install
/bin/sh busy-wait.sh $DATABASE_URL
python3 manage.py migrate
python3 manage.py collectstatic --no-input
#python3 manage.py collectstatic --no-input
python3 manage.py rebuild_index --noinput &
user_created=$(python3 create_admin.py 2>&1)
@ -63,4 +65,5 @@ if [ $lack_pwd -eq 0 ]; then
fi
/bin/sh gunicorn_start.sh no-venv
/bin/sh gunicorn_start.sh no-venv &
/usr/sbin/nginx -g "daemon off;"

Loading…
Cancel
Save