diff --git a/sapl/relatorios/urls.py b/sapl/relatorios/urls.py index e31f5dcab..9ca2284a0 100644 --- a/sapl/relatorios/urls.py +++ b/sapl/relatorios/urls.py @@ -5,7 +5,8 @@ from .views import (relatorio_capa_processo, relatorio_documento_administrativo, relatorio_espelho, relatorio_etiqueta_protocolo, relatorio_materia, relatorio_ordem_dia, relatorio_pauta_sessao, - relatorio_protocolo, relatorio_sessao_plenaria) + relatorio_protocolo, relatorio_sessao_plenaria, + resumo_ata_pdf) app_name = AppConfig.name @@ -28,4 +29,6 @@ urlpatterns = [ relatorio_etiqueta_protocolo, name='relatorio_etiqueta_protocolo'), url(r'^relatorios/pauta-sessao/(?P\d+)/$', relatorio_pauta_sessao, name='relatorio_pauta_sessao'), + url(r'^relatorios/(?P\d+)/resumo_ata$', + resumo_ata_pdf, name='resumo_ata_pdf'), ] diff --git a/sapl/relatorios/views.py b/sapl/relatorios/views.py index 53331eadd..dec1d50b7 100755 --- a/sapl/relatorios/views.py +++ b/sapl/relatorios/views.py @@ -2,12 +2,15 @@ from datetime import datetime as dt import html import logging import re +import tempfile from django.core.exceptions import ObjectDoesNotExist from django.http import Http404, HttpResponse from django.utils import timezone from django.utils.translation import ugettext_lazy as _ +from django.template.loader import render_to_string +from sapl.settings import MEDIA_URL from sapl.base.models import Autor, CasaLegislativa from sapl.comissoes.models import Comissao from sapl.materia.models import (Autoria, MateriaLegislativa, Numeracao, @@ -24,12 +27,20 @@ from sapl.sessao.models import (ExpedienteMateria, ExpedienteSessao, from sapl.settings import STATIC_ROOT from sapl.utils import LISTA_DE_UFS, TrocaTag, filiacao_data +from sapl.sessao.views import (get_identificação_basica, get_mesa_diretora, + get_presenca_sessao,get_expedientes, + get_materias_expediente,get_oradores_expediente, + get_presenca_ordem_do_dia,get_materias_ordem_do_dia, + get_oradores_explicações_pessoais, get_ocorrencias_da_sessão) + from .templates import (pdf_capa_processo_gerar, pdf_documento_administrativo_gerar, pdf_espelho_gerar, pdf_etiqueta_protocolo_gerar, pdf_materia_gerar, pdf_ordem_dia_gerar, pdf_pauta_sessao_gerar, pdf_protocolo_gerar, pdf_sessao_plenaria_gerar) +from weasyprint import HTML, CSS + def get_kwargs_params(request, fields): kwargs = {} @@ -1199,3 +1210,65 @@ def get_pauta_sessao(sessao, casa): return (lst_expediente_materia, lst_votacao, inf_basicas_dic) + +def make_pdf(base_url,main_template,header_template,main_css='',header_css=''): + html = HTML(base_url=base_url, string=main_template) + main_doc = html.render(stylesheets=[]) + + def get_page_body(boxes): + for box in boxes: + if box.element_tag == 'body': + return box + return get_page_body(box.all_children()) + + # Template of header + html = HTML(base_url=base_url,string=header_template) + header = html.render(stylesheets=[CSS(string='@page {size:A4; margin:1cm;}')]) + + header_page = header.pages[0] + header_body = get_page_body(header_page._page_box.all_children()) + header_body = header_body.copy_with_children(header_body.all_children()) + + for page in main_doc.pages: + page_body = get_page_body(page._page_box.all_children()) + page_body.children += header_body.all_children() + + pdf_file = main_doc.write_pdf() + + return pdf_file + + +def resumo_ata_pdf(request,pk): + base_url = request.build_absolute_uri() + casa = CasaLegislativa.objects.first() + rodape = ' '.join(get_rodape(casa)) + + sessao_plenaria = SessaoPlenaria.objects.get(pk=pk) + + context = {} + context.update(get_identificação_basica(sessao_plenaria)) + context.update(get_mesa_diretora(sessao_plenaria)) + context.update(get_presenca_sessao(sessao_plenaria)) + context.update(get_expedientes(sessao_plenaria)) + context.update(get_materias_expediente(sessao_plenaria)) + context.update(get_oradores_expediente(sessao_plenaria)) + context.update(get_presenca_ordem_do_dia(sessao_plenaria)) + context.update(get_materias_ordem_do_dia(sessao_plenaria)) + context.update(get_oradores_explicações_pessoais(sessao_plenaria)) + context.update(get_ocorrencias_da_sessão(sessao_plenaria)) + context.update({'object':sessao_plenaria}) + context.update({'data': dt.today().strftime('%d/%m/%Y')}) + context.update({'rodape':rodape}) + header_context = {"casa":casa, 'logotipo':casa.logotipo, 'MEDIA_URL': MEDIA_URL} + + html_template = render_to_string('relatorios/relatorio_ata.html',context) + html_header = render_to_string('relatorios/header_ata.html', header_context) + + pdf_file = make_pdf(base_url=base_url,main_template=html_template,header_template=html_header) + + response = HttpResponse(content_type='application/pdf;') + response['Content-Disposition'] = 'inline; filename=relatorio.pdf' + response['Content-Transfer-Encoding'] = 'binary' + response.write(pdf_file) + + return response \ No newline at end of file diff --git a/sapl/sessao/tests/test_sessao_view.py b/sapl/sessao/tests/test_sessao_view.py index 17b77e8d8..edab4c6fa 100644 --- a/sapl/sessao/tests/test_sessao_view.py +++ b/sapl/sessao/tests/test_sessao_view.py @@ -4,7 +4,21 @@ from django.utils.translation import ugettext_lazy as _ from model_mommy import mommy from sapl.parlamentares.models import Legislatura, SessaoLegislativa -from sapl.sessao.models import SessaoPlenaria, TipoSessaoPlenaria +from sapl.sessao.models import (SessaoPlenaria, TipoSessaoPlenaria, + IntegranteMesa, SessaoPlenariaPresenca, + JustificativaAusencia, ExpedienteSessao, + TipoExpediente, ExpedienteMateria, + Orador, OcorrenciaSessao) + +from sapl.parlamentares.models import Parlamentar, CargoMesa, Filiacao + +from sapl.sessao.views import (get_identificação_basica, get_conteudo_multimidia, + get_mesa_diretora, get_presenca_sessao, + get_expedientes, get_materias_expediente, + get_oradores_expediente, get_presenca_ordem_do_dia, + get_materias_ordem_do_dia, get_oradores_explicações_pessoais, + get_ocorrencias_da_sessão + ) @pytest.mark.django_db(transaction=False) @@ -47,3 +61,90 @@ def test_incluir_sessao_errors(admin_client): [_('Este campo é obrigatório.')]) assert (response.context_data['form'].errors['hora_inicio'] == [_('Este campo é obrigatório.')]) + +@pytest.mark.django_db(transaction=False) +class TestResumoView(): + def setup(self): + self.sessao_plenaria = mommy.make(SessaoPlenaria) + self.parlamentar = mommy.make(Parlamentar) + self.cargo_mesa = mommy.make(CargoMesa) + + self.integrante_mesa = IntegranteMesa(sessao_plenaria=self.sessao_plenaria, + parlamentar=self.parlamentar, + cargo=self.cargo_mesa) + self.integrante_mesa.save() + + def test_get_identificação_basica(self): + id_basica = get_identificação_basica(self.sessao_plenaria) + info_basica = id_basica['basica'] + assert info_basica[0] == 'Tipo de Sessão: ' + str(self.sessao_plenaria.tipo) + + data_inicio = self.sessao_plenaria.data_inicio + abertura = data_inicio.strftime('%d/%m/%Y') if data_inicio else '' + assert info_basica[1] == 'Abertura: ' + abertura +' - '+ self.sessao_plenaria.hora_inicio + + data_fim = self.sessao_plenaria.data_fim + encerramento = data_fim.strftime('%d/%m/%Y') + ' -' if data_fim else '' + assert info_basica[2] == 'Encerramento: ' + encerramento +' '+ self.sessao_plenaria.hora_fim + + def test_get_conteudo_multimidia(self): + multimidia = get_conteudo_multimidia(self.sessao_plenaria) + url_audio = _('Audio: Indisponível') + multimidia_video = _('Video: Indisponível') + + if self.sessao_plenaria.url_audio: + url_audio = _('Audio: ') + str(sessao_plenaria.url_audio) + if self.sessao_plenaria.url_video: + multimidia_video = _('Video: ') + str(sessao_plenaria.url_video) + + assert multimidia == {'multimidia_audio':url_audio, + 'multimidia_video':multimidia_video} + + def test_get_mesa_diretora(self): + mesa = get_mesa_diretora(self.sessao_plenaria) + assert mesa == {'mesa':[{ + 'cargo': self.cargo_mesa, + 'parlamentar': self.parlamentar + }]} + + def test_get_presenca_sessao(self): + justificativa = mommy.make(JustificativaAusencia,sessao_plenaria=self.sessao_plenaria) + presenca = mommy.make(SessaoPlenariaPresenca,sessao_plenaria=self.sessao_plenaria) + + resposta_presenca = get_presenca_sessao(self.sessao_plenaria) + assert resposta_presenca['presenca_sessao'] == [presenca.parlamentar] + assert resposta_presenca['justificativa_ausencia'][0] == justificativa + + def test_get_expedientes(self): + tipo_expediente = mommy.make(TipoExpediente) + expediente = mommy.make(ExpedienteSessao,sessao_plenaria=self.sessao_plenaria,tipo=tipo_expediente) + + resposta_expediente = get_expedientes(self.sessao_plenaria) + + assert resposta_expediente['expedientes'] == [{ + 'conteudo': expediente.conteudo, + 'tipo': tipo_expediente + }] + + def test_get_materias_expediente(self): + pass + + def test_get_oradores_explicações_pessoais(self): + parlamentar = mommy.make(Parlamentar) + partido_sigla = mommy.make(Filiacao, parlamentar=parlamentar) + orador = mommy.make(Orador,sessao_plenaria=self.sessao_plenaria,parlamentar=parlamentar) + + resultado_get_oradores = get_oradores_explicações_pessoais(self.sessao_plenaria) + + assert resultado_get_oradores['oradores_explicacoes'] == [{ + 'numero_ordem': orador.numero_ordem, + 'parlamentar': parlamentar, + 'sgl_partido': partido_sigla.partido.sigla + }] + + def test_get_ocorrencias_da_sessão(self): + ocorrencia = mommy.make(OcorrenciaSessao, sessao_plenaria=self.sessao_plenaria) + resultado_get_ocorrencia = get_ocorrencias_da_sessão(self.sessao_plenaria) + + assert resultado_get_ocorrencia['ocorrencias_da_sessao'][0] == ocorrencia + diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index d00fd73a4..c72a08c32 100755 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -1294,137 +1294,290 @@ def get_turno(turno): else: return '' +def get_identificação_basica(sessao_plenaria): + # ===================================================================== + # Identificação Básica + data_inicio = sessao_plenaria.data_inicio + abertura = data_inicio.strftime('%d/%m/%Y') if data_inicio else '' + data_fim = sessao_plenaria.data_fim + encerramento = data_fim.strftime('%d/%m/%Y') + ' -' if data_fim else '' + return({'basica': [ + _('Tipo de Sessão: %(tipo)s') % {'tipo': sessao_plenaria.tipo}, + _('Abertura: %(abertura)s - %(hora_inicio)s') % { + 'abertura': abertura, 'hora_inicio': sessao_plenaria.hora_inicio}, + _('Encerramento: %(encerramento)s %(hora_fim)s') % { + 'encerramento': encerramento, 'hora_fim': sessao_plenaria.hora_fim} + ]}) + +def get_conteudo_multimidia(sessao_plenaria): + context = {} + if sessao_plenaria.url_audio: + context['multimidia_audio'] = _('Audio: ') + str(sessao_plenaria.url_audio) + else: + context['multimidia_audio'] = _('Audio: Indisponível') + if sessao_plenaria.url_video: + context['multimidia_video'] = _('Video: ') + str(sessao_plenaria.url_video) + else: + context['multimidia_video'] = _('Video: Indisponível') + return context -class ResumoView(DetailView): - template_name = 'sessao/resumo.html' - model = SessaoPlenaria - logger = logging.getLogger(__name__) - - def get(self, request, *args, **kwargs): - self.object = self.get_object() - context = self.get_context_data(object=self.object) - - # ===================================================================== - # Identificação Básica - data_inicio = self.object.data_inicio - abertura = data_inicio.strftime('%d/%m/%Y') if data_inicio else '' - - data_fim = self.object.data_fim - encerramento = data_fim.strftime('%d/%m/%Y') + ' -' if data_fim else '' +def get_mesa_diretora(sessao_plenaria): + mesa = IntegranteMesa.objects.filter(sessao_plenaria=sessao_plenaria) + integrantes = [] + for m in mesa: + parlamentar = Parlamentar.objects.get( + id=m.parlamentar_id) + cargo = CargoMesa.objects.get( + id=m.cargo_id) + integrante = {'parlamentar': parlamentar, 'cargo': cargo} + integrantes.append(integrante) + return ({'mesa': ordenar_integrantes_por_cargo(integrantes)}) + +def get_presenca_sessao(sessao_plenaria): + presencas = SessaoPlenariaPresenca.objects.filter( + sessao_plenaria_id=sessao_plenaria.id + ).order_by('parlamentar__nome_parlamentar') + + parlamentares_sessao = [p.parlamentar for p in presencas] + + ausentes_sessao = JustificativaAusencia.objects.filter( + sessao_plenaria_id=sessao_plenaria.id + ).order_by('parlamentar__nome_parlamentar') + + return ({'presenca_sessao': parlamentares_sessao, + 'justificativa_ausencia': ausentes_sessao}) + +def get_expedientes(sessao_plenaria): + expediente = ExpedienteSessao.objects.filter( + sessao_plenaria_id=sessao_plenaria.id).order_by('tipo__nome') + expedientes = [] + for e in expediente: + tipo = TipoExpediente.objects.get(id=e.tipo_id) + conteudo = e.conteudo + ex = {'tipo': tipo, 'conteudo': conteudo} + expedientes.append(ex) + return ({'expedientes': expedientes}) + +def get_materias_expediente(sessao_plenaria): + materias = ExpedienteMateria.objects.filter( + sessao_plenaria_id=sessao_plenaria.id) + + materias_expediente = [] + for m in materias: + + ementa = m.materia.ementa + titulo = m.materia + numero = m.numero_ordem + tramitacao = m.materia.tramitacao_set.last() + turno = None - context.update({'basica': [ - _('Tipo de Sessão: %(tipo)s') % {'tipo': self.object.tipo}, - _('Abertura: %(abertura)s - %(hora_inicio)s') % { - 'abertura': abertura, 'hora_inicio': self.object.hora_inicio}, - _('Encerramento: %(encerramento)s %(hora_fim)s') % { - 'encerramento': encerramento, 'hora_fim': self.object.hora_fim} - ]}) - # ===================================================================== - # Conteúdo Multimídia - if self.object.url_audio: - context.update({'multimidia_audio': - _('Audio: ') + str(self.object.url_audio)}) - else: - context.update({'multimidia_audio': _('Audio: Indisponível')}) - - if self.object.url_video: - context.update({'multimidia_video': - _('Video: ') + str(self.object.url_video)}) + if tramitacao: + turno = get_turno(tramitacao.turno) + + rv = m.registrovotacao_set.first() + rp = m.retiradapauta_set.filter(materia=m.materia).first() + if rv: + resultado = rv.tipo_resultado_votacao.nome + resultado_observacao = rv.observacao + elif rp: + resultado = rp.tipo_de_retirada.descricao + resultado_observacao = rp.observacao else: - context.update({'multimidia_video': _('Video: Indisponível')}) - - # ===================================================================== - # Mesa Diretora - mesa = IntegranteMesa.objects.filter( - sessao_plenaria=self.object) + resultado = _('Matéria não votada') + resultado_observacao = _(' ') + + autoria = Autoria.objects.filter(materia_id=m.materia_id) + autor = [str(x.autor) for x in autoria] + + mat = {'ementa': ementa, + 'titulo': titulo, + 'numero': numero, + 'turno': turno, + 'resultado': resultado, + 'resultado_observacao': resultado_observacao, + 'autor': autor, + 'numero_protocolo': m.materia.numero_protocolo, + 'numero_processo': m.materia.numeracao_set.last(), + 'observacao': m.observacao + } + materias_expediente.append(mat) + + context = {'materia_expediente': materias_expediente} + return context - integrantes = [] - for m in mesa: - parlamentar = Parlamentar.objects.get( - id=m.parlamentar_id) - cargo = CargoMesa.objects.get( - id=m.cargo_id) - integrante = {'parlamentar': parlamentar, 'cargo': cargo} - integrantes.append(integrante) +def get_oradores_expediente(sessao_plenaria): + oradores = [] + for orador in OradorExpediente.objects.filter( + sessao_plenaria_id=sessao_plenaria.id).order_by('numero_ordem'): + numero_ordem = orador.numero_ordem + url_discurso = orador.url_discurso + observacao = orador.observacao + parlamentar = Parlamentar.objects.get( + id=orador.parlamentar_id) + ora = {'numero_ordem': numero_ordem, + 'url_discurso': url_discurso, + 'parlamentar': parlamentar, + 'observacao': observacao + } + oradores.append(ora) + context = {'oradores': oradores} + return context - context.update({'mesa': ordenar_integrantes_por_cargo(integrantes)}) +def get_presenca_ordem_do_dia(sessao_plenaria): + mesa_aux = get_mesa_diretora(sessao_plenaria) + presencas = PresencaOrdemDia.objects.filter( + sessao_plenaria_id=sessao_plenaria.id + ).order_by('parlamentar__nome_parlamentar') - # ===================================================================== - # Presença Sessão - presencas = SessaoPlenariaPresenca.objects.filter( - sessao_plenaria_id=self.object.id - ).order_by('parlamentar__nome_parlamentar') + parlamentares_mesa_dia = [m for m in mesa_aux['mesa']] + + presidente_dia = '' + for m in mesa_aux['mesa']: + if m['cargo'].descricao == 'Presidente': + presidente_dia = [m['parlamentar']] + break - parlamentares_sessao = [p.parlamentar for p in presencas] + parlamentares_ordem = [p.parlamentar for p in presencas] - ausentes_sessao = JustificativaAusencia.objects.filter( - sessao_plenaria_id=self.object.id - ).order_by('parlamentar__nome_parlamentar') + cont = 0 + for index, parlamentar in enumerate(parlamentares_ordem): + try: + if parlamentar == parlamentares_mesa_dia[cont]["parlamentar"]: + del(parlamentares_ordem[index]) + cont += 1 + except IndexError: + pass - context.update({'presenca_sessao': parlamentares_sessao, - 'justificativa_ausencia': ausentes_sessao}) + context ={} + context.update({'presenca_ordem': parlamentares_ordem}) - # ===================================================================== - # Expedientes - expediente = ExpedienteSessao.objects.filter( - sessao_plenaria_id=self.object.id).order_by('tipo__nome') + config_assinatura_ata = AppsAppConfig.objects.first().assinatura_ata + if config_assinatura_ata == 'T' and parlamentares_ordem: + context.update( + {'texto_assinatura': 'Assinatura de Todos os Parlamentares Presentes na Sessão'}) + context.update({'assinatura_mesa':parlamentares_mesa_dia,'assinatura_presentes': parlamentares_ordem}) + elif config_assinatura_ata == 'M' and parlamentares_mesa_dia: + context.update( + {'texto_assinatura': 'Assinatura da Mesa Diretora da Sessão'}) + context.update({'assinatura_presentes': parlamentares_mesa_dia}) + elif config_assinatura_ata == 'P' and presidente_dia: + context.update( + {'texto_assinatura': 'Assinatura do Presidente da Sessão'}) + context.update({'assinatura_presentes': presidente_dia}) - expedientes = [] - for e in expediente: - tipo = TipoExpediente.objects.get(id=e.tipo_id) - conteudo = e.conteudo - ex = {'tipo': tipo, 'conteudo': conteudo} - expedientes.append(ex) - context.update({'expedientes': expedientes}) + return context - # ===================================================================== - # Matérias Expediente - materias = ExpedienteMateria.objects.filter( - sessao_plenaria_id=self.object.id) +def get_materias_ordem_do_dia(sessao_plenaria): + ordem = OrdemDia.objects.filter(sessao_plenaria_id=sessao_plenaria.id) + materias_ordem = [] + for o in ordem: + ementa = o.materia.ementa + ementa_observacao = o.observacao + titulo = o.materia + numero = o.numero_ordem + tramitacao = o.materia.tramitacao_set.last() + turno = None + if tramitacao: + turno = get_turno(tramitacao.turno) - materias_expediente = [] - for m in materias: + # Verificar resultado + rv = o.registrovotacao_set.filter(materia=o.materia).first() + rp = o.retiradapauta_set.filter(materia=o.materia).first() + if rv: + resultado = rv.tipo_resultado_votacao.nome + resultado_observacao = rv.observacao - ementa = m.materia.ementa - titulo = m.materia - numero = m.numero_ordem - tramitacao = m.materia.tramitacao_set.last() - turno = None + elif rp: + resultado = rp.tipo_de_retirada.descricao + resultado_observacao = rp.observacao - if tramitacao: - turno = get_turno(tramitacao.turno) + else: + resultado = _('Matéria não votada') + resultado_observacao = _(' ') + + voto_sim = "" + voto_nao = "" + voto_abstencoes = "" + voto_nominal = [] + + if o.tipo_votacao == 2: + votos = VotoParlamentar.objects.filter(ordem=o.id) + for voto in votos: + aux_voto = (voto.parlamentar.nome_completo, voto.voto) + voto_nominal.append(aux_voto) + try: + voto = RegistroVotacao.objects.filter(ordem=o.id).last() + voto_sim = voto.numero_votos_sim + voto_nao = voto.numero_votos_nao + voto_abstencoes = voto.numero_abstencoes + except AttributeError: + voto_sim = " Não Informado" + voto_nao = " Não Informado" + voto_abstencoes = " Não Informado" + + autoria = Autoria.objects.filter( + materia_id=o.materia_id) + autor = [str(x.autor) for x in autoria] + mat = {'ementa': ementa, + 'ementa_observacao': ementa_observacao, + 'titulo': titulo, + 'numero': numero, + 'turno': turno, + 'resultado': resultado, + 'resultado_observacao': resultado_observacao, + 'autor': autor, + 'numero_protocolo': o.materia.numero_protocolo, + 'numero_processo': o.materia.numeracao_set.last(), + 'tipo_votacao': o.TIPO_VOTACAO_CHOICES[o.tipo_votacao], + 'voto_sim':voto_sim, + 'voto_nao':voto_nao, + 'voto_abstencoes':voto_abstencoes, + 'voto_nominal': voto_nominal, + } + materias_ordem.append(mat) + + context = {'materias_ordem': materias_ordem} + return context - rv = m.registrovotacao_set.first() - rp = m.retiradapauta_set.filter(materia=m.materia).first() - if rv: - resultado = rv.tipo_resultado_votacao.nome - resultado_observacao = rv.observacao - elif rp: - resultado = rp.tipo_de_retirada.descricao - resultado_observacao = rp.observacao +def get_oradores_explicações_pessoais(sessao_plenaria): + oradores_explicacoes = [] + for orador in Orador.objects.filter( + sessao_plenaria_id=sessao_plenaria.id).order_by('numero_ordem'): + for parlamentar in Parlamentar.objects.filter( + id=orador.parlamentar.id): + partido_sigla = Filiacao.objects.filter( + parlamentar=parlamentar).last() + if not partido_sigla: + sigla = '' else: - resultado = _('Matéria não votada') - resultado_observacao = _(' ') + sigla = partido_sigla.partido.sigla + oradores = { + 'numero_ordem': orador.numero_ordem, + 'parlamentar': parlamentar, + 'sgl_partido': sigla + } + oradores_explicacoes.append(oradores) + context = {'oradores_explicacoes': oradores_explicacoes} + return context - autoria = Autoria.objects.filter(materia_id=m.materia_id) - autor = [str(x.autor) for x in autoria] +def get_ocorrencias_da_sessão(sessao_plenaria): + ocorrencias_sessao = OcorrenciaSessao.objects.filter( + sessao_plenaria_id=sessao_plenaria.id) + context = {'ocorrencias_da_sessao': ocorrencias_sessao} + return context + - mat = {'ementa': ementa, - 'titulo': titulo, - 'numero': numero, - 'turno': turno, - 'resultado': resultado, - 'resultado_observacao': resultado_observacao, - 'autor': autor, - 'numero_protocolo': m.materia.numero_protocolo, - 'numero_processo': m.materia.numeracao_set.last(), - 'observacao': m.observacao - } - materias_expediente.append(mat) + +class ResumoView(DetailView): + template_name = 'sessao/resumo.html' + model = SessaoPlenaria + logger = logging.getLogger(__name__) - context.update({'materia_expediente': materias_expediente}) - - # Votos de Votação Nominal de Matérias Expediente + def get_context(self,*args, **kwargs): + self.object = self.get_object() + context = self.get_context_data(object=self.object) + + # Votos de Votação Nominal de Matérias Expediente materias_expediente_votacao_nominal = ExpedienteMateria.objects.filter( sessao_plenaria_id=self.object.id, tipo_votacao=2).order_by('-materia') @@ -1446,107 +1599,34 @@ class ResumoView(DetailView): votacoes.append(dados_votacao) context.update({'votos_nominais_materia_expediente': votacoes}) - + + # ===================================================================== + # Identificação Básica + context.update(get_identificação_basica(self.object)) + # ===================================================================== + # Conteúdo Multimídia + context.update(get_conteudo_multimidia(self.object)) + # ===================================================================== + # Mesa Diretora + context.update(get_mesa_diretora(self.object)) + # ===================================================================== + # Presença Sessão + context.update(get_presenca_sessao(self.object)) + # ===================================================================== + # Expedientes + context.update(get_expedientes(self.object)) + # ===================================================================== + # Matérias Expediente + context.update(get_materias_expediente(self.object)) # ===================================================================== # Oradores Expediente - oradores = [] - for orador in OradorExpediente.objects.filter( - sessao_plenaria_id=self.object.id).order_by('numero_ordem'): - numero_ordem = orador.numero_ordem - url_discurso = orador.url_discurso - observacao = orador.observacao - parlamentar = Parlamentar.objects.get( - id=orador.parlamentar_id) - ora = {'numero_ordem': numero_ordem, - 'url_discurso': url_discurso, - 'parlamentar': parlamentar, - 'observacao': observacao - } - oradores.append(ora) - - context.update({'oradores': oradores}) - + context.update(get_oradores_expediente(self.object)) # ===================================================================== # Presença Ordem do Dia - presencas = PresencaOrdemDia.objects.filter( - sessao_plenaria_id=self.object.id - ).order_by('parlamentar__nome_parlamentar') - - parlamentares_mesa_dia = [m['parlamentar'] for m in context['mesa']] - # composicao_mesa = ComposicaoMesa.objects.filter(sessao_legislativa=sessao) - - presidente_dia = '' - for m in context['mesa']: - if m['cargo'].descricao == 'Presidente': - presidente_dia = [m['parlamentar']] - break - - parlamentares_ordem = [p.parlamentar for p in presencas] - - context.update({'presenca_ordem': parlamentares_ordem}) - - config_assinatura_ata = AppsAppConfig.objects.first().assinatura_ata - if config_assinatura_ata == 'T' and parlamentares_ordem: - context.update( - {'texto_assinatura': 'Assinatura de Todos os Parlamentares Presentes na Sessão'}) - context.update({'assinatura_presentes': parlamentares_ordem}) - elif config_assinatura_ata == 'M' and parlamentares_mesa_dia: - context.update( - {'texto_assinatura': 'Assinatura da Mesa Diretora da Sessão'}) - context.update({'assinatura_presentes': parlamentares_mesa_dia}) - elif config_assinatura_ata == 'P' and presidente_dia: - context.update( - {'texto_assinatura': 'Assinatura do Presidente da Sessão'}) - context.update({'assinatura_presentes': presidente_dia}) - + context.update(get_presenca_ordem_do_dia(self.object)) # ===================================================================== # Matérias Ordem do Dia - ordem = OrdemDia.objects.filter( - sessao_plenaria_id=self.object.id) - materias_ordem = [] - for o in ordem: - ementa = o.materia.ementa - ementa_observacao = o.observacao - titulo = o.materia - numero = o.numero_ordem - tramitacao = o.materia.tramitacao_set.last() - turno = None - if tramitacao: - turno = get_turno(tramitacao.turno) - - # Verificar resultado - rv = o.registrovotacao_set.filter(materia=o.materia).first() - rp = o.retiradapauta_set.filter(materia=o.materia).first() - if rv: - resultado = rv.tipo_resultado_votacao.nome - resultado_observacao = rv.observacao - elif rp: - resultado = rp.tipo_de_retirada.descricao - resultado_observacao = rp.observacao - else: - resultado = _('Matéria não votada') - resultado_observacao = _(' ') - - autoria = Autoria.objects.filter( - materia_id=o.materia_id) - autor = [str(x.autor) for x in autoria] - - mat = {'ementa': ementa, - 'ementa_observacao': ementa_observacao, - 'titulo': titulo, - 'numero': numero, - 'turno': turno, - 'resultado': resultado, - 'resultado_observacao': resultado_observacao, - 'autor': autor, - 'numero_protocolo': o.materia.numero_protocolo, - 'numero_processo': o.materia.numeracao_set.last() - } - materias_ordem.append(mat) - - context.update({'materias_ordem': materias_ordem}) - - # Votos de Votação Nominal de Matérias Ordem do Dia + # Votos de Votação Nominal de Matérias Ordem do Dia materias_ordem_dia_votacao_nominal = OrdemDia.objects.filter( sessao_plenaria_id=self.object.id, tipo_votacao=2).order_by('-materia') @@ -1569,34 +1649,13 @@ class ResumoView(DetailView): context.update({'votos_nominais_materia_ordem_dia': votacoes_od}) + context.update(get_materias_ordem_do_dia(self.object)) # ===================================================================== # Oradores nas Explicações Pessoais - oradores_explicacoes = [] - for orador in Orador.objects.filter( - sessao_plenaria_id=self.object.id).order_by('numero_ordem'): - for parlamentar in Parlamentar.objects.filter( - id=orador.parlamentar.id): - partido_sigla = Filiacao.objects.filter( - parlamentar=parlamentar).last() - if not partido_sigla: - sigla = '' - else: - sigla = partido_sigla.partido.sigla - oradores = { - 'numero_ordem': orador.numero_ordem, - 'parlamentar': parlamentar, - 'sgl_partido': sigla - } - oradores_explicacoes.append(oradores) - context.update({'oradores_explicacoes': oradores_explicacoes}) - + context.update(get_oradores_explicações_pessoais(self.object)) # ===================================================================== # Ocorrẽncias da Sessão - ocorrencias_sessao = OcorrenciaSessao.objects.filter( - sessao_plenaria_id=self.object.id) - - context.update({'ocorrencias_da_sessao': ocorrencias_sessao}) - + context.update(get_ocorrencias_da_sessão(self.object)) # ===================================================================== # Indica a ordem com a qual o template será renderizado ordenacao = ResumoOrdenacao.objects.first() @@ -1667,9 +1726,14 @@ class ResumoView(DetailView): 'decimo_terceiro_ordenacao': dict_ord_template['ocorr_sessao'] }) + return context + + def get(self, request, *args, **kwargs): + context = self.get_context() return self.render_to_response(context) + class ResumoAtaView(ResumoView): template_name = 'sessao/resumo_ata.html' logger = logging.getLogger(__name__) diff --git a/sapl/static/sapl/css/header-relatorio.css b/sapl/static/sapl/css/header-relatorio.css new file mode 100644 index 000000000..65f6f629d --- /dev/null +++ b/sapl/static/sapl/css/header-relatorio.css @@ -0,0 +1,62 @@ +html body p { + border-top: 1px solid black; + text-align: center; + font-size: 11pt; + padding: 5px; + margin-top: -15px; +} +html body section { + box-sizing: border-box; +} +html body section dl { + display: flex; + flex-wrap: wrap; + rows: 2; + columns: 2; +} +html body section dt{ + width: 50px; +} +html body section dd { + max-width:550px; + text-align: center; +} +html body section dd ul li { + list-style-type: none; + margin-left: 90px; + margin-bottom: -15px; + +} +h2 { + font-size: 14pt; +} +h3 { + font-size: 10pt; + color: #6e6e6e; +} +ul { + padding: 0; + list-style: none; + margin-top:10px; +} + +html body section dt img { + max-width:80px; + margin-left: 20px; + margin-left: 50px; + +} +h3 { + font-size: 10pt; + color: #6e6e6e; +} +ul { + padding: 0; + list-style: none; + margin-top:10px; +} + +html body section dt img { + max-width:80px; + margin-left: 20px; +} \ No newline at end of file diff --git a/sapl/static/sapl/css/relatorio.css b/sapl/static/sapl/css/relatorio.css new file mode 100644 index 000000000..c3f2ec21f --- /dev/null +++ b/sapl/static/sapl/css/relatorio.css @@ -0,0 +1,56 @@ +@page{ + margin-top: 4.5cm; + size: A4 portrait; +} + +h2.gray-title{ + color: gray; + font-size: 14pt; + break-after: avoid-page; + page-break-after: avoid; +} + +h3 { + font-size: 10pt; + break-after: avoid-page; + page-break-after: avoid; +} + +p { + font-size: 10pt; + text-align: justify; + text-justify: inter-word; +} + +fieldset { + border: 0; +} + +html body section { + box-sizing: border-box; +} + +html body section dl { + display: flex; + flex-wrap: wrap; + columns: 5; +} + +html body section dt{ + width: 50px; +} + +html body section dd { + text-align: center; +} + +html body section dd ul li { + list-style-type: none; + margin-left: 50px; +} + +fieldset { + page-break-after: avoid; + margin:5px; + padding:0px; +} \ No newline at end of file diff --git a/sapl/templates/relatorios/header_ata.html b/sapl/templates/relatorios/header_ata.html new file mode 100644 index 000000000..494d2c60b --- /dev/null +++ b/sapl/templates/relatorios/header_ata.html @@ -0,0 +1,31 @@ +{% load common_tags %} +{% load render_bundle from webpack_loader %} +{% load webpack_static from webpack_loader %} +{% load static %} + + + + + + + + + + +
+
+
+ +
+
+
    +
  • {{casa}}

  • +
  • Sistema de Apoio ao Processo Legislativo

  • +
+
+
+
+

+ + + \ No newline at end of file diff --git a/sapl/templates/relatorios/relatorio_ata.html b/sapl/templates/relatorios/relatorio_ata.html new file mode 100644 index 000000000..581343677 --- /dev/null +++ b/sapl/templates/relatorios/relatorio_ata.html @@ -0,0 +1,101 @@ +{% load common_tags %} +{% load static %} + + + + + + +

Extrato Reunião

+ {% include 'sessao/blocos_ata/identificacao_basica.html' %} + {% include 'sessao/blocos_ata/mesa_diretora.html' %} + {% include 'sessao/blocos_ata/lista_presenca.html' %} + {% include 'sessao/blocos_ata/expedientes.html' %} + {% include 'sessao/blocos_ata/materias_expediente.html' %} + {% include 'sessao/blocos_ata/oradores_expediente.html' %} + {% include 'sessao/blocos_ata/lista_presenca_ordem_dia.html' %} + {% include 'sessao/blocos_ata/materias_ordem_dia.html' %} + {% include 'sessao/blocos_ata/oradores_explicacoes.html' %} + + {% if assinatura_mesa or assinatura_presentes %} + +
+ {{texto_assinatura}} + + + + + + + {% for p in assinatura_mesa %} + {% if forloop.counter0|divisibleby:2 %} + + + + {% endif %} + {% endfor %} + + {% for p in assinatura_presentes %} + {% if forloop.counter0|divisibleby:2 %} + + + + {% endif %} + {% endfor %} + +
+
____________________
+

{{p.cargo}}: {{p.parlamentar.nome_completo}} / {{ p.parlamentar|filiacao_data_filter:object.data_inicio }}

+


+
+ {% else %} +
____________________
+

{{p.cargo}}: {{p.parlamentar.nome_completo}} / {{ p.parlamentar|filiacao_data_filter:object.data_inicio }}

+


+
+
+
_____________________
+

{{p.nome_completo}} / {{ p|filiacao_data_filter:object.data_inicio }}

+


+
+ {% else %} +
_____________________
+

{{p.nome_completo}} / {{ p|filiacao_data_filter:object.data_inicio }}

+


+
+
+ {% endif%} +
+ + \ No newline at end of file diff --git a/sapl/templates/sessao/blocos_ata/assinaturas.html b/sapl/templates/sessao/blocos_ata/assinaturas.html index 88d9dd04a..1282af63b 100644 --- a/sapl/templates/sessao/blocos_ata/assinaturas.html +++ b/sapl/templates/sessao/blocos_ata/assinaturas.html @@ -1,13 +1,17 @@ {% load common_tags %} - -

-

+
{{texto_assinatura}}


+ {% for p in assinatura_mesa %} +
___________________________________________
+ {{p.cargo}}: {{p.parlamentar.nome_completo}} / {{ p.parlamentar|filiacao_data_filter:object.data_inicio }} +


+
+ {% endfor %} {% for p in assinatura_presentes %}
___________________________________________
- {{p.nome_parlamentar}} / {{ p|filiacao_data_filter:object.data_inicio }} + {{p.nome_completo}} / {{ p|filiacao_data_filter:object.data_inicio }}


{% endfor %} diff --git a/sapl/templates/sessao/blocos_ata/lista_presenca.html b/sapl/templates/sessao/blocos_ata/lista_presenca.html index 68e869cb5..329fde406 100644 --- a/sapl/templates/sessao/blocos_ata/lista_presenca.html +++ b/sapl/templates/sessao/blocos_ata/lista_presenca.html @@ -5,7 +5,7 @@ {% if presenca_sessao %} Lista de Presença na Sessão: {% for p in presenca_sessao %} - {{p.nome_parlamentar}} / {{ p|filiacao_data_filter:object.data_inicio }} ; + {{p.nome_completo}} / {{ p|filiacao_data_filter:object.data_inicio }} ; {% endfor %} {% endif %}

@@ -13,7 +13,7 @@ {% if justificativa_ausencia %} Justificativas de Ausências na Sessão: {% for j in justificativa_ausencia %} - {{j.parlamentar}} / {{ j.tipo_ausencia }} ; + {{j.parlamentar.nome_completo}} / {{ j.tipo_ausencia }} ; {% endfor %} {% endif %}

diff --git a/sapl/templates/sessao/blocos_ata/lista_presenca_ordem_dia.html b/sapl/templates/sessao/blocos_ata/lista_presenca_ordem_dia.html index 685ffd2bd..d6c8014ca 100644 --- a/sapl/templates/sessao/blocos_ata/lista_presenca_ordem_dia.html +++ b/sapl/templates/sessao/blocos_ata/lista_presenca_ordem_dia.html @@ -5,7 +5,7 @@ {% if presenca_ordem %} Lista de Presença na Ordem do Dia: {% for p in presenca_ordem %} - {{p.nome_parlamentar}} / {{ p|filiacao_data_filter:object.data_inicio }} ; + {{p.nome_completo}} / {{ p|filiacao_data_filter:object.data_inicio }} ; {% endfor %} {% endif %}

diff --git a/sapl/templates/sessao/blocos_ata/materias_ordem_dia.html b/sapl/templates/sessao/blocos_ata/materias_ordem_dia.html index c5ffd15df..9aa620a04 100644 --- a/sapl/templates/sessao/blocos_ata/materias_ordem_dia.html +++ b/sapl/templates/sessao/blocos_ata/materias_ordem_dia.html @@ -1,24 +1,34 @@
- -

- {% if materias_ordem %} - Matérias da Ordem do Dia: - {% for m in materias_ordem %} - {{m.numero}} - {{m.titulo}} - {% if m.turno %} - Turno:{{m.turno}} +
+ Matérias da Ordem do Dia: +

+ {% for m in materias_ordem %} +

+ {{m.numero}} - {{m.titulo}}
+ Turno:{{m.turno}}
+ Autor: {{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }} + {% if m.numero_protocolo %} + Número de Protocolo: {{ m.numero_protocolo }} + {% endif %} + {% if m.numero_processo %} + Processo: {{ m.numero_processo }} + {% endif %} +

Descrição: {{m.ementa|safe}}

+ Resultado: {{m.resultado}} {{m.resultado_observacao}} +
+

Tipo: {{m.tipo_votacao}}

+
Sim:{{m.voto_sim}}
+
Não:{{m.voto_nao}} +
Abstenções:{{m.voto_abstencoes}}
+
+ {% if m.voto_nominal%} + Votos Nominais +
    + {% for voto in m.voto_nominal %} +
  • {{voto.0}} - {{voto.1}}
  • + {% endfor %} +
{% endif %} - Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }} - {% if m.numero_protocolo %} - Número de Protocolo: {{ m.numero_protocolo }} - {% endif %} - {% if m.numero_processo %} - Processo: {{ m.numero_processo }} - {% endif %} - {{m.ementa|safe}} - {{m.resultado}} {{m.resultado_observacao}} - {% endfor %} - {% endif %} -

