Project

General

Profile

Actions

Defect #23511

closed

Progress of parent task should be calculated using total estimated hours of children

Added by Zouheir Najai over 7 years ago. Updated over 7 years ago.

Status:
Closed
Priority:
Normal
Category:
Issues
Target version:
Start date:
Due date:
% Done:

0%

Estimated time:
Resolution:
Fixed
Affected version:

Description

Problem of calculating the percentage of completion of a Issue(see the attached file).

When "child" has "sub-child": estimated_hours is nil, therefore is not accounted in "average" (line 1534).

Issue.total_estimated_hours has to be accounted in this estimate.

app/model/issue.rb:

   1511   def recalculate_attributes_for(issue_id)
   1512     if issue_id && p = Issue.find_by_id(issue_id)
   1513       if p.priority_derived?
   1514         # priority = highest priority of children
   1515         if priority_position = p.children.joins(:priority).maximum("#{IssuePriority.table_name}.position")
   1516           p.priority = IssuePriority.find_by_position(priority_position)
   1517         end
   1518       end
   1519
   1520       if p.dates_derived?
   1521         # start/due dates = lowest/highest dates of children
   1522         p.start_date = p.children.minimum(:start_date)
   1523         p.due_date = p.children.maximum(:due_date)
   1524         if p.start_date && p.due_date && p.due_date < p.start_date
   1525           p.start_date, p.due_date = p.due_date, p.start_date
   1526         end
   1527       end
   1528
   1529       if p.done_ratio_derived?
   1530         # done ratio = weighted average ratio of leaves
   1531         unless Issue.use_status_for_done_ratio? && p.status && p.status.default_done_ratio
   1532           child_count = p.children.count
   1533           if child_count > 0
   1534             average = p.children.where("estimated_hours > 0").average(:estimated_hours).to_f
   1535             if average == 0
   1536               average = 1
   1537             end
   1538             done = p.children.joins(:status).
   1539               sum("COALESCE(CASE WHEN estimated_hours > 0 THEN estimated_hours ELSE NULL END, #{average}) " +
   1540                   "* (CASE WHEN is_closed = #{self.class.connection.quoted_true} THEN 100 ELSE COALESCE(done_ratio, 0) END)").to_f
   1541             progress = done / (average * child_count)
   1542             p.done_ratio = progress.round
   1543           end
   1544         end
   1545       end
   1546
   1547       # ancestors will be recursively updated
   1548       p.save(:validate => false)
   1549     end
   1550   end

Possible Fix:

--- issue.rb.ori        2016-08-01 11:44:53.220332666 -0400
+++ issue.rb    2016-08-01 11:45:07.395332666 -0400
@@ -1531,13 +1531,12 @@
         unless Issue.use_status_for_done_ratio? && p.status && p.status.default_done_ratio
           child_count = p.children.count
           if child_count > 0
-            average = p.children.where("estimated_hours > 0").average(:estimated_hours).to_f
+            average = p.total_estimated_hours / child_count
             if average == 0
               average = 1
             end
-            done = p.children.joins(:status).
-              sum("COALESCE(CASE WHEN estimated_hours > 0 THEN estimated_hours ELSE NULL END, #{average}) " +
-                  "* (CASE WHEN is_closed = #{self.class.connection.quoted_true} THEN 100 ELSE COALESCE(done_ratio, 0) END)").to_f
+            done = 0
+            p.children.each { |c| done += (c.total_estimated_hours * c.done_ratio) }
             progress = done / (average * child_count)
             p.done_ratio = progress.round
           end

When one manually enter the estimated time.
In the original program, based on the average of other tasks to calculate progress. I keep the same approach in the patch :

--- issue.rb.ori        2016-08-01 11:44:53.220332666 -0400
+++ issue.rb    2016-08-01 13:42:18.138330460 -0400
@@ -1531,13 +1531,19 @@
         unless Issue.use_status_for_done_ratio? && p.status && p.status.default_done_ratio
           child_count = p.children.count
           if child_count > 0
-            average = p.children.where("estimated_hours > 0").average(:estimated_hours).to_f
+            average = (p.total_estimated_hours||=0) / child_count
             if average == 0
               average = 1
             end
-            done = p.children.joins(:status).
-              sum("COALESCE(CASE WHEN estimated_hours > 0 THEN estimated_hours ELSE NULL END, #{average}) " +
-                  "* (CASE WHEN is_closed = #{self.class.connection.quoted_true} THEN 100 ELSE COALESCE(done_ratio, 0) END)").to_f
+            done = 0
+            p.children.each do |c|
+               dr =  c.closed_on.nil? ? (c.done_ratio||=0) : 100
+               unless c.total_estimated_hours.nil? || c.total_estimated_hours == 0
+                       done += (c.total_estimated_hours * c.done_ratio)
+               else
+                       done += average * c.done_ratio
+               end
+           end
             progress = done / (average * child_count)
             p.done_ratio = progress.round
           end

Files


Related issues

Related to Redmine - Defect #20995: Automatic done ratio calculation in issue tree is wrong in some casesClosedJean-Philippe Lang

Actions
Related to Redmine - Defect #24457: Progress of version should be calculated the same way as parent tasksClosedMarius BĂLTEANU

Actions
Has duplicate Redmine - Defect #24213: % Done is not correct for parent to parents when calculated from subtasksClosed

Actions
Has duplicate Redmine - Defect #23151: done_ratio calculation with multi-level sub tasks and estimated hoursClosed

Actions
Actions

Also available in: Atom PDF