# -*- 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 + 1) if milestone_days else 0 while current_date <= (milestone.estimated_finish + datetime.timedelta(days=1)): 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)