# HG changeset patch # User olivier # Date 1435166922 -7200 # Wed Jun 24 19:28:42 2015 +0200 # Branch 3.1-stable # Node ID 9503bb851665eb24f605b20f2603da496fdf8a1a # Parent d6875328ffbcd415da50b8896a00ee679042d6e5 Redmine.org #4776 - Estimated time patch for RM 3.0.3 diff -r d6875328ffbc -r 9503bb851665 app/controllers/issues_controller.rb --- a/app/controllers/issues_controller.rb Sun Jul 26 07:10:55 2015 +0000 +++ b/app/controllers/issues_controller.rb Wed Jun 24 19:28:42 2015 +0200 @@ -65,6 +65,10 @@ end @issue_count = @query.issue_count + #[OHO-start] time info in issue lists + @issue_sum_estimated = @query.issue_sum_estimated + @issue_sum_spent = @query.issue_sum_spent + #[OHO-end] @issue_pages = Paginator.new @issue_count, @limit, params['page'] @offset ||= @issue_pages.offset @issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version], @@ -72,7 +76,10 @@ :offset => @offset, :limit => @limit) @issue_count_by_group = @query.issue_count_by_group - + #[OHO-start] time info in issue lists + @issue_sum_spent_by_group = @query.issue_sum_spent_by_group + @issue_sum_estimated_by_group = @query.issue_sum_estimated_by_group + #[OHO-end] respond_to do |format| format.html { render :template => 'issues/index', :layout => !request.xhr? } format.api { diff -r d6875328ffbc -r 9503bb851665 app/helpers/issues_helper.rb --- a/app/helpers/issues_helper.rb Sun Jul 26 07:10:55 2015 +0000 +++ b/app/helpers/issues_helper.rb Wed Jun 24 19:28:42 2015 +0200 @@ -32,7 +32,8 @@ end end - def grouped_issue_list(issues, query, issue_count_by_group, &block) +#[OHO-start] modified function to handle 2 more variables for estimated and spent time + def grouped_issue_list(issues, query, issue_count_by_group, issue_sum_estimated_by_group, issue_sum_spent_by_group, &block) previous_group, first = false, true issue_list(issues) do |issue, level| group_name = group_count = nil @@ -43,12 +44,18 @@ group_name = column_content(query.group_by_column, issue) end group_name ||= "" - group_count = issue_count_by_group[group] + issue_count_by_group.respond_to?(:has_key?) ? group_count = issue_count_by_group[group] : group_count = issue_count_by_group + issue_sum_estimated_by_group.respond_to?(:has_key?) ? group_estimated_hours = issue_sum_estimated_by_group[group] : group_estimated_hours = 0 + issue_sum_spent_by_group.respond_to?(:has_key?) ? group_spent_hours = issue_sum_spent_by_group[group] : group_spent_hours = 0 + group_estimated_hours = 0 if group_estimated_hours.nil? + group_spent_hours = 0 if group_spent_hours.nil? end - yield issue, level, group_name, group_count + yield issue, level, group_name, group_count, group_estimated_hours, group_spent_hours previous_group, first = group, false end end +#[OHO-end] + # Renders a HTML/CSS tooltip # diff -r d6875328ffbc -r 9503bb851665 app/models/issue_query.rb --- a/app/models/issue_query.rb Sun Jul 26 07:10:55 2015 +0000 +++ b/app/models/issue_query.rb Wed Jun 24 19:28:42 2015 +0200 @@ -297,6 +297,23 @@ raise StatementInvalid.new(e.message) end + #[OHO-start] time info for issue lists + # Returns sum of all the issue's estimated_hours + def issue_sum_estimated + Issue.visible.joins(:status, :project).where(statement).sum(:estimated_hours) + rescue ::ActiveRecord::StatementInvalid => e + raise StatementInvalid.new(e.message) + end + + # Returns sum of all the issue's spent time + def issue_sum_spent + TimeEntry.visible.joins(:issue, :project).where(statement).sum(:hours) + rescue ::ActiveRecord::StatementInvalid => e + raise StatementInvalid.new(e.message) + end + #[OHO-end] + + # Returns the issue count by group or nil if query is not grouped def issue_count_by_group r = nil @@ -322,6 +339,60 @@ raise StatementInvalid.new(e.message) end + #[OHO-start] time info for issue lists + # Returns sum of the issue's estimated_hours by group or nil if query is not grouped + def issue_sum_estimated_by_group + r = nil + if grouped? + begin + r = Issue.visible. + joins(:status, :project). + where(statement). + group(group_by_statement). + joins(joins_for_order_statement(group_by_statement)). + sum(:estimated_hours) + rescue ActiveRecord::RecordNotFound + r= {nil => 0} + end + + c = group_by_column + if c.is_a?(QueryCustomFieldColumn) && r.respond_to?(:has_keys?) + r = r.keys.inject({}) {|h, k| h[c.custom_field.cast_value(k)] = r[k]; h} + end + end + r + rescue ::ActiveRecord::StatementInvalid => e + raise StatementInvalid.new(e.message) + end + + # Returns sum of the issue's spent time by group or nil if query is not grouped + def issue_sum_spent_by_group + r = nil + # Spent hours not available for project grouping as it leads to an ambiguous column name SQL issue + if grouped? && group_by_statement != "project" + begin + # Problem with parent/child tasks: time is counted for both parents and children + r = TimeEntry.visible. + joins(:issue, :project). + where(statement). + joins(joins_for_order_statement(group_by_statement)). + group(group_by_statement). + sum(:hours) + rescue ActiveRecord::RecordNotFound + r= {nil => 0} + end + + c = group_by_column + if c.is_a?(QueryCustomFieldColumn) && r.respond_to?(:has_keys?) + r = r.keys.inject({}) {|h, k| h[c.custom_field.cast_value(k)] = r[k]; h} + end + end + r + rescue ::ActiveRecord::StatementInvalid => e + raise StatementInvalid.new(e.message) + end + #[OHO-end] + # Returns the issues # Valid options are :order, :offset, :limit, :include, :conditions def issues(options={}) diff -r d6875328ffbc -r 9503bb851665 app/models/time_entry.rb --- a/app/models/time_entry.rb Sun Jul 26 07:10:55 2015 +0000 +++ b/app/models/time_entry.rb Wed Jun 24 19:28:42 2015 +0200 @@ -23,6 +23,15 @@ belongs_to :issue belongs_to :user belongs_to :activity, :class_name => 'TimeEntryActivity' +#[OHO-start] Added groupable fields to be able to group on those fields for spent time calculation in grouped issue lists (issue_query.rb) + belongs_to :status, :class_name => 'IssueStatus' + belongs_to :author, :class_name => 'User' + belongs_to :assigned_to, :class_name => 'Principal' + belongs_to :fixed_version, :class_name => 'Version' + belongs_to :priority, :class_name => 'IssuePriority' + belongs_to :category, :class_name => 'IssueCategory' + belongs_to :tracker, :class_name => 'Tracker' +#[OHO-end] attr_protected :user_id, :tyear, :tmonth, :tweek diff -r d6875328ffbc -r 9503bb851665 app/views/issues/_list.html.erb --- a/app/views/issues/_list.html.erb Sun Jul 26 07:10:55 2015 +0000 +++ b/app/views/issues/_list.html.erb Wed Jun 24 19:28:42 2015 +0200 @@ -15,13 +15,28 @@ - <% grouped_issue_list(issues, @query, @issue_count_by_group) do |issue, level, group_name, group_count| -%> + <% #[OHO-start] time info in issue lists: modified to add variables + grouped_issue_list(issues, @query, @issue_count_by_group, @issue_sum_estimated_by_group, @issue_sum_spent_by_group) do |issue, level, group_name, group_count, group_estimated_hours, group_spent_hours| + #[OHO-end] + -%> <% if group_name %> <% reset_cycle %>   <%= group_name %> <%= group_count %> + <% #[OHO-start] time info in issue lists + if (group_estimated_hours > 0 || group_spent_hours > 0) %>(<% + if group_estimated_hours > 0 + %><%= l(:field_estimated_hours) %>: <%= l_hours(group_estimated_hours) %><% + end + if group_spent_hours > 0 && group_estimated_hours > 0 %>, <% + end + if group_spent_hours > 0 %><%= l(:label_spent_time) %>: <%= l_hours(group_spent_hours) %><% + end%>)<% + end + #[OHO-end] + %> <%= link_to_function("#{l(:button_collapse_all)}/#{l(:button_expand_all)}", "toggleAllRowGroups(this)", :class => 'toggle-all') %> @@ -42,4 +57,12 @@ -<% end -%> +<% end %> +<% + #[OHO] time info in issue lists +%> +

