コード例 #1
0
    def get_ticket_group_stats(self, ticket_ids):

        # ticket_ids is a list of ticket id as number.
        total_count = len(ticket_ids)
        status_count = {'closed': 0, 'new': 0, 'reopened': 0}

        if total_count:
            db = self.env.get_db_cnx()
            cursor = db.cursor()
            str_ids = [str(x) for x in sorted(ticket_ids)]
            cursor.execute("""
                SELECT status, count(status) FROM ticket
                WHERE id IN (%s) GROUP BY status""" % ",".join(str_ids))

            for status, count in cursor.fetchall():
                status_count[status] = count

        inprogress_cnt = total_count - (status_count['new'] + \
            status_count['reopened'] + status_count['closed'])

        stat = TicketGroupStats('ticket status', 'ticket')
        stat.add_interval('closed', status_count['closed'], {
            'status': 'closed',
            'group': 'resolution'
        }, 'closed', True)
        stat.add_interval('inprogress', inprogress_cnt,
                          {'status': ['accepted', 'assigned']}, 'inprogress',
                          False)
        stat.add_interval('new',
                          status_count['new'] + status_count['reopened'],
                          {'status': ['new', 'reopened']}, 'new', False)

        stat.refresh_calcs()
        return stat
コード例 #2
0
ファイル: web_ui.py プロジェクト: svn2github/sumstatsplugin
 def get_ticket_group_stats(self, ticket_ids):
     stat = TicketGroupStats(self.drilldown_label, self.sum_label)
     for group in self._get_groups(ticket_ids):
         stat.add_interval(
             title=group.get('label', group['name']),
             count=group.get('total', 0),
             qry_args=group.get('query_args', {}),
             css_class=group.get('css_class', group['name']),
             overall_completion=as_bool(group.get('overall_completion')))
     stat.refresh_calcs()
     return stat
コード例 #3
0
    def get_ticket_resolution_group_stats(self, ticket_ids):
        # ticket_ids is a list of ticket ids with type int

        stat = TicketGroupStats('ticket resolution', 'ticket')

        if len(ticket_ids):
            db = self.env.get_db_cnx()
            cursor = db.cursor()
            str_ids = [str(x) for x in sorted(ticket_ids)]

            cursor.execute("""
                SELECT resolution, count(resolution) FROM ticket
                WHERE status='closed' AND id IN (%s)""" % ",".join(str_ids))

            resolution_count = {}
            for resolution, count in cursor.fetchall():
                resolution_count[resolution] = count

            for key, value in resolution_count.iteritems():
                if key in ('fixed',
                           'completed'):  # default ticket type 'defect'
                    stat.add_interval(key, value, {'resolution': key}, 'value',
                                      True)
                else:
                    stat.add_interval(key, value, {'resolution': key}, 'waste',
                                      False)

        stat.refresh_calcs()
        return stat
コード例 #4
0
ファイル: model.py プロジェクト: nyuhuhuu/trachacks
    def get_ticket_resolution_group_stats(self, ticket_ids):
        # ticket_ids is a list of ticket ids with type int

        stat = TicketGroupStats('ticket resolution', 'ticket')

        if len(ticket_ids):
            db = self.env.get_db_cnx()
            cursor = db.cursor()
            str_ids = [str(x) for x in sorted(ticket_ids)]

            cursor.execute("""
                SELECT resolution, count(resolution) FROM ticket
                WHERE status='closed' AND id IN (%s)"""
                % ",".join(str_ids))

            resolution_count = {}
            for resolution, count in cursor.fetchall():
                resolution_count[resolution] = count

            for key, value in resolution_count.iteritems():
                if key in ('fixed', 'completed'):  # default ticket type 'defect'
                    stat.add_interval(key, value, {'resolution': key},
                                      'value', True)
                else:
                    stat.add_interval(key, value, {'resolution': key},
                                      'waste', False)

        stat.refresh_calcs()
        return stat
