Merge pull request #464 from taigaio/making-total_points-and-total_sprints-nullable
Making total_points and total_sprints nullable valuesremotes/origin/logger
commit
ca6239eda2
|
@ -0,0 +1,26 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('projects', '0026_auto_20150911_1237'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='project',
|
||||
name='total_milestones',
|
||||
field=models.IntegerField(verbose_name='total of milestones', null=True, blank=True),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='project',
|
||||
name='total_story_points',
|
||||
field=models.FloatField(verbose_name='total story points', null=True, blank=True),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
|
@ -146,9 +146,9 @@ class Project(ProjectDefaults, TaggedMixin, models.Model):
|
|||
members = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="projects",
|
||||
through="Membership", verbose_name=_("members"),
|
||||
through_fields=("project", "user"))
|
||||
total_milestones = models.IntegerField(default=0, null=False, blank=False,
|
||||
total_milestones = models.IntegerField(null=True, blank=True,
|
||||
verbose_name=_("total of milestones"))
|
||||
total_story_points = models.FloatField(default=0, verbose_name=_("total story points"))
|
||||
total_story_points = models.FloatField(null=True, blank=True, verbose_name=_("total story points"))
|
||||
|
||||
is_backlog_activated = models.BooleanField(default=True, null=False, blank=True,
|
||||
verbose_name=_("active backlog panel"))
|
||||
|
|
|
@ -342,16 +342,6 @@ class ProjectSerializer(WatchersValidator, LikedResourceSerializerMixin, Watched
|
|||
def get_notify_level(self, obj):
|
||||
return getattr(obj, "notify_level", None)
|
||||
|
||||
def validate_total_milestones(self, attrs, source):
|
||||
"""
|
||||
Check that total_milestones is not null, it's an optional parameter but
|
||||
not nullable in the model.
|
||||
"""
|
||||
value = attrs[source]
|
||||
if value is None:
|
||||
raise serializers.ValidationError(_("Total milestones must be major or equal to zero"))
|
||||
return attrs
|
||||
|
||||
|
||||
class ProjectDetailSerializer(ProjectSerializer):
|
||||
us_statuses = UserStoryStatusSerializer(many=True, required=False) # User Stories
|
||||
|
|
|
@ -23,6 +23,14 @@ import copy
|
|||
from taiga.projects.history.models import HistoryEntry
|
||||
|
||||
|
||||
def _get_total_story_points(project):
|
||||
return (project.total_story_points if project.total_story_points is not None else
|
||||
sum(project.calculated_points["defined"].values()))
|
||||
|
||||
def _get_total_milestones(project):
|
||||
return (project.total_milestones if project.total_milestones is not None else
|
||||
project.milestones.count())
|
||||
|
||||
def _get_milestones_stats_for_backlog(project):
|
||||
"""
|
||||
Get collection of stats for each millestone of project.
|
||||
|
@ -33,8 +41,12 @@ def _get_milestones_stats_for_backlog(project):
|
|||
current_client_increment = 0
|
||||
|
||||
optimal_points_per_sprint = 0
|
||||
if project.total_story_points and project.total_milestones:
|
||||
optimal_points_per_sprint = project.total_story_points / project.total_milestones
|
||||
|
||||
total_story_points = _get_total_story_points(project)
|
||||
total_milestones = _get_total_milestones(project)
|
||||
|
||||
if total_story_points and total_milestones:
|
||||
optimal_points_per_sprint = total_story_points / total_milestones
|
||||
|
||||
future_team_increment = sum(project.future_team_increment.values())
|
||||
future_client_increment = sum(project.future_client_increment.values())
|
||||
|
@ -50,11 +62,11 @@ def _get_milestones_stats_for_backlog(project):
|
|||
team_increment = 0
|
||||
client_increment = 0
|
||||
|
||||
for current_milestone in range(0, max(milestones_count, project.total_milestones)):
|
||||
optimal_points = (project.total_story_points -
|
||||
for current_milestone in range(0, max(milestones_count, total_milestones)):
|
||||
optimal_points = (total_story_points -
|
||||
(optimal_points_per_sprint * current_milestone))
|
||||
|
||||
evolution = (project.total_story_points - current_evolution
|
||||
evolution = (total_story_points - current_evolution
|
||||
if current_evolution is not None else None)
|
||||
|
||||
if current_milestone < milestones_count:
|
||||
|
@ -83,8 +95,8 @@ def _get_milestones_stats_for_backlog(project):
|
|||
}
|
||||
|
||||
optimal_points -= optimal_points_per_sprint
|
||||
evolution = (project.total_story_points - current_evolution
|
||||
if current_evolution is not None and project.total_story_points else None)
|
||||
evolution = (total_story_points - current_evolution
|
||||
if current_evolution is not None and total_story_points else None)
|
||||
yield {
|
||||
'name': _('Project End'),
|
||||
'optimal': optimal_points,
|
||||
|
@ -104,6 +116,7 @@ def _count_status_object(status_obj, counting_storage):
|
|||
counting_storage[status_obj.id]['id'] = status_obj.id
|
||||
counting_storage[status_obj.id]['color'] = status_obj.color
|
||||
|
||||
|
||||
def _count_owned_object(user_obj, counting_storage):
|
||||
if user_obj:
|
||||
if user_obj.id in counting_storage:
|
||||
|
@ -126,6 +139,7 @@ def _count_owned_object(user_obj, counting_storage):
|
|||
counting_storage[0]['id'] = 0
|
||||
counting_storage[0]['color'] = 'black'
|
||||
|
||||
|
||||
def get_stats_for_project_issues(project):
|
||||
project_issues_stats = {
|
||||
'total_issues': 0,
|
||||
|
@ -283,6 +297,7 @@ def _get_closed_tasks_per_member_stats(project):
|
|||
closed_tasks = {p["assigned_to"]: p["count"] for p in closed_tasks}
|
||||
return closed_tasks
|
||||
|
||||
|
||||
def get_member_stats_for_project(project):
|
||||
base_counters = {id: 0 for id in project.members.values_list("id", flat=True)}
|
||||
closed_bugs = base_counters.copy()
|
||||
|
|
Loading…
Reference in New Issue