Browse Source

Fix #3106 - Cópia de Matérias entre Sessões Plenárias (#3129)

* Fix #3106 - Cópia de Matérias entre Sessões Plenárias

Adiciona novos botões e Adiciona novos endpoints

Adiciona novos templates

Implementa cópia de matérias

Correção de permissão e refatoração

Captura de erro

Correções e Alterações

Update sapl/sessao/views.py

Co-Authored-By: Edward Ribeiro <eribeiro@users.noreply.github.com>

Retirar comentários

Refatoração

Correção template

Altera posição botão

Aplica subnav nas telas

Corrigir apresentação de erro

Implementa materias_sessao_plenaria_ajax

Refatora template

Exclui cód. não utilizado

Refatoração url

Correções

Refatoração

Refatoração

Refatoração

Correção

Correção e Refatoração

* Refatoração

Co-authored-by: Edward <9326037+edwardoliveira@users.noreply.github.com>

* Refatoração

Co-authored-by: Edward <9326037+edwardoliveira@users.noreply.github.com>

* Altera verif. categoria materia

* Refatoração

* Refatoração

* Refatoração

* Altera label botão

* Evita duplo clique no submit

* Altera label opção menu

* Altera títulos

* Adiciona nome sessão atual no título da pág.

Co-authored-by: Edward <9326037+edwardoliveira@users.noreply.github.com>
pull/3244/head
João Rodrigues 4 years ago
committed by GitHub
parent
commit
bec89d424e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      sapl/sessao/urls.py
  2. 189
      sapl/sessao/views.py
  3. 16
      sapl/templates/sessao/expedientemateria_list.html
  4. 14
      sapl/templates/sessao/ordemdia_list.html
  5. 7
      sapl/templates/sessao/subnav.yaml
  6. 144
      sapl/templates/sessao/transf_mat_sessao.html

13
sapl/sessao/urls.py

