#NEWLINE# @ permission_required ( 'entries.view_entry_summary' ) #NEWLINE# def report_productivity( request ) : #NEWLINE# #INDENT# report = [ ] #NEWLINE# organize_by = None #NEWLINE# form = ProductivityReportForm ( ( request . GET or None ) ) #NEWLINE# if form . is_valid ( ) : #NEWLINE# #INDENT# project = form . cleaned_data [ 'project' ] #NEWLINE# organize_by = form . cleaned_data [ 'organize_by' ] #NEWLINE# export = request . GET . get ( 'export' , False ) #NEWLINE# actualsQ = Q ( project = project , end_time__isnull = False ) #NEWLINE# actuals = Entry . objects . filter ( actualsQ ) #NEWLINE# projections = ProjectHours . objects . filter ( project = project ) #NEWLINE# entry_count = ( actuals . count ( ) + projections . count ( ) ) #NEWLINE# if ( ( organize_by == 'week' ) and ( entry_count > 0 ) ) : #NEWLINE# #INDENT# ( amin , amax , pmin , pmax ) = ( None , None , None , None ) #NEWLINE# if ( actuals . count ( ) > 0 ) : #NEWLINE# #INDENT# amin = list ( actuals . aggregate ( Min ( 'start_time' ) ) . values ( ) ) [ 0 ] #NEWLINE# amin = utils . get_week_start ( amin ) . date ( ) #NEWLINE# amax = list ( actuals . aggregate ( Max ( 'start_time' ) ) . values ( ) ) [ 0 ] #NEWLINE# amax = utils . get_week_start ( amax ) . date ( ) #NEWLINE# #UNINDENT# if ( projections . count ( ) > 0 ) : #NEWLINE# #INDENT# pmin = list ( projections . aggregate ( Min ( 'week_start' ) ) . values ( ) ) [ 0 ] #NEWLINE# pmax = list ( projections . aggregate ( Max ( 'week_start' ) ) . values ( ) ) [ 0 ] #NEWLINE# #UNINDENT# current = ( min ( amin , pmin ) if ( amin and pmin ) else ( amin or pmin ) ) #NEWLINE# latest = ( max ( amax , pmax ) if ( amax and pmax ) else ( amax or pmax ) ) #NEWLINE# while ( current <= latest ) : #NEWLINE# #INDENT# next_week = ( current + relativedelta ( days = 7 ) ) #NEWLINE# actual_hours = actuals . filter ( start_time__gte = current , start_time__lt = next_week ) #NEWLINE# actual_hours = list ( actual_hours . aggregate ( Sum ( 'hours' ) ) . values ( ) ) [ 0 ] #NEWLINE# projected_hours = projections . filter ( week_start__gte = current , week_start__lt = next_week ) #NEWLINE# projected_hours = list ( projected_hours . aggregate ( Sum ( 'hours' ) ) . values ( ) ) [ 0 ] #NEWLINE# report . append ( [ date_format_filter ( current , 'M j, Y' ) , ( actual_hours or 0 ) , ( projected_hours or 0 ) ] ) #NEWLINE# current = next_week #NEWLINE# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# if ( ( organize_by == 'user' ) and ( entry_count > 0 ) ) : #NEWLINE# #INDENT# vals = ( 'user' , 'user__first_name' , 'user__last_name' ) #NEWLINE# ausers = list ( actuals . values_list ( * vals ) . distinct ( ) ) #NEWLINE# pusers = list ( projections . values_list ( * vals ) . distinct ( ) ) #NEWLINE# key = ( lambda x : ( x [ 1 ] + x [ 2 ] ) . lower ( ) ) #NEWLINE# users = sorted ( list ( set ( ( ausers + pusers ) ) ) , key = key ) #NEWLINE# for user in users : #NEWLINE# #INDENT# name = '{0} {1}' . format ( user [ 1 ] , user [ 2 ] ) #NEWLINE# actual_hours = actuals . filter ( user = user [ 0 ] ) #NEWLINE# actual_hours = list ( actual_hours . aggregate ( Sum ( 'hours' ) ) . values ( ) ) [ 0 ] #NEWLINE# projected_hours = projections . filter ( user = user [ 0 ] ) #NEWLINE# projected_hours = list ( projected_hours . aggregate ( Sum ( 'hours' ) ) . values ( ) ) [ 0 ] #NEWLINE# report . append ( [ name , ( actual_hours or 0 ) , ( projected_hours or 0 ) ] ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# col_headers = [ organize_by . title ( ) , 'Worked Hours' , 'Assigned Hours' ] #NEWLINE# report . insert ( 0 , col_headers ) #NEWLINE# if export : #NEWLINE# #INDENT# response = HttpResponse ( content_type = 'text/csv' ) #NEWLINE# filename = '{0}_productivity' . format ( project . name ) #NEWLINE# content_disp = 'attachment; filename={0}.csv' . format ( filename ) #NEWLINE# response [ 'Content-Disposition' ] = content_disp #NEWLINE# writer = csv . writer ( response ) #NEWLINE# for row in report : #NEWLINE# #INDENT# writer . writerow ( row ) #NEWLINE# #UNINDENT# return response #NEWLINE# #UNINDENT# #UNINDENT# return render ( request , 'timepiece/reports/productivity.html' , { #NEWLINE# #INDENT# 'form' : form , #NEWLINE# 'report' : json . dumps ( report , cls = DecimalEncoder ) , #NEWLINE# 'type' : ( organize_by or '' ) , #NEWLINE# 'total_worked' : sum ( [ r [ 1 ] for r in report [ 1 : ] ] ) , #NEWLINE# 'total_assigned' : sum ( [ r [ 2 ] for r in report [ 1 : ] ] ) , #NEWLINE# #UNINDENT# } )