コード例 #5
0
ファイル: model.py プロジェクト: lexqt/EduTracMetrix
    def get_ticket_resolution_group_stats(self, ticket_ids, pid):

        stat = TicketGroupStats(_('ticket resolution'), '')

        if len(ticket_ids):
            db = self.env.get_db_cnx()
            cursor = db.cursor()

            count_by_resolution = [] # list of dictionaries with keys name and count
            for resolution in model.Resolution.select(self.env, pid=pid, db=db):
                cursor.execute('''
                    SELECT COUNT(*) FROM ticket
                    WHERE project_id=%s AND status = 'closed' AND resolution=%s AND id IN %s
                    ''', (pid, resolution.name, tuple(ticket_ids)))

                count = cursor.fetchone()[0]
                if count > 0:
                    count_by_resolution.append({'name': resolution.name, 'count': count})

            for t in count_by_resolution:
                if t['name'] in self.done_resolutions:
                    stat.add_interval(t['name'], t['count'],
                                      {'resolution': t['name']}, 'value', True)
                else:
                    stat.add_interval(t['name'], t['count'],
                                      {'resolution': t['name']}, 'waste', False)

        stat.refresh_calcs()
        return stat
コード例 #6
0
 def _build_story_statistics(self, req, stats_provider, sprint_name):
     """
     Assemble statistics for all stories in the given sprint_name so 
     that the progress bar can be displayed.
     """
     sprint_stats = dict()
     
     if not sprint_name:
         return sprint_stats
     
     cmd_get_stories = SprintController.ListTicketsHavingPropertiesCommand(self.env,
                                                                           sprint=sprint_name,
                                                                           properties=[Key.STORY_POINTS])
     stories = self.controller.process_command(cmd_get_stories)
     type_dict = dict()
     closed_stories = list()
     inprogress_stories = list()
     for story in stories:
         if story[Key.STATUS] == Status.CLOSED:
             closed_stories.append(story)
         elif story[Key.STATUS] != Status.NEW:
             inprogress_stories.append(story)
         type_dict[story[Key.TYPE]] = True
     type_names = type_dict.keys()
     number_open_stories = len(stories) - (len(closed_stories) + \
                                           len(inprogress_stories))
     
     try:
         stat = TicketGroupStats('User Stories status', 'stories')
         stat.add_interval(_('Completed'), len(closed_stories), 
                           qry_args={Key.STATUS: Status.CLOSED},
                           css_class='closed', overall_completion=True)
         stat.add_interval(_('In Progress'), len(inprogress_stories), 
                           qry_args={Key.STATUS: Status.ACCEPTED},
                           css_class='inprogress')
         stat.add_interval(_('Open'), number_open_stories, 
                           qry_args={Key.STATUS: [Status.NEW, 
                                                  Status.REOPENED]},
                           css_class='open')
         stat.refresh_calcs()
         sprint_stats = self._build_sprint_stats_data(req, stat, sprint_name, 
                                                      type_names=type_names)
     except Exception, e:
         # The DB is closed? And we don't break for statistics
         error(stats_provider, "ERROR: %s" % to_unicode(e))
コード例 #7
0
ファイル: widget.py プロジェクト: nagyist/agilo
 def build_stats_object_for_roadmap_macro(self, contingent, unit=None):
     """Return a TicketGroupStats instance loaded with the parameters for
     time used vs. time left."""
     stats = TicketGroupStats('used contingent', unit)
     time_left = contingent.amount - contingent.actual
     stats.add_interval('used', contingent.actual, None, 'closed', overall_completion=True)
     stats.add_interval('left', time_left, None, None)
     stats.refresh_calcs()
     used_interval = stats.intervals[0]
     if stats.done_percent > 90:
         used_interval['css_class'] = 'critical'
     elif stats.done_percent > 70:
         used_interval['css_class'] = 'warning'
     return stats
