mirror of
https://github.com/meineerde/redmine.git
synced 2026-01-31 11:37:14 +00:00
Adds estimated remaining hours issue query column calculated based on estimated time and done ratio (#37862).
Patch by Jens Krämer (@jkraemer). git-svn-id: https://svn.redmine.org/redmine/trunk@22800 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
61c7d539dc
commit
6fa12a95ab
@ -190,7 +190,7 @@ module QueriesHelper
|
||||
def total_tag(column, value)
|
||||
label = content_tag('span', "#{column.caption}:")
|
||||
value =
|
||||
if [:hours, :spent_hours, :total_spent_hours, :estimated_hours, :total_estimated_hours].include? column.name
|
||||
if [:hours, :spent_hours, :total_spent_hours, :estimated_hours, :total_estimated_hours, :estimated_remaining_hours].include? column.name
|
||||
format_hours(value)
|
||||
else
|
||||
format_object(value)
|
||||
@ -269,7 +269,7 @@ module QueriesHelper
|
||||
'span',
|
||||
value.to_s(item) {|other| link_to_issue(other, :subject => false, :tracker => false)}.html_safe,
|
||||
:class => value.css_classes_for(item))
|
||||
when :hours, :estimated_hours, :total_estimated_hours
|
||||
when :hours, :estimated_hours, :total_estimated_hours, :estimated_remaining_hours
|
||||
format_hours(value)
|
||||
when :spent_hours
|
||||
link_to_if(value > 0, format_hours(value), project_time_entries_path(item.project, :issue_id => "#{item.id}"))
|
||||
|
||||
@ -18,6 +18,22 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class IssueQuery < Query
|
||||
class EstimatedRemainingHoursColumn < QueryColumn
|
||||
COLUMN_SQL = Arel.sql("COALESCE(#{Issue.table_name}.estimated_hours, 0) * (100 - COALESCE(#{Issue.table_name}.done_ratio, 0)) / 100")
|
||||
|
||||
def initialize
|
||||
super :estimated_remaining_hours, totalable: true, sortable: COLUMN_SQL
|
||||
end
|
||||
|
||||
def value(object)
|
||||
(object.estimated_hours || 0) * (100 - (object.done_ratio || 0)) / 100
|
||||
end
|
||||
|
||||
def value_object(object)
|
||||
value(object)
|
||||
end
|
||||
end
|
||||
|
||||
self.queried_class = Issue
|
||||
self.view_permission = :view_issues
|
||||
|
||||
@ -50,6 +66,7 @@ class IssueQuery < Query
|
||||
QueryColumn.new(:due_date, :sortable => "#{Issue.table_name}.due_date", :groupable => true),
|
||||
QueryColumn.new(:estimated_hours, :sortable => "#{Issue.table_name}.estimated_hours",
|
||||
:totalable => true),
|
||||
EstimatedRemainingHoursColumn.new,
|
||||
QueryColumn.new(
|
||||
:total_estimated_hours,
|
||||
:sortable =>
|
||||
@ -330,7 +347,9 @@ class IssueQuery < Query
|
||||
end
|
||||
|
||||
disabled_fields = Tracker.disabled_core_fields(trackers).map {|field| field.delete_suffix('_id')}
|
||||
disabled_fields << "total_estimated_hours" if disabled_fields.include?("estimated_hours")
|
||||
if disabled_fields.include?("estimated_hours")
|
||||
disabled_fields += %w[total_estimated_hours estimated_remaining_hours]
|
||||
end
|
||||
@available_columns.reject! do |column|
|
||||
disabled_fields.include?(column.name.to_s)
|
||||
end
|
||||
@ -370,6 +389,10 @@ class IssueQuery < Query
|
||||
map_total(scope.sum(:estimated_hours)) {|t| t.to_f.round(2)}
|
||||
end
|
||||
|
||||
def total_for_estimated_remaining_hours(scope)
|
||||
map_total(scope.sum(EstimatedRemainingHoursColumn::COLUMN_SQL)) {|t| t.to_f.round(2)}
|
||||
end
|
||||
|
||||
# Returns sum of all the issue's time entries hours
|
||||
def total_for_spent_hours(scope)
|
||||
total = scope.joins(:time_entries).
|
||||
|
||||
@ -399,6 +399,7 @@ de:
|
||||
field_watcher: Beobachter
|
||||
field_default_assigned_to: Standardbearbeiter
|
||||
field_unique_id: Eindeutige ID
|
||||
field_estimated_remaining_hours: Geschätzter verbleibender Aufwand
|
||||
|
||||
general_csv_decimal_separator: ','
|
||||
general_csv_encoding: ISO-8859-1
|
||||
|
||||
@ -418,6 +418,7 @@ en:
|
||||
field_default_project_query: Default project query
|
||||
field_default_time_entry_activity: Default spent time activity
|
||||
field_any_searchable: Any searchable text
|
||||
field_estimated_remaining_hours: Estimated remaining time
|
||||
|
||||
setting_app_title: Application title
|
||||
setting_welcome_text: Welcome text
|
||||
|
||||
@ -2388,6 +2388,11 @@ class QueryTest < ActiveSupport::TestCase
|
||||
assert_include :estimated_hours, q.available_totalable_columns.map(&:name)
|
||||
end
|
||||
|
||||
def test_available_totalable_columns_should_include_estimated_remaining_hours
|
||||
q = IssueQuery.new
|
||||
assert_include :estimated_remaining_hours, q.available_totalable_columns.map(&:name)
|
||||
end
|
||||
|
||||
def test_available_totalable_columns_should_include_spent_hours
|
||||
User.current = User.find(1)
|
||||
|
||||
@ -2461,6 +2466,29 @@ class QueryTest < ActiveSupport::TestCase
|
||||
)
|
||||
end
|
||||
|
||||
def test_total_for_estimated_remaining_hours
|
||||
Issue.delete_all
|
||||
Issue.generate!(:estimated_hours => 5.5, :done_ratio => 50)
|
||||
Issue.generate!(:estimated_hours => 1.1, :done_ratio => 100)
|
||||
Issue.generate!
|
||||
|
||||
q = IssueQuery.new
|
||||
assert_equal 2.75, q.total_for(:estimated_remaining_hours)
|
||||
end
|
||||
|
||||
def test_total_by_group_for_estimated_remaining_hours
|
||||
Issue.delete_all
|
||||
Issue.generate!(:estimated_hours => 5.5, :assigned_to_id => 2, :done_ratio => 50)
|
||||
Issue.generate!(:estimated_hours => 1.1, :assigned_to_id => 3, :done_ratio => 100)
|
||||
Issue.generate!(:estimated_hours => 3.5, :done_ratio => 0)
|
||||
|
||||
q = IssueQuery.new(:group_by => 'assigned_to')
|
||||
assert_equal(
|
||||
{nil => 3.5, User.find(2) => 2.75, User.find(3) => 0},
|
||||
q.total_by_group_for(:estimated_remaining_hours)
|
||||
)
|
||||
end
|
||||
|
||||
def test_total_for_spent_hours
|
||||
TimeEntry.delete_all
|
||||
TimeEntry.generate!(:hours => 5.5)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user