Refactoring a little the milestone and project models

remotes/origin/enhancement/email-actions
Jesús Espino 2013-11-05 15:41:42 +01:00
parent 8ee3554720
commit 44ff29f511
3 changed files with 46 additions and 46 deletions

View File

@ -0,0 +1,9 @@
import collections
def dict_sum(*args):
result = collections.Counter()
for arg in args:
assert isinstance(arg, dict)
result += collections.Counter(arg)
return result

View File

@ -5,13 +5,13 @@ from django.conf import settings
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from greenmine.base.utils.slug import slugify_uniquely from greenmine.base.utils.slug import slugify_uniquely
from greenmine.base.utils.dicts import dict_sum
from greenmine.base.notifications.models import WatchedMixin from greenmine.base.notifications.models import WatchedMixin
from greenmine.projects.userstories.models import UserStory from greenmine.projects.userstories.models import UserStory
import reversion import reversion
import itertools import itertools
import copy
import datetime import datetime
@ -83,23 +83,15 @@ class Milestone(WatchedMixin):
return result return result
def _dict_sum(self, dict1, dict2):
dict_result = copy.copy(dict2)
for key, value in dict1.items():
if key in dict_result:
dict_result[key] += value
else:
dict_result[key] = value
return dict_result
@property @property
def total_points(self): def total_points(self):
return self._get_user_stories_points([us for us in self.user_stories.all()]) return self._get_user_stories_points([us for us in self.user_stories.all()])
@property @property
def closed_points(self): def closed_points(self):
return self._get_user_stories_points([us for us in self.user_stories.all() return self._get_user_stories_points(
if us.is_closed]) [us for us in self.user_stories.all() if us.is_closed]
)
@property @property
def client_increment_points(self): def client_increment_points(self):
@ -113,9 +105,10 @@ class Milestone(WatchedMixin):
team_requirement=False team_requirement=False
) )
client_increment = self._get_user_stories_points(user_stories) client_increment = self._get_user_stories_points(user_stories)
shared_increment = {key: value/2 for key, value in shared_increment = {
self.shared_increment_points.items()} key: value/2 for key, value in self.shared_increment_points.items()
return self._dict_sum(client_increment, shared_increment) }
return dict_sum(client_increment, shared_increment)
@property @property
def team_increment_points(self): def team_increment_points(self):
@ -129,9 +122,10 @@ class Milestone(WatchedMixin):
team_requirement=True team_requirement=True
) )
team_increment = self._get_user_stories_points(user_stories) team_increment = self._get_user_stories_points(user_stories)
shared_increment = {key: value/2 for key, value in shared_increment = {
self.shared_increment_points.items()} key: value/2 for key, value in self.shared_increment_points.items()
return self._dict_sum(team_increment, shared_increment) }
return dict_sum(team_increment, shared_increment)
@property @property
def shared_increment_points(self): def shared_increment_points(self):
@ -153,8 +147,11 @@ class Milestone(WatchedMixin):
} }
def closed_points_by_date(self, date): def closed_points_by_date(self, date):
return self._get_user_stories_points([us for us in self.user_stories.filter(finish_date__lt=date + datetime.timedelta(days=1)) return self._get_user_stories_points([
if us.is_closed]) us for us in self.user_stories.filter(
finish_date__lt=date + datetime.timedelta(days=1)
) if us.is_closed
])
# Reversion registration (usufull for base.notification and for meke a historical) # Reversion registration (usufull for base.notification and for meke a historical)

View File

