Browse Source

feat: nova funcionalidade para leitura em bloco de materias do expediente (#3618)

* feat: nova funcionalidade para leitura em bloco de materias do expediente

* fix: Ajustes na Leitura em bloco, inclusao da funcionalidade para Ordem do dia

Co-authored-by: joao <joao@mezzoplanejamento.com.br>
pull/3628/merge
joaohortsenado 2 years ago
committed by Edward Oliveira
parent
commit
d39b65a828
  1. 7
      sapl/sessao/urls.py
  2. 264
      sapl/sessao/views.py
  3. 114
      sapl/templates/sessao/leitura/leitura_bloco.html
  4. 6
      sapl/templates/sessao/subnav.yaml

7
sapl/sessao/urls.py

@ -31,6 +31,7 @@ from sapl.sessao.views import (AdicionarVariasMateriasExpediente,
sessao_legislativa_legislatura_ajax,
VotacaoEmBlocoOrdemDia, VotacaoEmBlocoExpediente,
VotacaoEmBlocoSimbolicaView, VotacaoEmBlocoNominalView,
LeituraEmBlocoExpediente, LeituraEmBlocoOrdemDia,
recuperar_nome_tipo_sessao,
ExpedienteLeituraView,
OrdemDiaLeituraView,
@ -158,6 +159,12 @@ urlpatterns = [
url(r'^sessao/(?P<pk>\d+)/votacao_bloco_expediente$',
VotacaoEmBlocoExpediente.as_view(),
name='votacao_bloco_expediente'),
url(r'^sessao/(?P<pk>\d+)/leitura_bloco_expediente$',
LeituraEmBlocoExpediente.as_view(),
name='leitura_bloco_expediente'),
url(r'^sessao/(?P<pk>\d+)/leitura_bloco_ordem_dia$',
LeituraEmBlocoOrdemDia.as_view(),
name='leitura_bloco_ordem_dia'),
url(r'^sessao/(?P<pk>\d+)/resumo$',
ResumoView.as_view(), name='resumo'),
url(r'^sessao/(?P<pk>\d+)/resumo_ata$',

264
sapl/sessao/views.py

@ -38,10 +38,10 @@ from sapl.materia.models import (Autoria, TipoMateriaLegislativa,
from sapl.materia.views import MateriaLegislativaPesquisaView
from sapl.parlamentares.models import (Filiacao, Legislatura, Mandato,
Parlamentar, SessaoLegislativa)
from sapl.protocoloadm.models import TipoDocumentoAdministrativo,\
from sapl.protocoloadm.models import TipoDocumentoAdministrativo, \
DocumentoAdministrativo
from sapl.sessao.apps import AppConfig
from sapl.sessao.forms import ExpedienteMateriaForm, OrdemDiaForm, OrdemExpedienteLeituraForm,\
from sapl.sessao.forms import ExpedienteMateriaForm, OrdemDiaForm, OrdemExpedienteLeituraForm, \
CorrespondenciaForm, CorrespondenciaEmLoteFilterSet
from sapl.sessao.models import Correspondencia
from sapl.settings import TIME_ZONE
@ -62,7 +62,6 @@ from .models import (Bancada, CargoBancada, CargoMesa,
RetiradaPauta, TipoJustificativa, JustificativaAusencia, OradorOrdemDia,
ORDENACAO_RESUMO, RegistroLeitura)
TipoSessaoCrud = CrudAux.build(TipoSessaoPlenaria, 'tipo_sessao_plenaria')
TipoJustificativaCrud = CrudAux.build(TipoJustificativa, 'tipo_justificativa')
CargoBancadaCrud = CrudAux.build(CargoBancada, '')
@ -167,7 +166,8 @@ def verifica_sessao_iniciada(request, spk, is_leitura=False):
username = request.user.username
aux_text = 'leitura' if is_leitura else 'votação'
logger.info('user=' + username + '. Não é possível abrir matérias para {}. '
'Esta SessaoPlenaria (id={}) não foi iniciada ou está finalizada.'.format(aux_text, spk))
'Esta SessaoPlenaria (id={}) não foi iniciada ou está finalizada.'.format(
aux_text, spk))
msg = _('Não é possível abrir matérias para {}. '
'Esta Sessão Plenária não foi iniciada ou está finalizada.'
' Vá em "Abertura"->"Dados Básicos" e altere os valores dos campos necessários.'.format(aux_text))
@ -199,7 +199,7 @@ def abrir_votacao(request, pk, spk):
materia_votacao = model.objects.get(id=pk)
is_leitura = materia_votacao.tipo_votacao == 4
if (verifica_presenca(request, presenca_model, spk, is_leitura) and
verifica_votacoes_abertas(request) and
verifica_votacoes_abertas(request) and
verifica_sessao_iniciada(request, spk, is_leitura)):
materia_votacao.votacao_aberta = True
sessao = SessaoPlenaria.objects.get(id=spk)
@ -235,22 +235,22 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
num_protocolo = materia.numero_protocolo if materia.numero_protocolo else "-"
sessao_plenaria = SessaoPlenaria.objects.get(id=pk)
data_sessao = sessao_plenaria.data_fim if sessao_plenaria.data_fim else sessao_plenaria.data_inicio
tramitacao = Tramitacao.objects\
.select_related('materia', 'status', 'materia__tipo')\
.filter(materia=materia, turno__isnull=False, data_tramitacao__lte=data_sessao)\
.exclude(turno__exact='')\
.order_by('-data_tramitacao', '-id')\
.first()
tramitacao = Tramitacao.objects \
.select_related('materia', 'status', 'materia__tipo') \
.filter(materia=materia, turno__isnull=False, data_tramitacao__lte=data_sessao) \
.exclude(turno__exact='') \
.order_by('-data_tramitacao', '-id') \
.first()
turno = '-'
if tramitacao:
for t in Tramitacao.TURNO_CHOICES:
if t[0] == tramitacao.turno:
turno = t[1]
break
materia_em_tramitacao = MateriaEmTramitacao.objects\
.select_related("materia", "tramitacao")\
.filter(materia=materia)\
.first()
materia_em_tramitacao = MateriaEmTramitacao.objects \
.select_related("materia", "tramitacao") \
.filter(materia=materia) \
.first()
# idUnica para cada materia
idAutor = "autor" + str(i)
idAutores = "autores" + str(i)
@ -274,8 +274,8 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
exist_leitura = obj.registroleitura_set.filter(
materia=obj.materia).exists()
if (obj.tipo_votacao != 4 and not exist_resultado and not exist_retirada) or\
(obj.tipo_votacao == 4 and not exist_leitura):
if (obj.tipo_votacao != LEITURA and not exist_resultado and not exist_retirada) or \
(obj.tipo_votacao == LEITURA and not exist_leitura):
if obj.votacao_aberta:
url = ''
if is_expediente:
@ -472,11 +472,11 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'mid': obj.materia_id})
resultado = (
'<a href="%s?page=%s">%s<br/><br/>%s</a>' % (
url,
context.get('page', 1),
resultado_descricao,
resultado_observacao))
'<a href="%s?page=%s">%s<br/><br/>%s</a>' % (
url,
context.get('page', 1),
resultado_descricao,
resultado_observacao))
else:
if obj.tipo_votacao == NOMINAL:
@ -487,7 +487,7 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'pk': obj.sessao_plenaria_id,
'oid': obj.pk,
'mid': obj.materia_id}) + \
'?&materia=expediente'
'?&materia=expediente'
else:
url = reverse(
'sapl.sessao:votacao_nominal_transparencia',
@ -495,7 +495,7 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'pk': obj.sessao_plenaria_id,
'oid': obj.pk,
'mid': obj.materia_id}) + \
'?&materia=ordem'
'?&materia=ordem'
resultado = ('<a href="%s">%s<br/>%s</a>' %
(url,
@ -510,7 +510,7 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'pk': obj.sessao_plenaria_id,
'oid': obj.pk,
'mid': obj.materia_id}) + \
'?&materia=expediente'
'?&materia=expediente'
else:
url = reverse(
'sapl.sessao:votacao_simbolica_transparencia',
@ -518,7 +518,7 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'pk': obj.sessao_plenaria_id,
'oid': obj.pk,
'mid': obj.materia_id}) + \
'?&materia=ordem'
'?&materia=ordem'
resultado = ('<a href="%s">%s<br/>%s</a>' %
(url,
@ -673,8 +673,8 @@ class TransferenciaMateriasSessaoAbstract(PermissionRequiredMixin, ListView):
exp = ExpedienteMateria.objects.filter(sessao_plenaria=sessao)
numero_ordem = exp.last().numero_ordem if exp.exists() else 0
for num_ordem, expediente in enumerate(
ExpedienteMateria.objects.filter(id__in=marcadas),
numero_ordem + 1
ExpedienteMateria.objects.filter(id__in=marcadas),
numero_ordem + 1
):
lista_expediente.append(
ExpedienteMateria(
@ -694,7 +694,7 @@ class TransferenciaMateriasSessaoAbstract(PermissionRequiredMixin, ListView):
o = OrdemDia.objects.filter(sessao_plenaria=sessao)
numero_ordem = o.last().numero_ordem if o.exists() else 0
for num_ordem, ordemdia in enumerate(
OrdemDia.objects.filter(id__in=marcadas), numero_ordem + 1
OrdemDia.objects.filter(id__in=marcadas), numero_ordem + 1
):
lista_ordemdia.append(
OrdemDia(
@ -780,9 +780,9 @@ class MateriaOrdemDiaCrud(MasterDetailCrud):
pk=self.kwargs['pk']).data_inicio.strftime('%d/%m/%Y')
max_numero_ordem = OrdemDia.objects.filter(
sessao_plenaria=self.kwargs['pk']).aggregate(
Max('numero_ordem'))['numero_ordem__max']
Max('numero_ordem'))['numero_ordem__max']
self.initial['numero_ordem'] = (
max_numero_ordem if max_numero_ordem else 0) + 1
max_numero_ordem if max_numero_ordem else 0) + 1
return self.initial
def get_success_url(self):
@ -923,9 +923,9 @@ class ExpedienteMateriaCrud(MasterDetailCrud):
pk=self.kwargs['pk']).data_inicio.strftime('%d/%m/%Y')
max_numero_ordem = ExpedienteMateria.objects.filter(
sessao_plenaria=self.kwargs['pk']).aggregate(
Max('numero_ordem'))['numero_ordem__max']
Max('numero_ordem'))['numero_ordem__max']
initial['numero_ordem'] = (
max_numero_ordem if max_numero_ordem else 0) + 1
max_numero_ordem if max_numero_ordem else 0) + 1
return initial
def get_success_url(self):
@ -1312,7 +1312,7 @@ class SessaoCrud(Crud):
username = self.request.user.username
self.logger.error('user=' + username + '. Cadastre alguma legislatura antes de adicionar '
'uma sessão plenária!')
'uma sessão plenária!')
messages.add_message(self.request, messages.ERROR, msg)
return {}
@ -1405,7 +1405,7 @@ class PresencaView(FormMixin, PresencaMixin, DetailView):
# Id dos parlamentares presentes
marcados = request.POST.getlist('presenca_ativos') \
+ request.POST.getlist('presenca_inativos')
+ request.POST.getlist('presenca_inativos')
# Deletar os que foram desmarcados
deletar = set(presentes_banco) - set(marcados)
@ -1461,7 +1461,7 @@ class PainelView(PermissionRequiredForAppCrudMixin, TemplateView):
username = self.request.user.username
self.logger.error('user=' + username + '. Você precisa primeiro configurar os cronômetros'
' nas Configurações da Aplicação')
' nas Configurações da Aplicação')
msg = _(
'Você precisa primeiro configurar os cronômetros \
nas Configurações da Aplicação')
@ -1520,7 +1520,7 @@ class PresencaOrdemDiaView(FormMixin, PresencaMixin, DetailView):
# Id dos parlamentares presentes
marcados = request.POST.getlist('presenca_ativos') \
+ request.POST.getlist('presenca_inativos')
+ request.POST.getlist('presenca_inativos')
# Deletar os que foram desmarcados
deletar = set(presentes_banco) - set(marcados)
@ -1782,7 +1782,7 @@ def insere_parlamentar_composicao(request):
username = request.user.username
if request.user.has_perm(
'%s.add_%s' % (
AppConfig.label, IntegranteMesa._meta.model_name)):
AppConfig.label, IntegranteMesa._meta.model_name)):
composicao = IntegranteMesa()
@ -1815,8 +1815,9 @@ def insere_parlamentar_composicao(request):
cargo_id=composicao.cargo.id).exists()
if parlamentar_ja_inserido:
logger.debug("user=" + username + ". Parlamentar (id={}) já inserido na sessao_plenaria(id={}) e cargo(ìd={})."
.format(request.POST['parlamentar'], composicao.sessao_plenaria.id, composicao.cargo.id))
logger.debug(
"user=" + username + ". Parlamentar (id={}) já inserido na sessao_plenaria(id={}) e cargo(ìd={})."
.format(request.POST['parlamentar'], composicao.sessao_plenaria.id, composicao.cargo.id))
return JsonResponse({'msg': ('Parlamentar já inserido!', 0)})
composicao.save()
@ -1843,8 +1844,8 @@ def remove_parlamentar_composicao(request):
logger = logging.getLogger(__name__)
username = request.user.username
if request.POST and request.user.has_perm(
'%s.delete_%s' % (
AppConfig.label, IntegranteMesa._meta.model_name)):
'%s.delete_%s' % (
AppConfig.label, IntegranteMesa._meta.model_name)):
if 'composicao_mesa' in request.POST:
try:
@ -1968,7 +1969,6 @@ def get_mesa_diretora(sessao_plenaria):
def get_presenca_sessao(sessao_plenaria):
parlamentares_sessao = [p.parlamentar for p in SessaoPlenariaPresenca.objects.filter(
sessao_plenaria_id=sessao_plenaria.id
).order_by('parlamentar__nome_parlamentar').distinct()]
@ -2029,7 +2029,8 @@ def get_materias_expediente(sessao_plenaria):
for m in ExpedienteMateria.objects.select_related("materia").filter(sessao_plenaria_id=sessao_plenaria.id):
tramitacao = ''
data_sessao = sessao_plenaria.data_fim if sessao_plenaria.data_fim else sessao_plenaria.data_inicio
for aux_tramitacao in Tramitacao.objects.filter(materia=m.materia, data_tramitacao__lte=data_sessao).order_by('-data_tramitacao', '-id'):
for aux_tramitacao in Tramitacao.objects.filter(materia=m.materia, data_tramitacao__lte=data_sessao).order_by(
'-data_tramitacao', '-id'):
if aux_tramitacao.turno:
tramitacao = aux_tramitacao
break
@ -2175,7 +2176,8 @@ def get_materias_ordem_do_dia(sessao_plenaria):
for o in OrdemDia.objects.filter(sessao_plenaria_id=sessao_plenaria.id):
tramitacao = ''
data_sessao = sessao_plenaria.data_fim if sessao_plenaria.data_fim else sessao_plenaria.data_inicio
for aux_tramitacao in Tramitacao.objects.filter(materia=o.materia, data_tramitacao__lte=data_sessao).order_by('-data_tramitacao', '-id'):
for aux_tramitacao in Tramitacao.objects.filter(materia=o.materia, data_tramitacao__lte=data_sessao).order_by(
'-data_tramitacao', '-id'):
if aux_tramitacao.turno:
tramitacao = aux_tramitacao
break
@ -2316,8 +2318,8 @@ class ResumoView(DetailView):
# Votos de Votação Nominal de Matérias Expediente
votacoes = []
for mevn in ExpedienteMateria.objects.filter(sessao_plenaria_id=self.object.id, tipo_votacao=2)\
.order_by('-materia'):
for mevn in ExpedienteMateria.objects.filter(sessao_plenaria_id=self.object.id, tipo_votacao=2) \
.order_by('-materia'):
votos_materia = []
titulo_materia = mevn.materia
registro = RegistroVotacao.objects.filter(expediente=mevn)
@ -2437,7 +2439,7 @@ class ResumoView(DetailView):
})
except KeyError as e:
self.logger.error("KeyError: " + str(e) + ". Erro ao tentar utilizar "
"configuração de ordenação. Utilizando ordenação padrão.")
"configuração de ordenação. Utilizando ordenação padrão.")
context.update({
'primeiro_ordenacao': 'identificacao_basica.html',
'segundo_ordenacao': 'conteudo_multimidia.html',
@ -2510,7 +2512,6 @@ class ExpedienteView(FormMixin, DetailView):
list_conteudo = request.POST.getlist('conteudo')
for tipo, conteudo in zip(list_tipo, list_conteudo):
ExpedienteSessao.objects.filter(
sessao_plenaria_id=self.object.id,
tipo_id=tipo).delete()
@ -2523,8 +2524,9 @@ class ExpedienteView(FormMixin, DetailView):
msg = _('Registro salvo com sucesso')
messages.add_message(self.request, messages.SUCCESS, msg)
self.logger.info('user=' + username + '. ExpedienteSessao(sessao_plenaria_id={} e tipo_id={}) salvo com sucesso.'
.format(self.object.id, tipo))
self.logger.info(
'user=' + username + '. ExpedienteSessao(sessao_plenaria_id={} e tipo_id={}) salvo com sucesso.'
.format(self.object.id, tipo))
return self.form_valid(form)
else:
@ -2609,7 +2611,8 @@ class OcorrenciaSessaoView(FormMixin, DetailView):
username = self.request.user.username
self.logger.info(
'user=' + username + '. OcorrenciaSessao de sessao_plenaria_id={} atualizada com sucesso.'.format(self.object.id))
'user=' + username + '. OcorrenciaSessao de sessao_plenaria_id={} atualizada com sucesso.'.format(
self.object.id))
@method_decorator(permission_required('sessao.add_ocorrenciasessao'))
def post(self, request, *args, **kwargs):
@ -2677,7 +2680,8 @@ class ConsideracoesFinaisView(FormMixin, DetailView):
username = self.request.user.username
self.logger.info(
'user=' + username + '. consideracoesFinais de sessao_plenaria_id={} atualizada com sucesso.'.format(self.object.id))
'user=' + username + '. consideracoesFinais de sessao_plenaria_id={} atualizada com sucesso.'.format(
self.object.id))
@method_decorator(permission_required('sessao.add_consideracoesfinais'))
def post(self, request, *args, **kwargs):
@ -2701,7 +2705,6 @@ class ConsideracoesFinaisView(FormMixin, DetailView):
class VotacaoEditView(SessaoPermissionMixin):
'''
Votação Simbólica e Secreta
'''
@ -2716,7 +2719,7 @@ class VotacaoEditView(SessaoPermissionMixin):
materia_id = kwargs['mid']
ordem_id = kwargs['oid']
if(int(request.POST['anular_votacao']) == 1):
if (int(request.POST['anular_votacao']) == 1):
RegistroVotacao.objects.filter(ordem_id=ordem_id).delete()
ordem = OrdemDia.objects.get(id=ordem_id)
@ -2752,7 +2755,7 @@ class VotacaoEditView(SessaoPermissionMixin):
'&nbsp;', ' ', strip_tags(votacao.observacao)),
'resultado': votacao.tipo_resultado_votacao.nome,
'tipo_resultado':
votacao.tipo_resultado_votacao_id}
votacao.tipo_resultado_votacao_id}
context.update({'votacao_titulo': titulo,
'votacao': votacao_existente,
'tipos': self.get_tipos_votacao()})
@ -2774,7 +2777,6 @@ class VotacaoEditView(SessaoPermissionMixin):
class VotacaoView(SessaoPermissionMixin):
"""
Votação Simbólica e Secreta
"""
@ -2895,7 +2897,8 @@ class VotacaoView(SessaoPermissionMixin):
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(materia_id, ordem_id) + str(e))
'e da ordem de id={}. '.format(materia_id, ordem_id) + str(
e))
return self.form_invalid(form)
else:
ordem = OrdemDia.objects.get(id=ordem_id)
@ -3108,7 +3111,7 @@ class VotacaoNominalAbstract(SessaoPermissionMixin):
# Caso todas as opções sejam 'Não votou', fecha a votação
if nao_votou == len(request.POST.getlist('voto_parlamentar')):
self.logger.error('user=' + username + '. Não é possível finalizar a votação sem '
'nenhum voto')
'nenhum voto')
form.add_error(None, 'Não é possível finalizar a votação sem '
'nenhum voto')
return self.form_invalid(form)
@ -3266,7 +3269,8 @@ class VotacaoNominalEditAbstract(SessaoPermissionMixin):
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))
'user=' + username + '. Objeto OrdemDia com id={} ou RegistroVotacao de OrdemDia não existe.'.format(
ordem_id))
raise Http404()
materia = ordem.materia
@ -3354,7 +3358,7 @@ class VotacaoNominalEditAbstract(SessaoPermissionMixin):
'user=' + username + '. Objeto ExpedienteMateria com id={} não existe.'.format(expediente_id))
raise Http404()
if(int(request.POST['anular_votacao']) == 1):
if (int(request.POST['anular_votacao']) == 1):
fechar_votacao_materia(materia_votacao)
return self.form_valid(form)
@ -3430,7 +3434,7 @@ class VotacaoNominalTransparenciaDetailView(TemplateView):
'&nbsp;', ' ', strip_tags(votacao.observacao)),
'resultado': votacao.tipo_resultado_votacao.nome,
'tipo_resultado':
votacao.tipo_resultado_votacao_id}
votacao.tipo_resultado_votacao_id}
context.update({'resultado_votacao': votacao_existente,
'tipos': self.get_tipos_votacao()})
@ -3470,7 +3474,7 @@ class VotacaoNominalExpedienteDetailView(DetailView):
'&nbsp;', ' ', strip_tags(votacao.observacao)),
'resultado': votacao.tipo_resultado_votacao.nome,
'tipo_resultado':
votacao.tipo_resultado_votacao_id}
votacao.tipo_resultado_votacao_id}
context.update({'votacao': votacao_existente,
'tipos': self.get_tipos_votacao()})
@ -3518,7 +3522,7 @@ class VotacaoSimbolicaTransparenciaDetailView(TemplateView):
'&nbsp;', ' ', strip_tags(votacao.observacao)),
'resultado': votacao.tipo_resultado_votacao.nome,
'tipo_resultado':
votacao.tipo_resultado_votacao_id}
votacao.tipo_resultado_votacao_id}
context.update({'resultado_votacao': votacao_existente,
'tipos': self.get_tipos_votacao()})
@ -3530,7 +3534,6 @@ class VotacaoSimbolicaTransparenciaDetailView(TemplateView):
class VotacaoExpedienteView(SessaoPermissionMixin):
"""
Votação Simbólica e Secreta
"""
@ -3683,7 +3686,6 @@ class VotacaoExpedienteView(SessaoPermissionMixin):
class VotacaoExpedienteEditView(SessaoPermissionMixin):
"""
Votação Simbólica e Secreta
"""
@ -3735,7 +3737,7 @@ class VotacaoExpedienteEditView(SessaoPermissionMixin):
'&nbsp;', ' ', strip_tags(votacao.observacao)),
'resultado': votacao.tipo_resultado_votacao.nome,
'tipo_resultado':
votacao.tipo_resultado_votacao_id}
votacao.tipo_resultado_votacao_id}
context.update({'votacao_titulo': titulo,
'votacao': votacao_existente})
@ -3887,8 +3889,8 @@ class PautaSessaoDetailView(DetailView):
# =====================================================================
# Expedientes
expedientes = []
for e in ExpedienteSessao.objects.select_related("tipo").filter(sessao_plenaria_id=self.object.id)\
.order_by('tipo__ordenacao'):
for e in ExpedienteSessao.objects.select_related("tipo").filter(sessao_plenaria_id=self.object.id) \
.order_by('tipo__ordenacao'):
conteudo = e.conteudo
from sapl.relatorios.views import is_empty
if not is_empty(conteudo):
@ -4070,7 +4072,8 @@ def verifica_materia_sessao_plenaria_ajax(request):
materia=id_materia_selecionada
).exists()
return JsonResponse({'is_materia_presente': is_materia_presente, 'is_materia_presente_any_sessao': is_materia_presente_any_sessao})
return JsonResponse(
{'is_materia_presente': is_materia_presente, 'is_materia_presente_any_sessao': is_materia_presente_any_sessao})
class AdicionarVariasMateriasExpediente(PermissionRequiredForAppCrudMixin,
@ -4217,7 +4220,7 @@ class AdicionarVariasMateriasOrdemDia(AdicionarVariasMateriasExpediente):
MateriaLegislativa.objects.get(id=m))
messages.add_message(request, messages.ERROR, msg)
self.logger.error('user=' + username + '. Formulário Inválido. Você esqueceu de selecionar '
'o tipo de votação de MateriaLegislativa com id={}'.format(m))
'o tipo de votação de MateriaLegislativa com id={}'.format(m))
return self.get(request, self.kwargs)
@ -4316,7 +4319,6 @@ class JustificativaAusenciaCrud(MasterDetailCrud):
@property
def layout_display(self):
layout = super().layout_display
if self.object.ausencia == 2:
@ -4335,7 +4337,6 @@ class JustificativaAusenciaCrud(MasterDetailCrud):
layout_key = None
def get_context_data_old(self, **kwargs):
context = super().get_context_data(**kwargs)
presencas = SessaoPlenariaPresenca.objects.filter(
@ -4371,7 +4372,6 @@ class JustificativaAusenciaCrud(MasterDetailCrud):
kwargs={'pk': self.kwargs['pk']})
class UpdateView(MasterDetailCrud.UpdateView):
form_class = JustificativaAusenciaForm
layout_key = None
@ -4384,6 +4384,97 @@ class JustificativaAusenciaCrud(MasterDetailCrud):
pass
class LeituraEmBloco(PermissionRequiredForAppCrudMixin, ListView):
template_name = 'sessao/leitura/leitura_bloco.html'
app_label = AppConfig.label
expediente = True
paginate_by = 100
def get_queryset(self):
return ExpedienteMateria.objects.filter(sessao_plenaria_id=self.kwargs['pk'],
retiradapauta=None, tipo_votacao=LEITURA, registroleitura__materia=None)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['pk'] = self.kwargs['pk']
context['root_pk'] = self.kwargs['pk']
if not verifica_sessao_iniciada(self.request, self.kwargs['pk']):
context['sessao_iniciada'] = False
return context
context['sessao_iniciada'] = True
context['turno_choices'] = Tramitacao.TURNO_CHOICES
context['title'] = SessaoPlenaria.objects.get(id=self.kwargs['pk'])
if self.expediente:
context['expediente'] = True
else:
context['expediente'] = False
return context
def post(self, request, *args, **kwargs):
if 'marcadas_4' in request.POST:
models = None
selectedlist = request.POST.getlist('marcadas_4')
if request.POST['origem'] == 'ordem':
models = OrdemDia.objects.filter(id__in=selectedlist)
elif request.POST['origem'] == 'expediente':
models = ExpedienteMateria.objects.filter(id__in=selectedlist)
if not models:
messages.add_message(self.request, messages.ERROR,
_('Impossível localizar as matérias selecionadas'))
return self.get(request, self.kwargs)
materias = [m.materia for m in models]
RegistroLeitura.objects.filter(materia__in=materias).delete()
leituras = []
for m in models:
obj = None
if isinstance(m, ExpedienteMateria):
obj = RegistroLeitura(expediente=m, materia=m.materia,
observacao=request.POST['observacao'],
user=self.request.user,
ip=get_client_ip(self.request))
elif isinstance(m, OrdemDia):
obj = RegistroLeitura(ordem=m, materia=m.materia,
observacao=request.POST['observacao'],
user=self.request.user,
ip=get_client_ip(self.request))
leituras.append(obj)
RegistroLeitura.objects.bulk_create(leituras)
else:
messages.add_message(self.request, messages.ERROR, _('Nenhuma matéria selecionada para leitura em Bloco'))
return self.get(request, self.kwargs)
return HttpResponseRedirect(self.get_success_url())
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']})
class LeituraEmBlocoExpediente(LeituraEmBloco):
expediente = True
paginate_by = 100
def get_queryset(self):
return ExpedienteMateria.objects.filter(sessao_plenaria_id=self.kwargs['pk'],
retiradapauta=None, tipo_votacao=LEITURA, registroleitura__materia=None)
class LeituraEmBlocoOrdemDia(LeituraEmBloco):
expediente = False
paginate_by = 100
def get_queryset(self):
return OrdemDia.objects.filter(sessao_plenaria_id=self.kwargs['pk'],
retiradapauta=None, tipo_votacao=LEITURA, registroleitura__materia=None)
class VotacaoEmBlocoExpediente(PermissionRequiredForAppCrudMixin, ListView):
template_name = 'sessao/votacao/votacao_bloco.html'
app_label = AppConfig.label
@ -4423,7 +4514,6 @@ class VotacaoEmBlocoOrdemDia(VotacaoEmBlocoExpediente):
class VotacaoEmBlocoSimbolicaView(PermissionRequiredForAppCrudMixin, TemplateView):
"""
Votação Simbólica
"""
@ -4519,8 +4609,8 @@ class VotacaoEmBlocoSimbolicaView(PermissionRequiredForAppCrudMixin, TemplateVie
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={}. '
'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:
@ -4551,8 +4641,10 @@ class VotacaoEmBlocoSimbolicaView(PermissionRequiredForAppCrudMixin, TemplateVie
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))
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
@ -4716,7 +4808,7 @@ class VotacaoEmBlocoNominalView(PermissionRequiredForAppCrudMixin, TemplateView)
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.')
'nenhum resultado da votação.')
return self.form_invalid(form, context)
qtde_votos = (int(request.POST['votos_sim']) +
@ -4727,9 +4819,9 @@ class VotacaoEmBlocoNominalView(PermissionRequiredForAppCrudMixin, TemplateView)
# 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.')
'nenhum voto.')
form.add_error(None, 'Não é possível finalizar a votação sem '
'nenhum voto.')
'nenhum voto.')
return self.form_invalid(form, context)
if request.POST['origem'] == 'ordem':
@ -5155,9 +5247,9 @@ class CorrespondenciaCrud(MasterDetailCrud):
initial = super().get_initial()
max_numero_ordem = Correspondencia.objects.filter(
sessao_plenaria=self.kwargs['pk']).aggregate(
Max('numero_ordem'))['numero_ordem__max']
Max('numero_ordem'))['numero_ordem__max']
initial['numero_ordem'] = (
max_numero_ordem if max_numero_ordem else 0) + 1
max_numero_ordem if max_numero_ordem else 0) + 1
return initial
@ -5258,8 +5350,8 @@ class CorrespondenciaEmLoteView(PermissionRequiredMixin, FilterView):
sessao_plenaria = SessaoPlenaria.objects.get(
pk=self.kwargs['pk'])
not_list = [self.kwargs['pk']] + \
[m for m in sessao_plenaria.correspondencias.values_list(
'id', flat=True)]
[m for m in sessao_plenaria.correspondencias.values_list(
'id', flat=True)]
context['object_list'] = context['object_list'].exclude(
pk__in=not_list)

