Opened 9 years ago

Last modified 21 months ago

#4376 new enhancement

Show "remaining estimated hours" in the Roadmap

Reported by: Jeff Hammel Owned by:
Priority: normal Component: TracHoursPlugin
Severity: normal Keywords:
Cc: julien.perville@…, fabien.catteau@… Trac Release: 0.11


I extended the Roadmap screen to display the "remaining estimated hours" per milestone on side of the existing 'estimated hours' and 'total hours'.

The "remaining estimated hours" is the sum of all (estimated times - total time) for each non-closed tickets in a milestone.

Example: imagine that we have a milestone with a total estimated of 20h, and we have worked for 4h so far; then the remaining estimated time is 16h. Now we close a ticket of that milestone that was previously estimated to 2h in only 1h, then the remaining estimated time should drop to 14h (and not to 15h since that ticket that was estimated to 2h has been closed even if we only put 1h of work in it).

Here is a patch over r20999 implements that new feature, feel free to include it into TracHours under same licence as TracHours.

Index: trachours/
--- trachours/	(revision 21074)
+++ trachours/	(working copy)
@@ -1009,7 +1009,8 @@
         hours = {}
         for milestone in data['milestones']:
             hours[] = dict(totalhours=0., 
-                                         estimatedhours=0.,)
+                                         estimatedhours=0.,
+                                         remaininghours=0.,)
             db = self.env.get_db_cnx()
             cursor = db.cursor()
@@ -1020,14 +1021,20 @@
                 hours[]['date'] = Ticket(self.env, tickets[0]).time_created
             for ticket in tickets:
                 ticket = Ticket(self.env, ticket)
-                for field in 'totalhours', 'estimatedhours':
-                    try:
-                        time = float(ticket[field])
-                    except (ValueError, TypeError):
-                        time = 0.
-                    hours[][field] += time
-                    if ticket.time_created < hours[]['date']:
-                        hours[]['date'] = ticket.time_created
+                try:
+                    total_time = float(ticket['totalhours'])
+                except (ValueError, TypeError):
+                    total_time = 0.
+                hours[]['totalhours'] += total_time
+                try:
+                    estimated_time = float(ticket['estimatedhours'])
+                except (ValueError, TypeError):
+                    estimated_time = 0.
+                hours[]['estimatedhours'] += estimated_time
+                if ticket['status'] != 'closed':
+                    hours[]['remaininghours'] += estimated_time - total_time
+                if ticket.time_created < hours[]['date']:
+                    hours[]['date'] = ticket.time_created
         class MilestoneMarkup(object): # TODO: move elsewhere
             def __init__(self, buffer, hours, href):
@@ -1039,19 +1046,23 @@
                 hours = self.hours[milestone]
                 estimatedhours = hours['estimatedhours']
                 totalhours = hours['totalhours']
-                if not (estimatedhours or totalhours):
+                remaininghours = hours['remaininghours']
+                if not (estimatedhours or totalhours or remaininghours):
                     return iter([])
                 items = []
                 if estimatedhours:
-                    items.append(tag.dt("Estimated Hours:"))
+                    items.append(tag.dt("Total Estimated Hours:"))
                 date = hours['date']
                 link = self.href("hours", milestone=milestone, 
-                items.append(tag.dt(tag.a("Total Hours:", href=link)))
+                items.append(tag.dt(tag.a("Total Worked Hours:", href=link)))
                 items.append(tag.dd(tag.a(str(totalhours), href=link)))
+                if remaininghours:
+                    items.append(tag.dt("Remaining Estimated Hours:"))
+                    items.append(tag.dd(str(remaininghours)))
                 return iter(tag.dl(*items))
         find_xpath = "//li[@class='milestone']//h2/a"

Attachments (0)

Change History (3)

comment:1 Changed 9 years ago by Jeff Hammel

CCing original ticket author, julien.perville@...

comment:2 Changed 7 years ago by Ryan J Ollos

Owner: changed from Jeff Hammel to Ryan J Ollos

Reassigning ticket to new maintainer.

comment:3 Changed 21 months ago by Ryan J Ollos

Owner: Ryan J Ollos deleted

Modify Ticket

Change Properties
Set your email in Preferences
as new The ticket will remain with no owner.

Add Comment

E-mail address and name can be saved in the Preferences.

Note: See TracTickets for help on using tickets.