taiga-back/greenmine/projects/milestones/api.py

77 lines
3.2 KiB
Python

# -*- 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
from greenmine.base.api import ModelCrudViewSet
from greenmine.base.notifications.api import NotificationSenderMixin
from . import serializers
from . import models
from . import permissions
import datetime
class MilestoneViewSet(NotificationSenderMixin, ModelCrudViewSet):
queryset = models.Milestone.objects.all().order_by("-estimated_start")
serializer_class = serializers.MilestoneSerializer
permission_classes = (IsAuthenticated, permissions.MilestonePermission)
filter_backends = (filters.IsProjectMemberFilterBackend,)
filter_fields = ("project",)
create_notification_template = "create_milestone_notification"
update_notification_template = "update_milestone_notification"
destroy_notification_template = "destroy_milestone_notification"
def pre_conditions_on_save(self, obj):
super().pre_conditions_on_save(obj)
if (obj.project.owner != self.request.user and
obj.project.memberships.filter(user=self.request.user).count() == 0):
raise exc.PreconditionError("You must not add a new milestone to this project.")
def pre_save(self, obj):
if not obj.id:
obj.owner = self.request.user
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': milestone.tasks.all().count(),
'completed_tasks': milestone.tasks.all().filter(status__is_closed=True).count(),
'days': []
}
current_date = milestone.estimated_start
sumTotalPoints = sum(total_points.values())
optimal_points = sumTotalPoints
milestone_days = (milestone.estimated_finish - milestone.estimated_start).days
optimal_points_per_day = sumTotalPoints / milestone_days if milestone_days else 0
while current_date <= milestone.estimated_finish:
milestone_stats['days'].append({
'day': current_date,
'name': current_date.day,
'open_points': sumTotalPoints - 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)