コード例 #8
0
    def get_ticket_group_stats(self, ticket_ids):
        
        # ticket_ids is a list of ticket id as number.
        total_cnt = len(ticket_ids)
        if total_cnt:
            cursor = self.env.get_db_cnx().cursor() # get database connection
            str_ids = [str(x) for x in sorted(ticket_ids)] # create list of ticket id as string
            
            
            closed_cnt = cursor.execute("SELECT count(1) FROM ticket "
                                        "WHERE status = 'closed' AND id IN "
                                        "(%s)" % ",".join(str_ids)) # execute query and get cursor obj.
            closed_cnt = 0
            for cnt, in cursor:
                closed_cnt = cnt
                
            active_cnt = cursor.execute("SELECT count(1) FROM ticket "
                                        "WHERE status IN ('new', 'reopened') "
                                        "AND id IN (%s)" % ",".join(str_ids)) # execute query and get cursor obj.
            active_cnt = 0
            for cnt, in cursor:
                active_cnt = cnt
                
        else:
            closed_cnt = 0
            active_cnt = 0

        inprogress_cnt = total_cnt - ( active_cnt + closed_cnt)

        stat = TicketGroupStats('ticket status', 'ticket')
        stat.add_interval('closed', closed_cnt,
                          {'status': 'closed', 'group': 'resolution'},
                          'closed', True)
        stat.add_interval('inprogress', inprogress_cnt,
                          {'status': ['accepted', 'assigned']},
                          'inprogress', False)
        stat.add_interval('new', active_cnt,
                          {'status': ['new', 'reopened']},
                          'new', False)
                          
        stat.refresh_calcs()
        return stat
コード例 #9
0
ファイル: model.py プロジェクト: lexqt/EduTracMetrix
    def get_ticket_group_stats(self, ticket_ids, pid):

        total_cnt = len(ticket_ids)
        if total_cnt:

            db = self.env.get_db_cnx()
            cursor = db.cursor()

            closed_cnt = cursor.execute('''
                SELECT COUNT(*) FROM ticket
                WHERE status = 'closed' AND project_id=%s AND id IN %s
                ''', (pid, tuple(ticket_ids)))
            closed_cnt = cursor.fetchone()[0]

            active_cnt = cursor.execute('''
                SELECT COUNT(*) FROM ticket
                WHERE project_id=%s AND status IN %s AND id IN %s
                ''', (pid, tuple(self.new_statuses), tuple(ticket_ids)))
            active_cnt = cursor.fetchone()[0]

        else:
            closed_cnt = 0
            active_cnt = 0

        inprogress_cnt = total_cnt - ( active_cnt + closed_cnt)

        stat = TicketGroupStats(_('ticket status'), '')
        stat.add_interval(_('Closed'), closed_cnt,
                          {'status': 'closed', 'group': 'resolution'},
                          'closed', True)
        stat.add_interval(_('In progress'), inprogress_cnt,
                          {'status': ['!closed']+['!'+st for st in self.new_statuses]},
                          'inprogress', False)
        stat.add_interval(_('New'), active_cnt,
                          {'status': self.new_statuses},
                          'new', False)

        stat.refresh_calcs()
        return stat
コード例 #10
0
 def get_ticket_group_stats(self, ticket_ids):
     stat = TicketGroupStats(self.drilldown_label, self.sum_label)
     for group in self._get_groups(ticket_ids):
         stat.add_interval(title=group.get('label', group['name']),
                           count=group.get('total', 0),
                           qry_args=group.get('query_args', {}),
                           css_class=group.get('css_class', group['name']),
                           overall_completion=as_bool(
                               group.get('overall_completion')))
     stat.refresh_calcs()
     return stat
コード例 #11
0
ファイル: model.py プロジェクト: nyuhuhuu/trachacks
    def get_ticket_group_stats(self, ticket_ids):

        # ticket_ids is a list of ticket id as number.
        total_count = len(ticket_ids)
        status_count = {
            'closed': 0,
            'new': 0,
            'reopened': 0
        }

        if total_count:
            db = self.env.get_db_cnx()
            cursor = db.cursor()
            str_ids = [str(x) for x in sorted(ticket_ids)]
            cursor.execute("""
                SELECT status, count(status) FROM ticket
                WHERE id IN (%s) GROUP BY status"""
                % ",".join(str_ids))

            for status, count in cursor.fetchall():
                status_count[status] = count

        inprogress_cnt = total_count - (status_count['new'] + \
            status_count['reopened'] + status_count['closed'])

        stat = TicketGroupStats('ticket status', 'ticket')
        stat.add_interval('closed', status_count['closed'],
                          {'status': 'closed', 'group': 'resolution'},
                          'closed', True)
        stat.add_interval('inprogress', inprogress_cnt,
                          {'status': ['accepted', 'assigned']},
                          'inprogress', False)
        stat.add_interval('new', status_count['new'] + status_count['reopened'],
                          {'status': ['new', 'reopened']},
                          'new', False)

        stat.refresh_calcs()
        return stat