@ -12,20 +12,20 @@ from django.utils.translation import ugettext_lazy as _
from picklefield.fields import PickledObjectField from picklefield.fields import PickledObjectField
from greenmine.base.utils.slug import slugify_uniquely from greenmine.base.utils.slug import slugify_uniquely
from greenmine.base.notifications.models import WatchedMixin from greenmine.base.utils.dicts import dict_sum
from greenmine.projects.userstories.models import UserStory from greenmine.projects.userstories.models import UserStory
from . import choices from . import choices
import reversion import reversion
import itertools import itertools
import copy
def get_attachment_file_path(instance, filename): def get_attachment_file_path(instance, filename):
return "attachment-files/{project}/{model}/{filename}".format( return "attachment-files/{project}/{model}/{filename}".format(
project=instance.project.slug, project=instance.project.slug,
model=instance.content_type.model, model=instance.content_type.model,
filename=filename) filename=filename
)
class Attachment(models.Model): class Attachment(models.Model):
@ -106,6 +106,7 @@ class Project(models.Model):
verbose_name=_("total story points")) verbose_name=_("total story points"))
tags = PickledObjectField(null=False, blank=True, tags = PickledObjectField(null=False, blank=True,
verbose_name=_("tags")) verbose_name=_("tags"))
class Meta: class Meta:
verbose_name = "project" verbose_name = "project"
verbose_name_plural = "projects" verbose_name_plural = "projects"
@ -136,8 +137,10 @@ class Project(models.Model):
def get_users(self): def get_users(self):
user_model = get_user_model() user_model = get_user_model()
return user_model.objects.filter(id__in=list(self.memberships.values_list( return user_model.objects.filter(
"user", flat=True))) id__in=list(self.memberships.values_list("user", flat=True))
)
def update_role_points(self): def update_role_points(self):
rolepoints_model = get_model("userstories", "RolePoints") rolepoints_model = get_model("userstories", "RolePoints")
@ -152,8 +155,8 @@ class Project(models.Model):
for us in self.user_stories.all(): for us in self.user_stories.all():
for role in roles: for role in roles:
if not us.role_points.filter(role=role).exists(): if not us.role_points.filter(role=role).exists():
sp = rolepoints_model.objects.create(role=role, user_story=us, rolepoints_model.objects.create(role=role, user_story=us,
points=null_points_value) points=null_points_value)
# Now remove rolepoints associated with not existing roles. # Now remove rolepoints associated with not existing roles.
rp_query = rolepoints_model.objects.filter(user_story__in=self.user_stories.all()) rp_query = rolepoints_model.objects.filter(user_story__in=self.user_stories.all())
@ -174,16 +177,6 @@ class Project(models.Model):
return result return result
def _dict_sum(self, dict1, dict2):
dict_result = copy.copy(dict2)
for key, value in dict1.items():
if key in dict_result:
dict_result[key] += value
else:
dict_result[key] = value
return dict_result
@property @property
def future_team_increment(self): def future_team_increment(self):
user_stories = UserStory.objects.none() user_stories = UserStory.objects.none()
@ -197,7 +190,7 @@ class Project(models.Model):
) )
team_increment = self._get_user_stories_points(user_stories) team_increment = self._get_user_stories_points(user_stories)
shared_increment = {key: value/2 for key, value in self.future_shared_increment.items()} shared_increment = {key: value/2 for key, value in self.future_shared_increment.items()}
return self._dict_sum(team_increment, shared_increment) return dict_sum(team_increment, shared_increment)
@property @property
def future_client_increment(self): def future_client_increment(self):
@ -212,7 +205,7 @@ class Project(models.Model):
) )
client_increment = self._get_user_stories_points(user_stories) client_increment = self._get_user_stories_points(user_stories)
shared_increment = {key: value/2 for key, value in self.future_shared_increment.items()} shared_increment = {key: value/2 for key, value in self.future_shared_increment.items()}
return self._dict_sum(client_increment, shared_increment) return dict_sum(client_increment, shared_increment)
@property @property
def future_shared_increment(self): def future_shared_increment(self):
@ -227,8 +220,8 @@ class Project(models.Model):
) )
return self._get_user_stories_points(user_stories) return self._get_user_stories_points(user_stories)
# User Stories common Models
# User Stories common Models
class UserStoryStatus(models.Model): class UserStoryStatus(models.Model):
name = models.CharField(max_length=255, null=False, blank=False, name = models.CharField(max_length=255, null=False, blank=False,
verbose_name=_("name")) verbose_name=_("name"))
@ -420,6 +413,7 @@ class QuestionStatus(models.Model):
reversion.register(Project) reversion.register(Project)
reversion.register(Attachment) reversion.register(Attachment)
# On membership object is created/changed, update # On membership object is created/changed, update
# role-points relation. # role-points relation.
@receiver(models.signals.post_save, sender=Membership, @receiver(models.signals.post_save, sender=Membership,
@ -449,12 +443,12 @@ def project_post_save(sender, instance, created, **kwargs):
for order, name, is_closed in choices.US_STATUSES: for order, name, is_closed in choices.US_STATUSES:
UserStoryStatus.objects.create(name=name, order=order, UserStoryStatus.objects.create(name=name, order=order,
is_closed=is_closed, project=instance) is_closed=is_closed, project=instance)
# Tasks # Tasks
for order, name, is_closed, color in choices.TASK_STATUSES: for order, name, is_closed, color in choices.TASK_STATUSES:
TaskStatus.objects.create(name=name, order=order, color=color, TaskStatus.objects.create(name=name, order=order, color=color,
is_closed=is_closed, project=instance) is_closed=is_closed, project=instance)
# Issues # Issues
for order, name in choices.PRIORITY_CHOICES: for order, name in choices.PRIORITY_CHOICES:
@ -465,7 +459,7 @@ def project_post_save(sender, instance, created, **kwargs):
for order, name, is_closed in choices.ISSUE_STATUSES: for order, name, is_closed in choices.ISSUE_STATUSES:
IssueStatus.objects.create(name=name, order=order, IssueStatus.objects.create(name=name, order=order,
is_closed=is_closed, project=instance) is_closed=is_closed, project=instance)
for order, name in choices.ISSUE_TYPES: for order, name in choices.ISSUE_TYPES:
IssueType.objects.create(project=instance, name=name, order=order) IssueType.objects.create(project=instance, name=name, order=order)
@ -473,4 +467,4 @@ def project_post_save(sender, instance, created, **kwargs):
# Questions # Questions
for order, name, is_closed in choices.QUESTION_STATUS: for order, name, is_closed in choices.QUESTION_STATUS:
QuestionStatus.objects.create(name=name, order=order, QuestionStatus.objects.create(name=name, order=order,
is_closed=is_closed, project=instance) is_closed=is_closed, project=instance)