ScrumBurndownPlugin: burndown_job.py

File burndown_job.py, 3.4 kB (added by sambloomquist, 2 years ago)
Line 
1 # Copyright (C) 2006 Sam Bloomquist <spooninator@hotmail.com>
2 # All rights reserved.
3 #
4 # This software may at some point consist of voluntary contributions made by
5 # many individuals. For the exact contribution history, see the revision
6 # history and logs, available at http://projects.edgewall.com/trac/.
7 #
8 # Author: Sam Bloomquist <spooninator@hotmail.com>
9
10 import time
11 import sys
12
13 from trac.core import *
14 from trac.util import format_date
15 from trac.env import open_environment
16
17 def main():
18     if len(sys.argv) != 2:
19         print >> sys.stderr, 'Must supply a trac_env as an argument to the burndown_job'
20         sys.exit(1)
21        
22     env_path = sys.argv[1]
23    
24     # today's date
25     today = format_date(int(time.time()))
26    
27     # open up a connection to the trac database
28     env = open_environment(env_path)
29     db = env.get_db_cnx()
30     cursor = db.cursor()
31    
32     # make sure that there isn't already an entry for today in the burndown table
33     cursor.execute("SELECT id FROM burndown WHERE date = '%s'" % today)
34     row = cursor.fetchone()
35     needs_update = False
36     if row:
37         print >> sys.stderr, 'burndown_job.py has already been run today - update needed'
38         needs_update = True
39     else:
40         print >> sys.stderr, 'first run of burndown_job.py today - insert needed'
41    
42     # get arrays of the various components and milestones in the trac environment
43     cursor.execute("SELECT name AS comp FROM component")
44     components = cursor.fetchall()
45     cursor.execute("SELECT name, started, completed FROM milestone")
46     milestones = cursor.fetchall()
47    
48     for mile in milestones:
49         if mile[1] and not mile[2]: # milestone started, but not completed
50             for comp in components:
51                 sqlSelect =     "SELECT est.value AS estimate, ts.value AS spent "\
52                                     "FROM ticket t "\
53                                     "    LEFT OUTER JOIN ticket_custom est ON (t.id = est.ticket AND est.name = 'estimatedhours') "\
54                                     "    LEFT OUTER JOIN ticket_custom ts ON (t.id = ts.ticket AND ts.name = 'totalhours') "\
55                                     "WHERE t.component = '%s' AND t.milestone = '%s' "
56                 cursor.execute(sqlSelect % (comp[0], mile[0]))
57            
58                 rows = cursor.fetchall()
59                 hours = 0
60                 estimate = 0
61                 spent = 0
62                 if rows:
63                     for estimate, spent in rows:
64                         if not estimate:
65                             estimate = 0
66                         if not spent:
67                             spent = 0
68                    
69                         hours += float(estimate) - float(spent)
70                
71                 if needs_update:
72                     cursor.execute("UPDATE burndown SET hours_remaining = '%f' WHERE date = '%s' AND milestone_name = '%s'"\
73                                         "AND component_name = '%s'" % (hours, today, mile[0], comp[0]))
74                 else:
75                     cursor.execute("INSERT INTO burndown(id,component_name, milestone_name, date, hours_remaining) "\
76                                         "    VALUES(NULL,'%s','%s','%s',%f)" % (comp[0], mile[0], today, hours))
77                                      
78     db.commit()
79
80 if __name__ == '__main__':
81     main()