コード例 #12
0
    def get_ticket_group_stats(self, ticket_ids):

        # ticket_ids is a list of ticket id as number.
        total_cnt = len(ticket_ids)
        if total_cnt:

            db = self.env.get_db_cnx()
            cursor = db.cursor()

            type_count = []  # list of dictionary with key name and count

            for type in model.Type.select(self.env):

                cursor.execute(
                    "SELECT COUNT(*) FROM ticket "
                    "WHERE type = %%s AND id IN (%s)" %
                    (",".join(['%s'] * len(ticket_ids))),
                    (type.name, ) + tuple(ticket_ids))
                count = cursor.fetchone()[0]
                if count > 0:
                    type_count.append({'name': type.name, 'count': count})

        else:
            type_count = []

        stat = TicketGroupStats('ticket type', 'ticket')

        for type in type_count:

            if type['name'] != 'defect':  # default ticket type 'defect'

                stat.add_interval(type['name'], type['count'],
                                  {'type': type['name']}, 'value', True)

            else:
                stat.add_interval(type['name'], type['count'],
                                  {'type': type['name']}, 'waste', False)

        stat.refresh_calcs()
        return stat
コード例 #13
0
    def get_ticket_resolution_group_stats(self, ticket_ids):
        
        # ticket_ids is a list of ticket id as number.
        total_cnt = len(ticket_ids)
        if total_cnt:
            str_ids = [str(x) for x in sorted(ticket_ids)] # create list of ticket id as string
            cursor = self.env.get_db_cnx().cursor()  # get database connection    
            
            type_count = [] # list of dictionary with key name and count
            for type in model.Resolution.select(self.env):
                
                #Replace possible single-quotes in resolution strings with double single-quotes,
                #as required for SQLite queries (see th:#3684, http://www.sqlite.org/faq.html#q14)
                count = cursor.execute("SELECT count(1) FROM ticket "
                                        "WHERE status = 'closed' AND resolution = '%s' AND id IN "
                                        "(%s)" % (type.name.replace("'","''"), ",".join(str_ids)))
                count = 0
                for cnt, in cursor:
                    count = cnt

                if count > 0:
                    type_count.append({'name':type.name,'count':count})

        else:
            type_count = []
        
        stat = TicketGroupStats('ticket resolution', 'ticket')
        
        
        for type in type_count:
                
            if type['name'] in ('fixed', 'completed'): # default ticket type 'defect'
        
                stat.add_interval(type['name'], type['count'],
                                  {'resolution': type['name']}, 'value', True)
            
            else:
                stat.add_interval(type['name'], type['count'],
                                  {'resolution': type['name']}, 'waste', False)
                          
        stat.refresh_calcs()
        return stat
コード例 #14
0
    def get_ticket_group_stats(self, ticket_ids):
        
        # ticket_ids is a list of ticket id as number.
        total_cnt = len(ticket_ids)
        if total_cnt:
            str_ids = [str(x) for x in sorted(ticket_ids)] # create list of ticket id as string
            cursor = self.env.get_db_cnx().cursor()  # get database connection    
            
            type_count = [] # list of dictionary with key name and count
            
            for type in model.Type.select(self.env):
            
                count = cursor.execute("SELECT count(1) FROM ticket "
                                        "WHERE type = '%s' AND id IN "
                                        "(%s)" % (type.name, ",".join(str_ids))) # execute query and get cursor obj.
                count = 0
                for cnt, in cursor:
                    count = cnt

                if count > 0:
                    type_count.append({'name':type.name,'count':count})

        else:
            type_count = []
        
        stat = TicketGroupStats('ticket type', 'ticket')
        
        
        for type in type_count:
                
            if type['name'] != 'defect': # default ticket type 'defect'
        
                stat.add_interval(type['name'], type['count'],
                                  {'type': type['name']}, 'value', True)
            
            else:
                stat.add_interval(type['name'], type['count'],
                                  {'type': type['name']}, 'waste', False)
                          
        stat.refresh_calcs()
        return stat
