Some extra api optimizations
parent
99691372a5
commit
ca09cda87c
|
@ -47,7 +47,12 @@ class MilestoneViewSet(HistoryResourceMixin, WatchedResourceMixin, ModelCrudView
|
|||
qs = qs.prefetch_related("user_stories",
|
||||
"user_stories__role_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")
|
||||
return qs
|
||||
|
||||
|
|
|
@ -91,46 +91,62 @@ class Milestone(WatchedModelMixin, models.Model):
|
|||
@property
|
||||
def total_points(self):
|
||||
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
|
||||
def closed_points(self):
|
||||
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()
|
||||
if self.estimated_start and self.estimated_finish:
|
||||
user_stories = UserStory.objects.filter(
|
||||
created_date__gte=self.estimated_start,
|
||||
created_date__lt=self.estimated_finish,
|
||||
project_id=self.project_id,
|
||||
client_requirement=client_requirement,
|
||||
team_requirement=team_requirement
|
||||
).prefetch_related('role_points', 'role_points__points')
|
||||
return self._get_user_stories_points(user_stories)
|
||||
user_stories = filter(
|
||||
lambda x: x.created_date.date() >= self.estimated_start and x.created_date.date() < self.estimated_finish,
|
||||
self.project.user_stories.all()
|
||||
)
|
||||
self._increments['client_increment'] = self._get_user_stories_points(
|
||||
[us for us in user_stories if us.client_requirement is True and us.team_requirement is False]
|
||||
)
|
||||
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
|
||||
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 = {
|
||||
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)
|
||||
|
||||
@property
|
||||
def team_increment_points(self):
|
||||
team_increment = self._get_points_increment(False, True)
|
||||
team_increment = self._get_increment_points()["team_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)
|
||||
|
||||
@property
|
||||
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):
|
||||
return self._get_user_stories_points([
|
||||
|
|
|
@ -254,23 +254,20 @@ class Project(ProjectDefaults, TaggedMixin, models.Model):
|
|||
return dict_sum(*flat_role_dicts)
|
||||
|
||||
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_milestone = last_milestones[0] if last_milestones else None
|
||||
if last_milestone:
|
||||
user_stories = userstory_model.objects.filter(
|
||||
user_stories = self.user_stories.filter(
|
||||
created_date__gte=last_milestone.estimated_finish,
|
||||
project_id=self.id,
|
||||
client_requirement=client_requirement,
|
||||
team_requirement=team_requirement
|
||||
).prefetch_related('role_points', 'role_points__points')
|
||||
)
|
||||
else:
|
||||
user_stories = userstory_model.objects.filter(
|
||||
project_id=self.id,
|
||||
user_stories = self.user_stories.filter(
|
||||
client_requirement=client_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)
|
||||
|
||||
@property
|
||||
|
@ -291,15 +288,26 @@ class Project(ProjectDefaults, TaggedMixin, models.Model):
|
|||
|
||||
@property
|
||||
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
|
||||
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
|
||||
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):
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.db.models import Q, Count
|
||||
from django.apps import apps
|
||||
import datetime
|
||||
import copy
|
||||
|
||||
from taiga.projects.history.models import HistoryEntry
|
||||
|
||||
|
||||
def _get_milestones_stats_for_backlog(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_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
|
||||
team_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_per_sprint * current_milestone))
|
||||
|
||||
evolution = (project.total_story_points - current_evolution
|
||||
if current_evolution is not None else None)
|
||||
|
||||
if current_milestone < milestones.count():
|
||||
if current_milestone < milestones_count:
|
||||
ml = milestones[current_milestone]
|
||||
|
||||
milestone_name = ml.name
|
||||
team_increment = current_team_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_team_increment += sum(ml.team_increment_points.values())
|
||||
current_client_increment += sum(ml.client_increment_points.values())
|
||||
|
||||
else:
|
||||
milestone_name = "Future sprint"
|
||||
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):
|
||||
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()
|
||||
speed = 0
|
||||
if closed_milestones != 0:
|
||||
|
@ -205,11 +219,11 @@ def get_stats_for_project(project):
|
|||
'total_milestones': project.total_milestones,
|
||||
'total_points': project.total_story_points,
|
||||
'closed_points': closed_points,
|
||||
'closed_points_per_role': project.closed_points,
|
||||
'defined_points': sum(project.defined_points.values()),
|
||||
'defined_points_per_role': project.defined_points,
|
||||
'assigned_points': sum(project.assigned_points.values()),
|
||||
'assigned_points_per_role': project.assigned_points,
|
||||
'closed_points_per_role': points["closed"],
|
||||
'defined_points': sum(points["defined"].values()),
|
||||
'defined_points_per_role': points["defined"],
|
||||
'assigned_points': sum(points["assigned"].values()),
|
||||
'assigned_points_per_role': points["assigned"],
|
||||
'milestones': _get_milestones_stats_for_backlog(project),
|
||||
'speed': speed,
|
||||
}
|
||||
|
|
|
@ -59,10 +59,10 @@ class UserStoryViewSet(OCCResourceMixin, HistoryResourceMixin, WatchedResourceMi
|
|||
|
||||
def get_queryset(self):
|
||||
qs = self.model.objects.all()
|
||||
qs = qs.prefetch_related("points",
|
||||
"role_points",
|
||||
qs = qs.prefetch_related("role_points",
|
||||
"role_points__points",
|
||||
"role_points__role")
|
||||
"role_points__role",
|
||||
"watchers")
|
||||
qs = qs.select_related("milestone", "project")
|
||||
return qs
|
||||
|
||||
|
|
|
@ -124,8 +124,7 @@ class UserStory(OCCModelMixin, WatchedModelMixin, BlockedMixin, TaggedMixin, mod
|
|||
return self.role_points
|
||||
|
||||
def get_total_points(self):
|
||||
not_null_role_points = self.role_points.select_related("points").\
|
||||
exclude(points__value__isnull=True)
|
||||
not_null_role_points = [rp for rp in self.role_points.all() if rp.points.value is not None]
|
||||
|
||||
#If we only have None values the sum should be None
|
||||
if not not_null_role_points:
|
||||
|
|
Loading…
Reference in New Issue