import json from datetime import datetime from django.contrib import messages from django.contrib.contenttypes.models import ContentType from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist from django.core.urlresolvers import reverse, reverse_lazy from django.db.models import F, Q from django.db.models.aggregates import Count from django.http import JsonResponse from django.http.response import HttpResponseRedirect from django.templatetags.static import static from django.utils import timezone from django.utils.datastructures import MultiValueDictKeyError from django.utils.translation import ugettext_lazy as _ from django.views.decorators.clickjacking import xframe_options_exempt from django.views.generic import FormView from django.views.generic.edit import UpdateView from sapl.base.models import Autor from sapl.comissoes.models import Participacao from sapl.crud.base import (RP_CHANGE, RP_DETAIL, RP_LIST, Crud, CrudAux, CrudBaseForListAndDetailExternalAppView, MasterDetailCrud) from sapl.materia.models import Autoria, Proposicao, Relatoria from sapl.parlamentares.apps import AppConfig from sapl.utils import parlamentares_ativos from .forms import (FiliacaoForm, LegislaturaForm, MandatoForm, ParlamentarCreateForm, ParlamentarForm, VotanteForm) from .models import (CargoMesa, Coligacao, ComposicaoColigacao, ComposicaoMesa, Dependente, Filiacao, Frente, Legislatura, Mandato, NivelInstrucao, Parlamentar, Partido, SessaoLegislativa, SituacaoMilitar, TipoAfastamento, TipoDependente, Votante) CargoMesaCrud = CrudAux.build(CargoMesa, 'cargo_mesa') PartidoCrud = CrudAux.build(Partido, 'partidos') SessaoLegislativaCrud = CrudAux.build(SessaoLegislativa, 'sessao_legislativa') TipoDependenteCrud = CrudAux.build(TipoDependente, 'tipo_dependente') NivelInstrucaoCrud = CrudAux.build(NivelInstrucao, 'nivel_instrucao') TipoAfastamentoCrud = CrudAux.build(TipoAfastamento, 'tipo_afastamento') TipoMilitarCrud = CrudAux.build(SituacaoMilitar, 'tipo_situa_militar') DependenteCrud = MasterDetailCrud.build( Dependente, 'parlamentar', 'dependente') class VotanteView(MasterDetailCrud): model = Votante parent_field = 'parlamentar' UpdateView = None class BaseMixin(MasterDetailCrud.BaseMixin): list_field_names = ['user'] class CreateView(MasterDetailCrud.CreateView): form_class = VotanteForm layout_key = None class DetailView(MasterDetailCrud.DetailView): def detail_create_url(self): return None class DeleteView(MasterDetailCrud.DeleteView): def delete(self, *args, **kwargs): obj = self.get_object() obj.delete() return HttpResponseRedirect( reverse('sapl.parlamentares:votante_list', kwargs={'pk': obj.parlamentar.pk})) class FrenteList(MasterDetailCrud): model = Frente is_m2m = True parent_field = 'parlamentares' CreateView, UpdateView, DeleteView = None, None, None class BaseMixin(Crud.PublicMixin, MasterDetailCrud.BaseMixin): list_field_names = ['nome', 'data_criacao'] @classmethod def url_name(cls, suffix): return '%s_parlamentar_%s' % (cls.model._meta.model_name, suffix) class RelatoriaParlamentarCrud(CrudBaseForListAndDetailExternalAppView): model = Relatoria parent_field = 'parlamentar' help_path = 'relatoria_parlamentar' namespace = AppConfig.name class BaseMixin(CrudBaseForListAndDetailExternalAppView.BaseMixin): @classmethod def url_name(cls, suffix): return '%s_parlamentar_%s' % (cls.model._meta.model_name, suffix) class ProposicaoParlamentarCrud(CrudBaseForListAndDetailExternalAppView): model = Proposicao list_field_names = ['tipo', 'descricao'] parent_field = 'autor__parlamentar_set' namespace = AppConfig.name class BaseMixin(CrudBaseForListAndDetailExternalAppView.BaseMixin): @classmethod def url_name(cls, suffix): return '%s_parlamentar_%s' % (cls.model._meta.model_name, suffix) class ListView(CrudBaseForListAndDetailExternalAppView.ListView): def get_context_data(self, **kwargs): context = CrudBaseForListAndDetailExternalAppView\ .ListView.get_context_data(self, **kwargs) return context def get_queryset(self): return super().get_queryset().filter( data_envio__isnull=False, data_recebimento__isnull=False) class DetailView(CrudBaseForListAndDetailExternalAppView.DetailView): @property def extras_url(self): if self.object.texto_articulado.exists(): ta = self.object.texto_articulado.first() yield (str(reverse_lazy( 'sapl.compilacao:ta_text', kwargs={'ta_id': ta.pk})) + '?back_type=history', 'btn-success', _('Texto Eletrônico')) class ParticipacaoParlamentarCrud(CrudBaseForListAndDetailExternalAppView): model = Participacao parent_field = 'parlamentar' namespace = AppConfig.name list_field_names = ['composicao__comissao__nome', 'cargo__nome', ( 'composicao__periodo__data_inicio', 'composicao__periodo__data_fim')] class BaseMixin(CrudBaseForListAndDetailExternalAppView.BaseMixin): @classmethod def url_name(cls, suffix): return '%s_parlamentar_%s' % (cls.model._meta.model_name, suffix) class ListView(CrudBaseForListAndDetailExternalAppView.ListView): ordering = ('-composicao__periodo') def get_rows(self, object_list): """ FIXME: Este metodo não será necessário quando get_rows for refatorada """ comissoes = [] for p in object_list: if p.cargo.nome != 'Relator': comissao = [ (p.composicao.comissao.nome, reverse( 'sapl.comissoes:comissao_detail', kwargs={ 'pk': p.composicao.comissao.pk})), (p.cargo.nome, None), (p.composicao.periodo.data_inicio.strftime( "%d/%m/%Y") + ' a ' + p.composicao.periodo.data_fim.strftime("%d/%m/%Y"), None) ] comissoes.append(comissao) return comissoes def get_headers(self): return [_('Comissão'), _('Cargo'), _('Período de participação'), ] class ColigacaoCrud(CrudAux): model = Coligacao help_path = 'tabelas_auxiliares#coligacao' class ListView(CrudAux.ListView): ordering = ('-numero_votos', 'nome') def get_context_data(self, **kwargs): context = super(ColigacaoCrud.ListView, self).get_context_data( kwargs=kwargs) rows = context['rows'] coluna_votos_recebidos = 2 for row in rows: if not row[coluna_votos_recebidos][0]: row[coluna_votos_recebidos] = ('0', None) return context class DetailView(CrudAux.DetailView): def get_context_data(self, **kwargs): context = super().get_context_data(kwargs=kwargs) coligacao = context['coligacao'] if not coligacao.numero_votos: coligacao.numero_votos = '0' context['subnav_template_name'] = \ 'parlamentares/subnav_coligacao.yaml' return context class UpdateView(CrudAux.UpdateView): def get_context_data(self, **kwargs): context = super(UpdateView, self).get_context_data(kwargs=kwargs) context['subnav_template_name'] = \ 'parlamentares/subnav_coligacao.yaml' return context def json_date_convert(date): ''' :param date: recebe a data de uma chamada ajax no formato de string "dd/mm/yyyy" :return: ''' return datetime.strptime(date, "%d/%m/%Y").date() def frente_atualiza_lista_parlamentares(request): ''' :param request: recebe os parâmetros do GET da chamada Ajax :return: retorna a lista atualizada dos parlamentares ''' ativos = json.loads(request.GET['ativos']) parlamentares = Parlamentar.objects.all() if ativos: if 'data_criacao' in request.GET and request.GET['data_criacao']: data_criacao = json_date_convert(request.GET['data_criacao']) if 'data_extincao' in request.GET and request.GET['data_extincao']: data_extincao = json_date_convert(request.GET['data_extincao']) parlamentares = parlamentares_ativos(data_criacao, data_extincao) else: parlamentares = parlamentares_ativos(data_criacao) parlamentares_list = [(p.id, p.__str__()) for p in parlamentares] return JsonResponse({'parlamentares_list': parlamentares_list}) def parlamentares_frente_selected(request): ''' :return: Lista com o id dos parlamentares em uma frente ''' try: frente = Frente.objects.get(id=int(request.GET['frente_id'])) except ObjectDoesNotExist: lista_parlamentar_id = [] else: lista_parlamentar_id = frente.parlamentares.all().values_list( 'id', flat=True) return JsonResponse({'id_list': list(lista_parlamentar_id)}) class FrenteCrud(CrudAux): model = Frente help_path = 'tabelas_auxiliares#tipo_situa_militar' list_field_names = ['nome', 'data_criacao', 'parlamentares'] class CreateView(CrudAux.CreateView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Update view é um indicador para o javascript # de que esta não é uma tela de edição de frente context['update_view'] = 0 return context class UpdateView(CrudAux.UpdateView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Update view é um indicador para o javascript # de que esta não é uma tela de edição de frente context['update_view'] = 1 return context class MandatoCrud(MasterDetailCrud): model = Mandato parent_field = 'parlamentar' public = [RP_DETAIL, RP_LIST] list_field_names = ['legislatura', 'votos_recebidos', 'coligacao', 'coligacao__numero_votos', 'titular'] class ListView(MasterDetailCrud.ListView): ordering = ('-legislatura__numero') def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) rows = context['rows'] coluna_coligacao = 2 coluna_votos_recebidos = 3 for row in rows: if not row[coluna_coligacao][0]: row[coluna_coligacao] = (' ', None) if not row[coluna_votos_recebidos][0]: row[coluna_votos_recebidos] = (' ', None) return context class CreateView(MasterDetailCrud.CreateView): form_class = MandatoForm def get_initial(self): return {'parlamentar': Parlamentar.objects.get( pk=self.kwargs['pk'])} class ComposicaoColigacaoCrud(MasterDetailCrud): model = ComposicaoColigacao parent_field = 'coligacao' help_path = '' class BaseMixin(MasterDetailCrud.BaseMixin): def get_context_data(self, **kwargs): context = super().get_context_data() context['subnav_template_name'] = \ 'parlamentares/subnav_coligacao.yaml' return context class ListView(MasterDetailCrud.ListView): ordering = '-partido__sigla' class LegislaturaCrud(CrudAux): model = Legislatura help_path = 'tabelas_auxiliares#legislatura' class CreateView(CrudAux.CreateView): form_class = LegislaturaForm def get_initial(self): try: ultima_legislatura = Legislatura.objects.latest('numero') numero = ultima_legislatura.numero + 1 except Legislatura.DoesNotExist: numero = 1 return {'numero': numero} class UpdateView(CrudAux.UpdateView): form_class = LegislaturaForm class DetailView(CrudAux.DetailView): def has_permission(self): return True @xframe_options_exempt def get(self, request, *args, **kwargs): return super().get(request, *args, **kwargs) class ListView(CrudAux.ListView): def has_permission(self): return True @xframe_options_exempt def get(self, request, *args, **kwargs): return super().get(request, *args, **kwargs) class FiliacaoCrud(MasterDetailCrud): model = Filiacao parent_field = 'parlamentar' help_path = '' public = [RP_LIST, RP_DETAIL] class BaseMixin(MasterDetailCrud.BaseMixin): ordering = '-data' class UpdateView(MasterDetailCrud.UpdateView): form_class = FiliacaoForm class CreateView(MasterDetailCrud.CreateView): form_class = FiliacaoForm class ParlamentarCrud(Crud): model = Parlamentar public = [RP_LIST, RP_DETAIL] class BaseMixin(Crud.BaseMixin): ordered_list = False list_field_names = [ 'avatar_html', 'nome_parlamentar', 'filiacao_atual', 'ativo', 'mandato_titular'] class DetailView(Crud.DetailView): def get_template_names(self): if self.request.user.has_perm(self.permission(RP_CHANGE)): if 'iframe' not in self.request.GET: if not self.request.session.get('iframe'): return ['crud/detail.html'] elif self.request.GET['iframe'] == '0': return ['crud/detail.html'] return ['parlamentares/parlamentar_perfil_publico.html'] @xframe_options_exempt def get(self, request, *args, **kwargs): return super().get(request, *args, **kwargs) class UpdateView(Crud.UpdateView): form_class = ParlamentarForm class CreateView(Crud.CreateView): form_class = ParlamentarCreateForm @property def layout_key(self): return 'ParlamentarCreate' def form_valid(self, form): ''' Reimplementa form_valid devido ao save de ParlamentarCreateForm ser específico, sendo necessário isolar padrão do crud que aciona form.save(commit=False) para registrar dados de auditoria se o model implementá-los, bem como de container se também implement. ''' return super(Crud.CreateView, self).form_valid(form) class ListView(Crud.ListView): template_name = "parlamentares/parlamentares_list.html" paginate_by = None @xframe_options_exempt def get(self, request, *args, **kwargs): return super().get(request, *args, **kwargs) def take_legislatura_id(self): try: return int(self.request.GET['pk']) except: for l in Legislatura.objects.all(): if l.atual(): return l.id return 0 def get_queryset(self): queryset = super().get_queryset() legislatura_id = self.take_legislatura_id() if legislatura_id != 0: return queryset.filter( mandato__legislatura_id=legislatura_id).annotate( mandato_titular=F('mandato__titular')) else: try: l = Legislatura.objects.all().order_by( '-data_inicio').first() except ObjectDoesNotExist: return Legislatura.objects.all() else: if l is None: return Legislatura.objects.all() return queryset.filter(mandato__legislatura_id=l).annotate( mandato_titular=F('mandato__titular')) def get_headers(self): return ['', _('Parlamentar'), _('Partido'), _('Ativo?'), _('Titular?')] def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Adiciona legislatura para filtrar parlamentares legislaturas = Legislatura.objects.all().order_by('-numero') context['legislaturas'] = legislaturas context['legislatura_id'] = self.take_legislatura_id() # Tira Link do avatar_html e coloca no nome for row in context['rows']: # preenche coluna foto, se vazia if not row[0][0]: img = "