コード例 #15
0
ファイル: model.py プロジェクト: nyuhuhuu/trachacks
    def get_ticket_group_stats(self, ticket_ids):

        # ticket_ids is a list of ticket id as number.
        total_cnt = len(ticket_ids)
        if total_cnt:

            db = self.env.get_db_cnx()
            cursor = db.cursor()

            type_count = [] # list of dictionary with key name and count

            for type in model.Type.select(self.env):

                cursor.execute("SELECT COUNT(*) FROM ticket "
                               "WHERE type = %%s AND id IN (%s)"
                               % (",".join(['%s'] * len(ticket_ids))), (type.name,) + tuple(ticket_ids))
                count = cursor.fetchone()[0]
                if count > 0:
                    type_count.append({'name':type.name, 'count':count})

        else:
            type_count = []

        stat = TicketGroupStats('ticket type', 'ticket')


        for type in type_count:

            if type['name'] != 'defect': # default ticket type 'defect'

                stat.add_interval(type['name'], type['count'],
                                  {'type': type['name']}, 'value', True)

            else:
                stat.add_interval(type['name'], type['count'],
                                  {'type': type['name']}, 'waste', False)

        stat.refresh_calcs()
        return stat
コード例 #16
0
ファイル: model.py プロジェクト: lexqt/EduTracMetrix
    def get_ticket_group_stats(self, ticket_ids, pid):

        total_cnt = len(ticket_ids)
        if total_cnt:

            db = self.env.get_db_cnx()
            cursor = db.cursor()

            type_count = [] # list of dictionary with key name and count

            for type in model.Type.select(self.env, pid=pid):

                cursor.execute('''
                    SELECT COUNT(*) FROM ticket
                    WHERE project_id=%s AND type = %s AND id IN %s
                    ''', (pid, type.name, tuple(ticket_ids)))
                count = cursor.fetchone()[0]
                if count > 0:
                    type_count.append({'name':type.name, 'count':count})

        else:
            type_count = []

        stat = TicketGroupStats(_('ticket type'), '')


        for type in type_count:

            if type['name'] not in self.waste_types:

                stat.add_interval(type['name'], type['count'],
                                  {'type': type['name']}, 'value', True)

            else:
                stat.add_interval(type['name'], type['count'],
                                  {'type': type['name']}, 'waste', False)

        stat.refresh_calcs()
        return stat
コード例 #17
0
ファイル: web_ui.py プロジェクト: pombredanne/trachacks
 def get_ticket_group_stats(self, ticket_ids):
     total_cnt = len(ticket_ids)
     stat = TicketGroupStats('ticket status', 'ticket')
     if total_cnt:
         cursor = self.env.get_db_cnx().cursor()
         id_list = ','.join([str(x) for x in ticket_ids])
         for title, status, color, countsToProg in self.groups:
             status_list = ','.join(["'%s'" % s for s in status])
             sql = ("SELECT count(1) FROM ticket"
                    " WHERE status IN (%s)"
                    " AND id IN (%s)" % (status_list, id_list))
             cursor.execute(sql)
             count = 0
             for cnt, in cursor:
                 count = cnt
             stat.add_interval(title, int(count), {'status': status}, title,
                               countsToProg)
     stat.refresh_calcs()
     return stat
コード例 #18
0
ファイル: roadmap.py プロジェクト: khoi-huynh/trac
 def setUp(self):
     self.stats = TicketGroupStats('title', 'units')
