1
0
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:
Marius Balteanu 2024-05-01 07:49:29 +00:00
parent 61c7d539dc
commit 6fa12a95ab
5 changed files with 56 additions and 3 deletions

View File

@ -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}"))

View File

@ -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).

View File

@ -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

View File

@ -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

View File

@ -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)