- +
+ {% endfor %}
\ No newline at end of file diff --git a/sapl/templates/sessao/blocos_ata/mesa_diretora.html b/sapl/templates/sessao/blocos_ata/mesa_diretora.html index f09e9b8e0..fb27b0fcc 100644 --- a/sapl/templates/sessao/blocos_ata/mesa_diretora.html +++ b/sapl/templates/sessao/blocos_ata/mesa_diretora.html @@ -4,7 +4,7 @@ Mesa Diretora: {% for m in mesa %} {{m.cargo}}: - {{m.parlamentar.nome_parlamentar}} / {{ m.parlamentar.filiacao_atual }} ; + {{m.parlamentar.nome_completo}} / {{ m.parlamentar.filiacao_atual }} ; {% endfor %} {% endif %}

diff --git a/sapl/templates/sessao/blocos_ata/oradores_expediente.html b/sapl/templates/sessao/blocos_ata/oradores_expediente.html index 8bc420b3c..bc39db224 100644 --- a/sapl/templates/sessao/blocos_ata/oradores_expediente.html +++ b/sapl/templates/sessao/blocos_ata/oradores_expediente.html @@ -3,7 +3,7 @@ {% if oradores %} Oradores do Expediente: {% for o in oradores %} -
{{o.numero_ordem}} - {{o.parlamentar}}
+
{{o.numero_ordem}} - {{o.parlamentar.nome_completo}}
{{o.url_discurso}}
{{o.observacao}}

