Some extra api optimizations

remotes/origin/enhancement/email-actions
Alejandro Alonso 2014-12-22 10:02:31 +01:00 committed by David Barragán Merino
parent 99691372a5
commit ca09cda87c
6 changed files with 85 additions and 43 deletions

View File

@ -47,7 +47,12 @@ class MilestoneViewSet(HistoryResourceMixin, WatchedResourceMixin, ModelCrudView
qs = qs.prefetch_related("user_stories", qs = qs.prefetch_related("user_stories",
"user_stories__role_points", "user_stories__role_points",
"user_stories__role_points__points", "user_stories__role_points__points",
"user_stories__role_points__role") "user_stories__role_points__role",
"user_stories__generated_from_issue",
"user_stories__project",
"watchers",
"user_stories__watchers")
qs = qs.select_related("project")
qs = qs.order_by("-estimated_start") qs = qs.order_by("-estimated_start")
return qs return qs

View File

@ -91,46 +91,62 @@ class Milestone(WatchedModelMixin, models.Model):
@property @property
def total_points(self): def total_points(self):
return self._get_user_stories_points( return self._get_user_stories_points(
[us for us in self.user_stories.all().prefetch_related('role_points', 'role_points__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( return self._get_user_stories_points(
[us for us in self.user_stories.all().prefetch_related('role_points', 'role_points__points') if us.is_closed] [us for us in self.user_stories.all() if us.is_closed]
) )
def _get_points_increment(self, client_requirement, team_requirement): def _get_increment_points(self):
if hasattr(self, "_increments"):
return self._increments
self._increments = {
"client_increment": {},
"team_increment": {},
"shared_increment": {},
}
user_stories = UserStory.objects.none() user_stories = UserStory.objects.none()
if self.estimated_start and self.estimated_finish: if self.estimated_start and self.estimated_finish:
user_stories = UserStory.objects.filter( user_stories = filter(
created_date__gte=self.estimated_start, lambda x: x.created_date.date() >= self.estimated_start and x.created_date.date() < self.estimated_finish,
created_date__lt=self.estimated_finish, self.project.user_stories.all()
project_id=self.project_id, )
client_requirement=client_requirement, self._increments['client_increment'] = self._get_user_stories_points(
team_requirement=team_requirement [us for us in user_stories if us.client_requirement is True and us.team_requirement is False]
).prefetch_related('role_points', 'role_points__points') )
return self._get_user_stories_points(user_stories) self._increments['team_increment'] = self._get_user_stories_points(
[us for us in user_stories if us.client_requirement is False and us.team_requirement is True]
)
self._increments['shared_increment'] = self._get_user_stories_points(
[us for us in user_stories if us.client_requirement is True and us.team_requirement is True]
)
return self._increments
@property @property
def client_increment_points(self): def client_increment_points(self):
client_increment = self._get_points_increment(True, False) self._get_increment_points()
client_increment = self._get_increment_points()["client_increment"]
shared_increment = { shared_increment = {
key: value/2 for key, value in self.shared_increment_points.items() key: value/2 for key, value in self._get_increment_points()["shared_increment"].items()
} }
return 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):
team_increment = self._get_points_increment(False, True) team_increment = self._get_increment_points()["team_increment"]
shared_increment = { shared_increment = {
key: value/2 for key, value in self.shared_increment_points.items() key: value/2 for key, value in self._get_increment_points()["shared_increment"].items()
} }
return 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):
return self._get_points_increment(True, True) return self._get_increment_points()["shared_increment"]
def closed_points_by_date(self, date): def closed_points_by_date(self, date):
return self._get_user_stories_points([ return self._get_user_stories_points([

View File

@ -254,23 +254,20 @@ class Project(ProjectDefaults, TaggedMixin, models.Model):
return dict_sum(*flat_role_dicts) return dict_sum(*flat_role_dicts)
def _get_points_increment(self, client_requirement, team_requirement): def _get_points_increment(self, client_requirement, team_requirement):
userstory_model = apps.get_model("userstories", "UserStory")
user_stories = userstory_model.objects.none()
last_milestones = self.milestones.order_by('-estimated_finish') last_milestones = self.milestones.order_by('-estimated_finish')
last_milestone = last_milestones[0] if last_milestones else None last_milestone = last_milestones[0] if last_milestones else None
if last_milestone: if last_milestone:
user_stories = userstory_model.objects.filter( user_stories = self.user_stories.filter(
created_date__gte=last_milestone.estimated_finish, created_date__gte=last_milestone.estimated_finish,
project_id=self.id,
client_requirement=client_requirement, client_requirement=client_requirement,
team_requirement=team_requirement team_requirement=team_requirement
).prefetch_related('role_points', 'role_points__points') )
else: else:
user_stories = userstory_model.objects.filter( user_stories = self.user_stories.filter(
project_id=self.id,
client_requirement=client_requirement, client_requirement=client_requirement,
team_requirement=team_requirement team_requirement=team_requirement
).prefetch_related('role_points', 'role_points__points') )
user_stories = user_stories.prefetch_related('role_points', 'role_points__points')
return self._get_user_stories_points(user_stories) return self._get_user_stories_points(user_stories)
@property @property
@ -291,15 +288,26 @@ class Project(ProjectDefaults, TaggedMixin, models.Model):
@property @property
def closed_points(self): def closed_points(self):
return self._get_user_stories_points(self.user_stories.filter(is_closed=True).prefetch_related('role_points', 'role_points__points')) return self.calculated_points["closed"]
@property @property
def defined_points(self): def defined_points(self):
return self._get_user_stories_points(self.user_stories.all().prefetch_related('role_points', 'role_points__points')) return self.calculated_points["defined"]
@property @property
def assigned_points(self): def assigned_points(self):
return self._get_user_stories_points(self.user_stories.filter(milestone__isnull=False).prefetch_related('role_points', 'role_points__points')) return self.calculated_points["assigned"]
@property
def calculated_points(self):
user_stories = self.user_stories.all().prefetch_related('role_points', 'role_points__points')
closed_user_stories = user_stories.filter(is_closed=True)
assigned_user_stories = user_stories.filter(milestone__isnull=False)
return {
"defined": self._get_user_stories_points(user_stories),
"closed": self._get_user_stories_points(closed_user_stories),
"assigned": self._get_user_stories_points(assigned_user_stories),
}
class ProjectModulesConfig(models.Model): class ProjectModulesConfig(models.Model):

View File

@ -15,12 +15,12 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.db.models import Q, Count from django.db.models import Q, Count
from django.apps import apps
import datetime import datetime
import copy import copy
from taiga.projects.history.models import HistoryEntry from taiga.projects.history.models import HistoryEntry
def _get_milestones_stats_for_backlog(project): def _get_milestones_stats_for_backlog(project):
""" """
Get collection of stats for each millestone of project. Get collection of stats for each millestone of project.
@ -37,20 +37,27 @@ def _get_milestones_stats_for_backlog(project):
future_team_increment = sum(project.future_team_increment.values()) future_team_increment = sum(project.future_team_increment.values())
future_client_increment = sum(project.future_client_increment.values()) future_client_increment = sum(project.future_client_increment.values())
milestones = project.milestones.order_by('estimated_start') milestones = project.milestones.order_by('estimated_start').\
prefetch_related("user_stories",
"user_stories__role_points",
"user_stories__role_points__points")
milestones = list(milestones)
milestones_count = len(milestones)
optimal_points = 0 optimal_points = 0
team_increment = 0 team_increment = 0
client_increment = 0 client_increment = 0
for current_milestone in range(0, max(milestones.count(), project.total_milestones)):
for current_milestone in range(0, max(milestones_count, project.total_milestones)):
optimal_points = (project.total_story_points - optimal_points = (project.total_story_points -
(optimal_points_per_sprint * current_milestone)) (optimal_points_per_sprint * current_milestone))
evolution = (project.total_story_points - current_evolution evolution = (project.total_story_points - current_evolution
if current_evolution is not None else None) if current_evolution is not None else None)
if current_milestone < milestones.count(): if current_milestone < milestones_count:
ml = milestones[current_milestone] ml = milestones[current_milestone]
milestone_name = ml.name milestone_name = ml.name
team_increment = current_team_increment team_increment = current_team_increment
client_increment = current_client_increment client_increment = current_client_increment
@ -58,6 +65,7 @@ def _get_milestones_stats_for_backlog(project):
current_evolution += sum(ml.closed_points.values()) current_evolution += sum(ml.closed_points.values())
current_team_increment += sum(ml.team_increment_points.values()) current_team_increment += sum(ml.team_increment_points.values())
current_client_increment += sum(ml.client_increment_points.values()) current_client_increment += sum(ml.client_increment_points.values())
else: else:
milestone_name = "Future sprint" milestone_name = "Future sprint"
team_increment = current_team_increment + future_team_increment, team_increment = current_team_increment + future_team_increment,
@ -194,7 +202,13 @@ def get_stats_for_project_issues(project):
def get_stats_for_project(project): def get_stats_for_project(project):
closed_points = sum(project.closed_points.values()) project = apps.get_model("projects", "Project").objects.\
prefetch_related("milestones",
"user_stories").\
get(id=project.id)
points = project.calculated_points
closed_points = sum(points["closed"].values())
closed_milestones = project.milestones.filter(closed=True).count() closed_milestones = project.milestones.filter(closed=True).count()
speed = 0 speed = 0
if closed_milestones != 0: if closed_milestones != 0:
@ -205,11 +219,11 @@ def get_stats_for_project(project):
'total_milestones': project.total_milestones, 'total_milestones': project.total_milestones,
'total_points': project.total_story_points, 'total_points': project.total_story_points,
'closed_points': closed_points, 'closed_points': closed_points,
'closed_points_per_role': project.closed_points, 'closed_points_per_role': points["closed"],
'defined_points': sum(project.defined_points.values()), 'defined_points': sum(points["defined"].values()),
'defined_points_per_role': project.defined_points, 'defined_points_per_role': points["defined"],
'assigned_points': sum(project.assigned_points.values()), 'assigned_points': sum(points["assigned"].values()),
'assigned_points_per_role': project.assigned_points, 'assigned_points_per_role': points["assigned"],
'milestones': _get_milestones_stats_for_backlog(project), 'milestones': _get_milestones_stats_for_backlog(project),
'speed': speed, 'speed': speed,
} }

View File

@ -59,10 +59,10 @@ class UserStoryViewSet(OCCResourceMixin, HistoryResourceMixin, WatchedResourceMi
def get_queryset(self): def get_queryset(self):
qs = self.model.objects.all() qs = self.model.objects.all()
qs = qs.prefetch_related("points", qs = qs.prefetch_related("role_points",
"role_points",
"role_points__points", "role_points__points",
"role_points__role") "role_points__role",
"watchers")
qs = qs.select_related("milestone", "project") qs = qs.select_related("milestone", "project")
return qs return qs

View File

@ -124,8 +124,7 @@ class UserStory(OCCModelMixin, WatchedModelMixin, BlockedMixin, TaggedMixin, mod
return self.role_points return self.role_points
def get_total_points(self): def get_total_points(self):
not_null_role_points = self.role_points.select_related("points").\ not_null_role_points = [rp for rp in self.role_points.all() if rp.points.value is not None]
exclude(points__value__isnull=True)
#If we only have None values the sum should be None #If we only have None values the sum should be None
if not not_null_role_points: if not not_null_role_points: