Browse Source

Fix #2099 - Votação em bloco (#2416)

* votacao em bloco

* votacao em bloco - em andamento

* feita a tela de votacao em bloco

* feita a tela de votacao em bloco

* votacao em bloco- em andamento

* inicio da nova tela da votacao em bloco - em andamento

* inicio da nova tela da votacao em bloco - em andamento

* Tela de votacao em bloco simbolica. Em progresso.

* tela votacao em bloco exibindo as informacoes corretas

* Check all incluso para seleção de ordens desejadas.

* inicio da tela de votacao para votacao em bloco ordem dia

* Alteracoes na votacao em bloco

* adicionado  salvamento da votacao

* correcoes na votacao e no checkbox de marcar todos

* adicionada votacao em bloco nominal no expediente

* inicio da votacao nominal em bloco

* Tela votacao em bloco.

* votacao nominal em bloco

* pequenas mudancas

* inicio da correcao de alguns bugs, como formulario invalido

* correcao de erro quando nao ha presentes

* correcoes de erros

* cancelar votacao simbolica

* correcoes diversas e insercao dos menus

* Menu adicionado

* votacao em bloco

* ajusta menu e lança erro se root_pk ou object estiver faltando no contexto

* ajusta contexto para votação em bloco no expediente
pull/2179/head
Cesar Augusto de Carvalho 6 years ago
committed by Edward
parent
commit
956e0898e2
  1. 58
      sapl/base/templatetags/menus.py
  2. 1
      sapl/materia/models.py
  3. 1
      sapl/relatorios/views.py
  4. 126
      sapl/sessao/forms.py
  5. 18
      sapl/sessao/urls.py
  6. 615
      sapl/sessao/views.py
  7. 503
      sapl/static/styles/app.css
  8. 1136
      sapl/static/styles/compilacao.css
  9. 3
      sapl/templates/auth/user_list.html
  10. 4
      sapl/templates/sessao/subnav.yaml
  11. 76
      sapl/templates/sessao/votacao/nominal.html
  12. 173
      sapl/templates/sessao/votacao/votacao_bloco_expediente.html
  13. 174
      sapl/templates/sessao/votacao/votacao_bloco_ordem.html
  14. 149
      sapl/templates/sessao/votacao/votacao_nominal_bloco.html
  15. 80
      sapl/templates/sessao/votacao/votacao_simbolica_bloco.html

58
sapl/base/templatetags/menus.py

@ -1,3 +1,5 @@
import logging
from django import template from django import template
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -6,6 +8,8 @@ import yaml
register = template.Library() register = template.Library()
logger = logging.getLogger(__name__)
@register.inclusion_tag('menus/menu.html', takes_context=True) @register.inclusion_tag('menus/menu.html', takes_context=True)
def menu(context, path=None): def menu(context, path=None):
@ -84,7 +88,7 @@ def nav_run(context, path=None):
menu = yaml.load(rendered) menu = yaml.load(rendered)
resolve_urls_inplace(menu, root_pk, rm, context) resolve_urls_inplace(menu, root_pk, rm, context)
except Exception as e: except Exception as e:
print(_("""Erro na conversão do yaml %s. App: %s. raise Exception(_("""Erro na conversão do yaml %s. App: %s.
Erro: Erro:
%s %s
""") % ( """) % (
@ -113,25 +117,61 @@ def resolve_urls_inplace(menu, pk, rm, context):
menu['url'] = '' menu['url'] = ''
menu['active'] = '' menu['active'] = ''
else: else:
if ':' in url_name: if '/' in url_name:
pass
elif ':' in url_name:
try: try:
menu['url'] = reverse('%s' % menu['url'], menu['url'] = reverse('%s' % menu['url'])
kwargs={'pk': pk})
except: except:
try: try:
menu['url'] = reverse('%s' % menu['url']) menu['url'] = reverse('%s' % menu['url'],
kwargs={'pk': pk})
except: except:
pass # tem que ser root_pk pois quando está sendo
# renderizado um detail, update, delete
# e ainda sim é necessário colocar o menu,
# nestes, casos o pk da url é do detail, e não
# do master, porém, os menus do subnav, apontam para
# outras áreas que as urls destas são construídas
# com pk do master, e não do detail... por isso
# no contexto deve ter, ou root_pk, ou object
# sendo que qualquer um dos dois,deverá ser o
# master.
# Estes detalhes são relevantes quando usa-se
# o menu isolado. Por outro lado, quando usado
# conjuntamente com o crud, este configura o contexto
# como se deve para o menus.py
log = """
Erro na construção do Menu:
menu: {}
url: {}
1) Verifique se a url existe
2) Se existe no contexto um desses itens:
- context['root_pk'] pk do master
- context['object'] objeto do master
""".format(menu['title'], menu['url'])
logger.error(log)
raise Exception(log)
else: else:
try: try:
menu['url'] = reverse('%s:%s' % ( menu['url'] = reverse('%s:%s' % (
rm.app_name, menu['url']), kwargs={'pk': pk}) rm.app_name, menu['url']))
except: except:
try: try:
menu['url'] = reverse('%s:%s' % ( menu['url'] = reverse('%s:%s' % (
rm.app_name, menu['url'])) rm.app_name, menu['url']), kwargs={'pk': pk})
except: except:
pass log = """Erro na construção do Menu:
menu: {}
url: {}
1) Verifique se a url existe
2) Se existe no contexto um desses itens:
- context['root_pk'] pk do master
- context['object'] objeto do master
""".format(menu['title'], menu['url'])
logger.error(log)
raise Exception(log)
menu['active'] = 'active'\ menu['active'] = 'active'\
if context['request'].path == menu['url'] else '' if context['request'].path == menu['url'] else ''

1
sapl/materia/models.py

@ -16,6 +16,7 @@ from sapl.comissoes.models import Comissao
from sapl.compilacao.models import (PerfilEstruturalTextoArticulado, from sapl.compilacao.models import (PerfilEstruturalTextoArticulado,
TextoArticulado) TextoArticulado)
from sapl.parlamentares.models import Parlamentar from sapl.parlamentares.models import Parlamentar
#from sapl.protocoloadm.models import Protocolo
from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, SaplGenericForeignKey, from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, SaplGenericForeignKey,
SaplGenericRelation, restringe_tipos_de_arquivo_txt, SaplGenericRelation, restringe_tipos_de_arquivo_txt,
texto_upload_path) texto_upload_path)

1
sapl/relatorios/views.py

@ -1111,7 +1111,6 @@ def get_pauta_sessao(sessao, casa):
sessao_plenaria=sessao): sessao_plenaria=sessao):
materia = MateriaLegislativa.objects.filter( materia = MateriaLegislativa.objects.filter(
id=votacao.materia.id).first() id=votacao.materia.id).first()
dic_votacao = {} dic_votacao = {}
dic_votacao["tipo_materia"] = materia.tipo.sigla + ' - ' + materia.tipo.descricao dic_votacao["tipo_materia"] = materia.tipo.sigla + ' - ' + materia.tipo.descricao
dic_votacao["num_ordem"] = votacao.numero_ordem dic_votacao["num_ordem"] = votacao.numero_ordem

126
sapl/sessao/forms.py

@ -1,4 +1,4 @@
from django.contrib import messages
from datetime import datetime from datetime import datetime
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
@ -23,11 +23,10 @@ from sapl.parlamentares.models import Parlamentar, Legislatura, Mandato
from sapl.utils import (RANGE_DIAS_MES, RANGE_MESES, from sapl.utils import (RANGE_DIAS_MES, RANGE_MESES,
MateriaPesquisaOrderingFilter, autor_label, MateriaPesquisaOrderingFilter, autor_label,
autor_modal, timezone) autor_modal, timezone)
from .models import (Bancada, Bloco, ExpedienteMateria, Orador, JustificativaAusencia, from .models import (Bancada, Bloco, ExpedienteMateria, JustificativaAusencia,
OradorExpediente, OrdemDia, PresencaOrdemDia, SessaoPlenaria, Orador, OradorExpediente, OrdemDia, PresencaOrdemDia, SessaoPlenaria,
SessaoPlenariaPresenca, TipoResultadoVotacao, OcorrenciaSessao, SessaoPlenariaPresenca, TipoJustificativa, TipoResultadoVotacao,
RetiradaPauta, TipoRetiradaPauta) OcorrenciaSessao, RegistroVotacao, RetiradaPauta, TipoRetiradaPauta)
def recupera_anos(): def recupera_anos():
@ -520,12 +519,43 @@ class OcorrenciaSessaoForm(ModelForm):
class VotacaoForm(forms.Form): class VotacaoForm(forms.Form):
votos_sim = forms.CharField(label='Sim') votos_sim = forms.IntegerField(label='Sim')
votos_nao = forms.CharField(label='Não') votos_nao = forms.IntegerField(label='Não')
abstencoes = forms.CharField(label='Abstenções') abstencoes = forms.IntegerField(label='Abstenções')
total_votos = forms.CharField(required=False, label='total') total_presentes = forms.IntegerField(required=False, widget=forms.HiddenInput())
voto_presidente = forms.IntegerField(label='A totalização inclui o voto do Presidente?')
total_votos = forms.IntegerField(required=False, label='total')
observacao = forms.CharField(required=False , label='Observação')
resultado_votacao = forms.CharField(label='Resultado da Votação') resultado_votacao = forms.CharField(label='Resultado da Votação')
def clean(self):
cleaned_data = super(VotacaoForm, self).clean()
if not self.is_valid():
return cleaned_data
votos_sim = cleaned_data['votos_sim']
votos_nao = cleaned_data['votos_nao']
abstencoes = cleaned_data['abstencoes']
qtde_presentes = cleaned_data['total_presentes']
qtde_votos = votos_sim + votos_nao + abstencoes
voto_presidente = cleaned_data['voto_presidente']
if not voto_presidente:
qtde_presentes -= 1
if qtde_votos != qtde_presentes:
raise ValidationError('O total de votos não corresponde com a quantidade de presentes!')
return cleaned_data
# def save(self, commit=False):
# #TODO Verificar se esse códido é utilizado
# votacao = super(VotacaoForm, self).save(commit)
# votacao.materia = self.cleaned_data['materia']
# votacao.save()
# return votacao
class VotacaoNominalForm(forms.Form): class VotacaoNominalForm(forms.Form):
resultado_votacao = forms.ModelChoiceField(label='Resultado da Votação', resultado_votacao = forms.ModelChoiceField(label='Resultado da Votação',
@ -891,3 +921,79 @@ class JustificativaAusenciaForm(ModelForm):
justificativa.materias_do_expediente.clear() justificativa.materias_do_expediente.clear()
justificativa.materias_da_ordem_do_dia.clear() justificativa.materias_da_ordem_do_dia.clear()
return justificativa return justificativa
class VotacaoEmBlocoFilterSet(MateriaLegislativaFilterSet):
o = MateriaPesquisaOrderingFilter()
tramitacao__status = django_filters.ModelChoiceFilter(
required=True,
queryset=StatusTramitacao.objects.all(),
label=_('Status da Matéria'))
class Meta:
model = MateriaLegislativa
fields = ['tramitacao__status',
'numero',
'numero_protocolo',
'ano',
'tipo',
'data_apresentacao',
'data_publicacao',
'autoria__autor__tipo',
# FIXME 'autoria__autor__partido',
'relatoria__parlamentar_id',
'local_origem_externa',
'em_tramitacao',
]
def __init__(self, *args, **kwargs):
super(MateriaLegislativaFilterSet, self).__init__(*args, **kwargs)
self.filters['tipo'].label = 'Tipo de Matéria'
self.filters['autoria__autor__tipo'].label = 'Tipo de Autor'
# self.filters['autoria__autor__partido'].label = 'Partido do Autor'
self.filters['relatoria__parlamentar_id'].label = 'Relatoria'
row1 = to_row(
[('tramitacao__status', 12)])
row2 = to_row(
[('tipo', 12)])
row3 = to_row(
[('numero', 4),
('ano', 4),
('numero_protocolo', 4)])
row4 = to_row(
[('data_apresentacao', 6),
('data_publicacao', 6)])
row5 = to_row(
[('autoria__autor', 0),
(Button('pesquisar',
'Pesquisar Autor',
css_class='btn btn-primary btn-sm'), 2),
(Button('limpar',
'limpar Autor',
css_class='btn btn-primary btn-sm'), 10)])
row6 = to_row(
[('autoria__autor__tipo', 6),
# ('autoria__autor__partido', 6)
])
row7 = to_row(
[('relatoria__parlamentar_id', 6),
('local_origem_externa', 6)])
row8 = to_row(
[('em_tramitacao', 6),
('o', 6)])
row9 = to_row(
[('ementa', 12)])
self.form.helper = FormHelper()
self.form.helper.form_method = 'GET'
self.form.helper.layout = Layout(
Fieldset(_('Pesquisa de Matéria'),
row1, row2, row3,
HTML(autor_label),
HTML(autor_modal),
row4, row5, row6, row7, row8, row9,
form_actions(label='Pesquisar'))
)

18
sapl/sessao/urls.py

@ -28,7 +28,9 @@ from sapl.sessao.views import (AdicionarVariasMateriasExpediente,
remove_parlamentar_composicao, remove_parlamentar_composicao,
reordernar_materias_expediente, reordernar_materias_expediente,
reordernar_materias_ordem, reordernar_materias_ordem,
sessao_legislativa_legislatura_ajax) sessao_legislativa_legislatura_ajax,
VotacaoEmBlocoOrdemDia, VotacaoEmBlocoExpediente,
VotacaoEmBlocoSimbolicaView,VotacaoEmBlocoNominalView)
from .apps import AppConfig from .apps import AppConfig
@ -115,6 +117,16 @@ urlpatterns = [
url(r'^sessao/(?P<pk>\d+)/presencaordemdia$', url(r'^sessao/(?P<pk>\d+)/presencaordemdia$',
PresencaOrdemDiaView.as_view(), PresencaOrdemDiaView.as_view(),
name='presencaordemdia'), name='presencaordemdia'),
url(r'^sessao/(?P<pk>\d+)/votacao_bloco_ordemdia$',
VotacaoEmBlocoOrdemDia.as_view(),
name='votacao_bloco_ordemdia'),
url(r'^sessao/(?P<pk>\d+)/votacao_bloco/votnom$',
VotacaoEmBlocoNominalView.as_view(), name='votacaobloconom'),
url(r'^sessao/(?P<pk>\d+)/votacao_bloco/votsimb$',
VotacaoEmBlocoSimbolicaView.as_view(), name='votacaoblocosimb'),
url(r'^sessao/(?P<pk>\d+)/votacao_bloco_expediente$',
VotacaoEmBlocoExpediente.as_view(),
name='votacao_bloco_expediente'),
url(r'^sessao/(?P<pk>\d+)/resumo$', url(r'^sessao/(?P<pk>\d+)/resumo$',
ResumoView.as_view(), name='resumo'), ResumoView.as_view(), name='resumo'),
url(r'^sessao/(?P<pk>\d+)/resumo_ata$', url(r'^sessao/(?P<pk>\d+)/resumo_ata$',
@ -133,6 +145,10 @@ urlpatterns = [
VotacaoEditView.as_view(), name='votacaosecretaedit'), VotacaoEditView.as_view(), name='votacaosecretaedit'),
url(r'^sessao/(?P<pk>\d+)/matordemdia/votsimb/(?P<oid>\d+)/(?P<mid>\d+)$', url(r'^sessao/(?P<pk>\d+)/matordemdia/votsimb/(?P<oid>\d+)/(?P<mid>\d+)$',
VotacaoView.as_view(), name='votacaosimbolica'), VotacaoView.as_view(), name='votacaosimbolica'),
url(r'^sessao/(?P<pk>\d+)/matordemdia/votsimbbloco/$',
VotacaoView.as_view(), name='votacaosimbolicabloco'),
url(r'^sessao/(?P<pk>\d+)/matordemdia/votsimb' url(r'^sessao/(?P<pk>\d+)/matordemdia/votsimb'
'/view/(?P<oid>\d+)/(?P<mid>\d+)$', '/view/(?P<oid>\d+)/(?P<mid>\d+)$',
VotacaoEditView.as_view(), name='votacaosimbolicaedit'), VotacaoEditView.as_view(), name='votacaosimbolicaedit'),

615
sapl/sessao/views.py

@ -1,6 +1,6 @@
from operator import itemgetter
import logging import logging
from operator import itemgetter
from re import sub from re import sub
from django.contrib import messages from django.contrib import messages
@ -57,7 +57,8 @@ TipoSessaoCrud = CrudAux.build(TipoSessaoPlenaria, 'tipo_sessao_plenaria')
TipoExpedienteCrud = CrudAux.build(TipoExpediente, 'tipo_expediente') TipoExpedienteCrud = CrudAux.build(TipoExpediente, 'tipo_expediente')
TipoJustificativaCrud = CrudAux.build(TipoJustificativa, 'tipo_justificativa') TipoJustificativaCrud = CrudAux.build(TipoJustificativa, 'tipo_justificativa')
CargoBancadaCrud = CrudAux.build(CargoBancada, '') CargoBancadaCrud = CrudAux.build(CargoBancada, '')
TipoResultadoVotacaoCrud = CrudAux.build(TipoResultadoVotacao, 'tipo_resultado_votacao') TipoResultadoVotacaoCrud = CrudAux.build(
TipoResultadoVotacao, 'tipo_resultado_votacao')
TipoRetiradaPautaCrud = CrudAux.build(TipoRetiradaPauta, 'tipo_retirada_pauta') TipoRetiradaPautaCrud = CrudAux.build(TipoRetiradaPauta, 'tipo_retirada_pauta')
@ -87,7 +88,8 @@ def verifica_presenca(request, model, spk):
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
if not model.objects.filter(sessao_plenaria_id=spk).exists(): if not model.objects.filter(sessao_plenaria_id=spk).exists():
username = request.user.username username = request.user.username
logger.error("user=" + username + ". Votação não pode ser aberta sem presenças (sessao_plenaria_id={}).".format(spk)) logger.error("user=" + username +
". Votação não pode ser aberta sem presenças (sessao_plenaria_id={}).".format(spk))
msg = _('Votação não pode ser aberta sem presenças') msg = _('Votação não pode ser aberta sem presenças')
messages.add_message(request, messages.ERROR, msg) messages.add_message(request, messages.ERROR, msg)
return False return False
@ -301,7 +303,7 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
retirada_descricao = retirada.tipo_de_retirada.descricao retirada_descricao = retirada.tipo_de_retirada.descricao
retirada_observacao = retirada.observacao retirada_observacao = retirada.observacao
url = reverse('sapl.sessao:retiradapauta_detail', url = reverse('sapl.sessao:retiradapauta_detail',
kwargs={'pk': retirada.id}) kwargs={'pk': retirada.id})
resultado = ('<a href="%s">%s<br/>%s</a>' % resultado = ('<a href="%s">%s<br/>%s</a>' %
(url, (url,
retirada_descricao, retirada_descricao,
@ -798,7 +800,8 @@ class PresencaView(FormMixin, PresencaMixin, DetailView):
sessao.parlamentar = Parlamentar.objects.get(id=p) sessao.parlamentar = Parlamentar.objects.get(id=p)
sessao.save() sessao.save()
username = request.user.username username = request.user.username
self.logger.info("user=" + username + ". SessaoPlenariaPresenca salva com sucesso (parlamentar_id={})!".format(p)) self.logger.info(
"user=" + username + ". SessaoPlenariaPresenca salva com sucesso (parlamentar_id={})!".format(p))
msg = _('Presença em Sessão salva com sucesso!') msg = _('Presença em Sessão salva com sucesso!')
messages.add_message(request, messages.SUCCESS, msg) messages.add_message(request, messages.SUCCESS, msg)
@ -850,7 +853,7 @@ class PainelView(PermissionRequiredForAppCrudMixin, TemplateView):
cronometro_aparte = cronometro_aparte.seconds cronometro_aparte = cronometro_aparte.seconds
cronometro_ordem = cronometro_ordem.seconds cronometro_ordem = cronometro_ordem.seconds
cronometro_consideracoes = cronometro_consideracoes.seconds cronometro_consideracoes = cronometro_consideracoes.seconds
context = TemplateView.get_context_data(self, **kwargs) context = TemplateView.get_context_data(self, **kwargs)
context.update({ context.update({
'head_title': str(_('Painel Plenário')), 'head_title': str(_('Painel Plenário')),
@ -904,9 +907,10 @@ class PresencaOrdemDiaView(FormMixin, PresencaMixin, DetailView):
ordem.sessao_plenaria = self.object ordem.sessao_plenaria = self.object
ordem.parlamentar = Parlamentar.objects.get(id=p) ordem.parlamentar = Parlamentar.objects.get(id=p)
ordem.save() ordem.save()
username = request.user.username
self.logger.info(
'user=' + username + '. PresencaOrdemDia (parlamentar com id={}) salva com sucesso!'.format(p))
username = request.user.username
self.logger.info('user=' + username + '. PresencaOrdemDia (parlamentar com id={}) salva com sucesso!'.format(p))
msg = _('Presença em Ordem do Dia salva com sucesso!') msg = _('Presença em Ordem do Dia salva com sucesso!')
messages.add_message(request, messages.SUCCESS, msg) messages.add_message(request, messages.SUCCESS, msg)
@ -1041,11 +1045,13 @@ class MesaView(FormMixin, DetailView):
username = request.user.username username = request.user.username
try: try:
self.logger.debug("user=" + username + ". Tentando obter SessaoPlenaria com id={}".format(kwargs['pk'])) self.logger.debug(
"user=" + username + ". Tentando obter SessaoPlenaria com id={}".format(kwargs['pk']))
sessao = SessaoPlenaria.objects.get( sessao = SessaoPlenaria.objects.get(
id=kwargs['pk']) id=kwargs['pk'])
except ObjectDoesNotExist: except ObjectDoesNotExist:
self.logger.error("user=" + username + ". SessaoPlenaria com id={} não existe.".format(kwargs['pk'])) self.logger.error(
"user=" + username + ". SessaoPlenaria com id={} não existe.".format(kwargs['pk']))
mensagem = _('Esta Sessão Plenária não existe!') mensagem = _('Esta Sessão Plenária não existe!')
messages.add_message(request, messages.INFO, mensagem) messages.add_message(request, messages.INFO, mensagem)
@ -1100,11 +1106,13 @@ def atualizar_mesa(request):
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
username = request.user.username username = request.user.username
try: try:
logger.debug("user=" + username + ". Tentando obter SessaoPlenaria com id={}.".format(request.GET['sessao'])) logger.debug("user=" + username +
". Tentando obter SessaoPlenaria com id={}.".format(request.GET['sessao']))
sessao = SessaoPlenaria.objects.get( sessao = SessaoPlenaria.objects.get(
id=int(request.GET['sessao'])) id=int(request.GET['sessao']))
except ObjectDoesNotExist: except ObjectDoesNotExist:
logger.error("user=" + username + ". SessaoPlenaria com id={} inexistente.".format(request.GET['sessao'])) logger.error("user=" + username +
". SessaoPlenaria com id={} inexistente.".format(request.GET['sessao']))
return JsonResponse({'msg': ('Sessão Inexistente!', 0)}) return JsonResponse({'msg': ('Sessão Inexistente!', 0)})
# Atualiza os componentes da view após a mudança # Atualiza os componentes da view após a mudança
@ -1152,19 +1160,23 @@ def insere_parlamentar_composicao(request):
composicao = IntegranteMesa() composicao = IntegranteMesa()
try: try:
logger.debug("user=" + username + ". Tentando obter SessaoPlenaria com id={}.".format(request.POST['sessao'])) logger.debug(
"user=" + username + ". Tentando obter SessaoPlenaria com id={}.".format(request.POST['sessao']))
composicao.sessao_plenaria = SessaoPlenaria.objects.get( composicao.sessao_plenaria = SessaoPlenaria.objects.get(
id=int(request.POST['sessao'])) id=int(request.POST['sessao']))
except MultiValueDictKeyError: except MultiValueDictKeyError:
logger.error("user=" + username + ". SessaoPlenaria com id={} não existe.".format(request.POST['sessao'])) logger.error(
"user=" + username + ". SessaoPlenaria com id={} não existe.".format(request.POST['sessao']))
return JsonResponse({'msg': ('A Sessão informada não existe!', 0)}) return JsonResponse({'msg': ('A Sessão informada não existe!', 0)})
try: try:
logger.debug("user=" + username + ". Tentando obter Parlamentar com id={}.".format(request.POST['parlamentar'])) logger.debug(
"user=" + username + ". Tentando obter Parlamentar com id={}.".format(request.POST['parlamentar']))
composicao.parlamentar = Parlamentar.objects.get( composicao.parlamentar = Parlamentar.objects.get(
id=int(request.POST['parlamentar'])) id=int(request.POST['parlamentar']))
except MultiValueDictKeyError: except MultiValueDictKeyError:
logger.error("user=" + username + ". Parlamentar com id={} não existe.".format(request.POST['parlamentar'])) logger.error(
"user=" + username + ". Parlamentar com id={} não existe.".format(request.POST['parlamentar']))
return JsonResponse({ return JsonResponse({
'msg': ('Nenhum parlamentar foi inserido!', 0)}) 'msg': ('Nenhum parlamentar foi inserido!', 0)})
@ -1183,10 +1195,12 @@ def insere_parlamentar_composicao(request):
composicao.save() composicao.save()
except MultiValueDictKeyError as e: except MultiValueDictKeyError as e:
logger.error("user=" + username + ". Nenhum cargo foi inserido! " + str(e)) logger.error("user=" + username +
". Nenhum cargo foi inserido! " + str(e))
return JsonResponse({'msg': ('Nenhum cargo foi inserido!', 0)}) return JsonResponse({'msg': ('Nenhum cargo foi inserido!', 0)})
logger.info("user=" + username + ". Parlamentar (id={}) inserido com sucesso na sessao_plenaria(id={}) e cargo(ìd={}).") logger.info("user=" + username +
". Parlamentar (id={}) inserido com sucesso na sessao_plenaria(id={}) e cargo(ìd={}).")
return JsonResponse({'msg': ('Parlamentar inserido com sucesso!', 1)}) return JsonResponse({'msg': ('Parlamentar inserido com sucesso!', 1)})
else: else:
@ -1207,7 +1221,8 @@ def remove_parlamentar_composicao(request):
if 'composicao_mesa' in request.POST: if 'composicao_mesa' in request.POST:
try: try:
logger.debug("user=" + username + ". Tentando remover IntegranteMesa com id={}".format(request.POST['composicao_mesa'])) logger.debug("user=" + username + ". Tentando remover IntegranteMesa com id={}".format(
request.POST['composicao_mesa']))
IntegranteMesa.objects.get( IntegranteMesa.objects.get(
id=int(request.POST['composicao_mesa'])).delete() id=int(request.POST['composicao_mesa'])).delete()
except ObjectDoesNotExist: except ObjectDoesNotExist:
@ -1217,12 +1232,14 @@ def remove_parlamentar_composicao(request):
{'msg': ( {'msg': (
'Composição da Mesa não pôde ser removida!', 0)}) 'Composição da Mesa não pôde ser removida!', 0)})
logger.info("user=" + username + ". IntegranteMesa com id={} removido com sucesso.") logger.info("user=" + username +
". IntegranteMesa com id={} removido com sucesso.")
return JsonResponse( return JsonResponse(
{'msg': ( {'msg': (
'Parlamentar excluido com sucesso!', 1)}) 'Parlamentar excluido com sucesso!', 1)})
else: else:
logger.debug("user=" + username + ". Nenhum parlamentar selecionado para ser excluido!") logger.debug("user=" + username +
". Nenhum parlamentar selecionado para ser excluido!")
return JsonResponse( return JsonResponse(
{'msg': ( {'msg': (
'Selecione algum parlamentar para ser excluido!', 0)}) 'Selecione algum parlamentar para ser excluido!', 0)})
@ -1349,7 +1366,6 @@ class ResumoView(DetailView):
context.update({'presenca_sessao': parlamentares_sessao, context.update({'presenca_sessao': parlamentares_sessao,
'justificativa_ausencia': ausentes_sessao}) 'justificativa_ausencia': ausentes_sessao})
# ===================================================================== # =====================================================================
# Expedientes # Expedientes
expediente = ExpedienteSessao.objects.filter( expediente = ExpedienteSessao.objects.filter(
@ -1450,13 +1466,16 @@ class ResumoView(DetailView):
config_assinatura_ata = AppsAppConfig.objects.first().assinatura_ata config_assinatura_ata = AppsAppConfig.objects.first().assinatura_ata
if config_assinatura_ata == 'T' and parlamentares_ordem: if config_assinatura_ata == 'T' and parlamentares_ordem:
context.update({'texto_assinatura': 'Assinatura de Todos os Parlamentares Presentes na Sessão'}) context.update(
{'texto_assinatura': 'Assinatura de Todos os Parlamentares Presentes na Sessão'})
context.update({'assinatura_presentes': parlamentares_ordem}) context.update({'assinatura_presentes': parlamentares_ordem})
elif config_assinatura_ata == 'M' and parlamentares_mesa_dia: elif config_assinatura_ata == 'M' and parlamentares_mesa_dia:
context.update({'texto_assinatura': 'Assinatura da Mesa Diretora da Sessão'}) context.update(
{'texto_assinatura': 'Assinatura da Mesa Diretora da Sessão'})
context.update({'assinatura_presentes': parlamentares_mesa_dia}) context.update({'assinatura_presentes': parlamentares_mesa_dia})
elif config_assinatura_ata == 'P' and presidente_dia: elif config_assinatura_ata == 'P' and presidente_dia:
context.update({'texto_assinatura': 'Assinatura do Presidente da Sessão'}) context.update(
{'texto_assinatura': 'Assinatura do Presidente da Sessão'})
context.update({'assinatura_presentes': presidente_dia}) context.update({'assinatura_presentes': presidente_dia})
# ===================================================================== # =====================================================================
@ -1609,7 +1628,8 @@ class ExpedienteView(FormMixin, DetailView):
if 'apagar-expediente' in request.POST: if 'apagar-expediente' in request.POST:
ExpedienteSessao.objects.filter( ExpedienteSessao.objects.filter(
sessao_plenaria_id=self.object.id).delete() sessao_plenaria_id=self.object.id).delete()
self.logger.info('user=' + username + '. ExpedienteSessao de sessao_plenaria_id={} deletado.'.format(self.object.id)) self.logger.info(
'user=' + username + '. ExpedienteSessao de sessao_plenaria_id={} deletado.'.format(self.object.id))
return self.form_valid(form) return self.form_valid(form)
if form.is_valid(): if form.is_valid():
@ -1635,7 +1655,8 @@ class ExpedienteView(FormMixin, DetailView):
return self.form_valid(form) return self.form_valid(form)
else: else:
self.logger.error("user=" + username + ". Erro ao salvar registro (sessao_plenaria_id={}).".format(self.object.id)) self.logger.error(
"user=" + username + ". Erro ao salvar registro (sessao_plenaria_id={}).".format(self.object.id))
msg = _('Erro ao salvar ExpedienteSessao') msg = _('Erro ao salvar ExpedienteSessao')
messages.add_message(self.request, messages.SUCCESS, msg) messages.add_message(self.request, messages.SUCCESS, msg)
return self.form_invalid(form) return self.form_invalid(form)
@ -1705,7 +1726,8 @@ class OcorrenciaSessaoView(FormMixin, DetailView):
messages.add_message(self.request, messages.SUCCESS, msg) messages.add_message(self.request, messages.SUCCESS, msg)
username = self.request.user.username username = self.request.user.username
self.logger.info('user=' + username + '. OcorrenciaSessao de sessao_plenaria_id={} atualizada com sucesso.'.format(self.object.id)) self.logger.info(
'user=' + username + '. OcorrenciaSessao de sessao_plenaria_id={} atualizada com sucesso.'.format(self.object.id))
@method_decorator(permission_required('sessao.add_ocorrenciasessao')) @method_decorator(permission_required('sessao.add_ocorrenciasessao'))
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
@ -1954,14 +1976,16 @@ class VotacaoNominalAbstract(SessaoPermissionMixin):
if RegistroVotacao.objects.filter(ordem_id=ordem_id).exists(): if RegistroVotacao.objects.filter(ordem_id=ordem_id).exists():
msg = _('Esta matéria já foi votada!') msg = _('Esta matéria já foi votada!')
messages.add_message(request, messages.ERROR, msg) messages.add_message(request, messages.ERROR, msg)
self.logger.info('user=' + username + '. Matéria (ordem_id={}) já votada!'.format(ordem_id)) self.logger.info(
'user=' + username + '. Matéria (ordem_id={}) já votada!'.format(ordem_id))
return HttpResponseRedirect(reverse( return HttpResponseRedirect(reverse(
'sapl.sessao:ordemdia_list', kwargs={'pk': kwargs['pk']})) 'sapl.sessao:ordemdia_list', kwargs={'pk': kwargs['pk']}))
try: try:
ordem = OrdemDia.objects.get(id=ordem_id) ordem = OrdemDia.objects.get(id=ordem_id)
except ObjectDoesNotExist: except ObjectDoesNotExist:
self.logger.error('user=' + username + '. Objeto OrdemDia (pk={}) não existe.'.format(ordem_id)) self.logger.error(
'user=' + username + '. Objeto OrdemDia (pk={}) não existe.'.format(ordem_id))
raise Http404() raise Http404()
presentes = PresencaOrdemDia.objects.filter( presentes = PresencaOrdemDia.objects.filter(
@ -1971,7 +1995,8 @@ class VotacaoNominalAbstract(SessaoPermissionMixin):
materia_votacao = ordem materia_votacao = ordem
if not ordem.votacao_aberta: if not ordem.votacao_aberta:
self.logger.error('user=' + username + '. A votação para esta OrdemDia (id={}) encontra-se fechada!'.format(ordem_id)) self.logger.error(
'user=' + username + '. A votação para esta OrdemDia (id={}) encontra-se fechada!'.format(ordem_id))
msg = _('A votação para esta matéria encontra-se fechada!') msg = _('A votação para esta matéria encontra-se fechada!')
messages.add_message(request, messages.ERROR, msg) messages.add_message(request, messages.ERROR, msg)
return HttpResponseRedirect(reverse( return HttpResponseRedirect(reverse(
@ -1984,7 +2009,8 @@ class VotacaoNominalAbstract(SessaoPermissionMixin):
expediente_id = kwargs['oid'] expediente_id = kwargs['oid']
if (RegistroVotacao.objects.filter( if (RegistroVotacao.objects.filter(
expediente_id=expediente_id).exists()): expediente_id=expediente_id).exists()):
self.logger.error("user=" + username + ". RegistroVotacao (expediente_id={}) já existe.".format(expediente_id)) self.logger.error(
"user=" + username + ". RegistroVotacao (expediente_id={}) já existe.".format(expediente_id))
msg = _('Esta matéria já foi votada!') msg = _('Esta matéria já foi votada!')
messages.add_message(request, messages.ERROR, msg) messages.add_message(request, messages.ERROR, msg)
return HttpResponseRedirect(reverse( return HttpResponseRedirect(reverse(
@ -1992,10 +2018,12 @@ class VotacaoNominalAbstract(SessaoPermissionMixin):
kwargs={'pk': kwargs['pk']})) kwargs={'pk': kwargs['pk']}))
try: try:
self.logger.debug("user=" + username + ". Tentando obter Objeto ExpedienteMateria com id={}.".format(expediente_id)) self.logger.debug(
"user=" + username + ". Tentando obter Objeto ExpedienteMateria com id={}.".format(expediente_id))
expediente = ExpedienteMateria.objects.get(id=expediente_id) expediente = ExpedienteMateria.objects.get(id=expediente_id)
except ObjectDoesNotExist: except ObjectDoesNotExist:
self.logger.error('user=' + username + '. Objeto ExpedienteMateria com id={} não existe.'.format(expediente_id)) self.logger.error(
'user=' + username + '. Objeto ExpedienteMateria com id={} não existe.'.format(expediente_id))
raise Http404() raise Http404()
presentes = SessaoPlenariaPresenca.objects.filter( presentes = SessaoPlenariaPresenca.objects.filter(
@ -2005,7 +2033,8 @@ class VotacaoNominalAbstract(SessaoPermissionMixin):
materia_votacao = expediente materia_votacao = expediente
if not expediente.votacao_aberta: if not expediente.votacao_aberta:
msg = _('A votação para este ExpedienteMateria (id={}) encontra-se fechada!'.format(expediente_id)) msg = _(
'A votação para este ExpedienteMateria (id={}) encontra-se fechada!'.format(expediente_id))
messages.add_message(request, messages.ERROR, msg) messages.add_message(request, messages.ERROR, msg)
return HttpResponseRedirect(reverse( return HttpResponseRedirect(reverse(
'sapl.sessao:expedientemateria_list', 'sapl.sessao:expedientemateria_list',
@ -2033,19 +2062,23 @@ class VotacaoNominalAbstract(SessaoPermissionMixin):
if self.ordem: if self.ordem:
ordem_id = kwargs['oid'] ordem_id = kwargs['oid']
try: try:
self.logger.debug("user=" + username + ". Tentando obter objeto OrdemDia com id={}.".format(ordem_id)) self.logger.debug(
"user=" + username + ". Tentando obter objeto OrdemDia com id={}.".format(ordem_id))
materia_votacao = OrdemDia.objects.get(id=ordem_id) materia_votacao = OrdemDia.objects.get(id=ordem_id)
except ObjectDoesNotExist: except ObjectDoesNotExist:
self.logger.error('user=' + username + '. Objeto OrdemDia com id={} não existe.'.format(ordem_id)) self.logger.error(
'user=' + username + '. Objeto OrdemDia com id={} não existe.'.format(ordem_id))
raise Http404() raise Http404()
elif self.expediente: elif self.expediente:
expediente_id = kwargs['oid'] expediente_id = kwargs['oid']
try: try:
self.logger.debug("user=" + username + ". Tentando obter ExpedienteMateria com id={}.".format(expediente_id)) self.logger.debug(
"user=" + username + ". Tentando obter ExpedienteMateria com id={}.".format(expediente_id))
materia_votacao = ExpedienteMateria.objects.get( materia_votacao = ExpedienteMateria.objects.get(
id=expediente_id) id=expediente_id)
except ObjectDoesNotExist: except ObjectDoesNotExist:
self.logger.error('user=' + username + '. Objeto ExpedienteMateria com id={} não existe.'.format(expediente_id)) self.logger.error(
'user=' + username + '. Objeto ExpedienteMateria com id={} não existe.'.format(expediente_id))
raise Http404() raise Http404()
if form.is_valid(): if form.is_valid():
@ -2231,7 +2264,8 @@ class VotacaoNominalEditAbstract(SessaoPermissionMixin):
votacao = RegistroVotacao.objects.filter(ordem_id=ordem_id).last() votacao = RegistroVotacao.objects.filter(ordem_id=ordem_id).last()
if not ordem or not votacao: if not ordem or not votacao:
self.logger.error('user=' + username + '. Objeto OrdemDia com id={} ou RegistroVotacao de OrdemDia não existe.'.format(ordem_id)) self.logger.error(
'user=' + username + '. Objeto OrdemDia com id={} ou RegistroVotacao de OrdemDia não existe.'.format(ordem_id))
raise Http404() raise Http404()
materia = ordem.materia materia = ordem.materia
@ -2304,7 +2338,8 @@ class VotacaoNominalEditAbstract(SessaoPermissionMixin):
try: try:
materia_votacao = OrdemDia.objects.get(id=ordem_id) materia_votacao = OrdemDia.objects.get(id=ordem_id)
except ObjectDoesNotExist: except ObjectDoesNotExist:
self.logger.error('user=' + username + '. Objeto OrdemDia com id={} não existe.'.format(ordem_id)) self.logger.error(
'user=' + username + '. Objeto OrdemDia com id={} não existe.'.format(ordem_id))
raise Http404() raise Http404()
elif self.expediente: elif self.expediente:
@ -2314,7 +2349,8 @@ class VotacaoNominalEditAbstract(SessaoPermissionMixin):
materia_votacao = ExpedienteMateria.objects.get( materia_votacao = ExpedienteMateria.objects.get(
id=expediente_id) id=expediente_id)
except ObjectDoesNotExist: except ObjectDoesNotExist:
self.logger.error('user=' + username + '. Objeto ExpedienteMateria com id={} não existe.'.format(expediente_id)) self.logger.error(
'user=' + username + '. Objeto ExpedienteMateria com id={} não existe.'.format(expediente_id))
raise Http404() raise Http404()
if(int(request.POST['anular_votacao']) == 1): if(int(request.POST['anular_votacao']) == 1):
@ -2993,7 +3029,8 @@ class AdicionarVariasMateriasExpediente(PermissionRequiredForAppCrudMixin,
msg = _('%s adicionado(a) com sucesso!' msg = _('%s adicionado(a) com sucesso!'
% MateriaLegislativa.objects.get(id=m)) % MateriaLegislativa.objects.get(id=m))
messages.add_message(request, messages.SUCCESS, msg) messages.add_message(request, messages.SUCCESS, msg)
self.logger.info("user=" + username + ". MateriaLegislativa de id={} adicionado(a) com sucesso!".format(m)) self.logger.info(
"user=" + username + ". MateriaLegislativa de id={} adicionado(a) com sucesso!".format(m))
except MultiValueDictKeyError: except MultiValueDictKeyError:
msg = _('Formulário Inválido. Você esqueceu de selecionar ' + msg = _('Formulário Inválido. Você esqueceu de selecionar ' +
'%s' % '%s' %
@ -3068,7 +3105,8 @@ class AdicionarVariasMateriasOrdemDia(AdicionarVariasMateriasExpediente):
msg = _('%s adicionado(a) com sucesso!' msg = _('%s adicionado(a) com sucesso!'
% MateriaLegislativa.objects.get(id=m)) % MateriaLegislativa.objects.get(id=m))
messages.add_message(request, messages.SUCCESS, msg) messages.add_message(request, messages.SUCCESS, msg)
self.logger.debug('user=' + username + '. MateriaLegislativa de id={} adicionado(a) com sucesso!'.format(m)) self.logger.debug(
'user=' + username + '. MateriaLegislativa de id={} adicionado(a) com sucesso!'.format(m))
except MultiValueDictKeyError: except MultiValueDictKeyError:
msg = _('Formulário Inválido. Você esqueceu de selecionar ' + msg = _('Formulário Inválido. Você esqueceu de selecionar ' +
'o tipo de votação de %s' % 'o tipo de votação de %s' %
@ -3129,7 +3167,8 @@ def mudar_ordem_materia_sessao(request):
numero_ordem=posicao_inicial) numero_ordem=posicao_inicial)
except ObjectDoesNotExist: except ObjectDoesNotExist:
username = request.user.username username = request.user.username
logger.error("user=" + username + ". Materia com sessao_plenaria={} e numero_ordem={}.".format(pk_sessao, posicao_inicial)) logger.error("user=" + username +
". Materia com sessao_plenaria={} e numero_ordem={}.".format(pk_sessao, posicao_inicial))
raise # TODO tratar essa exceção raise # TODO tratar essa exceção
# Se a posição inicial for menor que a final, todos que # Se a posição inicial for menor que a final, todos que
@ -3241,13 +3280,494 @@ class JustificativaAusenciaCrud(MasterDetailCrud):
pass pass
class VotacaoEmBlocoExpediente(ListView):
model = ExpedienteMateria
template_name = 'sessao/votacao/votacao_bloco_expediente.html'
app_label = AppConfig.label
context_object_name = 'expedientes'
logger = logging.getLogger(__name__)
def get_queryset(self):
kwargs = self.kwargs
return ExpedienteMateria.objects.filter(sessao_plenaria_id=kwargs['pk'],
resultado='')
def get_context_data(self, **kwargs):
context = super(VotacaoEmBlocoExpediente,
self).get_context_data(**kwargs)
context['turno_choices'] = Tramitacao.TURNO_CHOICES
context['title'] = SessaoPlenaria.objects.get(id=self.kwargs['pk'])
context['pk'] = self.kwargs['pk']
context['root_pk'] = self.kwargs['pk']
return context
class VotacaoEmBlocoOrdemDia(ListView):
model = OrdemDia
template_name = 'sessao/votacao/votacao_bloco_ordem.html'
app_label = AppConfig.label
logger = logging.getLogger(__name__)
context_object_name = 'ordem_dia'
parent_field = 'sessao_plenaria'
def get_queryset(self):
return OrdemDia.objects.filter(sessao_plenaria_id=self.kwargs['pk'],
resultado='')
def get_context_data(self, **kwargs):
context = super(VotacaoEmBlocoOrdemDia,
self).get_context_data(**kwargs)
context['turno_choices'] = Tramitacao.TURNO_CHOICES
context['pk'] = self.kwargs['pk']
context['root_pk'] = self.kwargs['pk']
context['title'] = SessaoPlenaria.objects.get(id=self.kwargs['pk'])
return context
class VotacaoEmBlocoSimbolicaView(TemplateView):
"""
Votação Simbólica
"""
template_name = 'sessao/votacao/votacao_simbolica_bloco.html'
logger = logging.getLogger(__name__)
def post(self, request, *args, **kwargs):
if not 'context' in locals():
context = {'pk': self.kwargs['pk'],
'root_pk': self.kwargs['pk'],
'title': SessaoPlenaria.objects.get(id=self.kwargs['pk'])
}
if 'marcadas_1' in request.POST:
context.update({'resultado_votacao': TipoResultadoVotacao.objects.all(),
'origem': request.POST['origem']})
# marcadas_1 se refere a votação simbólica e marcadas_2 a votação
# nominal
if request.POST['origem'] == 'ordem':
ordens = OrdemDia.objects.filter(
id__in=request.POST.getlist('marcadas_1'))
qtde_presentes = PresencaOrdemDia.objects.filter(
sessao_plenaria_id=self.kwargs['pk']).count()
context.update({'ordens': ordens,
'total_presentes': qtde_presentes})
else:
expedientes = ExpedienteMateria.objects.filter(
id__in=request.POST.getlist('marcadas_1'))
qtde_presentes = SessaoPlenariaPresenca.objects.filter(
sessao_plenaria_id=self.kwargs['pk']).count()
context.update({'expedientes': expedientes,
'total_presentes': qtde_presentes})
if 'salvar-votacao' in request.POST:
form = VotacaoForm(request.POST)
if form.is_valid():
origem = request.POST['origem']
if origem == 'ordem':
ordens = OrdemDia.objects.filter(
id__in=request.POST.getlist('ordens'))
for ordem in ordens:
try:
votacao = RegistroVotacao()
votacao.numero_votos_sim = int(
request.POST['votos_sim'])
votacao.numero_votos_nao = int(
request.POST['votos_nao'])
votacao.numero_abstencoes = int(
request.POST['abstencoes'])
votacao.observacao = request.POST['observacao']
votacao.materia = ordem.materia
votacao.ordem = ordem
resultado = TipoResultadoVotacao.objects.get(
id=request.POST['resultado_votacao'])
votacao.tipo_resultado_votacao = resultado
votacao.save()
except Exception as e:
username = request.user.username
self.logger.error('user=' + username + '. Problemas ao salvar '
'RegistroVotacao da materia de id={} '
'e da ordem de id={}. '
.format(ordem.materia.id, ordem.id) + str(e))
return self.form_invalid(form, context)
else:
ordem.resultado = resultado.nome
ordem.votacao_aberta = False
ordem.save()
else:
expedientes = ExpedienteMateria.objects.filter(
id__in=request.POST.getlist('expedientes'))
for expediente in expedientes:
try:
votacao = RegistroVotacao()
votacao.numero_votos_sim = int(
request.POST['votos_sim'])
votacao.numero_votos_nao = int(
request.POST['votos_nao'])
votacao.numero_abstencoes = int(
request.POST['abstencoes'])
votacao.observacao = request.POST['observacao']
votacao.materia = expediente.materia
votacao.expediente = expediente
resultado = TipoResultadoVotacao.objects.get(
id=request.POST['resultado_votacao'])
votacao.tipo_resultado_votacao = resultado
votacao.save()
except Exception as e:
username = request.user.username
self.logger.error('user=' + username + '. Problemas ao salvar RegistroVotacao da materia de id={} '
'e da ordem de id={}. '.format(expediente.materia.id, expediente.id) + str(e))
return self.form_invalid(form, context)
else:
expediente.resultado = resultado.nome
expediente.votacao_aberta = False
expediente.save()
return HttpResponseRedirect(self.get_success_url())
else:
return self.form_invalid(form, context)
if 'cancelar-votacao' in request.POST:
if request.POST['origem'] == 'ordem':
ordens = OrdemDia.objects.filter(
id__in=request.POST.getlist('ordens'))
for ordem in ordens:
ordem.votacao_aberta = False
ordem.save()
else:
expedientes = ExpedienteMateria.objects.filter(
id__in=request.POST.getlist('expedientes'))
for expediente in expedientes:
expediente.votacao_aberta = False
expediente.save()
return HttpResponseRedirect(self.get_success_url())
return self.render_to_response(context)
def get_tipos_votacao(self):
for tipo in TipoResultadoVotacao.objects.all():
yield tipo
def get_success_url(self):
if self.request.POST['origem'] == 'ordem':
return reverse('sapl.sessao:ordemdia_list',
kwargs={'pk': self.kwargs['pk']})
else:
return reverse('sapl.sessao:expedientemateria_list',
kwargs={'pk': self.kwargs['pk']})
def form_invalid(self, form, context):
errors_tuple = [(form[e].label, form.errors[e])
for e in form.errors if e in form.fields]
error_message = '<ul>'
for e in errors_tuple:
error_message += '<li><b>%s</b>: %s</li>' % (e[0], e[1][0])
for e in form.non_field_errors():
error_message += '<li>%s</li>' % e
error_message += '</ul>'
messages.add_message(self.request, messages.ERROR, error_message)
if self.request.POST['origem'] == 'ordem':
ordens = OrdemDia.objects.filter(
id__in=self.request.POST.getlist('ordens'))
qtde_presentes = PresencaOrdemDia.objects.filter(
sessao_plenaria_id=self.kwargs['pk']).count()
context.update({'ordens': ordens,
'total_presentes': qtde_presentes})
elif self.request.POST['origem'] == 'expediente':
expedientes = ExpedienteMateria.objects.filter(
id__in=self.request.POST.getlist('expedientes'))
qtde_presentes = SessaoPlenariaPresenca.objects.filter(
sessao_plenaria_id=self.kwargs['pk']).count()
context.update({'expedientes': expedientes,
'total_presentes': qtde_presentes})
context.update({'resultado_votacao': TipoResultadoVotacao.objects.all(),
'form': form,
'origem': self.request.POST['origem']})
return self.render_to_response(context)
class VotacaoEmBlocoNominalView(TemplateView):
"""
Votação Nominal
"""
template_name = 'sessao/votacao/votacao_nominal_bloco.html'
logger = logging.getLogger(__name__)
def post(self, request, *args, **kwargs):
username = request.user.username
form = VotacaoNominalForm(request.POST)
if not 'context' in locals():
context = {'pk': self.kwargs['pk'],
'root_pk': self.kwargs['pk'],
'title': SessaoPlenaria.objects.get(id=self.kwargs['pk']),
'subnav_template_name': 'sessao/subnav.yaml'}
if 'marcadas_2' in request.POST:
context.update({'resultado_votacao': TipoResultadoVotacao.objects.all(),
'origem': request.POST['origem']})
# marcadas_1 se refere a votação simbólica e marcadas_2 a votação
# nominal
if request.POST['origem'] == 'ordem':
ordens = OrdemDia.objects.filter(
id__in=request.POST.getlist('marcadas_2'))
presentes = PresencaOrdemDia.objects.filter(
sessao_plenaria_id=kwargs['pk'])
context.update({'ordens': ordens})
else:
expedientes = ExpedienteMateria.objects.filter(
id__in=request.POST.getlist('marcadas_2'))
presentes = SessaoPlenariaPresenca.objects.filter(
sessao_plenaria_id=kwargs['pk'])
context.update({'expedientes': expedientes})
total_presentes = presentes.count()
context.update({'parlamentares': self.get_parlamentares(),
'total_presentes': total_presentes})
if 'cancelar-votacao' in request.POST:
if request.POST['origem'] == 'ordem':
for ordem_id in request.POST.getlist('ordens'):
ordem = OrdemDia.objects.get(id=ordem_id)
fechar_votacao_materia(ordem)
return HttpResponseRedirect(reverse(
'sapl.sessao:ordemdia_list', kwargs={'pk': self.kwargs['pk']}))
else:
for expediente_id in request.POST.getlist('expedientes'):
expediente = ExpedienteMateria.objects.get(
id=expediente_id)
fechar_votacao_materia(expediente)
return HttpResponseRedirect(reverse(
'sapl.sessao:expedientemateria_list',
kwargs={'pk': self.kwargs['pk']}))
if 'salvar-votacao' in request.POST:
if form.is_valid():
if form.cleaned_data['resultado_votacao'] == None:
form.add_error(None, 'Não é possível finalizar a votação sem '
'nenhum resultado da votação.')
return self.form_invalid(form, context)
qtde_votos = (int(request.POST['votos_sim']) +
int(request.POST['votos_nao']) +
int(request.POST['abstencoes']) +
int(request.POST['nao_votou']))
# Caso todas as opções sejam 'Não votou', fecha a votação
if int(request.POST['nao_votou']) == qtde_votos:
self.logger.error('user=' + username + '. Não é possível finalizar a votação sem '
'nenhum voto.')
form.add_error(None, 'Não é possível finalizar a votação sem '
'nenhum voto.')
return self.form_invalid(form, context)
if request.POST['origem'] == 'ordem':
for ordem_id in request.POST.getlist('ordens'):
ordem = OrdemDia.objects.get(id=ordem_id)
# Remove todas as votação desta matéria, caso existam
RegistroVotacao.objects.filter(
ordem_id=ordem_id).delete()
votacao = RegistroVotacao()
votacao.numero_votos_sim = int(
request.POST['votos_sim'])
votacao.numero_votos_nao = int(
request.POST['votos_nao'])
votacao.numero_abstencoes = int(
request.POST['abstencoes'])
votacao.observacao = request.POST['observacao']
votacao.materia = ordem.materia
votacao.ordem = ordem
votacao.tipo_resultado_votacao = form.cleaned_data['resultado_votacao']
votacao.save()
for votos in request.POST.getlist('voto_parlamentar'):
v = votos.split(':')
voto = v[0]
parlamentar_id = v[1]
voto_parlamentar = VotoParlamentar.objects.get_or_create(
parlamentar_id=parlamentar_id,
ordem_id=ordem_id)[0]
voto_parlamentar.voto = voto
voto_parlamentar.parlamentar_id = parlamentar_id
voto_parlamentar.votacao_id = votacao.id
voto_parlamentar.save()
ordem.resultado = form.cleaned_data['resultado_votacao'].nome
ordem.votacao_aberta = False
ordem.save()
VotoParlamentar.objects.filter(
ordem_id=ordem_id,
votacao__isnull=True).delete()
else:
for expediente_id in request.POST.getlist('expedientes'):
expediente = ExpedienteMateria.objects.get(
id=expediente_id)
RegistroVotacao.objects.filter(
expediente_id=expediente_id).delete()
votacao = RegistroVotacao()
votacao.numero_votos_sim = int(
request.POST['votos_sim'])
votacao.numero_votos_nao = int(
request.POST['votos_nao'])
votacao.numero_abstencoes = int(
request.POST['abstencoes'])
votacao.observacao = request.POST['observacao']
votacao.materia = expediente.materia
votacao.expediente = expediente
votacao.tipo_resultado_votacao = form.cleaned_data['resultado_votacao']
votacao.save()
# Salva os votos de cada parlamentar
for votos in request.POST.getlist('voto_parlamentar'):
v = votos.split(':')
voto = v[0]
parlamentar_id = v[1]
voto_parlamentar = VotoParlamentar.objects.get_or_create(
parlamentar_id=parlamentar_id,
expediente_id=expediente_id)[0]
voto_parlamentar.voto = voto
voto_parlamentar.parlamentar_id = parlamentar_id
voto_parlamentar.votacao_id = votacao.id
voto_parlamentar.save()
expediente.resultado = form.cleaned_data['resultado_votacao'].nome
expediente.votacao_aberta = False
expediente.save()
VotoParlamentar.objects.filter(
expediente_id=expediente_id,
votacao__isnull=True).delete()
return HttpResponseRedirect(self.get_success_url())
else:
return self.form_invalid(form, context)
return self.render_to_response(context)
def get_parlamentares(self):
# campos hidden ainda não preenchidos
if 'marcadas_2' in self.request.POST:
if self.request.POST['origem'] == 'ordem':
presencas = PresencaOrdemDia.objects.filter(
sessao_plenaria_id=self.kwargs['pk'])
ordens_id = self.request.POST.getlist('marcadas_2')
voto_parlamentar = VotoParlamentar.objects.filter(
ordem=ordens_id[0])
else:
presencas = PresencaOrdemDia.objects.filter(
sessao_plenaria_id=self.kwargs['pk'])
expedientes_id = self.request.POST.getlist('marcadas_2')
voto_parlamentar = VotoParlamentar.objects.filter(
expediente=expedientes_id[0])
# campos hidden já preenchidos
else:
if self.request.POST['origem'] == 'ordem':
presencas = PresencaOrdemDia.objects.filter(
sessao_plenaria_id=self.kwargs['pk'])
ordens_id = self.request.POST.getlist('ordens')
voto_parlamentar = VotoParlamentar.objects.filter(
ordem=ordens_id[0])
else:
presencas = PresencaOrdemDia.objects.filter(
sessao_plenaria_id=self.kwargs['pk'])
expedientes_id = self.request.POST.getlist('expedientes')
voto_parlamentar = VotoParlamentar.objects.filter(
expediente=expedientes_id[0])
presentes = [p.parlamentar for p in presencas]
for parlamentar in Parlamentar.objects.filter(ativo=True):
if parlamentar in presentes:
try:
voto = voto_parlamentar.get(
parlamentar=parlamentar)
except ObjectDoesNotExist:
username = self.request.user.username
self.logger.error('user=' + username + '. Objeto voto_parlamentar do ' +
'parlamentar de id={} não existe.'.format(parlamentar.pk))
yield [parlamentar, None]
else:
yield [parlamentar, voto.voto]
def get_success_url(self):
if self.request.POST['origem'] == 'ordem':
return reverse('sapl.sessao:ordemdia_list',
kwargs={'pk': self.kwargs['pk']})
else:
return reverse('sapl.sessao:expedientemateria_list',
kwargs={'pk': self.kwargs['pk']})
def form_invalid(self, form, context):
errors_tuple = [(form[e].label, form.errors[e])
for e in form.errors if e in form.fields]
error_message = '<ul>'
for e in errors_tuple:
error_message += '<li><b>%s</b>: %s</li>' % (e[0], e[1][0])
for e in form.non_field_errors():
error_message += '<li>%s</li>' % e
error_message += '</ul>'
messages.add_message(self.request, messages.ERROR, error_message)
if self.request.POST['origem'] == 'ordem':
ordens = OrdemDia.objects.filter(
id__in=self.request.POST.getlist('ordens'))
presentes = PresencaOrdemDia.objects.filter(
sessao_plenaria_id=self.kwargs['pk'])
context.update({'ordens': ordens})
elif self.request.POST['origem'] == 'expediente':
expedientes = ExpedienteMateria.objects.filter(
id__in=self.request.POST.getlist('expedientes'))
presentes = SessaoPlenariaPresenca.objects.filter(
sessao_plenaria_id=self.kwargs['pk'])
context.update({'expedientes': expedientes})
total_presentes = presentes.count()
context.update({'parlamentares': self.get_parlamentares(),
'total_presentes': total_presentes,
'resultado_votacao': TipoResultadoVotacao.objects.all(),
'form': form,
'origem': self.request.POST['origem']})
return self.render_to_response(context)
class RetiradaPautaCrud(MasterDetailCrud): class RetiradaPautaCrud(MasterDetailCrud):
model = RetiradaPauta model = RetiradaPauta
public = [RP_LIST, RP_DETAIL, ] public = [RP_LIST, RP_DETAIL, ]
parent_field = 'sessao_plenaria' parent_field = 'sessao_plenaria'
class BaseMixin(MasterDetailCrud.BaseMixin): class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['tipo_de_retirada', 'materia', 'observacao', 'parlamentar'] list_field_names = ['tipo_de_retirada',
'materia', 'observacao', 'parlamentar']
class ListView(MasterDetailCrud.ListView): class ListView(MasterDetailCrud.ListView):
paginate_by = 10 paginate_by = 10
@ -3269,7 +3789,8 @@ class RetiradaPautaCrud(MasterDetailCrud):
layout_key = None layout_key = None
def get_initial(self): def get_initial(self):
sessao_plenaria = RetiradaPauta.objects.get(id=self.kwargs['pk']).sessao_plenaria sessao_plenaria = RetiradaPauta.objects.get(
id=self.kwargs['pk']).sessao_plenaria
return {'sessao_plenaria': sessao_plenaria} return {'sessao_plenaria': sessao_plenaria}
class DeleteView(MasterDetailCrud.DeleteView): class DeleteView(MasterDetailCrud.DeleteView):

503
sapl/static/styles/app.css

@ -0,0 +1,503 @@
.container-home {
position: relative;
padding: 2em 1.5em 1.5em 1.5em;
max-width: 1000px;
margin: 0 auto; }
.container-home a:hover {
color: #444;
-webkit-transition: 0.3s ease-in;
-moz-transition: 0.3s ease-in;
-o-transition: 0.3s ease-in; }
.container-home #homeIndex {
text-align: center; }
.container-home .homeBanner span {
color: white;
font-size: 32px;
font-weight: 600;
display: inline-block;
vertical-align: middle;
padding: 2px 45px 4px;
border: 2px solid; }
.container-home .homeBanner::after {
display: inline-block;
vertical-align: middle;
height: 100%; }
.container-home .homeBlock {
display: inline-block;
position: relative;
background-color: #F3F3F3;
width: 190px;
height: 260px;
margin: 3px;
text-align: center;
font-size: 0;
overflow: hidden; }
.container-home .homeBlock > a {
display: block;
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0; }
.container-home .homeBlock::after {
content: '';
display: inline-block;
vertical-align: middle;
height: 100%;
overflow: visible;
clear: none;
visibility: initial; }
.container-home .homeContent {
position: relative;
padding: 10px;
text-align: justify;
font-size: 14px;
color: #FFF;
opacity: 0;
transition: opacity 0.5s ease;
display: inline-block;
vertical-align: middle; }
.container-home .homeContent p {
display: block;
line-height: 13px;
font-size: 80%;
color: white; }
.container-home .homeIcon {
position: relative;
display: inline-block;
width: 105px;
height: 105px;
border-radius: 50%;
background: #364347;
z-index: 1; }
.container-home .homeIcon::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
background: #364347;
top: 0;
left: 0;
transform: scale(0.95);
transition: transform 0.6s ease; }
.container-home .homeIcon img {
position: absolute;
margin: auto;
top: 0;
bottom: 0;
right: 0;
left: 0;
transition: opacity 0.4s 0.4s ease; }
.container-home .homeFront {
position: absolute;
top: 46%;
width: 100%;
font-size: 0;
transform: translateY(-60%); }
.container-home .homeFront h2 {
position: absolute;
margin-top: 18px;
font-size: 22px;
font-weight: 700;
color: #595959 !important;
width: 100%;
padding: 0 6%;
z-index: 0; }
.container-home .homeTitle {
display: block;
height: 32px;
text-align: center;
width: 100%;
opacity: 0;
transition: opacity 0.4s ease; }
.container-home .homeTitle::before {
content: '';
display: inline-block;
vertical-align: middle;
height: 100%; }
.container-home .homeTitle h2 {
display: inline-block;
vertical-align: middle;
max-width: 110px;
font-size: 14px;
color: white !important;
line-height: 1em; }
.container-home .homeTitle img {
display: inline-block;
vertical-align: middle;
height: 30px;
margin-right: 5px; }
.container-home .homeBlock:hover .homeIcon::before {
transform: scale(3.6) translateY(7px); }
.container-home .homeBlock:hover .homeContent {
opacity: 1;
transition-delay: 0.2s; }
.container-home .homeBlock:hover .homeIcon img {
opacity: 0;
transition-duration: 0.2s;
transition-delay: 0s; }
.container-home .homeBlock:hover .homeTitle {
opacity: 1; }
html {
position: relative;
min-height: 100%; }
body {
margin-bottom: 160px; }
h1, h2, h3, h4, h5, h6, form, dl, dt, dd, p, div, img, a {
margin: 0;
padding: 0; }
h1, .h1 {
font-size: 30px; }
h2, .h2 {
font-size: 24px; }
h3, .h3 {
font-size: 20px; }
h4, .h4 {
font-size: 16px; }
h5, .h5 {
font-size: 14px; }
h6, .h6 {
font-size: 12px; }
p {
margin: 0.5em 0; }
p .control-label {
font-weight: bold; }
label {
margin-bottom: 0;
line-height: 1; }
fieldset fieldset {
font-size: 95%; }
fieldset fieldset legend {
font-size: 18px; }
.page-header {
margin: 20px 0px 10px; }
.caret.top {
transform: rotate(180deg); }
.btn:hover, .btn:focus {
color: inherit; }
.btn-default.btn-excluir {
color: #d9534f; }
.btn-default.btn-excluir:hover {
color: #fff;
border-color: #de6764;
background-color: #de6764; }
.btn-cancel-iframe {
position: relative;
text-align: right;
opacity: 0.5; }
.btn-cancel-iframe:hover {
opacity: 1; }
.btn-cancel-iframe a {
padding: 10px;
display: inline-block; }
.legend {
display: block;
width: 100%;
padding: 0;
margin-bottom: 20px;
font-size: 21px;
line-height: inherit;
color: #333333;
border: 0;
border-bottom: 1px solid #e5e5e5;
clear: both; }
.grid-gutter-width-right {
margin-right: 15px; }
.controls-file {
padding: 10px;
border: 1px solid #d6e1e5;
border-radius: 4px; }
.controls-file label.checkbox-inline {
margin: 0px;
display: block; }
.help-block-danger {
margin: 15px;
padding: 15px;
border: 2px dashed #f00; }
.control-label {
margin: 0; }
.form-control-static {
padding-top: 0;
min-height: auto; }
.form-control-static img {
max-width: 100%; }
.pagination {
padding-top: 25px; }
.modal .alert {
margin-bottom: 0; }
.avatar-parlamentar {
height: 128px;
width: 128px;
margin: 0 auto;
display: table; }
.masthead {
padding: 10px; }
.masthead .nav {
clear: both; }
.masthead .navbar-brand {
padding: 0px;
color: inherit;
font-size: 24px; }
.masthead .navbar-brand img.img-responsive {
height: 95px;
margin-right: 15px;
display: inline-block; }
.masthead .navbar-brand small {
color: #93A4AA;
font-size: 75%;
line-height: 25px; }
.masthead .navbar-brand .vcenter {
display: inline-block;
vertical-align: middle;
float: none;
padding: 10px; }
nav.navbar {
margin-bottom: 0;
border-radius: 0;
font-size: 15px; }
nav .navbar-nav > li > a {
padding-top: 0px;
padding-bottom: 0px;
line-height: 75px; }
nav .navbar-nav > li > a:hover {
background-color: #23527c; }
nav .navbar-nav > li:nth-child(2) > .dropdown-menu {
right: auto; }
nav .navbar-nav:last-child > li:last-child a {
padding-right: 0px; }
.controls-radio-checkbox {
padding: 0px;
border: 1px solid #d6e1e5;
border-radius: 4px;
min-height: 20px; }
.controls-radio-checkbox .checkbox, .controls-radio-checkbox .radio, .controls-radio-checkbox .checkbox-inline, .controls-radio-checkbox .radio-inline {
padding: 8px 8px 8px 36px;
margin: 0;
line-height: 1.6;
display: block; }
.controls-radio-checkbox .checkbox:hover, .controls-radio-checkbox .radio:hover, .controls-radio-checkbox .checkbox-inline:hover, .controls-radio-checkbox .radio-inline:hover {
background-color: #d6e1e5; }
.controls-radio-checkbox .checkbox .icons, .controls-radio-checkbox .radio .icons, .controls-radio-checkbox .checkbox-inline .icons, .controls-radio-checkbox .radio-inline .icons {
top: auto;
left: 8px; }
.controls-radio-checkbox .checkbox-inline, .controls-radio-checkbox .radio-inline {
display: inline-block; }
.controls-radio-checkbox .help-block {
margin: 15px;
padding: 15px;
border: 2px dashed #d6e1e5; }
.controls-radio-checkbox__old {
padding: 0px;
border: 1px solid #d6e1e5;
border-radius: 4px;
min-height: 20px; }
.controls-radio-checkbox__old label {
padding: 0;
line-height: 2.7;
padding-left: 36px; }
.controls-radio-checkbox__old label .icons {
top: 8px;
left: 8px; }
.controls-radio-checkbox__old label.checkbox-inline, .controls-radio-checkbox__old label.radio-inline {
padding-right: 8px; }
.controls-radio-checkbox__old label.checkbox-inline .icons, .controls-radio-checkbox__old label.radio-inline .icons {
top: 8px;
left: 8px; }
.controls-radio-checkbox__old .checkbox, .controls-radio-checkbox__old .radio, .controls-radio-checkbox__old .checkbox-inline, .controls-radio-checkbox__old .radio-inline {
margin: 0; }
.controls-radio-checkbox__old .checkbox:hover, .controls-radio-checkbox__old .radio:hover, .controls-radio-checkbox__old .checkbox-inline:hover, .controls-radio-checkbox__old .radio-inline:hover {
background-color: #d6e1e5; }
.manual, .manual ul {
padding-left: 1.5em;
list-style-type: none;
margin-top: 0;
font-size: 100%; }
.manual li {
display: list-item;
line-height: 1.5em;
padding-right: 0; }
.manual li a {
background-color: transparent;
border: none;
border-radius: none;
padding: 0; }
.container-tabaux .sidebar-tabaux {
background: #fafafa;
margin-top: -70px;
padding: 10px;
border: 1px solid #eee; }
.container-tabaux .sidebar-tabaux .navbar-right {
margin: 0; }
.container-tabaux .sidebar-tabaux .nav-pills > li + li {
margin-left: 0px; }
.container-tabaux .sidebar-tabaux li {
width: 100%; }
.container-tabaux .sidebar-tabaux span {
display: none; }
.container-tabaux .sidebar-tabaux .dropdown-menu {
padding: 0px;
right: 10px;
margin-top: -5px;
overflow: hidden; }
.container-tabaux .sidebar-tabaux .dropdown-menu a {
border: 0px; }
.container-tabaux ul {
list-style: none;
padding: 0; }
.container-tabaux .list {
font-family: "SourceSansProSemiBold", Helvetica, Arial, sans-serif;
font-size: 0px;
display: table;
width: 100%;
margin: 0; }
.container-tabaux .list ul {
display: table;
width: 100%;
margin: 0; }
.container-tabaux .list li {
width: calc(50%);
display: inline-block;
position: relative; }
.container-tabaux .list > li {
width: 100%;
border-bottom: 1px solid #eee;
padding-bottom: 20px;
margin-bottom: 20px; }
.container-tabaux .list .head_title {
color: #364347;
font-size: 2.4rem;
text-transform: none; }
.container-tabaux .list a span {
display: none; }
#styleparlamentar {
border: 0px solid #d6e1e5;
border-top-color: #d6e1e5;
border-right-color: #d6e1e5;
border-bottom-color: #d6e1e5;
border-left-color: #d6e1e5;
border-image-source: initial;
border-image-slice: initial;
border-image-repeat: initial;
font-size: 16px;
line-height: 1.467;
padding: 7px 12px;
height: 40px;
-webkit-appearance: none;
border-radius: 4px;
-webkit-box-shadow: none;
box-shadow: none;
margin-left: 1.0em; }
.footer {
background: #364347;
color: white;
text-align: center;
position: absolute;
width: 100%;
bottom: 0px; }
.footer p {
color: white;
margin-top: 10px; }
.footer .container {
padding-top: 25px; }
@media (max-width: 1199px) {
nav .container {
width: auto !important; }
.navbar-nav > li > a {
padding-left: 10.71429px;
padding-right: 10.71429px; } }
@media (max-width: 1091px) {
.container {
width: auto; }
.navbar-nav > li > a {
padding-left: 7.5px;
padding-right: 7.5px; }
.masthead .navbar-brand {
font-size: 22px; }
.masthead .navbar-brand img.img-responsive {
height: 60px;
margin-right: 7.5px; } }
@media (max-width: 991px) {
body {
margin: 0; }
.footer {
position: relative; }
.caret {
margin-left: 1px; }
.navbar-nav > li > a {
padding-left: 4px;
padding-right: 4px; } }
@media (max-width: 767px) {
nav .navbar-nav > li > a {
line-height: 2.5; }
nav .navbar-right {
position: absolute;
top: 0;
margin: 10px; }
nav .navbar-right > li {
vertical-align: top;
display: inline-block; }
nav .navbar-right > li a {
padding-left: 10px;
padding-right: 10px; }
nav .navbar-right .pesquisa.open ul {
position: absolute; }
nav .navbar-right .navbar-form {
margin: 8px 0; }
.table {
width: auto;
white-space: normal;
display: block;
overflow-x: auto; } }
@media (min-width: 1092px) and (max-width: 1199px) {
.container {
width: 1070px; } }
@media print {
a[href]:after {
content: none !important; } }

1136
sapl/static/styles/compilacao.css

File diff suppressed because it is too large

3
sapl/templates/auth/user_list.html

@ -29,7 +29,6 @@
</tbody> </tbody>
</table> </table>
{% endif %} {% endif %}
<a class="btn btn-default" href="{% url 'sapl.base:user_create' %}">Criar Usuário</a> <a class="btn btn-default" href="{% url 'sapl.base:user_create' %}">Criar Usuário</a>
</fieldset> </fieldset>
{% include 'paginacao.html'%}
{% endblock base_content %} {% endblock base_content %}

4
sapl/templates/sessao/subnav.yaml

@ -25,6 +25,8 @@
url: expedientemateria_list url: expedientemateria_list
- title: {% trans 'Oradores do Expediente' %} - title: {% trans 'Oradores do Expediente' %}
url: oradorexpediente_list url: oradorexpediente_list
- title: {% trans 'Votação em Bloco' %}
url: votacao_bloco_expediente
- title: {% trans 'Ordem do Dia' %} - title: {% trans 'Ordem do Dia' %}
children: children:
@ -32,6 +34,8 @@
url: ordemdia_list url: ordemdia_list
- title: {% trans 'Presença Ordem do Dia' %} - title: {% trans 'Presença Ordem do Dia' %}
url: presencaordemdia url: presencaordemdia
- title: {% trans 'Votação em Bloco' %}
url: votacao_bloco_ordemdia
- title: {% trans 'Painel Eletrônico' %} - title: {% trans 'Painel Eletrônico' %}
url: painel url: painel

76
sapl/templates/sessao/votacao/nominal.html

@ -72,46 +72,46 @@
window.history.back(); window.history.back();
} }
function conta_votos() { function conta_votos() {
var votos_sim = 0; var votos_sim = 0;
var votos_nao = 0; var votos_nao = 0;
var votos_abstencao = 0; var votos_abstencao = 0;
var nao_votou = 0; var nao_votou = 0;
$('[name=voto_parlamentar]').each(function() { $('[name=voto_parlamentar]').each(function() {
if (($(this).is(':hidden')) == false) { if (($(this).is(':hidden')) == false) {
switch ($(this).val().substring(0,4)) { switch ($(this).val().substring(0,4)) {
case "Sim:": case "Sim:":
votos_sim = votos_sim + 1; votos_sim = votos_sim + 1;
break; break;
case "Não:": case "Não:":
votos_nao = votos_nao + 1; votos_nao = votos_nao + 1;
break; break;
case "Abst": case "Abst":
votos_abstencao = votos_abstencao + 1; votos_abstencao = votos_abstencao + 1;
break; break;
case "Não ": case "Não ":
nao_votou = nao_votou + 1; nao_votou = nao_votou + 1;
break; break;
}; };
}; };
}); });
$("#soma_votos").empty(); $("#soma_votos").empty();
$("#soma_votos").append("<div class='row'><div class='col-md-12'>Sim: " + votos_sim + "</div></div>"); $("#soma_votos").append("<div class='row'><div class='col-md-12'>Sim: " + votos_sim + "</div></div>");
$("#soma_votos").append("<div class='row'><div class='col-md-12'>Não: " + votos_nao + "</div></div>"); $("#soma_votos").append("<div class='row'><div class='col-md-12'>Não: " + votos_nao + "</div></div>");
$("#soma_votos").append("<div class='row'><div class='col-md-12'>Abstenções: " + votos_abstencao + "</div></div>"); $("#soma_votos").append("<div class='row'><div class='col-md-12'>Abstenções: " + votos_abstencao + "</div></div>");
$("#soma_votos").append("<div class='row'><div class='col-md-12'>Ainda não votaram: " + nao_votou + "</div></div>"); $("#soma_votos").append("<div class='row'><div class='col-md-12'>Ainda não votaram: " + nao_votou + "</div></div>");
var t = setTimeout(function(){ var t = setTimeout(function(){
conta_votos() conta_votos()
}, 500); }, 500);
} }
conta_votos(); conta_votos();
window.onload = conta_votos(); window.onload = conta_votos();
$(window).on('beforeunload', function () { $(window).on('beforeunload', function () {
$("input[type=submit], input[type=button]").prop("disabled", "disabled"); $("input[type=submit], input[type=button]").prop("disabled", "disabled");
}); });
</script> </script>
{% endblock extra_js%} {% endblock extra_js%}

173
sapl/templates/sessao/votacao/votacao_bloco_expediente.html

@ -0,0 +1,173 @@
{% extends "crud/detail.html" %}
{% load i18n crispy_forms_tags %}
{% block base_content %}
<form method="POST" enctype="application/x-www-form-urlencoded" id="form" action="{% url 'sapl.sessao:votacaoblocosimb' pk %}">
{% csrf_token %}
<br><br>
<table class="table table-striped table-bordered">
<thead class="thead-default">
<tr>
<td><h3>{% trans "Tipo de Votação" %}</h3></td>
</tr>
</thead>
<tr>
<td class="col-md-12">
<fieldset id="tipo_votacao" name="tipo">
<input type="radio" name="tipo_votacao" id="tipo_votacao_1" value="1" onchange="alteraTipoVotacao()" checked="checked"> <label for="tipo">Simbólica</label>
</br>
<input type="radio" name="tipo_votacao" id="tipo_votacao_2" value="2" onchange="alteraTipoVotacao()" > <label for="tipo">Nominal</label>
</br>
</fieldset>
</td>
</tr>
</table>
<br>
<h3 id='frase_selecione'>Selecione o(s) expediente(s) desejado(s).</h3>
<table id='tab_ordens' class="table table-striped table-bordered">
<thead class="thead-default">
<tr>
<td><h3>{% trans "Expediente" %}</h3></td>
</tr>
</thead>
<div class="checkbox" id="check_all">
<label for="id_check_all">
<input type="checkbox" id="id_check_all" onchange="checkAll(this)" /> Marcar/Desmarcar Todos
</label>
</div>
{% for o in expedientes %}
<tr class="{% if o.tipo_votacao == 1 %}Simbolica{% else %}Nominal{% endif %}" {% if o.tipo_votacao == 2 %} style="display:none;" {% endif %}>
<td>
<input type="checkbox" name="marcadas_{{o.tipo_votacao}}" id="{{o.id}}" value="{{o.id}}" {% if check %} checked {% endif %}>
<strong><a href="{% url 'sapl.materia:materialegislativa_detail' o.id %}">{{o.materia.tipo.sigla}} {{o.materia.numero}}/{{o.materia.ano}} - {{o.materia.tipo}}</strong></a></br>
{% if o.materia.numeracao_set.last %}
<strong>Processo:</strong> &nbsp; {{o.materia.numeracao_set.last}}</br>
{% endif %}
<strong>Autor:</strong>
{% for a in o.materia.autoria_set.all %}
{% if not forloop.first %}
, &nbsp;&nbsp; {{a.autor|default_if_none:""}}
{% else %}
&nbsp;{{a.autor|default_if_none:""}}
{% endif %}
{% endfor %}
</br>
{% if o.materia.numero_protocolo %}
<strong>Protocolo:</strong> &nbsp; {{o.materia.numero_protocolo}}</br>
{% endif %}
{% if o.materia.tramitacao_set.last %}
{% if o.materia.tramitacao_set.last.turno %}
<strong>Turno:</strong>&nbsp;
{% for t in turno_choices %}
{% if t.0 == o.materia.tramitacao_set.last.turno %}
{{ t.1 }}
{% endif %}
{% endfor %}</br>
{% endif %}
{% endif %}
<strong>Ementa:</strong>&nbsp;{{ o.ementa|safe }}</br>
<p></p>
</td>
</tr>
{% endfor %}
</table>
<input type="submit" value="Registrar votação" class="btn btn-primary" id="but_reg">
<input type="hidden" id="origem" name="origem" value="expediente">
</form>
<table class="table table-striped table-bordered" style="display:none" id="nenhum_exp">
<tr>
<td>
<h3>Nenhuma matéria do expediente aberta.</h3>
</td>
</tr>
</table>
{% endblock base_content %}
{% block extra_js %}
<script>
$(document).ready(function(){
checa_tipo_votacao();
$('#tipo_votacao_1').prop('checked', true)
});
$(window).on('beforeunload', function () {
$("input[type=submit], input[type=button]").prop("disabled", "disabled");
});
</script>
<script language="JavaScript">
function checkAll(elem) {
let checkboxes = document.getElementsByName('marcadas_1');
if (elem.checked) {
for (let i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].type == 'checkbox') {
checkboxes[i].checked = true;
}
}
} else {
for (let i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].type == 'checkbox') {
checkboxes[i].checked = false;
}
}
}
checkboxes = document.getElementsByName('marcadas_2');
if (elem.checked) {
for (let i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].type == 'checkbox') {
checkboxes[i].checked = true;
}
}
} else {
for (let i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].type == 'checkbox') {
checkboxes[i].checked = false;
}
}
}
}
function alteraTipoVotacao() {
$(".Simbolica").toggle();
$(".Nominal").toggle();
checa_tipo_votacao();
}
function checa_tipo_votacao(){
tipo_votacao = document.querySelector('input[name="tipo_votacao"]:checked').value;
numero_ordens = document.getElementsByName('marcadas_'+tipo_votacao).length;
if(numero_ordens == 0){
document.getElementById('frase_selecione').style.display = 'none';
document.getElementById('tab_ordens').style.display = 'none';
document.getElementById('check_all').style.display = 'none';
document.getElementById('but_reg').style.display = 'none';
document.getElementById('nenhum_exp').style.display = '';
}
else{
document.getElementById('frase_selecione').style.display = '';
document.getElementById('tab_ordens').style.display = '';
document.getElementById('check_all').style.display = '';
document.getElementById('but_reg').style.display = '';
document.getElementById('nenhum_exp').style.display = 'none';
}
if(tipo_votacao == "1"){
$('#form').attr("action", "{% url 'sapl.sessao:votacaoblocosimb' pk %}")
}
else{
$('#form').attr("action", "{% url 'sapl.sessao:votacaobloconom' pk %}")
}
}
</script>
{% endblock extra_js%}

174
sapl/templates/sessao/votacao/votacao_bloco_ordem.html

@ -0,0 +1,174 @@
{% extends "crud/detail.html" %}
{% load i18n crispy_forms_tags %}
{% block base_content %}
<form method="POST" enctype="application/x-www-form-urlencoded" id="form" action="{% url 'sapl.sessao:votacaoblocosimb' pk %}">
{% csrf_token %}
<br><br>
<table class="table table-striped table-bordered">
<thead class="thead-default">
<tr>
<td><h3>{% trans "Tipo de Votação" %}</h3></td>
</tr>
</thead>
<tr>
<td class="col-md-12">
<fieldset id="tipo_votacao" name="tipo">
<input type="radio" name="tipo_votacao" id="tipo_votacao_1" value="1" onchange="alteraTipoVotacao()" checked="checked"> <label for="tipo">Simbólica</label>
</br>
<input type="radio" name="tipo_votacao" id="tipo_votacao_2" value="2" onchange="alteraTipoVotacao()" > <label for="tipo">Nominal</label>
</br>
</fieldset>
</td>
</tr>
</table>
<br>
<h3 id='frase_selecione'>Selecione a(s) ordem(s) do dia desejada(s).</h3>
<table id='tab_ordens' class="table table-striped table-bordered">
<thead class="thead-default">
<tr>
<td><h3>{% trans "Ordem do dia" %}</h3></td>
</tr>
</thead>
<div class="checkbox" id="check_all">
<label for="id_check_all">
<input type="checkbox" id="id_check_all" onchange="checkAll(this)" /> Marcar/Desmarcar Todos
</label>
</div>
{% for o in ordem_dia %}
<tr class="{% if o.tipo_votacao == 1 %}Simbolica{% else %}Nominal{% endif %}" {% if o.tipo_votacao == 2 %} style="display:none;" {% endif %}>
<td>
<input type="checkbox" name="marcadas_{{o.tipo_votacao}}" id="{{o.id}}" value="{{o.id}}" {% if check %} checked {% endif %}>
<strong><a href="{% url 'sapl.materia:materialegislativa_detail' o.id %}">{{o.materia.tipo.sigla}} {{o.materia.numero}}/{{o.materia.ano}} - {{o.materia.tipo}}</strong></a></br>
{% if o.materia.numeracao_set.last %}
<strong>Processo:</strong> &nbsp; {{o.materia.numeracao_set.last}}</br>
{% endif %}
<strong>Autor:</strong>
{% for a in o.materia.autoria_set.all %}
{% if not forloop.first %}
, &nbsp;&nbsp; {{a.autor|default_if_none:""}}
{% else %}
&nbsp;{{a.autor|default_if_none:""}}
{% endif %}
{% endfor %}
</br>
{% if o.materia.numero_protocolo %}
<strong>Protocolo:</strong> &nbsp; {{o.materia.numero_protocolo}}</br>
{% endif %}
{% if o.materia.tramitacao_set.last %}
{% if o.materia.tramitacao_set.last.turno %}
<strong>Turno:</strong>&nbsp;
{% for t in turno_choices %}
{% if t.0 == o.materia.tramitacao_set.last.turno %}
{{ t.1 }}
{% endif %}
{% endfor %}</br>
{% endif %}
{% endif %}
<strong>Ementa:</strong>&nbsp;{{ o.ementa|safe }}</br>
<p></p>
</td>
</tr>
{% endfor %}
</table>
<input type="submit" value="Registrar votação" class="btn btn-primary" id="but_reg">
<input type="hidden" id="origem" name="origem" value="ordem">
</form>
<table class="table table-striped table-bordered" style="display:none" id="nenhuma_ordem">
<tr>
<td>
<h3>Nenhuma ordem do dia aberta.</h3>
</td>
</tr>
</table>
{% endblock base_content %}
{% block extra_js %}
<script>
$(document).ready(function(){
checa_tipo_votacao();
$('#tipo_votacao_1').prop('checked', true)
});
$(window).on('beforeunload', function () {
$("input[type=submit], input[type=button]").prop("disabled", "disabled");
});
</script>
<script language="JavaScript">
function checkAll(elem) {
let checkboxes = document.getElementsByName('marcadas_1');
if (elem.checked) {
for (let i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].type == 'checkbox') {
checkboxes[i].checked = true;
}
}
} else {
for (let i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].type == 'checkbox') {
checkboxes[i].checked = false;
}
}
}
checkboxes = document.getElementsByName('marcadas_2');
if (elem.checked) {
for (let i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].type == 'checkbox') {
checkboxes[i].checked = true;
}
}
} else {
for (let i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].type == 'checkbox') {
checkboxes[i].checked = false;
}
}
}
}
function alteraTipoVotacao() {
$(".Simbolica").toggle();
$(".Nominal").toggle();
checa_tipo_votacao();
}
function checa_tipo_votacao(){
tipo_votacao = document.querySelector('input[name="tipo_votacao"]:checked').value;
numero_ordens = document.getElementsByName('marcadas_'+tipo_votacao).length;
if(numero_ordens == 0){
document.getElementById('frase_selecione').style.display = 'none';
document.getElementById('tab_ordens').style.display = 'none';
document.getElementById('check_all').style.display = 'none';
document.getElementById('but_reg').style.display = 'none';
document.getElementById('nenhuma_ordem').style.display = '';
}
else{
document.getElementById('frase_selecione').style.display = '';
document.getElementById('tab_ordens').style.display = '';
document.getElementById('check_all').style.display = '';
document.getElementById('but_reg').style.display = '';
document.getElementById('nenhuma_ordem').style.display = 'none';
}
if(tipo_votacao == "1"){
$('#form').attr("action", "{% url 'sapl.sessao:votacaoblocosimb' pk %}")
}
else{
$('#form').attr("action", "{% url 'sapl.sessao:votacaobloconom' pk %}")
}
}
</script>
{% endblock extra_js%}

149
sapl/templates/sessao/votacao/votacao_nominal_bloco.html

@ -0,0 +1,149 @@
{% extends "crud/detail.html" %}
{% load i18n crispy_forms_tags%}
{% block detail_content %}
<form method="post">
{% csrf_token %}
<fieldset>
<legend>Votação Nominal</legend>
{% if ordens %}
{% for o in ordens %}
<input type="hidden" id="ordens" name="ordens" value="{{o.id}}">
<div>
Matéria: {{o.materia}}
<br />
Ementa: {{o.materia.ementa|safe}}
</div>
<br />
{% endfor %}
{% else %}
{% for e in expedientes %}
<input type="hidden" id="expedientes" name="expedientes" value="{{e.id}}">
<div>
Matéria: {{e.materia}}
<br />
Ementa: {{e.materia.ementa|safe}}
</div>
<br />
{% endfor %}
{% endif %}
{% if total_presentes == 0 %}
<div class="alert alert-info alert-dismissible fade in" role="alert">
<div>Não existe nenhum parlamentar presente para que a votação ocorra.</div>
</div>
<a href="{% url 'sapl.sessao:sessaoplenaria_detail' pk %}" class="btn btn-warning">Voltar</a>
{% else %}
<fieldset class="form-group">
{% if parlamentares %}
<legend>Votos</legend>
<div class="row">
{% for parlamentar in parlamentares %}
<div class="col-md-4" id="styleparlamentar">{{parlamentar.0.nome_parlamentar}}</div>
<div class="col-md-5">
{% if parlamentar.1 %} <input type="hidden" name="voto_parlamentar" value="{{parlamentar.1}}:{{parlamentar.0.id}}" /> {% endif %}
<select id="voto_parlamentar" name="voto_parlamentar" class="form-control" {% if parlamentar.1 %} disabled {% endif %}>
<option value="Não Votou:{{parlamentar.0.id}}">Não Votou</option>
<option value="Sim:{{parlamentar.0.id}}" {% if parlamentar.1 == 'Sim' %} selected {% endif %}>Sim</option>
<option value="Não:{{parlamentar.0.id}}" {% if parlamentar.1 == 'Não' %} selected {% endif %}>Não</option>
<option value="Abstenção:{{parlamentar.0.id}}" {% if parlamentar.1 == 'Abstenção' %} selected {% endif %}>Abstenção</option>
</select>
</div>
{% endfor %}
</div>
{% endif %}
<br>
<legend>Situação da Votação:</legend>
<div id="soma_votos"></div>
<input type="hidden" id="votos_sim" name="votos_sim" value="">
<input type="hidden" id="votos_nao" name="votos_nao" value="">
<input type="hidden" id="abstencoes" name="abstencoes" value="">
<input type="hidden" id="nao_votou" name="nao_votou" value="">
</fieldset>
<div class="row">
<div class="col-md-12">
Resultado da Votação
<select id="resultado_votacao" name="resultado_votacao" class="form-control">
{% for tipo in resultado_votacao %}
<option value="{{tipo.id}}">{{tipo.nome}}</option>
{% endfor %}
</select>
</div>
</div>
<br />
<div class="row">
<div class="col-md-12">
Observações<br/>
<textarea id="observacao" name="observacao" style="width:100%;" rows="7"></textarea>
</div>
</div>
<input type="hidden" id="origem" name="origem" value="{{origem}}">
<br /><br />
<input type="submit" id="salvar-votacao" name="salvar-votacao" value="Fechar Votação" class="btn btn-primary" />
<input type="submit" id="cancelar-votacao" name="cancelar-votacao" value="Cancelar Votação" class="btn btn-warning" />
{% endif %}
</fieldset>
</form>
{% endblock detail_content %}
{% block extra_js %}
<script>
function voltar() {
window.history.back();
}
function conta_votos() {
var votos_sim = 0;
var votos_nao = 0;
var votos_abstencao = 0;
var nao_votou = 0;
$('[name=voto_parlamentar]').each(function() {
if (($(this).is(':hidden')) == false) {
switch ($(this).val().substring(0,4)) {
case "Sim:":
votos_sim = votos_sim + 1;
break;
case "Não:":
votos_nao = votos_nao + 1;
break;
case "Abst":
votos_abstencao = votos_abstencao + 1;
break;
case "Não ":
nao_votou = nao_votou + 1;
break;
};
};
});
$("#votos_sim").attr('value', votos_sim);
$("#votos_nao").attr('value', votos_nao);
$("#abstencoes").attr('value', votos_abstencao);
$("#nao_votou").attr('value', nao_votou);
$("#soma_votos").empty();
$("#soma_votos").append("<div class='row'><div class='col-md-12'>Sim: " + votos_sim + "</div></div>");
$("#soma_votos").append("<div class='row'><div class='col-md-12'>Não: " + votos_nao + "</div></div>");
$("#soma_votos").append("<div class='row'><div class='col-md-12'>Abstenções: " + votos_abstencao + "</div></div>");
$("#soma_votos").append("<div class='row'><div class='col-md-12'>Ainda não votaram: " + nao_votou + "</div></div>");
var t = setTimeout(function(){
conta_votos()
}, 500);
}
conta_votos();
window.onload = conta_votos();
$(window).on('beforeunload', function () {
$("input[type=submit], input[type=button]").prop("disabled", "disabled");
});
</script>
{% endblock extra_js%}

80
sapl/templates/sessao/votacao/votacao_simbolica_bloco.html

@ -0,0 +1,80 @@
{% extends "crud/detail.html" %}
{% load i18n crispy_forms_tags%}
{% block detail_content %}
<form id="form-votacao" method="post">
{% csrf_token %}
<fieldset class="form-group">
<legend>Votação Simbólica</legend>
<div>
{% if ordens %}
{% for o in ordens %}
<input type="hidden" id="ordens" name="ordens" value="{{o.id}}">
<b>Matéria:</b> {{o.materia|safe}}
<br />
<b>Ementa:</b> {{o.materia.ementa|safe}}
<br /> <br />
{% endfor %}
{% else %}
{% for e in expedientes %}
<input type="hidden" id="expedientes" name="expedientes" value="{{e.id}}">
<b>Matéria:</b> {{e.materia|safe}}
<br />
<b>Ementa:</b> {{e.materia.ementa|safe}}
<br /> <br />
{% endfor %}
{% endif %}
<b>Total presentes:</b> {{total_presentes}} (com presidente)
<input type="hidden" id="total_presentes" name="total_presentes" value="{{total_presentes}}">
</div>
<br />
{% if total_presentes == 0 %}
<div class="alert alert-info alert-dismissible fade in" role="alert">
<div>Não existe nenhum parlamentar presente para que a votação ocorra.</div>
</div>
<a href="{% url 'sapl.sessao:sessaoplenaria_detail' pk %}" class="btn btn-warning">Voltar</a>
{% else %}
<div class="row">
<div class="col-md-4">Sim: <input type="text" id="votos_sim" name="votos_sim" value="" class="form-control"/></div>
<div class="col-md-4">Não: <input type="text" id="votos_nao" name="votos_nao" value="" class="form-control"/></div>
<div class="col-md-4">Abstenções: <input type="text" id="abstencoes" name="abstencoes" value="" class="form-control"/></div>
</div>
<div class="row">
<div class="col-md-6">
A totalização inclui o voto do Presidente?
<select id="voto_presidente" name="voto_presidente" class="form-control">
<option value="1">Sim</option>
<option value="0" selected>Não</option>
</select>
</div>
<div class="col-md-6">
Resultado da Votação
<select id="resultado_votacao" name="resultado_votacao" class="form-control">
{% for tipo in resultado_votacao %}
<option value="{{tipo.id}}">{{tipo.nome}}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<div class="col-md-12">
Observações
<textarea id="observacao" name="observacao" cols="10" rows="10" class="form-control"></textarea>
</div>
</div>
<input type="hidden" id="origem" name="origem" value="{{origem}}">
<br /><br />
<input type="submit" id="salvar-votacao" name="salvar-votacao" value="Salvar" class="btn btn-primary" />
<input type="submit" id="cancelar-votacao" name="cancelar-votacao" value="Cancelar Votação" class="btn btn-warning" />
{% endif %}
</fieldset>
</form>
{% endblock detail_content %}
Loading…
Cancel
Save