@ -3,17 +3,17 @@
# sigi.apps.eventos.views
#
# Copyright (C) 2015 Interlegis
#
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@ -21,11 +21,14 @@
import calendar
import datetime
import locale
from django . http import HttpResponse , HttpResponseRedirect , HttpResponseForbidden
from django . core . paginator import Paginator , InvalidPage , EmptyPage
from django . contrib import messages
from django . contrib . auth . decorators import login_required
from django . shortcuts import render
from django . utils import translation
from django . utils . translation import ungettext , ugettext as _
from sigi . apps . eventos . models import Evento
from sigi . apps . eventos . models import Evento , Equipe , Convite
from sigi . apps . servidores . models import Servidor
from sigi . shortcuts import render_to_pdf
import csv
@ -36,28 +39,28 @@ def calendario(request):
mes_pesquisa = int ( request . GET . get ( ' mes ' , datetime . date . today ( ) . month ) )
ano_pesquisa = int ( request . GET . get ( ' ano ' , datetime . date . today ( ) . year ) )
formato = request . GET . get ( ' fmt ' , ' html ' )
dia1 = datetime . date ( ano_pesquisa , mes_pesquisa , 1 )
mes_anterior = dia1 - datetime . timedelta ( days = 1 )
mes_seguinte = dia1 . replace ( day = 28 ) + datetime . timedelta ( days = 4 ) # Ugly hack
mes_seguinte = mes_seguinte . replace ( day = 1 )
data = { ' mes_pesquisa ' : mes_pesquisa , ' ano_pesquisa ' : ano_pesquisa }
if Evento . objects . filter ( data_inicio__year = mes_anterior . year ,
if Evento . objects . filter ( data_inicio__year = mes_anterior . year ,
data_inicio__month = mes_anterior . month ) . exists ( ) :
data [ ' prev_button ' ] = { ' mes ' : mes_anterior . month , ' ano ' : mes_anterior . year }
if Evento . objects . filter ( data_inicio__year = mes_seguinte . year ,
if Evento . objects . filter ( data_inicio__year = mes_seguinte . year ,
data_inicio__month = mes_seguinte . month ) . exists ( ) :
data [ ' next_button ' ] = { ' mes ' : mes_seguinte . month , ' ano ' : mes_seguinte . year }
c = calendar . Calendar ( 6 )
dates = reduce ( lambda x , y : x + y , c . monthdatescalendar ( ano_pesquisa , mes_pesquisa ) )
eventos = [ ]
for evento in Evento . objects . filter ( data_inicio__year = ano_pesquisa ,
for evento in Evento . objects . filter ( data_inicio__year = ano_pesquisa ,
data_inicio__month = mes_pesquisa ) . order_by ( ' data_inicio ' ) :
start = dates . index ( evento . data_inicio )
if not evento . data_termino in dates :
@ -75,13 +78,13 @@ def calendario(request):
# Agrupa os eventos em linhas para melhorar a visualização
linhas = [ ]
for evento in eventos :
encaixado = False
for linha in linhas :
sobrepoe = False
for e in linha :
if ( ( ( evento [ ' evento ' ] . data_inicio > = e [ ' evento ' ] . data_inicio ) and
if ( ( ( evento [ ' evento ' ] . data_inicio > = e [ ' evento ' ] . data_inicio ) and
( evento [ ' evento ' ] . data_inicio < = e [ ' evento ' ] . data_termino ) ) or
( ( evento [ ' evento ' ] . data_termino > = e [ ' evento ' ] . data_inicio ) and
( evento [ ' evento ' ] . data_termino < = e [ ' evento ' ] . data_termino ) ) ) :
@ -96,7 +99,7 @@ def calendario(request):
# Adiciona uma nova linha porque este evento não se encaixa em nenhuma existente
linhas . append ( [ evento ] )
# Recalcula as distâncias dos eventos por linha para encaixar no calendário
# Recalcula as distâncias dos eventos por linha para encaixar no calendário
for linha in linhas :
anterior = None
for evento in linha :
@ -110,27 +113,27 @@ def calendario(request):
data [ ' dates ' ] = dates
data [ ' eventos ' ] = eventos
data [ ' linhas ' ] = linhas
if formato == ' pdf ' :
return render_to_pdf ( ' eventos/calendario_pdf.html ' , data )
return render ( request , ' eventos/calendario.html ' , data )
@login_required
def alocacao_equipe ( request ) :
ano_pesquisa = int ( request . GET . get ( ' ano ' , datetime . date . today ( ) . year ) )
formato = request . GET . get ( ' fmt ' , ' html ' )
data = { ' ano_pesquisa ' : ano_pesquisa }
if Evento . objects . filter ( data_inicio__year = ano_pesquisa - 1 ) . exists ( ) :
data [ ' prev_button ' ] = { ' ano ' : ano_pesquisa - 1 }
if Evento . objects . filter ( data_inicio__year = ano_pesquisa + 1 ) . exists ( ) :
data [ ' next_button ' ] = { ' ano ' : ano_pesquisa + 1 }
dados = [ ]
for evento in Evento . objects . filter ( data_inicio__year = ano_pesquisa ) . exclude ( status = ' C ' ) . prefetch_related ( ' equipe_set ' ) :
for p in evento . equipe_set . all ( ) :
registro = None
@ -141,36 +144,36 @@ def alocacao_equipe(request):
if not registro :
registro = [ p . membro . pk , p . membro . nome_completo , [ { ' dias ' : 0 , ' eventos ' : 0 } for x in range ( 1 , 13 ) ] ]
dados . append ( registro )
registro [ 2 ] [ evento . data_inicio . month - 1 ] [ ' dias ' ] + = ( evento . data_termino - evento . data_inicio ) . days + 1
registro [ 2 ] [ evento . data_inicio . month - 1 ] [ ' eventos ' ] + = 1
dados . sort ( lambda x , y : cmp ( x [ 1 ] , y [ 1 ] ) )
lang = ( translation . to_locale ( translation . get_language ( ) ) + ' .utf8 ' ) . encode ( )
locale . setlocale ( locale . LC_ALL , lang )
meses = [ calendar . month_name [ m ] for m in range ( 1 , 13 ) ]
linhas = [ [ _ ( u " Servidor " ) ] + meses + [ ' total ' ] ]
for r in dados :
r [ 2 ] . append ( reduce ( lambda x , y : { ' dias ' : x [ ' dias ' ] + y [ ' dias ' ] ,
' eventos ' : x [ ' eventos ' ] + y [ ' eventos ' ] } , r [ 2 ] ) )
linhas . append ( [ r [ 1 ] ] +
linhas . append ( [ r [ 1 ] ] +
[ _ ( ungettext ( u " %(dias)s dia " , u " %(dias)s dias " , d [ ' dias ' ] ) + " em " +
ungettext ( u " %(eventos)s evento " , u " %(eventos)s eventos " , d [ ' eventos ' ] )
) % d if d [ ' dias ' ] > 0 or d [ ' eventos ' ] > 0 else ' ' for d in r [ 2 ] ] )
# for registro in Servidor.objects.filter(equipe_evento__evento__data_inicio__year=ano_pesquisa).exclude(equipe_evento__evento__status='C').distinct():
# dados = [{'dias': 0, 'eventos': 0} for x in range(1,13)]
# for part in registro.equipe_evento.filter(evento__data_inicio__year=ano_pesquisa).exclude(evento__status='C'):
# dados[part.evento.data_inicio.month-1]['dias'] += (part.evento.data_termino -
# dados[part.evento.data_inicio.month-1]['dias'] += (part.evento.data_termino -
# part.evento.data_inicio).days + 1
# dados[part.evento.data_inicio.month-1]['eventos'] += 1
# dados.append([registro.nome_completo] + [_(ungettext(u"%(dias)s dia", u"%(dias)s dias", d['dias']) + " em " + ungettext(u"%(eventos)s evento", u"%(eventos)s eventos", d['eventos'])) % d if d['dias'] > 0 or d['eventos'] > 0 else '' for d in dados])
data [ ' linhas ' ] = linhas
if formato == ' pdf ' :
return render_to_pdf ( ' eventos/alocacao_equipe_pdf.html ' , data )
elif formato == ' csv ' :
@ -187,5 +190,178 @@ def alocacao_equipe(request):
' meses ' : { m [ 0 ] : m [ 1 ] for m in zip ( meses + [ ' total ' ] , d [ 2 ] ) }
} for d in dados ] }
return JsonResponse ( result )
return render ( request , ' eventos/alocacao_equipe.html ' , data )
return render ( request , ' eventos/alocacao_equipe.html ' , data )
# Views e functions para carrinho de exportação
def query_ordena ( qs , o ) :
from sigi . apps . eventos . admin import EventoAdmin
list_display = EventoAdmin . list_display
order_fields = [ ]
for order_number in o . split ( ' . ' ) :
order_number = int ( order_number )
order = ' '
if order_number != abs ( order_number ) :
order_number = abs ( order_number )
order = ' - '
order_fields . append ( order + list_display [ order_number - 1 ] )
qs = qs . order_by ( * order_fields )
return qs
def get_for_qs ( get , qs ) :
kwargs = { }
for k , v in get . iteritems ( ) :
if str ( k ) not in ( ' page ' , ' pop ' , ' q ' , ' _popup ' , ' o ' , ' ot ' ) :
kwargs [ str ( k ) ] = v
qs = qs . filter ( * * kwargs )
if ' o ' in get :
qs = query_ordena ( qs , get [ ' o ' ] )
return qs
def carrinhoOrGet_for_qs ( request ) :
if ' carrinho_eventos ' in request . session :
ids = request . session [ ' carrinho_eventos ' ]
qs = Evento . objects . filter ( pk__in = ids )
else :
qs = Evento . objects . all ( )
if request . GET :
qs = get_for_qs ( request . GET , qs )
return qs
def adicionar_eventos_carrinho ( request , queryset = None , id = None ) :
if request . method == ' POST ' :
ids_selecionados = request . POST . getlist ( ' _selected_action ' )
if ' carrinho_eventos ' not in request . session :
request . session [ ' carrinho_eventos ' ] = ids_selecionados
else :
lista = request . session [ ' carrinho_eventos ' ]
# Verifica se id já não está adicionado
for id in ids_selecionados :
if id not in lista :
lista . append ( id )
request . session [ ' carrinho_eventos ' ] = lista
@login_required
def visualizar_carrinho ( request ) :
qs = carrinhoOrGet_for_qs ( request )
paginator = Paginator ( qs , 100 )
try :
page = int ( request . GET . get ( ' page ' , ' 1 ' ) )
except ValueError :
page = 1
try :
paginas = paginator . page ( page )
except ( EmptyPage , InvalidPage ) :
paginas = paginator . page ( paginator . num_pages )
carrinhoIsEmpty = not ( ' carrinho_eventos ' in request . session )
return render (
request ,
' eventos/carrinho.html ' ,
{
' carIsEmpty ' : carrinhoIsEmpty ,
' paginas ' : paginas ,
' query_str ' : ' ? ' + request . META [ ' QUERY_STRING ' ]
}
)
@login_required
def excluir_carrinho ( request ) :
if ' carrinho_eventos ' in request . session :
del request . session [ ' carrinho_eventos ' ]
messages . info ( request , u ' O carrinho foi esvaziado ' )
return HttpResponseRedirect ( ' ../../ ' )
@login_required
def deleta_itens_carrinho ( request ) :
if request . method == ' POST ' :
ids_selecionados = request . POST . getlist ( ' _selected_action ' )
removed = 0
if ' carrinho_eventos ' in request . session :
lista = request . session [ ' carrinho_eventos ' ]
for item in ids_selecionados :
lista . remove ( item )
removed + = 1
if lista :
request . session [ ' carrinho_eventos ' ] = lista
else :
del lista
del request . session [ ' carrinho_eventos ' ]
messages . info ( request , u " {0} itens removidos do carrinho " . format ( removed ) )
return HttpResponseRedirect ( ' . ' )
@login_required
def export_csv ( request ) :
def serialize ( r , field ) :
value = ( getattr ( r , ' get_ {0} _display ' . format ( field . name ) , None ) or
getattr ( r , field . name , " " ) )
if callable ( value ) :
value = value ( )
if value is None :
value = " "
return unicode ( value ) . encode ( ' utf8 ' )
eventos_fields = Evento . _meta . fields
equipe_fields = Equipe . _meta . fields
convite_fields = Convite . _meta . fields
eventos = carrinhoOrGet_for_qs ( request )
eventos . select_related ( ' equipe ' , ' convite ' )
if not eventos :
messages . info ( request , _ ( u " Nenhum evento a exportar " ) )
return HttpResponseRedirect ( ' ../ ' )
max_equipe = max ( [ e . equipe_set . count ( ) for e in eventos ] )
max_convite = max ( [ e . convite_set . count ( ) for e in eventos ] )
head = [ f . verbose_name . encode ( ' utf8 ' ) for f in eventos_fields
if f . name != ' id ' ]
head . extend ( [ f . verbose_name . encode ( ' utf8 ' ) + " _ {0} " . format ( i + 1 )
for i in range ( max_equipe ) for f in Equipe . _meta . fields
if f . name not in ( ' id ' , ' evento ' ) ] )
head . extend ( [ f . verbose_name . encode ( ' utf8 ' ) + " _ {0} " . format ( i + 1 )
for i in range ( max_convite ) for f in Convite . _meta . fields
if f . name not in ( ' id ' , ' evento ' ) ] )
head . append ( ' total_participantes ' )
response = HttpResponse ( content_type = ' text/csv ' )
response [ ' Content-Disposition ' ] = ' attachment; filename=eventos.csv '
writer = csv . DictWriter ( response , fieldnames = head )
writer . writeheader ( )
for evento in eventos :
reg = { f . verbose_name . encode ( ' utf8 ' ) : serialize ( evento , f )
for f in Evento . _meta . fields if f . name != ' id ' }
reg [ ' total_participantes ' ] = 0
idx = 1
for membro in evento . equipe_set . all ( ) :
reg . update (
{
" {0} _ {1} " . format ( f . verbose_name . encode ( ' utf8 ' ) , idx ) :
serialize ( membro , f ) for f in Equipe . _meta . fields
if f . name not in ( ' id ' , ' evento ' )
}
)
idx + = 1
idx = 1
for convite in evento . convite_set . all ( ) :
reg . update (
{
" {0} _ {1} " . format ( f . verbose_name . encode ( ' utf8 ' ) , idx ) :
serialize ( convite , f ) for f in Convite . _meta . fields
if f . name not in ( ' id ' , ' evento ' )
}
)
reg [ ' total_participantes ' ] + = convite . qtde_participantes
idx + = 1
writer . writerow ( reg )
return response