Working sprint graph
parent
53ae1d3b1b
commit
e1454106af
|
@ -1,8 +1,11 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.decorators import detail_route
|
||||
from rest_framework.response import Response
|
||||
|
||||
from greenmine.base import filters
|
||||
from greenmine.base import exceptions as exc
|
||||
|
@ -13,6 +16,8 @@ from . import serializers
|
|||
from . import models
|
||||
from . import permissions
|
||||
|
||||
import datetime
|
||||
|
||||
|
||||
class MilestoneViewSet(NotificationSenderMixin, ModelCrudViewSet):
|
||||
model= models.Milestone
|
||||
|
@ -37,3 +42,33 @@ class MilestoneViewSet(NotificationSenderMixin, ModelCrudViewSet):
|
|||
|
||||
super().pre_save(obj)
|
||||
|
||||
@detail_route(methods=['get'])
|
||||
def stats(self, request, pk=None):
|
||||
milestone = get_object_or_404(models.Milestone, pk=pk)
|
||||
total_points = milestone.total_points
|
||||
milestone_stats = {
|
||||
'name': milestone.name,
|
||||
'estimated_start': milestone.estimated_start,
|
||||
'estimated_finish': milestone.estimated_finish,
|
||||
'total_points': total_points,
|
||||
'completed_points': milestone.closed_points.values(),
|
||||
'total_userstories': milestone.user_stories.count(),
|
||||
'completed_userstories': len([us for us in milestone.user_stories.all() if us.is_closed]),
|
||||
'total_tasks': sum([us.tasks.count() for us in milestone.user_stories.all()]),
|
||||
'completed_tasks': sum([us.tasks.filter(status__is_closed=True).count() for us in milestone.user_stories.all()]),
|
||||
'days': []
|
||||
}
|
||||
current_date = milestone.estimated_start
|
||||
optimal_points = sum(total_points.values())
|
||||
optimal_points_per_day = sum(total_points.values()) / (milestone.estimated_finish - milestone.estimated_start).days
|
||||
while current_date <= milestone.estimated_finish:
|
||||
milestone_stats['days'].append({
|
||||
'day': current_date,
|
||||
'name': current_date.day,
|
||||
'open_points': sum(total_points.values()) - sum(milestone.closed_points_by_date(current_date).values()),
|
||||
'optimal_points': optimal_points,
|
||||
})
|
||||
current_date = current_date + datetime.timedelta(days=1)
|
||||
optimal_points -= optimal_points_per_day
|
||||
|
||||
return Response(milestone_stats)
|
||||
|
|
|
@ -91,6 +91,10 @@ class Milestone(WatchedMixin):
|
|||
dict_result[key] = value
|
||||
return dict_result
|
||||
|
||||
@property
|
||||
def total_points(self):
|
||||
return self._get_user_stories_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()
|
||||
|
@ -147,6 +151,10 @@ class Milestone(WatchedMixin):
|
|||
"project_owner": (self.project, self.project.owner),
|
||||
}
|
||||
|
||||
def closed_points_by_date(self, date):
|
||||
return self._get_user_stories_points([us for us in self.user_stories.filter(finish_date__lte=date)
|
||||
if us.is_closed])
|
||||
|
||||
|
||||
# Reversion registration (usufull for base.notification and for meke a historical)
|
||||
reversion.register(Milestone)
|
||||
|
|
Loading…
Reference in New Issue