@ -34,7 +34,9 @@ from sapl.sessao.views import (AdicionarVariasMateriasExpediente,
recuperar_nome_tipo_sessao, recuperar_nome_tipo_sessao,
ExpedienteLeituraView, ExpedienteLeituraView,
OrdemDiaLeituraView, OrdemDiaLeituraView,
retirar_leitura) retirar_leitura,
TransferenciaMateriasExpediente, TransferenciaMateriasOrdemDia,
filtra_materias_copia_sessao_ajax)
from .apps import AppConfig from .apps import AppConfig
@ -75,6 +77,9 @@ urlpatterns = [
url(r'^sessao/sessao-legislativa-legislatura-ajax/', url(r'^sessao/sessao-legislativa-legislatura-ajax/',
sessao_legislativa_legislatura_ajax, sessao_legislativa_legislatura_ajax,
name='sessao_legislativa_legislatura_ajax_view'), name='sessao_legislativa_legislatura_ajax_view'),
url(r'^sessao/filtra-materias-copia-sessao-ajax/',
filtra_materias_copia_sessao_ajax,
name='filtra_materias_copia_sessao_ajax_view'),
url(r'^sessao/(?P<pk>\d+)/(?P<spk>\d+)/abrir-votacao$', url(r'^sessao/(?P<pk>\d+)/(?P<spk>\d+)/abrir-votacao$',
abrir_votacao, abrir_votacao,
@ -192,4 +197,10 @@ urlpatterns = [
url(r'^sessao/(?P<pk>\d+)/(?P<iso>\d+)/(?P<oid>\d+)/retirar-leitura$', url(r'^sessao/(?P<pk>\d+)/(?P<iso>\d+)/(?P<oid>\d+)/retirar-leitura$',
retirar_leitura, name='retirar_leitura'), retirar_leitura, name='retirar_leitura'),
url(r'^sessao/(?P<pk>\d+)/transf-mat-exp$',
TransferenciaMateriasExpediente.as_view(),
name="transf_mat_exp"),
url(r'^sessao/(?P<pk>\d+)/transf-mat-ordemdia$',
TransferenciaMateriasOrdemDia.as_view(),
name="transf_mat_ordemdia"),
] ]

189
sapl/sessao/views.py

@ -517,6 +517,194 @@ def get_presencas_generic(model, sessao, legislatura):
yield (m.parlamentar, False) yield (m.parlamentar, False)
# Constantes de identificação de categoria de Matéria Legislativa
# para Cópia de Matérias entre Sessões
MATERIAS_EXPEDIENTE = 1
MATERIAS_ORDEMDIA = 2
def filtra_materias_copia_sessao_ajax(request):
categoria_materia = int(request.GET['categoria_materia'])
sessao_plenaria = request.GET['sessao_plenaria_atual']
sessao_plenaria_destino = request.GET['sessao_plenaria_destino']
if categoria_materia == MATERIAS_EXPEDIENTE:
materias_sessao_destino = ExpedienteMateria.objects.filter(
sessao_plenaria=sessao_plenaria_destino
).values_list('materia__id')
lista_materias_disponiveis_copia = ExpedienteMateria.objects.filter(
sessao_plenaria=sessao_plenaria
).exclude(materia__id__in=materias_sessao_destino)
elif categoria_materia == MATERIAS_ORDEMDIA:
materias_sessao_destino = OrdemDia.objects.filter(
sessao_plenaria=sessao_plenaria_destino
).values_list('materia__id')
lista_materias_disponiveis_copia = OrdemDia.objects.filter(
sessao_plenaria=sessao_plenaria
).exclude(materia__id__in=materias_sessao_destino)
lista_materias = [
{
'id': opcao.id,
'materia_id': opcao.materia.id,
'materia_tipo_sigla': opcao.materia.tipo.sigla,
'materia_numero': opcao.materia.numero,
'materia_ano': opcao.materia.ano,
'materia_tipo_descricao': opcao.materia.tipo.descricao
} for opcao in lista_materias_disponiveis_copia
]
return JsonResponse({ 'materias': lista_materias })
class TransferenciaMateriasSessaoAbstract(PermissionRequiredMixin, ListView):
logger = logging.getLogger(__name__)
template_name = 'sessao/transf_mat_sessao.html'
def get_context_data(self, **kwargs):
context = super(
TransferenciaMateriasSessaoAbstract, self
).get_context_data(**kwargs)
sessao_plenaria_atual = SessaoPlenaria.objects.get(pk=self.kwargs['pk'])
context['subnav_template_name'] = 'sessao/subnav.yaml'
context['root_pk'] = self.kwargs['pk']
if not sessao_plenaria_atual.finalizada:
msg = _('A sessão plenária deve estar finalizada.')
messages.add_message(self.request, messages.ERROR, msg)
return context
if self.expediente:
context['title'] = '%s <small>(%s)</small>' % (
self.title, sessao_plenaria_atual.__str__()
)
context["categoria_materia"] = self.categoria_materia
materias_sessao = ExpedienteMateria.objects.filter(
sessao_plenaria=sessao_plenaria_atual
).exists()
elif self.ordem:
context["title"] = '%s <small>(%s)</small>' % (
self.title, sessao_plenaria_atual.__str__()
)
context["categoria_materia"] = self.categoria_materia
materias_sessao = OrdemDia.objects.filter(
sessao_plenaria=sessao_plenaria_atual
).exists()
if materias_sessao:
context['sessoes_destino'] = SessaoPlenaria.objects.filter(
data_inicio__gte=sessao_plenaria_atual.data_inicio
).exclude(pk=sessao_plenaria_atual.pk).order_by("-data_inicio")
context['materias_sessao'] = materias_sessao
return context
def post(self, request, *args, **kwargs):
marcadas = request.POST.getlist('opcao_id')
if not marcadas:
msg = _('Nenhuma matéria foi selecionada.')
messages.add_message(request, messages.ERROR, msg)
return self.get(request, self.kwargs)
sessao_plenaria_destino_id = request.POST['sessao_plenaria']
if not sessao_plenaria_destino_id:
self.logger.error(
"Sessão plenária de destino inexistente."
)
msg = _('Ocorreu um erro inesperado. Tente novamente.')
messages.add_message(request, messages.ERROR, msg)
msg_c = _(
'Se o problema persistir, entre em contato com o suporte do ' \
'Interlegis.'
)
messages.add_message(request, messages.WARNING, msg_c)
return self.get(request, self.kwargs)
sessao = SessaoPlenaria.objects.get(id=sessao_plenaria_destino_id)
if self.expediente:
lista_expediente = []
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
):
lista_expediente.append(
ExpedienteMateria(
sessao_plenaria=sessao, materia=expediente.materia,
data_ordem=expediente.data_ordem,
observacao=expediente.observacao,
numero_ordem=num_ordem,
tipo_votacao=expediente.tipo_votacao,
votacao_aberta=False, registro_aberto=False
)
)
ExpedienteMateria.objects.bulk_create(lista_expediente)
elif self.ordem:
lista_ordemdia = []
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
):
lista_ordemdia.append(
OrdemDia(
sessao_plenaria=sessao, materia=ordemdia.materia,
data_ordem=ordemdia.data_ordem,
observacao=ordemdia.observacao,
numero_ordem=num_ordem,
tipo_votacao=ordemdia.tipo_votacao,
votacao_aberta=False, registro_aberto=False
)
)
OrdemDia.objects.bulk_create(lista_ordemdia)
msg = _('Matéria(s) copiada(s) com sucesso.')
messages.add_message(request, messages.SUCCESS, msg)
success_url = reverse(
self.listagem_url, kwargs={'pk': sessao_plenaria_destino_id}
)
return HttpResponseRedirect(success_url)
class TransferenciaMateriasExpediente(TransferenciaMateriasSessaoAbstract):
expediente = True
ordem = False
title = "Copiar Matérias do Expediente"
categoria_materia = MATERIAS_EXPEDIENTE
listagem_url = 'sapl.sessao:expedientemateria_list'
model = ExpedienteMateria
permission_required = ('sessao.change_expedientemateria', )
class TransferenciaMateriasOrdemDia(TransferenciaMateriasSessaoAbstract):
expediente = False
ordem = True
title = "Copiar Matérias da Ordem do Dia"
categoria_materia = MATERIAS_ORDEMDIA
listagem_url = 'sapl.sessao:ordemdia_list'
model = OrdemDia
permission_required = ('sessao.change_ordemdia', )
class TipoExpedienteCrud(CrudAux): class TipoExpedienteCrud(CrudAux):
model = TipoExpediente model = TipoExpediente
@ -586,6 +774,7 @@ class MateriaOrdemDiaCrud(MasterDetailCrud):
self.paginate_by = None self.paginate_by = None
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
has_permition = self.request.user.has_module_perms(AppConfig.label) has_permition = self.request.user.has_module_perms(AppConfig.label)
return customize_link_materia(context, self.kwargs['pk'], has_permition, False) return customize_link_materia(context, self.kwargs['pk'], has_permition, False)