+ <%= l(:field_estimated_hours) %>: <%= l_hours(@issue_sum_estimated) %><% if @issue_sum_spent.present? %> + , <%= l(:label_spent_time) %>: <%= l_hours(@issue_sum_spent) %><% end %>) + +

# HG changeset patch # User olivier # Date 1439561476 -7200 # Fri Aug 14 16:11:16 2015 +0200 # Branch 3.1-stable # Node ID cf7b50cd32e3ad6b2edbb7ba2ad8841a52fca820 # Parent 9503bb851665eb24f605b20f2603da496fdf8a1a Fixed Error 500 when sorting on a field used for grouping diff -r 9503bb851665 -r cf7b50cd32e3 app/models/issue_query.rb --- a/app/models/issue_query.rb Wed Jun 24 19:28:42 2015 +0200 +++ b/app/models/issue_query.rb Fri Aug 14 16:11:16 2015 +0200 @@ -396,7 +396,8 @@ # Returns the issues # Valid options are :order, :offset, :limit, :include, :conditions def issues(options={}) - order_option = [group_by_sort_order, options[:order]].flatten.reject(&:blank?) +# [OHO-2015-08-14] Added .join(',').to_s.split(',').uniq to remove duplicates + order_option = [group_by_sort_order, options[:order]].flatten.reject(&:blank?).join(',').to_s.split(',').uniq scope = Issue.visible. joins(:status, :project).