annotate app/controllers/time_entry_reports_controller.rb @ 45:65d9e2cabaa3 luisf

Added tipoftheday to the config/settings in order to correct previous issues. Tip of the day is now working correctly. Added the heading strings to the locales files.
author luisf
date Tue, 23 Nov 2010 11:50:01 +0000
parents 94944d00e43c
children cbb26bc654de
rev   line source
chris@37 1 class TimeEntryReportsController < ApplicationController
chris@37 2 menu_item :issues
chris@37 3 before_filter :find_optional_project
chris@37 4 before_filter :load_available_criterias
chris@37 5
chris@37 6 helper :sort
chris@37 7 include SortHelper
chris@37 8 helper :issues
chris@37 9 helper :timelog
chris@37 10 include TimelogHelper
chris@37 11 helper :custom_fields
chris@37 12 include CustomFieldsHelper
chris@37 13
chris@37 14 def report
chris@37 15 @criterias = params[:criterias] || []
chris@37 16 @criterias = @criterias.select{|criteria| @available_criterias.has_key? criteria}
chris@37 17 @criterias.uniq!
chris@37 18 @criterias = @criterias[0,3]
chris@37 19
chris@37 20 @columns = (params[:columns] && %w(year month week day).include?(params[:columns])) ? params[:columns] : 'month'
chris@37 21
chris@37 22 retrieve_date_range
chris@37 23
chris@37 24 unless @criterias.empty?
chris@37 25 sql_select = @criterias.collect{|criteria| @available_criterias[criteria][:sql] + " AS " + criteria}.join(', ')
chris@37 26 sql_group_by = @criterias.collect{|criteria| @available_criterias[criteria][:sql]}.join(', ')
chris@37 27 sql_condition = ''
chris@37 28
chris@37 29 if @project.nil?
chris@37 30 sql_condition = Project.allowed_to_condition(User.current, :view_time_entries)
chris@37 31 elsif @issue.nil?
chris@37 32 sql_condition = @project.project_condition(Setting.display_subprojects_issues?)
chris@37 33 else
chris@37 34 sql_condition = "#{Issue.table_name}.root_id = #{@issue.root_id} AND #{Issue.table_name}.lft >= #{@issue.lft} AND #{Issue.table_name}.rgt <= #{@issue.rgt}"
chris@37 35 end
chris@37 36
chris@37 37 sql = "SELECT #{sql_select}, tyear, tmonth, tweek, spent_on, SUM(hours) AS hours"
chris@37 38 sql << " FROM #{TimeEntry.table_name}"
chris@37 39 sql << time_report_joins
chris@37 40 sql << " WHERE"
chris@37 41 sql << " (%s) AND" % sql_condition
chris@37 42 sql << " (spent_on BETWEEN '%s' AND '%s')" % [ActiveRecord::Base.connection.quoted_date(@from), ActiveRecord::Base.connection.quoted_date(@to)]
chris@37 43 sql << " GROUP BY #{sql_group_by}, tyear, tmonth, tweek, spent_on"
chris@37 44
chris@37 45 @hours = ActiveRecord::Base.connection.select_all(sql)
chris@37 46
chris@37 47 @hours.each do |row|
chris@37 48 case @columns
chris@37 49 when 'year'
chris@37 50 row['year'] = row['tyear']
chris@37 51 when 'month'
chris@37 52 row['month'] = "#{row['tyear']}-#{row['tmonth']}"
chris@37 53 when 'week'
chris@37 54 row['week'] = "#{row['tyear']}-#{row['tweek']}"
chris@37 55 when 'day'
chris@37 56 row['day'] = "#{row['spent_on']}"
chris@37 57 end
chris@37 58 end
chris@37 59
chris@37 60 @total_hours = @hours.inject(0) {|s,k| s = s + k['hours'].to_f}
chris@37 61
chris@37 62 @periods = []
chris@37 63 # Date#at_beginning_of_ not supported in Rails 1.2.x
chris@37 64 date_from = @from.to_time
chris@37 65 # 100 columns max
chris@37 66 while date_from <= @to.to_time && @periods.length < 100
chris@37 67 case @columns
chris@37 68 when 'year'
chris@37 69 @periods << "#{date_from.year}"
chris@37 70 date_from = (date_from + 1.year).at_beginning_of_year
chris@37 71 when 'month'
chris@37 72 @periods << "#{date_from.year}-#{date_from.month}"
chris@37 73 date_from = (date_from + 1.month).at_beginning_of_month
chris@37 74 when 'week'
chris@37 75 @periods << "#{date_from.year}-#{date_from.to_date.cweek}"
chris@37 76 date_from = (date_from + 7.day).at_beginning_of_week
chris@37 77 when 'day'
chris@37 78 @periods << "#{date_from.to_date}"
chris@37 79 date_from = date_from + 1.day
chris@37 80 end
chris@37 81 end
chris@37 82 end
chris@37 83
chris@37 84 respond_to do |format|
chris@37 85 format.html { render :layout => !request.xhr? }
chris@37 86 format.csv { send_data(report_to_csv(@criterias, @periods, @hours), :type => 'text/csv; header=present', :filename => 'timelog.csv') }
chris@37 87 end
chris@37 88 end
chris@37 89
chris@37 90 private
chris@37 91
chris@37 92 # TODO: duplicated in TimelogController
chris@37 93 def find_optional_project
chris@37 94 if !params[:issue_id].blank?
chris@37 95 @issue = Issue.find(params[:issue_id])
chris@37 96 @project = @issue.project
chris@37 97 elsif !params[:project_id].blank?
chris@37 98 @project = Project.find(params[:project_id])
chris@37 99 end
chris@37 100 deny_access unless User.current.allowed_to?(:view_time_entries, @project, :global => true)
chris@37 101 end
chris@37 102
chris@37 103 # Retrieves the date range based on predefined ranges or specific from/to param dates
chris@37 104 # TODO: duplicated in TimelogController
chris@37 105 def retrieve_date_range
chris@37 106 @free_period = false
chris@37 107 @from, @to = nil, nil
chris@37 108
chris@37 109 if params[:period_type] == '1' || (params[:period_type].nil? && !params[:period].nil?)
chris@37 110 case params[:period].to_s
chris@37 111 when 'today'
chris@37 112 @from = @to = Date.today
chris@37 113 when 'yesterday'
chris@37 114 @from = @to = Date.today - 1
chris@37 115 when 'current_week'
chris@37 116 @from = Date.today - (Date.today.cwday - 1)%7
chris@37 117 @to = @from + 6
chris@37 118 when 'last_week'
chris@37 119 @from = Date.today - 7 - (Date.today.cwday - 1)%7
chris@37 120 @to = @from + 6
chris@37 121 when '7_days'
chris@37 122 @from = Date.today - 7
chris@37 123 @to = Date.today
chris@37 124 when 'current_month'
chris@37 125 @from = Date.civil(Date.today.year, Date.today.month, 1)
chris@37 126 @to = (@from >> 1) - 1
chris@37 127 when 'last_month'
chris@37 128 @from = Date.civil(Date.today.year, Date.today.month, 1) << 1
chris@37 129 @to = (@from >> 1) - 1
chris@37 130 when '30_days'
chris@37 131 @from = Date.today - 30
chris@37 132 @to = Date.today
chris@37 133 when 'current_year'
chris@37 134 @from = Date.civil(Date.today.year, 1, 1)
chris@37 135 @to = Date.civil(Date.today.year, 12, 31)
chris@37 136 end
chris@37 137 elsif params[:period_type] == '2' || (params[:period_type].nil? && (!params[:from].nil? || !params[:to].nil?))
chris@37 138 begin; @from = params[:from].to_s.to_date unless params[:from].blank?; rescue; end
chris@37 139 begin; @to = params[:to].to_s.to_date unless params[:to].blank?; rescue; end
chris@37 140 @free_period = true
chris@37 141 else
chris@37 142 # default
chris@37 143 end
chris@37 144
chris@37 145 @from, @to = @to, @from if @from && @to && @from > @to
chris@37 146 @from ||= (TimeEntry.earilest_date_for_project(@project) || Date.today)
chris@37 147 @to ||= (TimeEntry.latest_date_for_project(@project) || Date.today)
chris@37 148 end
chris@37 149
chris@37 150 def load_available_criterias
chris@37 151 @available_criterias = { 'project' => {:sql => "#{TimeEntry.table_name}.project_id",
chris@37 152 :klass => Project,
chris@37 153 :label => :label_project},
chris@37 154 'version' => {:sql => "#{Issue.table_name}.fixed_version_id",
chris@37 155 :klass => Version,
chris@37 156 :label => :label_version},
chris@37 157 'category' => {:sql => "#{Issue.table_name}.category_id",
chris@37 158 :klass => IssueCategory,
chris@37 159 :label => :field_category},
chris@37 160 'member' => {:sql => "#{TimeEntry.table_name}.user_id",
chris@37 161 :klass => User,
chris@37 162 :label => :label_member},
chris@37 163 'tracker' => {:sql => "#{Issue.table_name}.tracker_id",
chris@37 164 :klass => Tracker,
chris@37 165 :label => :label_tracker},
chris@37 166 'activity' => {:sql => "#{TimeEntry.table_name}.activity_id",
chris@37 167 :klass => TimeEntryActivity,
chris@37 168 :label => :label_activity},
chris@37 169 'issue' => {:sql => "#{TimeEntry.table_name}.issue_id",
chris@37 170 :klass => Issue,
chris@37 171 :label => :label_issue}
chris@37 172 }
chris@37 173
chris@37 174 # Add list and boolean custom fields as available criterias
chris@37 175 custom_fields = (@project.nil? ? IssueCustomField.for_all : @project.all_issue_custom_fields)
chris@37 176 custom_fields.select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
chris@37 177 @available_criterias["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Issue' AND c.customized_id = #{Issue.table_name}.id)",
chris@37 178 :format => cf.field_format,
chris@37 179 :label => cf.name}
chris@37 180 end if @project
chris@37 181
chris@37 182 # Add list and boolean time entry custom fields
chris@37 183 TimeEntryCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
chris@37 184 @available_criterias["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'TimeEntry' AND c.customized_id = #{TimeEntry.table_name}.id)",
chris@37 185 :format => cf.field_format,
chris@37 186 :label => cf.name}
chris@37 187 end
chris@37 188
chris@37 189 # Add list and boolean time entry activity custom fields
chris@37 190 TimeEntryActivityCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
chris@37 191 @available_criterias["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Enumeration' AND c.customized_id = #{TimeEntry.table_name}.activity_id)",
chris@37 192 :format => cf.field_format,
chris@37 193 :label => cf.name}
chris@37 194 end
chris@37 195
chris@37 196 call_hook(:controller_timelog_available_criterias, { :available_criterias => @available_criterias, :project => @project })
chris@37 197 @available_criterias
chris@37 198 end
chris@37 199
chris@37 200 def time_report_joins
chris@37 201 sql = ''
chris@37 202 sql << " LEFT JOIN #{Issue.table_name} ON #{TimeEntry.table_name}.issue_id = #{Issue.table_name}.id"
chris@37 203 sql << " LEFT JOIN #{Project.table_name} ON #{TimeEntry.table_name}.project_id = #{Project.table_name}.id"
chris@37 204 # TODO: rename hook
chris@37 205 call_hook(:controller_timelog_time_report_joins, {:sql => sql} )
chris@37 206 sql
chris@37 207 end
chris@37 208
chris@37 209 end