diff --git a/sapl/sessao/urls.py b/sapl/sessao/urls.py index 5eb8872e7..79c43df49 100644 --- a/sapl/sessao/urls.py +++ b/sapl/sessao/urls.py @@ -34,7 +34,9 @@ from sapl.sessao.views import (AdicionarVariasMateriasExpediente, recuperar_nome_tipo_sessao, ExpedienteLeituraView, OrdemDiaLeituraView, - retirar_leitura) + retirar_leitura, + TransferenciaMateriasExpediente, TransferenciaMateriasOrdemDia, + filtra_materias_copia_sessao_ajax) from .apps import AppConfig @@ -75,6 +77,9 @@ urlpatterns = [ url(r'^sessao/sessao-legislativa-legislatura-ajax/', sessao_legislativa_legislatura_ajax, 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\d+)/(?P\d+)/abrir-votacao$', abrir_votacao, @@ -191,5 +196,11 @@ urlpatterns = [ url(r'^sessao/(?P\d+)/(?P\d+)/(?P\d+)/retirar-leitura$', retirar_leitura, name='retirar_leitura'), - + + url(r'^sessao/(?P\d+)/transf-mat-exp$', + TransferenciaMateriasExpediente.as_view(), + name="transf_mat_exp"), + url(r'^sessao/(?P\d+)/transf-mat-ordemdia$', + TransferenciaMateriasOrdemDia.as_view(), + name="transf_mat_ordemdia"), ] diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index 1dffe3961..576979cf7 100755 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -517,6 +517,194 @@ def get_presencas_generic(model, sessao, legislatura): 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 (%s)' % ( + 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 (%s)' % ( + 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): model = TipoExpediente @@ -586,6 +774,7 @@ class MateriaOrdemDiaCrud(MasterDetailCrud): self.paginate_by = None context = super().get_context_data(**kwargs) + has_permition = self.request.user.has_module_perms(AppConfig.label) return customize_link_materia(context, self.kwargs['pk'], has_permition, False) diff --git a/sapl/templates/sessao/expedientemateria_list.html b/sapl/templates/sessao/expedientemateria_list.html index b7d6870a9..f211e395c 100644 --- a/sapl/templates/sessao/expedientemateria_list.html +++ b/sapl/templates/sessao/expedientemateria_list.html @@ -2,69 +2,63 @@ {% load i18n %} {% load common_tags %} - {% block more_buttons %} - -{% if perms|get_add_perm:view %} - + {% if perms|get_add_perm:view %} {% blocktrans with verbose_name=view.verbose_name %} Adicionar Várias Matérias {% endblocktrans %} - - - + + + -{% endif %} - + {% endif %} {% endblock more_buttons %} {% block extra_js %} + + setTimeout(function(){ window.location.reload(true) }, 500); + } + }); + $(window).on('beforeunload', function () { + $('tbody').sortable('disable'); + $("input[type=submit], input[type=button]").prop("disabled", "disabled"); + }); + {% endblock %} diff --git a/sapl/templates/sessao/ordemdia_list.html b/sapl/templates/sessao/ordemdia_list.html index cf5b1fed4..29bb63ab4 100644 --- a/sapl/templates/sessao/ordemdia_list.html +++ b/sapl/templates/sessao/ordemdia_list.html @@ -2,67 +2,63 @@ {% load i18n %} {% load common_tags %} - {% block more_buttons %} - -{% if perms|get_add_perm:view %} + {% if perms|get_add_perm:view %} {% blocktrans with verbose_name=view.verbose_name %} Adicionar Várias Matérias {% endblocktrans %} - - + + -{% endif %} - + {% endif %} {% endblock more_buttons %} {% block extra_js %} + - + $('tbody').sortable('disable'); + $("input[type=submit], input[type=button]").prop("disabled", "disabled"); + }); + {% endblock %} diff --git a/sapl/templates/sessao/subnav.yaml b/sapl/templates/sessao/subnav.yaml index 59a127ad3..b36e6b9ef 100644 --- a/sapl/templates/sessao/subnav.yaml +++ b/sapl/templates/sessao/subnav.yaml @@ -28,6 +28,10 @@ - title: {% trans 'Votação em Bloco' %} url: votacao_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 + - title: {% trans 'Ordem do Dia' %} children: @@ -40,6 +44,9 @@ - title: {% trans 'Votação em Bloco' %} url: votacao_bloco_ordemdia 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' %} url: painel diff --git a/sapl/templates/sessao/transf_mat_sessao.html b/sapl/templates/sessao/transf_mat_sessao.html new file mode 100644 index 000000000..1df6841e0 --- /dev/null +++ b/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 %} +
+
+ {% csrf_token %} +
+ Sessão Plenária Destino +
+
+
+ + +
+
+
+
+ Matérias Disponíveis para Cópia na Sessão Atual +
+
+
+
+ {% else %} +
+

Nenhuma sessão plenária está apta a receber a(s) cópia(s).

+ {% endif %} + {% else %} +
+

Nenhuma máteria está disponível para cópia.

+ {% endif %} +{% endblock base_content %} + +{% block extra_js %} + +{% endblock %}