コード例 #19
0
ファイル: roadmap.py プロジェクト: khoi-huynh/trac
class TicketGroupStatsTestCase(unittest.TestCase):
    def setUp(self):
        self.stats = TicketGroupStats('title', 'units')

    def test_init(self):
        self.assertEqual('title', self.stats.title, 'title incorrect')
        self.assertEqual('units', self.stats.unit, 'unit incorrect')
        self.assertEqual(0, self.stats.count, 'count not zero')
        self.assertEqual(0, len(self.stats.intervals), 'intervals not empty')

    def test_add_iterval(self):
        self.stats.add_interval('intTitle', 3, {'k1': 'v1'}, 'css', 0)
        self.stats.refresh_calcs()
        self.assertEqual(3, self.stats.count, 'count not incremented')
        int = self.stats.intervals[0]
        self.assertEqual('intTitle', int['title'], 'title incorrect')
        self.assertEqual(3, int['count'], 'count incorrect')
        self.assertEqual({'k1': 'v1'}, int['qry_args'], 'query args incorrect')
        self.assertEqual('css', int['css_class'], 'css class incorrect')
        self.assertEqual(100, int['percent'], 'percent incorrect')
        self.stats.add_interval('intTitle', 3, {'k1': 'v1'}, 'css', 0)
        self.stats.refresh_calcs()
        self.assertEqual(50, int['percent'], 'percent not being updated')

    def test_add_interval_no_prog(self):
        self.stats.add_interval('intTitle', 3, {'k1': 'v1'}, 'css', 0)
        self.stats.add_interval('intTitle', 5, {'k1': 'v1'}, 'css', 0)
        self.stats.refresh_calcs()
        self.assertEqual(0, self.stats.done_count, 'count added for no prog')
        self.assertEqual(0, self.stats.done_percent, 'percent incremented')

    def test_add_interval_prog(self):
        self.stats.add_interval('intTitle', 3, {'k1': 'v1'}, 'css', 0)
        self.stats.add_interval('intTitle', 1, {'k1': 'v1'}, 'css', 1)
        self.stats.refresh_calcs()
        self.assertEqual(4, self.stats.count, 'count not incremented')
        self.assertEqual(1, self.stats.done_count, 'count not added to prog')
        self.assertEqual(25, self.stats.done_percent, 'done percent not incr')

    def test_add_interval_fudging(self):
        self.stats.add_interval('intTitle', 3, {'k1': 'v1'}, 'css', 0)
        self.stats.add_interval('intTitle', 5, {'k1': 'v1'}, 'css', 1)
        self.stats.refresh_calcs()
        self.assertEqual(8, self.stats.count, 'count not incremented')
        self.assertEqual(5, self.stats.done_count, 'count not added to prog')
        self.assertEqual(62, self.stats.done_percent,
                         'done percnt not fudged downward')
        self.assertEqual(62, self.stats.intervals[1]['percent'],
                         'interval percent not fudged downward')
        self.assertEqual(38, self.stats.intervals[0]['percent'],
                         'interval percent not fudged upward')
コード例 #20
0
ファイル: roadmap.py プロジェクト: esogs/IttecoTracPlugin
    def get_ticket_group_stats(self, tickets, field_name=None):
        total_cnt = 0
        ticket_ids= []
        for ticket in tickets:
            try:
                ticket_ids.append(ticket['id'])
                total_cnt += int(ticket.get(field_name, 0))
            except:
                pass

        if not field_name:
            return DefaultTicketGroupStatsProvider(self.env).get_ticket_group_stats(ticket_ids)

        all_statuses = set(TicketSystem(self.env).get_all_status())
        status_cnt = {}
        for s in all_statuses:
            status_cnt[s] = 0
        if total_cnt:
            cursor = self.env.get_db_cnx().cursor()
            str_ids = [str(x) for x in sorted(ticket_ids)]
            cursor.execute("SELECT status, sum(cast('0'||tc.value as int))"+\
                " FROM ticket t LEFT OUTER JOIN ticket_custom tc ON t.id=tc.ticket AND tc.name=%s "+\
                " WHERE id IN (%s) GROUP BY status" % ("%s,"*len(str_ids))[:-1], [field_name,]+str_ids)
            for s, cnt in cursor:
                status_cnt[s] = cnt

        stat = TicketGroupStats('ticket status', 'ticket')
        remaining_statuses = set(all_statuses)
        groups =  DefaultTicketGroupStatsProvider(self.env)._get_ticket_groups()
        catch_all_group = None
        # we need to go through the groups twice, so that the catch up group
        # doesn't need to be the last one in the sequence
        for group in groups:
            status_str = group['status'].strip()
            if status_str == '*':
                if catch_all_group:
                    raise TracError(_(
                        "'%(group1)s' and '%(group2)s' milestone groups "
                        "both are declared to be \"catch-all\" groups. "
                        "Please check your configuration.",
                        group1=group['name'], group2=catch_all_group['name']))
                catch_all_group = group
            else:
                group_statuses = set([s.strip()
                                      for s in status_str.split(',')]) \
                                      & all_statuses
                if group_statuses - remaining_statuses:
                    raise TracError(_(
                        "'%(groupname)s' milestone group reused status "
                        "'%(status)s' already taken by other groups. "
                        "Please check your configuration.",
                        groupname=group['name'],
                        status=', '.join(group_statuses - remaining_statuses)))
                else:
                    remaining_statuses -= group_statuses
                group['statuses'] = group_statuses
        if catch_all_group:
            catch_all_group['statuses'] = remaining_statuses
        for group in groups:
            group_cnt = 0
            query_args = {}
            for s, cnt in status_cnt.iteritems():
                if s in group['statuses']:
                    group_cnt += cnt or 0
                    query_args.setdefault('status', []).append(s)
            for arg in [kv for kv in group.get('query_args', '').split(',')
                        if '=' in kv]:
                k, v = [a.strip() for a in arg.split('=', 1)]
                query_args[k] = v
            stat.add_interval(group.get('label', group['name']), 
                              group_cnt, query_args,
                              group.get('css_class', group['name']),
                              bool(group.get('overall_completion')))
        stat.refresh_calcs()
        return stat
