aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Crute <mcrute@gmail.com>2010-07-15 00:02:52 -0400
committerMike Crute <mcrute@gmail.com>2010-07-15 00:02:52 -0400
commit7359bd23ec232c238fc07c579776f7869dd3f00d (patch)
tree8348e5e92d75aae9e0a547fe629ab2bb5ff48b3c
parentd58aaf406e6d87c3ed536ac0173fea1b7c29ba5d (diff)
downloadsnakeplan-7359bd23ec232c238fc07c579776f7869dd3f00d.tar.bz2
snakeplan-7359bd23ec232c238fc07c579776f7869dd3f00d.tar.xz
snakeplan-7359bd23ec232c238fc07c579776f7869dd3f00d.zip
Adjusting models to reflect new direction in project.
-rw-r--r--snakeplan/projects/admin.py9
-rw-r--r--snakeplan/projects/forms.py9
-rw-r--r--snakeplan/projects/models.py107
-rw-r--r--snakeplan/projects/urls.py24
-rw-r--r--snakeplan/projects/views/stories.py29
5 files changed, 109 insertions, 69 deletions
diff --git a/snakeplan/projects/admin.py b/snakeplan/projects/admin.py
index ba56193..e31187b 100644
--- a/snakeplan/projects/admin.py
+++ b/snakeplan/projects/admin.py
@@ -28,9 +28,10 @@ class ProjectAdmin(ModelAdmin):
28 ordering = ('name', ) 28 ordering = ('name', )
29 29
30 30
31site.register(models.Task)
32site.register(models.Story)
33site.register(models.Project, ProjectAdmin) 31site.register(models.Project, ProjectAdmin)
34site.register(models.Iteration) 32site.register(models.Iteration)
35site.register(models.DevelopmentIteration) 33site.register(models.Story)
36site.register(models.LoggedTime) 34site.register(models.Release)
35site.register(models.Feature)
36site.register(models.Task)
37site.register(models.Comment)
diff --git a/snakeplan/projects/forms.py b/snakeplan/projects/forms.py
new file mode 100644
index 0000000..68fbfe9
--- /dev/null
+++ b/snakeplan/projects/forms.py
@@ -0,0 +1,9 @@
1import models
2from django.forms import ModelForm
3
4
5class StoryForm(ModelForm):
6
7 class Meta:
8 model = models.Story
9 fields = ('project', 'name')
diff --git a/snakeplan/projects/models.py b/snakeplan/projects/models.py
index e707bb2..aca8e36 100644
--- a/snakeplan/projects/models.py
+++ b/snakeplan/projects/models.py
@@ -23,29 +23,23 @@ from django.db.models import Model
23from django.contrib.auth.models import User 23from django.contrib.auth.models import User
24 24
25 25
26STATUSES = ( 26DAY = (
27 (0, 'Draft'), 27 (0, 'Sunday'),
28 (1, 'Defined'), 28 (1, 'Monday'),
29 (2, 'Estimated'), 29 (2, 'Tuesday'),
30 (3, 'Planned'), 30 (3, 'Wednesday'),
31 (4, 'Implemented'), 31 (4, 'Thursday'),
32 (5, 'Verified'), 32 (5, 'Friday'),
33 (6, 'Accepted'), 33 (6, 'Saturday'),
34 )
35
36DISPOSITIONS = (
37 (0, 'Planned'),
38 (1, 'Carried Over'),
39 (2, 'Added'),
40 (3, 'Discovered'),
41 ) 34 )
42 35
43TASK_TYPES = ( 36STATUSES = (
44 (0, 'Feature'), 37 (0, 'Draft'),
45 (1, 'Debt'), 38 (1, 'Started'),
46 (2, 'Functional Test'), 39 (2, 'Finished'),
47 (3, 'Acceptance Test'), 40 (3, 'Delivered'),
48 (4, 'Overhead'), 41 (4, 'Accepted'),
42 (5, 'Rejected'),
49 ) 43 )
50 44
51 45
@@ -54,7 +48,14 @@ class Project(Model):
54 name = m.CharField(max_length=200) 48 name = m.CharField(max_length=200)
55 description = m.TextField(blank=True, null=True) 49 description = m.TextField(blank=True, null=True)
56 active = m.BooleanField(default=True) 50 active = m.BooleanField(default=True)
57 wiki_link = m.URLField(blank=True, null=True) 51 start_date = m.DateField()
52
53 iteration_starts = m.IntegerField(choices=DAY, default=0)
54 iteration_length = m.IntegerField(default=2)
55 initial_velocity = m.IntegerField(default=10)
56 velocity_time_period = m.IntegerField(default=3)
57
58 current_velocity = m.IntegerField(default=10)
58 59
59 def __unicode__(self): 60 def __unicode__(self):
60 return self.name 61 return self.name
@@ -64,73 +65,71 @@ class Iteration(Model):
64 65
65 project = m.ForeignKey(Project) 66 project = m.ForeignKey(Project)
66 67
67 name = m.CharField(max_length=200) 68 name = m.CharField(max_length=200, blank=True, null=True)
68 description = m.TextField(blank=True, null=True) 69 description = m.TextField(blank=True, null=True)
70 start_date = m.DateField(blank=True, null=True)
71 end_date = m.DateField(blank=True, null=True)
69 72
70 # It should not be possible to delete the backlog 73 team_strength = m.DecimalField(decimal_places=2, max_digits=1, default=1)
71 can_delete = m.BooleanField(default=True)
72 74
73 def __unicode__(self): 75 def __unicode__(self):
74 return self.name 76 return self.name
75 77
76 78
77# Not all iterations are actually open for development
78# for example, the Backlog is not a development iteration.
79class DevelopmentIteration(Iteration):
80
81 active = m.BooleanField(default=True)
82 start_date = m.DateField(blank=True, null=True)
83 end_date = m.DateField(blank=True, null=True)
84
85
86class Story(Model): 79class Story(Model):
87 80
88 class Meta: 81 class Meta:
89 verbose_name_plural = 'Stories' 82 verbose_name_plural = 'stories'
90 83
91 iteration = m.ForeignKey(Iteration) 84 project = m.ForeignKey(Project, related_name='stories')
85 iteration = m.ForeignKey(Iteration, blank=True, null=True)
92 tracker = m.ForeignKey(User, blank=True, null=True) 86 tracker = m.ForeignKey(User, blank=True, null=True)
93 customer = m.ForeignKey(User, blank=True, null=True, 87 customer = m.ForeignKey(User, blank=True, null=True,
94 related_name='story_customer') 88 related_name='story_customer')
95 89
96 name = m.CharField(max_length=200) 90 name = m.CharField(max_length=200)
97 disposition = m.IntegerField(choices=DISPOSITIONS, default=0)
98 status = m.IntegerField(choices=STATUSES, default=0) 91 status = m.IntegerField(choices=STATUSES, default=0)
99 priority = m.IntegerField() 92 accept_date = m.DateField(blank=True, null=True)
100 order = m.IntegerField()
101 description = m.TextField(blank=True, null=True) 93 description = m.TextField(blank=True, null=True)
94 order = m.IntegerField(default=0)
102 95
103 def __unicode__(self): 96 def __unicode__(self):
104 return self.name 97 return self.name
105 98
106 99
100class Release(Story):
101
102 release_date = m.DateField()
103
104
105class Feature(Story):
106
107 points = m.IntegerField(blank=True, null=True)
108
109
110class Bug(Story):
111 pass
112
113
107class Task(Model): 114class Task(Model):
108 115
109 story = m.ForeignKey(Story) 116 story = m.ForeignKey(Story)
110 acceptor = m.ForeignKey(User, blank=True, null=True)
111 117
112 name = m.CharField(max_length=200) 118 name = m.CharField(max_length=200)
113 completed = m.BooleanField(default=False) 119 completed = m.BooleanField(default=False)
114 task_type = m.IntegerField(choices=TASK_TYPES, default=0) 120 order = m.IntegerField(default=0)
115 disposition = m.IntegerField(choices=DISPOSITIONS, default=0)
116 estimated_hours = m.DecimalField(decimal_places=2, max_digits=5)
117 description = m.TextField(blank=True, null=True)
118 121
119 def __unicode__(self): 122 def __unicode__(self):
120 return self.name 123 return self.name
121 124
122 125
123class LoggedTime(Model): 126class Comment(Model):
124 127
125 task = m.ForeignKey(Task) 128 user = m.ForeignKey(User)
126 person1 = m.ForeignKey(User, blank=True, null=True, related_name="person1") 129 story = m.ForeignKey(Story)
127 person2 = m.ForeignKey(User, blank=True, null=True, related_name="person2")
128 130
129 logged_date = m.DateField() 131 post_date = m.DateTimeField(auto_now=True)
130 start_time = m.DateTimeField(blank=True, null=True) 132 comment = m.TextField()
131 end_time = m.DateTimeField(blank=True, null=True)
132 duration = m.DecimalField(decimal_places=2, max_digits=5)
133 description = m.TextField(blank=True, null=True)
134 133
135 def __unicode__(self): 134 def __unicode__(self):
136 return self.description 135 return self.comment
diff --git a/snakeplan/projects/urls.py b/snakeplan/projects/urls.py
index c59024c..3716885 100644
--- a/snakeplan/projects/urls.py
+++ b/snakeplan/projects/urls.py
@@ -22,16 +22,18 @@ from django.conf.urls.defaults import patterns, url
22 22
23 23
24urlpatterns = patterns('projects.views', 24urlpatterns = patterns('projects.views',
25 url(r'^$', 'project.index', name='project-list'), 25# url(r'^$', 'project.index', name='project-list'),
26 26#
27 # Projects 27# # Projects
28 url(r'^create/', 'project.create_project', name='create-project'), 28# url(r'^create/', 'project.create_project', name='create-project'),
29 url(r'^(\d+)/edit/', 'project.update_project', name='edit-project'), 29# url(r'^(\d+)/edit/', 'project.update_project', name='edit-project'),
30 url(r'^(\d+)/', 'project.project_iterations', name='project-iterations'), 30# url(r'^(\d+)/', 'project.project_iterations', name='project-iterations'),
31 31#
32 # Iterations 32# # Iterations
33 url(r'^(\d+)/iterations/(\d+)/', 'project.index'), 33# url(r'^(\d+)/iterations/(\d+)/', 'project.index'),
34#
35# # Stories
36# url(r'^(\d+)/stories/(\d+)/', 'project.index', name='iteration-stories'),
34 37
35 # Stories 38 url(r'^story/create/', 'stories.create_story', name='create-story'),
36 url(r'^(\d+)/stories/(\d+)/', 'project.index', name='iteration-stories'),
37) 39)
diff --git a/snakeplan/projects/views/stories.py b/snakeplan/projects/views/stories.py
new file mode 100644
index 0000000..afcb373
--- /dev/null
+++ b/snakeplan/projects/views/stories.py
@@ -0,0 +1,29 @@
1# vim: set filencoding=utf8
2"""
3Story Views
4
5@author: Mike Crute (mcrute@gmail.com)
6@organization: SoftGroup Interactive, Inc.
7@date: July 10, 2010
8"""
9
10# Licensed under the Apache License, Version 2.0 (the "License");
11# you may not use this file except in compliance with the License.
12# You may obtain a copy of the License at
13#
14# http://www.apache.org/licenses/LICENSE-2.0
15#
16# Unless required by applicable law or agreed to in writing, software
17# distributed under the License is distributed on an "AS IS" BASIS,
18# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19# See the License for the specific language governing permissions and
20# limitations under the License.
21
22from django.views.generic import list_detail, create_update
23from django.core.urlresolvers import reverse
24
25from projects import models, forms
26
27def create_story(request):
28 return create_update.create_object(request, form_class=forms.StoryForm,
29 post_save_redirect=reverse('create-story'))