16
sapl/templates/sessao/expedientemateria_list.html

@ -2,11 +2,8 @@
{% load i18n %} {% load i18n %}
{% load common_tags %} {% load common_tags %}
{% block more_buttons %} {% block more_buttons %}
{% if perms|get_add_perm:view %} {% if perms|get_add_perm:view %}
</a>
<a href="{% url 'sapl.sessao:adicionar_varias_materias_expediente' root_pk %}" class="btn btn-outline-primary"> <a href="{% url 'sapl.sessao:adicionar_varias_materias_expediente' root_pk %}" class="btn btn-outline-primary">
{% blocktrans with verbose_name=view.verbose_name %} Adicionar Várias Matérias {% endblocktrans %} {% blocktrans with verbose_name=view.verbose_name %} Adicionar Várias Matérias {% endblocktrans %}
</a> </a>
@ -22,11 +19,9 @@
</div> </div>
</a> </a>
{% endif %} {% endif %}
{% endblock more_buttons %} {% endblock more_buttons %}
{% block extra_js %} {% block extra_js %}
<script type="text/javascript"> <script type="text/javascript">
var pk_sessao = {{ root_pk }}; var pk_sessao = {{ root_pk }};
var pk_list = {{ object_list|to_list_pk|safe }}; var pk_list = {{ object_list|to_list_pk|safe }};
@ -38,21 +33,21 @@
}); });
$('tbody').sortable({ $('tbody').sortable({
start: function(event, ui) { start: function(event, ui) {
ui.item.startPos = ui.item.index(); ui.item.startPos = ui.item.index();
}, },
stop: function(event, ui) { stop: function(event, ui) {
var pos_ini = ui.item.startPos; var pos_ini = ui.item.startPos;
var pos_fim = ui.item.index(); var pos_fim = ui.item.index();
$.ajax({ $.ajax({
data: {pos_ini: pos_ini, data: {
pos_ini: pos_ini,
pos_fim: pos_fim, pos_fim: pos_fim,
pk_sessao: pk_sessao, pk_sessao: pk_sessao,
pk_list, pk_list,
materia: 'expediente'}, materia: 'expediente'
},
type: 'POST', type: 'POST',
url: "{% url 'sapl.sessao:mudar_ordem_materia_sessao' %}", url: "{% url 'sapl.sessao:mudar_ordem_materia_sessao' %}",
}); });
@ -60,11 +55,10 @@
setTimeout(function(){ window.location.reload(true) }, 500); setTimeout(function(){ window.location.reload(true) }, 500);
} }
}); });
$(window).on('beforeunload', function () { $(window).on('beforeunload', function () {
$('tbody').sortable('disable'); $('tbody').sortable('disable');
$("input[type=submit], input[type=button]").prop("disabled", "disabled"); $("input[type=submit], input[type=button]").prop("disabled", "disabled");
}); });
</script> </script>
{% endblock %} {% endblock %}

