source: timingandestimationplugin/branches/trac0.12-Permissions/timingandestimationplugin/api.py

Last change on this file was 12856, checked in by Russ Tyndall, 11 years ago

fixed broken import of module I refactored away last week fix #10988

File size: 11.7 KB
RevLine 
[1119]1import re
2import dbhelper
[1369]3import time
[3784]4from tande_filters import *
[4260]5from reports_filter import *
6from blackmagic import *
[1119]7from ticket_daemon import *
[4261]8from ticket_webui import *
[1119]9from usermanual import *
[4293]10from ticket_policy import *
[1119]11from trac.ticket import ITicketChangeListener, Ticket
12from trac.core import *
13from trac.env import IEnvironmentSetupParticipant
14from trac.perm import IPermissionRequestor, PermissionSystem
[3784]15from webui import *
[2298]16from query_webui import *
[2390]17from reportmanager import CustomReportManager
[2774]18from statuses import *
[2785]19from reports import all_reports
[7436]20from stopwatch import *
[1119]21
22## report columns
23## id|author|title|query|description
[3784]24
[1119]25class TimeTrackingSetupParticipant(Component):
26    """ This is the config that must be there for this plugin to work:
[3784]27
[1119]28        [ticket-custom]
29        totalhours = text
30        totalhours.value = 0
31        totalhours.label = Total Hours
32
33        billable = checkbox
34        billable.value = 1
35        billable.label = Is this billable?
36
37        hours = text
38        hours.value = 0
39        hours.label = Hours to Add
[3784]40
[1119]41        estimatedhours = text
42        estimatedhours.value = 0
43        estimatedhours.label = Estimated Hours?
[3784]44
[4293]45        internal = checkbox
46        internal.value = 0
47        internal.label = Internal?
48
[1119]49        """
50    implements(IEnvironmentSetupParticipant)
[2390]51    db_version_key = None
52    db_version = None
53    db_installed_version = None
[3784]54
[1119]55    """Extension point interface for components that need to participate in the
56    creation and upgrading of Trac environments, for example to create
57    additional database tables."""
58    def __init__(self):
[2390]59        # Setup logging
[2774]60        self.statuses_key = 'T&E-statuses'
[2390]61        self.db_version_key = 'TimingAndEstimationPlugin_Db_Version'
[4266]62        self.db_version = 8
[2390]63        # Initialise database schema version tracking.
[8141]64        self.db_installed_version = dbhelper.get_system_value(self.env, \
[3119]65            self.db_version_key) or 0
[2390]66
[1119]67    def environment_created(self):
68        """Called when a new Trac environment is created."""
69        if self.environment_needs_upgrade(None):
70            self.upgrade_environment(None)
[2390]71
[3784]72
[2390]73    def system_needs_upgrade(self):
74        return self.db_installed_version < self.db_version
[3784]75
[2390]76    def do_db_upgrade(self):
[9989]77        self.log.debug( "T&E Beginning DB Upgrade");
[2390]78        if self.db_installed_version < 1:
[9989]79            if not dbhelper.db_table_exists(self.env, 'bill_date'):
80                print "Creating bill_date table"
81                sql = """
82                CREATE TABLE bill_date (
83                time integer,
84                set_when integer,
85                str_value text
86                );"""
87                dbhelper.execute_non_query(self.env,  sql)
[2823]88
[3784]89
[2390]90        if self.db_installed_version < 5:
[8141]91            if dbhelper.db_table_exists(self.env, 'report_version'):
[4267]92                print "Dropping report_version table"
93                sql = "DELETE FROM report " \
94                    "WHERE author=%s AND id IN (SELECT report FROM report_version)"
[8141]95                dbhelper.execute_non_query(self.env, sql, 'Timing and Estimation Plugin')
[2349]96
[4267]97                sql = "DROP TABLE report_version"
[8141]98                dbhelper.execute_non_query(self.env, sql)
[3784]99
100        #version 6 upgraded reports
101
[4266]102
[4265]103        if self.db_installed_version < 7:
104            field_settings = "field settings"
[4293]105            self.config.set( field_settings, "fields", "billable, totalhours, hours, estimatedhours, internal" )
[4265]106            self.config.set( field_settings, "billable.permission", "TIME_VIEW:hide, TIME_RECORD:disable" )
107            self.config.set( field_settings, "hours.permission", "TIME_VIEW:remove, TIME_RECORD:disable" )
108            self.config.set( field_settings, "estimatedhours.permission", "TIME_RECORD:disable" )
[4293]109            self.config.set( field_settings, "internal.permission", "TIME_RECORD:hide")
[3784]110
[4266]111        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
112        # This statement block always goes at the end this method
[8141]113        dbhelper.set_system_value(self.env, self.db_version_key, self.db_version)
[4266]114        self.db_installed_version = self.db_version
115        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
116
[4265]117           
118
[2785]119    def reports_need_upgrade(self):
120        mgr = CustomReportManager(self.env, self.log)
[5493]121        db_reports = mgr.get_version_hash_by_group(CustomReportManager.TimingAndEstimationKey)
122        py_reports = {}
[2785]123        for report_group in all_reports:
124            for report in report_group['reports']:
[5493]125                py_reports[report['uuid']]= report['version']
126       
127        diff = [(uuid, version) for (uuid, version) in py_reports.items()
128                if not db_reports.has_key(uuid) or int(db_reports[uuid]) < int(version)]
129               
[3179]130        if len(diff) > 0:
[5493]131            self.log.debug ("T&E needs upgrades for the following reports: %s" %
132                            (diff, ))
[3179]133        return len(diff) > 0
[3784]134
[2774]135    def do_reports_upgrade(self, force=False):
[1626]136        self.log.debug( "Beginning Reports Upgrade");
[2390]137        mgr = CustomReportManager(self.env, self.log)
[8141]138        statuses = get_statuses(self.env)
[2774]139        stat_vars = status_variables(statuses)
[3784]140
[2785]141        for report_group in all_reports:
[1119]142            rlist = report_group["reports"]
[2349]143            group_title = report_group["title"]
[1119]144            for report in rlist:
145                title = report["title"]
146                new_version = report["version"]
[3784]147
[2774]148                sql = report["sql"].replace('#STATUSES#', stat_vars)
[2390]149                mgr.add_report(report["title"], "Timing and Estimation Plugin", \
[2774]150                               "Reports Must Be Accessed From the Management Screen",
151                               sql, report["uuid"], report["version"],
152                               CustomReportManager.TimingAndEstimationKey,
153                               group_title, force)
[1119]154
155    def ticket_fields_need_upgrade(self):
156        ticket_custom = "ticket-custom"
157        return not ( self.config.get( ticket_custom, "totalhours" ) and \
[4293]158                         self.config.get( ticket_custom, "hours" ) and \
159                         self.config.get( ticket_custom, "estimatedhours") and \
160                         self.config.get( ticket_custom, "internal") and \
161                         "InternalTicketsPolicy" in self.config.getlist("trac", "permission_policies"))
[3784]162
[1119]163    def do_ticket_field_upgrade(self):
164        ticket_custom = "ticket-custom"
[3784]165
[4293]166        if not self.config.get(ticket_custom,"totalhours"):
167            self.config.set(ticket_custom,"totalhours", "text")
[1554]168            self.config.set(ticket_custom,"totalhours.order", "4")
[4293]169            self.config.set(ticket_custom,"totalhours.value", "0")
170            self.config.set(ticket_custom,"totalhours.label", "Total Hours")
[1119]171
[4293]172
173        if not self.config.get(ticket_custom,"billable"):
174            self.config.set(ticket_custom,"billable", "checkbox")
175            self.config.set(ticket_custom,"billable.value", "1")
[1554]176            self.config.set(ticket_custom,"billable.order", "3")
[4293]177            self.config.set(ticket_custom,"billable.label", "Billable?")
[3784]178
[4293]179        if not self.config.get(ticket_custom,"hours"):
180            self.config.set(ticket_custom,"hours", "text")
181            self.config.set(ticket_custom,"hours.value", "0")
[1554]182            self.config.set(ticket_custom,"hours.order", "2")
[4293]183            self.config.set(ticket_custom,"hours.label", "Add Hours to Ticket")
[3784]184
[4293]185        if not self.config.get(ticket_custom,"estimatedhours"):
186            self.config.set(ticket_custom,"estimatedhours", "text")
187            self.config.set(ticket_custom,"estimatedhours.value", "0")
[1554]188            self.config.set(ticket_custom,"estimatedhours.order", "1")
[4293]189            self.config.set(ticket_custom,"estimatedhours.label", "Estimated Number of Hours")
[1119]190
[4293]191        if not self.config.get( ticket_custom, "internal"):
192            self.config.set(ticket_custom, "internal", "checkbox")
193            self.config.set(ticket_custom, "internal.value", "0")
194            self.config.set(ticket_custom, "internal.label", "Internal?")
195            self.config.set(ticket_custom,"internal.order", "5")
196
197        if "InternalTicketsPolicy" not in self.config.getlist("trac", "permission_policies"):
198            perms = ["InternalTicketsPolicy"]
199            other_policies = self.config.getlist("trac", "permission_policies")
200            if "DefaultPermissionPolicy" not in other_policies:
201                perms.append("DefaultPermissionPolicy")
202            perms.extend( other_policies )
203            self.config.set("trac", "permission_policies", ', '.join(perms))
204
[1119]205        self.config.save();
206
207    def needs_user_man(self):
[8141]208        maxversion = dbhelper.get_scalar(
209            self.env, "SELECT MAX(version) FROM wiki WHERE name like %s", 0,
210            user_manual_wiki_title)
[1119]211        if (not maxversion) or maxversion < user_manual_version:
212            return True
213        return False
214
215    def do_user_man_update(self):
[1444]216
[1369]217        when = int(time.time())
[1119]218        sql = """
219        INSERT INTO wiki (name,version,time,author,ipnr,text,comment,readonly)
[1369]220        VALUES ( %s, %s, %s, 'Timing and Estimation Plugin', '127.0.0.1', %s,'',0)
[1119]221        """
[8141]222        dbhelper.execute_non_query(self.env, sql,
[1119]223                                   user_manual_wiki_title,
224                                   user_manual_version,
[1369]225                                   when,
[1119]226                                   user_manual_content)
[3784]227
228
[1119]229    def environment_needs_upgrade(self, db):
230        """Called when Trac checks whether the environment needs to be upgraded.
[3784]231
[1119]232        Should return `True` if this participant needs an upgrade to be
233        performed, `False` otherwise.
234
235        """
[8141]236        sysUp = self.system_needs_upgrade()
237        # Dont check for upgrades that will break the transaction
238        # If we dont have a system, then everything needs to be updated
239        res = (sysUp,
240               sysUp or self.reports_need_upgrade(),
241               sysUp or self.have_statuses_changed(),
242               sysUp or self.ticket_fields_need_upgrade(),
243               sysUp or self.needs_user_man())
244        self.log.debug("T&E NEEDS UP?: sys:%s, rep:%s, stats:%s, fields:%s, man:%s" % \
245                       res)
246        r = False;
247        for i in res: r |= i
248        return r
[3784]249
[1119]250    def upgrade_environment(self, db):
251        """Actually perform an environment upgrade.
[3784]252
[1119]253        Implementations of this method should not commit any database
254        transactions. This is done implicitly after all participants have
255        performed the upgrades they need without an error being raised.
256        """
257        def p(s):
258            print s
259            return True
260        print "Timing and Estimation needs an upgrade"
[2390]261        p("Upgrading Database")
262        self.do_db_upgrade()
263        p("Upgrading reports")
[2774]264        self.do_reports_upgrade(force=self.have_statuses_changed())
[3784]265
[2774]266        #make sure we upgrade the statuses string so that we dont need to always rebuild the
267        # reports
[8141]268        stats = get_statuses(self.env)
[2774]269        val = ','.join(list(stats))
[8141]270        dbhelper.set_system_value(self.env, self.statuses_key, val)
[3784]271
[1119]272        if self.ticket_fields_need_upgrade():
273            p("Upgrading fields")
274            self.do_ticket_field_upgrade()
275        if self.needs_user_man():
276            p("Upgrading usermanual")
277            self.do_user_man_update()
278        print "Done Upgrading"
279
[2774]280    def have_statuses_changed(self):
281        """get the statuses from the last time we saved them,
282        compare them to the ones we have now (ignoring '' and None),
283        if we have different ones, throw return true
284        """
[8141]285        s = dbhelper.get_system_value(self.env, self.statuses_key)
[2774]286        if not s:
287            return True
[8141]288        sys_stats = get_statuses(self.env)
[2774]289        s = s.split(',')
290        sys_stats.symmetric_difference_update(s)
291        sys_stats.difference_update(['', None])
292        return len(sys_stats) > 0
Note: See TracBrowser for help on using the repository browser.