114
sapl/templates/sessao/leitura/leitura_bloco.html

@ -0,0 +1,114 @@
{% extends "crud/detail.html" %}
{% load i18n crispy_forms_tags %}
{% block base_content %}
{% if sessao_iniciada %}
<form method="POST" enctype="application/x-www-form-urlencoded" id="form" action="{% url 'sapl.sessao:leitura_bloco_expediente' pk %}">
{% csrf_token %}
<br><br>
<table class="table table-striped table-bordered">
<thead class="thead-default">
<tr>
<td><h3>{% trans "Mensagem de Leitura" %}</h3></td>
</tr>
</thead>
<tr>
<td class="col-md-12">
<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>
</td>
</tr>
</table>
<br>
<h3 id='frase_selecione'>{% if expediente %} Selecione o(s) expediente(s) desejado(s). {% else %} Selecione a(s) ordem(s) do dia desejada(s). {% endif %}</h3>
<table id='tab_mats' class="table table-striped table-bordered">
<thead class="thead-default">
<tr>
<td><h3> {% if expediente %} {% trans "Expediente" %} {% else %} {% trans "Ordem do Dia" %} {% endif %} </h3></td>
</tr>
</thead>
<div class="checkbox" id="check_all">
<label for="id_check_all">
<input type="checkbox" id="id_check_all" onchange="toggleCheck(this)" /> Marcar/Desmarcar Todos
</label>
</div>
{% for o in object_list %}
<tr class="{% if o.tipo_votacao == 4 %}Leitura{% endif %}" {% if o.tipo_votacao != 4 %} 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.materia.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.first %}
{% if o.materia.tramitacao_set.first.turno %}
<strong>Turno:</strong>&nbsp;
{% for t in turno_choices %}
{% if t.0 == o.materia.tramitacao_set.first.turno %}
{{ t.1 }}
{% endif %}
{% endfor %}<br>
{% endif %}
{% endif %}
<strong>Ementa:</strong>&nbsp;{{ o.materia.ementa|safe }}<br>
<p></p>
</td>
</tr>
{% endfor %}
</table>
{% include 'paginacao.html' %}
<table class="table table-striped table-bordered" style="display:none" id="nenhuma_mat">
<tr>
<td>
<h3>{% if expediente %} Nenhuma matéria do expediente aberta. {% else %} Nenhuma matéria da ordem do dia aberta. {% endif %} </h3>
</td>
</tr>
</table>
{% if expediente %}
<a href="{% url 'sapl.sessao:expedientemateria_list' pk %}" class="btn btn-warning mb-3" id="but_cancel">Voltar</a>
<input type="hidden" id="origem" name="origem" value="expediente">
{% else %}
<a href="{% url 'sapl.sessao:ordemdia_list' pk %}" class="btn btn-warning mb-3" id="but_cancel">Voltar</a>
<input type="hidden" id="origem" name="origem" value="ordem">
{% endif %}
<input type="submit" value="Registrar Leitura" class="btn btn-primary mb-3 float-right" id="but_reg">
</form>
{% endif %}
{% endblock base_content %}
{% block extra_js %}
<script>
function toggleCheck(elem) {
let checkboxes = document.getElementsByName('marcadas_4');
for (let i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].type == 'checkbox')
checkboxes[i].checked = elem.checked;
}
}
</script>
{% endblock extra_js%}

6
sapl/templates/sessao/subnav.yaml

@ -32,6 +32,9 @@
- title: {% trans 'Votação em Bloco' %}
url: votacao_bloco_expediente
check_permission: sessao.add_sessaoplenaria
- title: {% trans 'Leitura em Bloco' %}
url: leitura_bloco_expediente
check_permission: sessao.add_sessaoplenaria
- title: {% trans 'Copiar Matérias para Sessão Posterior' %}
url: transf_mat_exp
check_permission: sessao.add_sessaoplenaria
@ -48,6 +51,9 @@
- title: {% trans 'Votação em Bloco' %}
url: votacao_bloco_ordemdia
check_permission: sessao.add_sessaoplenaria
- title: {% trans 'Leitura em Bloco' %}
url: leitura_bloco_ordem_dia
check_permission: sessao.add_sessaoplenaria
- title: {% trans 'Copiar Matérias para Sessão Posterior' %}
url: transf_mat_ordemdia
check_permission: sessao.add_sessaoplenaria

Loading…
Cancel
Save