source: timingandestimationplugin/branches/trac0.10/timingandestimationplugin/api.py

Last change on this file was 3785, checked in by Russ Tyndall, 15 years ago

closes #3131
closes #3074
T&E(trac 10) 0.6.6

I brought the trac 10 branch up to the same version number of the plugin so that hopefully there is less confusion on my part about versions.

Fixes horrible bug relating to database access (due to my misunderstanding of which things were stateful in trac/python).

Fixed some bugs in the way billable values were being compared in the reports file (strong vs weak typed databases)

File size: 9.4 KB
Line 
1import re
2import dbhelper
3import time
4from ticket_daemon import *
5from usermanual import *
6from trac.log import logger_factory
7from trac.ticket import ITicketChangeListener, Ticket
8from trac.core import *
9from trac.env import IEnvironmentSetupParticipant
10from trac.perm import IPermissionRequestor, PermissionSystem
11from webui import *
12from ticket_webui import *
13from reportmanager import CustomReportManager
14
15## report columns
16## id|author|title|query|description
17
18class TimeTrackingSetupParticipant(Component):
19    """ This is the config that must be there for this plugin to work:
20
21        [ticket-custom]
22        totalhours = text
23        totalhours.value = 0
24        totalhours.label = Total Hours
25
26        billable = checkbox
27        billable.value = 1
28        billable.label = Is this billable?
29
30        hours = text
31        hours.value = 0
32        hours.label = Hours to Add
33
34        estimatedhours = text
35        estimatedhours.value = 0
36        estimatedhours.label = Estimated Hours?
37
38        """
39    implements(IEnvironmentSetupParticipant)
40
41    db_version_key = None
42    db_version = None
43    db_installed_version = None
44
45    """Extension point interface for components that need to participate in the
46    creation and upgrading of Trac environments, for example to create
47    additional database tables."""
48    def __init__(self):
49        # Setup logging
50        self.db_version_key = 'TimingAndEstimationPlugin_Db_Version'
51        self.db_version = 7
52        self.db_installed_version = None
53
54        # Initialise database schema version tracking.
55        db = self.env.get_db_cnx()
56        cursor = db.cursor()
57        cursor.execute("SELECT value FROM system WHERE name=%s", (self.db_version_key,))
58        try:
59            self.db_installed_version = int(cursor.fetchone()[0])
60        except:
61            self.db_installed_version = 0
62            cursor.execute("INSERT INTO system (name,value) VALUES(%s,%s)",
63                           (self.db_version_key, self.db_installed_version))
64            db.commit()
65            db.close()
66            print "Done"
67
68    def environment_created(self):
69        """Called when a new Trac environment is created."""
70        if self.environment_needs_upgrade(None):
71            self.upgrade_environment(None)
72
73    def system_needs_upgrade(self):
74        return self.db_installed_version < self.db_version
75
76    def do_db_upgrade(self):
77        # Legacy support hack (supports upgrades from 0.1.6 to 0.1.7)
78        if self.db_installed_version == 0:
79            bill_date = dbhelper.db_table_exists(self, 'bill_date');
80            report_version = dbhelper.db_table_exists(self, 'report_version');
81            if bill_date and report_version:
82                self.db_installed_version = 1
83        # End Legacy support hack
84
85
86        if self.db_installed_version < 1:
87            print "Creating bill_date table"
88            sql = """
89            CREATE TABLE bill_date (
90            time integer,
91            set_when integer,
92            str_value text
93            );
94            """
95            dbhelper.execute_non_query(self,  sql)
96
97            print "Creating report_version table"
98            sql = """
99            CREATE TABLE report_version (
100            report integer,
101            version integer,
102            UNIQUE (report, version)
103            );
104            """
105            dbhelper.execute_non_query(self, sql)
106
107        if self.db_installed_version < 4:
108            print "Upgrading report_version table to v4"
109            sql ="""
110            ALTER TABLE report_version ADD COLUMN tags varchar(1024) null;
111            """
112            dbhelper.execute_non_query(self, sql)
113
114        if self.db_installed_version < 5:
115            # In this version we convert to using reportmanager.py
116            # The easiest migration path is to remove all the reports!!
117            # They will be added back in later but all custom reports will be lost (deleted)
118            print "Dropping report_version table"
119            sql = "DELETE FROM report " \
120                  "WHERE author=%s AND id IN (SELECT report FROM report_version)"
121            dbhelper.execute_non_query(self,  sql, 'Timing and Estimation Plugin')
122
123            sql = "DROP TABLE report_version"
124            dbhelper.execute_non_query(self,  sql)
125
126        # 6 & 7 are report upgrades
127
128        # This statement block always goes at the end this method
129        dbhelper.set_system_value(self, self.db_version_key, self.db_version)
130        self.db_installed_version = self.db_version
131
132
133    def do_reports_upgrade(self):
134        self.log.debug( "Beginning Reports Upgrade");
135        mgr = CustomReportManager(self.env, self.log)
136        r = __import__("reports", globals(), locals(), ["all_reports"])
137
138        for report_group in r.all_reports:
139            rlist = report_group["reports"]
140            group_title = report_group["title"]
141            for report in rlist:
142                title = report["title"]
143                new_version = report["version"]
144                mgr.add_report(report["title"], "Timing and Estimation Plugin", \
145                               "", report["sql"], \
146                               report["uuid"], report["version"],
147                               "Timing and Estimation Plugin",
148                               group_title)
149
150
151    def ticket_fields_need_upgrade(self):
152        ticket_custom = "ticket-custom"
153        return not ( self.config.get( ticket_custom, "totalhours" ) and \
154                     #self.config.get( ticket_custom, "billable" ) and \
155                     #(self.config.get( ticket_custom, "billable" ) == "checkbox") and \
156                     #self.config.get( ticket_custom, "billable.order") and \
157                     #(not self.config.get( ticket_custom, "lastbilldate" )) and \
158
159                     self.config.get( ticket_custom, "hours" ) and \
160                     self.config.get( ticket_custom, "totalhours.order") and \
161                     self.config.get( ticket_custom, "hours.order") and \
162                     self.config.get( ticket_custom, "estimatedhours.order") and \
163                     self.config.get( ticket_custom, "estimatedhours"))
164
165    def do_ticket_field_upgrade(self):
166        ticket_custom = "ticket-custom"
167
168        self.config.set(ticket_custom,"totalhours", "text")
169        if not self.config.get( ticket_custom, "totalhours.order") :
170            self.config.set(ticket_custom,"totalhours.order", "4")
171        self.config.set(ticket_custom,"totalhours.value", "0")
172        self.config.set(ticket_custom,"totalhours.label", "Total Hours")
173
174        self.config.set(ticket_custom,"billable", "checkbox")
175        self.config.set(ticket_custom,"billable.value", "1")
176        if not self.config.get( ticket_custom, "billable.order") :
177            self.config.set(ticket_custom,"billable.order", "3")
178        self.config.set(ticket_custom,"billable.label", "Billable?")
179
180        self.config.set(ticket_custom,"hours", "text")
181        self.config.set(ticket_custom,"hours.value", "0")
182        if not self.config.get( ticket_custom, "hours.order") :
183            self.config.set(ticket_custom,"hours.order", "2")
184        self.config.set(ticket_custom,"hours.label", "Add Hours to Ticket")
185
186        self.config.set(ticket_custom,"estimatedhours", "text")
187        self.config.set(ticket_custom,"estimatedhours.value", "0")
188        if not self.config.get( ticket_custom, "estimatedhours.order") :
189            self.config.set(ticket_custom,"estimatedhours.order", "1")
190        self.config.set(ticket_custom,"estimatedhours.label", "Estimated Number of Hours")
191
192        self.config.save();
193
194    def needs_user_man(self):
195        maxversion = dbhelper.get_scalar(self, "SELECT MAX(version) FROM wiki WHERE name like %s", 0,
196                                         user_manual_wiki_title)
197        if (not maxversion) or maxversion < user_manual_version:
198            return True
199        return False
200
201    def do_user_man_update(self):
202
203        when = int(time.time())
204        sql = """
205        INSERT INTO wiki (name,version,time,author,ipnr,text,comment,readonly)
206        VALUES ( %s, %s, %s, 'Timing and Estimation Plugin', '127.0.0.1', %s,'',0)
207        """
208        dbhelper.execute_non_query(self, sql,
209                                   user_manual_wiki_title,
210                                   user_manual_version,
211                                   when,
212                                   user_manual_content)
213
214
215    def environment_needs_upgrade(self, db):
216        """Called when Trac checks whether the environment needs to be upgraded.
217
218        Should return `True` if this participant needs an upgrade to be
219        performed, `False` otherwise.
220
221        """
222        return (self.system_needs_upgrade()) or \
223               (self.ticket_fields_need_upgrade()) or \
224               (self.needs_user_man())
225
226    def upgrade_environment(self, db):
227        """Actually perform an environment upgrade.
228
229        Implementations of this method should not commit any database
230        transactions. This is done implicitly after all participants have
231        performed the upgrades they need without an error being raised.
232        """
233        def p(s):
234            print s
235            return True
236        print "Timing and Estimation needs an upgrade"
237        p("Upgrading Database")
238        self.do_db_upgrade()
239        p("Upgrading reports")
240        self.do_reports_upgrade()
241
242        if self.ticket_fields_need_upgrade():
243            p("Upgrading fields")
244            self.do_ticket_field_upgrade()
245        if self.needs_user_man():
246            p("Upgrading usermanual")
247            self.do_user_man_update()
248        print "Done Upgrading"
249
250
251
252
253
254
Note: See TracBrowser for help on using the repository browser.