You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
3.1 KiB

  1. from django.shortcuts import get_object_or_404
  2. from django_filters.rest_framework import DjangoFilterBackend
  3. from pydantic import ValidationError
  4. from rest_framework import filters, generics, status
  5. from rest_framework.permissions import IsAuthenticated
  6. from rest_framework.views import APIView, Response
  7. from examples.assignment.strategies import StrategyName
  8. from examples.assignment.usecase import bulk_assign
  9. from examples.assignment.workload import WorkloadAllocation
  10. from examples.models import Assignment
  11. from examples.serializers import AssignmentSerializer
  12. from projects.models import Project
  13. from projects.permissions import IsProjectAdmin, IsProjectStaffAndReadOnly
  14. class AssignmentList(generics.ListCreateAPIView):
  15. serializer_class = AssignmentSerializer
  16. permission_classes = [IsAuthenticated & (IsProjectAdmin | IsProjectStaffAndReadOnly)]
  17. filter_backends = (DjangoFilterBackend, filters.OrderingFilter)
  18. ordering_fields = ("created_at", "updated_at")
  19. model = Assignment
  20. @property
  21. def project(self):
  22. return get_object_or_404(Project, pk=self.kwargs["project_id"])
  23. def get_queryset(self):
  24. queryset = self.model.objects.filter(project=self.project, assignee=self.request.user)
  25. return queryset
  26. def perform_create(self, serializer):
  27. serializer.save(project=self.project)
  28. class AssignmentDetail(generics.RetrieveUpdateDestroyAPIView):
  29. queryset = Assignment.objects.all()
  30. serializer_class = AssignmentSerializer
  31. lookup_url_kwarg = "assignment_id"
  32. permission_classes = [IsAuthenticated & (IsProjectAdmin | IsProjectStaffAndReadOnly)]
  33. class ResetAssignment(APIView):
  34. permission_classes = [IsAuthenticated & IsProjectAdmin]
  35. @property
  36. def project(self):
  37. return get_object_or_404(Project, pk=self.kwargs["project_id"])
  38. def delete(self, *args, **kwargs):
  39. Assignment.objects.filter(project=self.project).delete()
  40. return Response(status=status.HTTP_204_NO_CONTENT)
  41. class BulkAssignment(APIView):
  42. serializer_class = AssignmentSerializer
  43. permission_classes = [IsAuthenticated & IsProjectAdmin]
  44. def post(self, *args, **kwargs):
  45. try:
  46. strategy_name = StrategyName[self.request.data["strategy_name"]]
  47. except KeyError:
  48. return Response(
  49. {"detail": "Invalid strategy name"},
  50. status=status.HTTP_400_BAD_REQUEST,
  51. )
  52. try:
  53. workload_allocation = WorkloadAllocation(workloads=self.request.data["workloads"])
  54. except ValidationError as e:
  55. return Response(
  56. {"detail": e.errors()},
  57. status=status.HTTP_400_BAD_REQUEST,
  58. )
  59. try:
  60. bulk_assign(
  61. project_id=self.kwargs["project_id"],
  62. strategy_name=strategy_name,
  63. member_ids=workload_allocation.member_ids,
  64. weights=workload_allocation.weights,
  65. )
  66. except ValueError as e:
  67. return Response(
  68. {"detail": str(e)},
  69. status=status.HTTP_400_BAD_REQUEST,
  70. )
  71. return Response(status=status.HTTP_201_CREATED)