diff --git a/sapl/templates/sessao/blocos_ata/oradores_explicacoes.html b/sapl/templates/sessao/blocos_ata/oradores_explicacoes.html index 18ced7b07..5af2b9ff2 100644 --- a/sapl/templates/sessao/blocos_ata/oradores_explicacoes.html +++ b/sapl/templates/sessao/blocos_ata/oradores_explicacoes.html @@ -3,7 +3,7 @@ {% if oradores_explicacoes %} Oradores das Explicações Pessoais: {% for o in oradores_explicacoes %} - {{o.numero_ordem}} - {{o.parlamentar.nome_parlamentar}} / {{ o.parlamentar.filiacao_atual }} ; + {{o.numero_ordem}} - {{o.parlamentar.nome_completo}} / {{ o.parlamentar.filiacao_atual }} ; {{o.url_discurso}} {% endfor %} {% endif %} diff --git a/sapl/templates/sessao/resumo_ata.html b/sapl/templates/sessao/resumo_ata.html index 47c7d7232..12507b79a 100644 --- a/sapl/templates/sessao/resumo_ata.html +++ b/sapl/templates/sessao/resumo_ata.html @@ -6,7 +6,17 @@

Extrato Eletrônico da {{sessaoplenaria}}

-{% endblock %} + +
+

+ + + Impressão PDF + + +

+
+{% endblock title %} {% block detail_content %} {% include 'sessao/blocos_ata/'|add:primeiro_ordenacao %}