Mercurial > hg > savane-forge
changeset 324:9275694cda61
Trackers: more static fields definition
author | Sylvain Beucler <beuc@beuc.net> |
---|---|
date | Sat, 21 Aug 2010 12:09:18 +0200 |
parents | 01ffc3eb965a |
children | c193bb0a8819 |
files | doc/savane3_trackers.txt doc/scripts/tracker_defsgen.py savane/tracker/defs.py savane/tracker/models.py |
diffstat | 4 files changed, 220 insertions(+), 129 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/savane3_trackers.txt +++ b/doc/savane3_trackers.txt @@ -1,1 +1,163 @@ -Cf. scripts/tracker_gendefs.py. +The static definition in savane.trackers.defs is generated using +scripts/tracker_gendefs.py. + +Trackers are described in Savane3 using a 3-level structure: + +- Field : definition + +- Field usage : additional definition (group=100) and partial overlay + (override values) infrastructure (group!=100) + +- Field value : possible values for dropdown (<select>) widgets + (default values and overlays) + +In trackers.defs we now have a single structure for field definition, +which was actually static in Savane3 despite being stored in the +database. The database now only contains per-group optional overlays. +In addition similar structures and values (common to +bugs/patch/support/task) are only defined once. + + +Here is a description of the Savane_3_ data structure, used as reference +to build this new implementation: + +- Field + + Site-wide field definitions for the 4 trackers: 70 fields each, + + 2 more for 'task' ('planned_starting_date', 'planned_close_date'), + 1 more for 'patch' ('revision tag' - but it's actually a bogus + entry in patch_field as there's nowhere to store its item value). + + The field item values are stored in the 'bugs'/'patch'/etc. table, + which has 73 columns (1 for the IP address + 1 for spamscore + 1 + col for each 72 Field - 1 for 'comment_type_id' which is not + stored). + + Fields are not necessarily displayed or/and editable ('bug_id', + 'group_id') but their definition may be used in other contexts, + such as list sort order. + + Most fields cannot be redefined (such as display_type or + scope). Usually fields that can be redefined are in FieldUsage, + where an entry with special group_id=100 contains the default + value. + + However some of the fields in this class ('display_size', + 'empty_ok', and 'keep_history') can be redefined through similar + fields in FieldUsage - in which case it's not clear whether the + default value is: + + - in Field(tracker_id, field_name) + + - or FieldUsage(tracker_id, group_id=100, field_name) + + At first glance it's defined here, all related values in + FieldUsage are set to NULL. + + Field definition is almost identical for all trackers (59 fields / + 73 have the same configuration). They could be regrouped. + + SELECT COUNT(*) FROM ( + SELECT field_name FROM bugs_field + UNION SELECT field_name FROM patch_field + UNION SELECT field_name FROM support_field + UNION SELECT field_name FROM task_field + ) subquery; + => 73 + + SELECT COUNT(*), field_name FROM ( + SELECT * FROM bugs_field + UNION SELECT * FROM patch_field + UNION SELECT * FROM support_field + UNION SELECT * FROM task_field + ) subquery + GROUP BY field_name HAVING COUNT(*) > 1; + -- Only slight differences in description , except for these 2: + +----------+---------------------+ + | COUNT(*) | field_name | + +----------+---------------------+ + ... + | 4 | priority | -- (required=1,empty_ok=0)(bugs,task) | (required=0,empty_ok=1)(patch,support) + | 2 | resolution_id | -- (required=1)(bugs,task) | (required=0)(patch,support) + ... + +----------+---------------------+ + 14 rows in set (0.00 sec) + + So we could just set required=0,empty_ok=1 for those 2. + +- Field usage: + + Field configuration overlay for each group + group == 100 means default + + + Differences between trackers for default values: + + SELECT COUNT(*) FROM ( + SELECT bug_field_id FROM bugs_field_usage + UNION SELECT bug_field_id FROM patch_field_usage + UNION SELECT bug_field_id FROM support_field_usage + UNION SELECT bug_field_id FROM task_field_usage + ) subquery; + => 73 + + SELECT bug_field_id, COUNT(*) FROM ( + SELECT * FROM bugs_field_usage WHERE group_id=100 + UNION SELECT * FROM patch_field_usage WHERE group_id=100 + UNION SELECT * FROM support_field_usage WHERE group_id=100 + UNION SELECT * FROM task_field_usage WHERE group_id=100 + ) subquery GROUP BY bug_field_id HAVING COUNT(*) > 2; + +--------------+----------+ + | bug_field_id | COUNT(*) | + +--------------+----------+ + | 92 | 2 | submitted_by + | 102 | 2 | severity + | 107 | 2 | bug_group_id + | 201 | 2 | platform_version_id + | 206 | 2 | hours + | 211 | 4 | priority + | 216 | 2 | originator_email + | 220 | 2 | percent_complete + +--------------+----------+ + + 92 -> (use_it=0)(patch,support) | (use_it=1)(bugs,task) + 102 -> (use_it,show_on_add,show_on_add_members=0)(patch,task) | (use_it,show_on_add,show_on_add_members=1)(bugs,support) + 107 -> (show_on_add,show_on_add_members=0)(patch,support) | (show_on_add,show_on_add_members=1)(bugs,task) [but use_it=0] + 201 -> (use_it,show_on_add,show_on_add_members=0)(bugs,patch,task) | (use_it,show_on_add,show_on_add_members=1)(support) + 201 -> (use_it,show_on_add,show_on_add_members=0)(bugs,patch,support) | (use_it,show_on_add,show_on_add_members=1)(task) + 211 -> (show_on_add,show_on_add_members,place) + bugs: 0,1,200 + patch: 1,1,150 + support: 0,0,150 + task: 1,1,200 + 216 -> (use_it,show_on_add=0)(task) | (use_it=1,show_on_add=2)(bugs,patch,support) + 220 -> (use_it,show_on_add_members=0)(bugs,patch,support) | (use_it,show_on_add_members=1)(task) + +- Field values: + + Choices overlay for a select-box (SB) field of a specific group + + Values that change between trackers: + SELECT bug_field_id,group_id,value_id,value FROM bugs_field_value WHERE group_id=100 + UNION SELECT bug_field_id,group_id,value_id,value FROM patch_field_value WHERE group_id=100 + UNION SELECT bug_field_id,group_id,value_id,value FROM support_field_value WHERE group_id=100 + UNION SELECT bug_field_id,group_id,value_id,value FROM task_field_value WHERE group_id=100 + ORDER BY bug_field_id,group_id,value_id; + + | 108 | 100 | 1 | Fixed | bugs + | 108 | 100 | 1 | Done | patch,support,task + + | 108 | 100 | 3 | Wont Fix | bugs + | 108 | 100 | 3 | Wont Do | patch,support + | 108 | 100 | 3 | Cancelled | task + + Savannah and Gna!-specific: + | 201 | 100 | 120 | Microsoft Windows | bugs,task + | 201 | 100 | 120 | *BSD | support + patch: (None) + | 201 | 100 | 130 | *BSD | bugs,task + | 201 | 100 | 130 | Microsoft Windows | support + patch: (None) + + => Regroup: put "Wont Do" everywhere, "Done" everywhere, and + manually revert woe/bsd in support.items
--- a/doc/scripts/tracker_defsgen.py +++ b/doc/scripts/tracker_defsgen.py @@ -15,7 +15,7 @@ defs = {} field_names = [] c.execute("""SELECT * FROM bugs_field""") -for row in c.fetchall(): +def process_row(row): name = row[1] field_names.append(name) defs[name] = '' @@ -29,12 +29,29 @@ + ": " if tfields[i] == 'label' or tfields[i] == 'description': defs[name] += '_("' + val + '"),' + elif (name=='priority' or name=='resolution_id' or name=='planned_starting_date' or name=='planned_close_date') \ + and tfields[i] == 'required': + # override priority.required so we have a common + # definition for all trackers + defs[name] += str(0)+"," + elif (name=='priority' or name=='resolution_id') \ + and tfields[i] == 'empty_ok': + # override priority.empty_ok so we have a common + # definition for all trackers + defs[name] += str(1)+"," elif type(val) == long: defs[name] += str(val)+"," else: defs[name] += "'"+val+"'," defs[name] += "\n" +for row in c.fetchall(): + process_row(row) + +c.execute("""SELECT * FROM task_field WHERE field_name IN ('planned_starting_date', 'planned_close_date')""") +for row in c.fetchall(): + process_row(row) + tfields = ['name','bug_field_id','group_id','use_it','show_on_add', 'show_on_add_members','place','custom_label', 'custom_description','custom_display_size',
--- a/savane/tracker/defs.py +++ b/savane/tracker/defs.py @@ -18,6 +18,8 @@ from django.utils.translation import ugettext, ugettext_lazy as _ +fields = {} + common = { 'bug_id' : { 'field_name': 'bug_id', @@ -242,7 +244,7 @@ 'label': _("Status"), 'description': _("Current resolution of the item"), 'scope': 'P', - 'required': 1, + 'required': 0, 'empty_ok': 1, 'keep_history': 1, 'special': 0, @@ -494,8 +496,8 @@ 'label': _("Priority"), 'description': _("How quickly the item should be handled"), 'scope': 'S', - 'required': 1, - 'empty_ok': 0, + 'required': 0, + 'empty_ok': 1, 'keep_history': 1, 'special': 0, 'custom': 0, @@ -1279,4 +1281,33 @@ 'place': 800, 'transition_default_auth': 'A', }, + 'planned_close_date' : { + 'field_name': 'planned_close_date', + 'display_type': 'DF', + 'display_size': '10/15', + 'label': _("Should be Finished on"), + 'description': _("Date and time when the item should be completed"), + 'scope': 'S', + 'required': 0, + 'empty_ok': 1, + 'keep_history': 1, + 'special': 0, + 'custom': 0, + 'planned_starting_date' : { + 'field_name': 'planned_starting_date', + 'display_type': 'DF', + 'display_size': '10/15', + 'label': _("Should Start On"), + 'description': _("Date and time when someone should start working on the item"), + 'scope': 'S', + 'required': 0, + 'empty_ok': 1, + 'keep_history': 1, + 'special': 0, + 'custom': 0, } + +fields['bugs'] = common.copy() +fields['patch'] = common.copy() +fields['support'] = common.copy() +fields['task'] = common.copy()
--- a/savane/tracker/models.py +++ b/savane/tracker/models.py @@ -140,57 +140,6 @@ class Field(models.Model): """ - Site-wide field definitions for the 4 trackers: 70 fields each, + - 2 more for 'task' ('planned_starting_date', 'planned_close_date'), - 1 more for 'patch' ('revision tag'). - - Most fields cannot be redefined (such as display_type or - scope). Usually fields that can be redefined are in FieldUsage, - where an entry with special group_id=100 contains the default - value. - - However some of the fields in this class ('display_size', - 'empty_ok', and 'keep_history') can be redefined through similar - fields in FieldUsage - in which case it's not clear whether the - default value is: - - - in Field(tracker_id, field_name) - - - or FieldUsage(tracker_id, group_id=100, field_name) - - At first glance it's defined here, all related values in - FieldUsage are set to NULL. - - Field definition is almost identical for all trackers (59 fields / - 73 have the same configuration). They could be regrouped. - - SELECT COUNT(*) FROM ( - SELECT field_name FROM bugs_field - UNION SELECT field_name FROM patch_field - UNION SELECT field_name FROM support_field - UNION SELECT field_name FROM task_field - ) subquery; - => 73 - - SELECT COUNT(*), field_name FROM ( - SELECT * FROM bugs_field - UNION SELECT * FROM patch_field - UNION SELECT * FROM support_field - UNION SELECT * FROM task_field - ) subquery - GROUP BY field_name HAVING COUNT(*) > 1; - -- Only slight differences in description , except for these 2: - +----------+---------------------+ - | COUNT(*) | field_name | - +----------+---------------------+ - ... - | 4 | priority | -- (required=1,empty_ok=0)(bugs,task) | (required=0,empty_ok=1)(patch,support) - | 2 | resolution_id | -- (required=1)(bugs,task) | (required=0)(patch,support) - ... - +----------+---------------------+ - 14 rows in set (0.00 sec) - - So we could just set required=0,empty_ok=1 for those 2. """ class Meta: unique_together = (('tracker', 'name'),) @@ -225,7 +174,7 @@ # Default value (fields can always override this except for 'summary' and 'details', cf. 'special') empty_ok = models.CharField(max_length=1, choices=EMPTY_OK_CHOICES, default='0') - # Default value + Field may store history changes + # Default value keep_history = models.BooleanField() # Field cannot be made optional (displayed unless 'bug_id' and 'group_id') # Also, field are not displayed (filled by the system) - except for 'summary', 'comment_type' and 'details' @@ -237,53 +186,9 @@ def __unicode__(self): return "%s.%s" % (self.tracker_id, self.name) -class FieldUsage(models.Model): +class FieldOverlay(models.Model): """ - Field configuration overlay for each group - group == NULL means default - - - Differences between trackers for default values: - - SELECT COUNT(*) FROM ( - SELECT bug_field_id FROM bugs_field_usage - UNION SELECT bug_field_id FROM patch_field_usage - UNION SELECT bug_field_id FROM support_field_usage - UNION SELECT bug_field_id FROM task_field_usage - ) subquery; - => 73 - - SELECT bug_field_id, COUNT(*) FROM ( - SELECT * FROM bugs_field_usage WHERE group_id=100 - UNION SELECT * FROM patch_field_usage WHERE group_id=100 - UNION SELECT * FROM support_field_usage WHERE group_id=100 - UNION SELECT * FROM task_field_usage WHERE group_id=100 - ) subquery GROUP BY bug_field_id HAVING COUNT(*) > 2; - +--------------+----------+ - | bug_field_id | COUNT(*) | - +--------------+----------+ - | 92 | 2 | submitted_by - | 102 | 2 | severity - | 107 | 2 | bug_group_id - | 201 | 2 | platform_version_id - | 206 | 2 | hours - | 211 | 4 | priority - | 216 | 2 | originator_email - | 220 | 2 | percent_complete - +--------------+----------+ - - 92 -> (use_it=0)(patch,support) | (use_it=1)(bugs,task) - 102 -> (use_it,show_on_add,show_on_add_members=0)(patch,task) | (use_it,show_on_add,show_on_add_members=1)(bugs,support) - 107 -> (show_on_add,show_on_add_members=0)(patch,support) | (show_on_add,show_on_add_members=1)(bugs,task) [but use_it=0] - 201 -> (use_it,show_on_add,show_on_add_members=0)(bugs,patch,task) | (use_it,show_on_add,show_on_add_members=1)(support) - 201 -> (use_it,show_on_add,show_on_add_members=0)(bugs,patch,support) | (use_it,show_on_add,show_on_add_members=1)(task) - 211 -> (show_on_add,show_on_add_members,place) - bugs: 0,1,200 - patch: 1,1,150 - support: 0,0,150 - task: 1,1,200 - 216 -> (use_it,show_on_add=0)(task) | (use_it=1,show_on_add=2)(bugs,patch,support) - 220 -> (use_it,show_on_add_members=0)(bugs,patch,support) | (use_it,show_on_add_members=1)(task) + Per-group tracker item definition override """ class Meta: unique_together = (('field', 'group'),) @@ -325,6 +230,7 @@ custom_display_size = models.CharField(max_length=255, blank=True, null=True) # The default value is in Field.display_size # rather than FieldUsage(group_id=100).custom_display_size + # If !Field.special custom_keep_history = models.BooleanField(_("keep field value changes in history")) # If Field.custom @@ -334,32 +240,7 @@ class FieldValue(models.Model): """ - Choices overlay for a select-box (SB) field of a specific group - - Values that change between trackers: - SELECT bug_field_id,group_id,value_id,value FROM bugs_field_value WHERE group_id=100 - UNION SELECT bug_field_id,group_id,value_id,value FROM patch_field_value WHERE group_id=100 - UNION SELECT bug_field_id,group_id,value_id,value FROM support_field_value WHERE group_id=100 - UNION SELECT bug_field_id,group_id,value_id,value FROM task_field_value WHERE group_id=100 - ORDER BY bug_field_id,group_id,value_id; - - | 108 | 100 | 1 | Fixed | bugs - | 108 | 100 | 1 | Done | patch,support,task - - | 108 | 100 | 3 | Wont Fix | bugs - | 108 | 100 | 3 | Wont Do | patch,support - | 108 | 100 | 3 | Cancelled | task - - Savannah and Gna!-specific: - | 201 | 100 | 120 | Microsoft Windows | bugs,task - | 201 | 100 | 120 | *BSD | support - patch: (None) - | 201 | 100 | 130 | *BSD | bugs,task - | 201 | 100 | 130 | Microsoft Windows | support - patch: (None) - - => Regroup: put "Wont Do" everywhere, "Done" everywhere, and - manually revert woe/bsd in support.items + Per-group tracker select box values override """ class Meta: unique_together = (('field', 'group', 'value_id'),)