14
sapl/templates/sessao/ordemdia_list.html

@ -2,9 +2,7 @@
{% load i18n %} {% load i18n %}
{% load common_tags %} {% load common_tags %}
{% block more_buttons %} {% block more_buttons %}
{% if perms|get_add_perm:view %} {% if perms|get_add_perm:view %}
<a href="{% url 'sapl.sessao:adicionar_varias_materias_ordem_dia' root_pk %}" class="btn btn-outline-primary"> <a href="{% url 'sapl.sessao:adicionar_varias_materias_ordem_dia' root_pk %}" class="btn btn-outline-primary">
{% blocktrans with verbose_name=view.verbose_name %} Adicionar Várias Matérias {% endblocktrans %} {% blocktrans with verbose_name=view.verbose_name %} Adicionar Várias Matérias {% endblocktrans %}
@ -21,11 +19,9 @@
</div> </div>
</a> </a>
{% endif %} {% endif %}
{% endblock more_buttons %} {% endblock more_buttons %}
{% block extra_js %} {% block extra_js %}
<script type="text/javascript"> <script type="text/javascript">
var pk_sessao = {{root_pk}}; var pk_sessao = {{root_pk}};
var pk_list = {{ object_list|to_list_pk|safe }}; var pk_list = {{ object_list|to_list_pk|safe }};
@ -37,21 +33,21 @@
}); });
$('tbody').sortable({ $('tbody').sortable({
start: function(event, ui) { start: function(event, ui) {
ui.item.startPos = ui.item.index(); ui.item.startPos = ui.item.index();
}, },
stop: function(event, ui) { stop: function(event, ui) {
var pos_ini = ui.item.startPos; var pos_ini = ui.item.startPos;
var pos_fim = ui.item.index(); var pos_fim = ui.item.index();
$.ajax({ $.ajax({
data: {pos_ini: pos_ini, data: {
pos_ini: pos_ini,
pos_fim: pos_fim, pos_fim: pos_fim,
pk_sessao: pk_sessao, pk_sessao: pk_sessao,
pk_list, pk_list,
materia: 'ordem'}, materia: 'ordem'
},
type: 'POST', type: 'POST',
url: "{% url 'sapl.sessao:mudar_ordem_materia_sessao' %}", url: "{% url 'sapl.sessao:mudar_ordem_materia_sessao' %}",
}); });
@ -59,10 +55,10 @@
setTimeout(function(){ window.location.reload(true) }, 500); setTimeout(function(){ window.location.reload(true) }, 500);
} }
}); });
$(window).on('beforeunload', function () { $(window).on('beforeunload', function () {
$('tbody').sortable('disable'); $('tbody').sortable('disable');
$("input[type=submit], input[type=button]").prop("disabled", "disabled"); $("input[type=submit], input[type=button]").prop("disabled", "disabled");
}); });
</script> </script>
{% endblock %} {% endblock %}

7
sapl/templates/sessao/subnav.yaml

@ -28,6 +28,10 @@
- title: {% trans 'Votação em Bloco' %} - title: {% trans 'Votação em Bloco' %}
url: votacao_bloco_expediente url: votacao_bloco_expediente
check_permission: sessao.add_sessaoplenaria check_permission: sessao.add_sessaoplenaria
- title: {% trans 'Copiar Matérias para Sessão Posterior' %}
url: transf_mat_exp
check_permission: sessao.add_sessaoplenaria
- title: {% trans 'Ordem do Dia' %} - title: {% trans 'Ordem do Dia' %}
children: children:
@ -40,6 +44,9 @@
- title: {% trans 'Votação em Bloco' %} - title: {% trans 'Votação em Bloco' %}
url: votacao_bloco_ordemdia url: votacao_bloco_ordemdia
check_permission: sessao.add_sessaoplenaria check_permission: sessao.add_sessaoplenaria
- title: {% trans 'Copiar Matérias para Sessão Posterior' %}
url: transf_mat_ordemdia
check_permission: sessao.add_sessaoplenaria
- title: {% trans 'Painel Eletrônico' %} - title: {% trans 'Painel Eletrônico' %}
url: painel url: painel

144
sapl/templates/sessao/transf_mat_sessao.html