コード例 #21
0
    def get_ticket_group_stats(self, tickets, field_name=None):
        total_cnt = 0
        ticket_ids = []
        for ticket in tickets:
            try:
                ticket_ids.append(ticket['id'])
                total_cnt += int(ticket.get(field_name, 0))
            except:
                pass

        if not field_name:
            return DefaultTicketGroupStatsProvider(
                self.env).get_ticket_group_stats(ticket_ids)

        all_statuses = set(TicketSystem(self.env).get_all_status())
        status_cnt = {}
        for s in all_statuses:
            status_cnt[s] = 0
        if total_cnt:
            cursor = self.env.get_db_cnx().cursor()
            str_ids = [str(x) for x in sorted(ticket_ids)]
            cursor.execute("SELECT status, sum(cast('0'||tc.value as int))"+\
                " FROM ticket t LEFT OUTER JOIN ticket_custom tc ON t.id=tc.ticket AND tc.name=%s "+\
                " WHERE id IN (%s) GROUP BY status" % ("%s,"*len(str_ids))[:-1], [field_name,]+str_ids)
            for s, cnt in cursor:
                status_cnt[s] = cnt

        stat = TicketGroupStats('ticket status', 'ticket')
        remaining_statuses = set(all_statuses)
        groups = DefaultTicketGroupStatsProvider(self.env)._get_ticket_groups()
        catch_all_group = None
        # we need to go through the groups twice, so that the catch up group
        # doesn't need to be the last one in the sequence
        for group in groups:
            status_str = group['status'].strip()
            if status_str == '*':
                if catch_all_group:
                    raise TracError(
                        _(
                            "'%(group1)s' and '%(group2)s' milestone groups "
                            "both are declared to be \"catch-all\" groups. "
                            "Please check your configuration.",
                            group1=group['name'],
                            group2=catch_all_group['name']))
                catch_all_group = group
            else:
                group_statuses = set([s.strip()
                                      for s in status_str.split(',')]) \
                                      & all_statuses
                if group_statuses - remaining_statuses:
                    raise TracError(
                        _(
                            "'%(groupname)s' milestone group reused status "
                            "'%(status)s' already taken by other groups. "
                            "Please check your configuration.",
                            groupname=group['name'],
                            status=', '.join(group_statuses -
                                             remaining_statuses)))
                else:
                    remaining_statuses -= group_statuses
                group['statuses'] = group_statuses
        if catch_all_group:
            catch_all_group['statuses'] = remaining_statuses
        for group in groups:
            group_cnt = 0
            query_args = {}
            for s, cnt in status_cnt.iteritems():
                if s in group['statuses']:
                    group_cnt += cnt or 0
                    query_args.setdefault('status', []).append(s)
            for arg in [
                    kv for kv in group.get('query_args', '').split(',')
                    if '=' in kv
            ]:
                k, v = [a.strip() for a in arg.split('=', 1)]
                query_args[k] = v
            stat.add_interval(group.get('label', group['name']),
                              group_cnt, query_args,
                              group.get('css_class', group['name']),
                              bool(group.get('overall_completion')))
        stat.refresh_calcs()
        return stat