@ -0,0 +1,144 @@
{% extends "crud/list.html" %}
{% load i18n %}
{% load common_tags %}
{% block base_content %}
{% if materias_sessao %}
{% if sessoes_destino %}
<div id="numero_resultados" style="text-align: right;"></div>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<fieldset>
<legend><b>Sessão Plenária Destino</b></legend>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label>Sessão Plenária*</label>
<select id="id_sessao_plenaria" class="select form-control" name="sessao_plenaria" required="True">
{% for sessao in sessoes_destino %}
<option value="{{ sessao.pk }}">{{ sessao }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
<br/>
<legend><b>Matérias Disponíveis para Cópia na Sessão Atual</b></legend>
<div id="tabela_materias"></div>
</fieldset>
<div id="submit_button"></div>
</form>
{% else %}
<br/>
<tr><td><h3 style="text-align: center;">Nenhuma sessão plenária está apta a receber a(s) cópia(s).</h3></td></tr>
{% endif %}
{% else %}
<br/>
<tr><td><h3 style="text-align: center;">Nenhuma máteria está disponível para cópia.</h3></td></tr>
{% endif %}
{% endblock base_content %}
{% block extra_js %}
<script language="Javascript">
function checkAll(elem) {
let checkboxes = document.getElementsByName('opcao_id');
for (let i=0; i<checkboxes.length; i++){
if (checkboxes[i].type == 'checkbox')
checkboxes[i].checked = elem.checked;
}
}
function buscar_materias_sessao() {
let categoria_materia = "{{ categoria_materia }}"
let pk_sessao_plenaria_atual = "{{ root_pk }}"
let id_sessao_plenaria = $("#id_sessao_plenaria").val();
$.get("{% url 'sapl.sessao:filtra_materias_copia_sessao_ajax_view' %}",
{
sessao_plenaria_atual: pk_sessao_plenaria_atual,
sessao_plenaria_destino: id_sessao_plenaria,
categoria_materia: categoria_materia
},
function(data) {
lista_materias = data['materias'];
numero_resultados = lista_materias.length;
if (numero_resultados == 0){
$("#numero_resultados").html(
"<h3>Existem " + numero_resultados + " matérias disponíveis para cópia.</h3>"
);
$("#tabela_materias").html(
'<table class="table table-striped table-hover">'+
'<div class="controls">'+
'<div class="checkbox">'+
'<label for="id_check_all">'+
'<input type="checkbox" id="id_check_all" onchange="checkAll(this)"/>Marcar/Desmarcar Todos'+
'</label>'+
'</div>'+
'</div>'+
'<thead><tr><td>Matéria</td></tr></thead>'+
'<tbody>'+
'<tr><td><h3 style="text-align: center;">Nenhuma máteria está disponível para cópia.</h3></td></tr>'+
'</tbody>'+
'</table>'
);
$("#submit_button").html("");
} else {
if (numero_resultados == 1){
$("#numero_resultados").html(
"<h3>{% trans 'Existe 1 matéria disponível para cópia.' %}</h3>"
);
} else {
$("#numero_resultados").html(
"<h3>Existem " + numero_resultados + " matérias disponíveis para cópia.</h3>"
);
}
var opcoes = "";
for (let i=0; i < lista_materias.length; i++){
opcoes += '<tr><td>'+
'<label for="' + lista_materias[i].materia_id + '">' +
'<input type="checkbox" id="' + lista_materias[i].materia_id + '" name="opcao_id" value="' + lista_materias[i].id + '" {% if check %} checked {% endif %}/> '+
lista_materias[i].materia_tipo_sigla + ' ' + lista_materias[i].materia_numero + '/' + lista_materias[i].materia_ano + ' - ' + lista_materias[i].materia_tipo_descricao +
'</label>'+
'</td></tr>'
}
$("#tabela_materias").html(
'<table class="table table-striped table-hover">'+
'<div class="controls">'+
'<div class="checkbox">'+
'<label for="id_check_all">'+
'<input type="checkbox" id="id_check_all" onchange="checkAll(this)"/>Marcar/Desmarcar Todos'+
'</label>'+
'</div>'+
'</div>'+
'<thead><tr><td>Matéria</td></tr></thead>'+
'<tbody>'+
opcoes +
'</tbody>'+
'</table>'
);
$("#submit_button").html(
'<input type="submit" value="Copiar" class="btn btn-primary"S>'
);
}
}
);
}
$(document).ready( function() {
// Identifica as matérias que já estão adicionadas na sessão destino
$("#id_sessao_plenaria").ready(buscar_materias_sessao);
$("#id_sessao_plenaria").change(buscar_materias_sessao);
$(window).on('beforeunload', function () {
$("input[type=submit]").prop("disabled", "disabled");
});
});
</script>
{% endblock %}
Loading…
Cancel
Save