Skip to content

Commit 1872a80

Browse files
committed
✨ [#127] Endpoints to create a response to a review
1 parent c6f4132 commit 1872a80

File tree

4 files changed

+63
-41
lines changed

4 files changed

+63
-41
lines changed

backend/src/openarchiefbeheer/destruction/api/permissions.py

-16
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,3 @@ def has_object_permission(self, request, view, destruction_list):
3333
request.user == destruction_list.author
3434
and destruction_list.status == ListStatus.new
3535
)
36-
37-
38-
class CanMakeRequestedChanges(permissions.BasePermission):
39-
message = _(
40-
"You are either not allowed to update this destruction list or "
41-
"the destruction list can currently not be updated."
42-
)
43-
44-
def has_permission(self, request, view):
45-
return request.user.role and request.user.role.can_start_destruction
46-
47-
def has_object_permission(self, request, view, destruction_list):
48-
return (
49-
request.user == destruction_list.author
50-
and destruction_list.status == ListStatus.changes_requested
51-
)

backend/src/openarchiefbeheer/destruction/api/serializers.py

+41-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from django.db import transaction
12
from django.db.models import Q
23
from django.utils.translation import gettext_lazy as _
34

@@ -349,9 +350,16 @@ class ActionZaakSerializer(serializers.Serializer):
349350
required=False, help_text=_("A new date for when this case should be archived.")
350351
)
351352

353+
def to_internal_value(self, data: dict) -> dict:
354+
internal_value = super().to_internal_value(data)
355+
356+
if archiefactiedatum := internal_value.get("archiefactiedatum"):
357+
internal_value["archiefactiedatum"] = archiefactiedatum.isoformat()
358+
return internal_value
359+
352360

353361
class ReviewItemResponseSerializer(serializers.ModelSerializer):
354-
action_zaak = ActionZaakSerializer()
362+
action_zaak = ActionZaakSerializer(required=False)
355363

356364
class Meta:
357365
model = ReviewItemResponse
@@ -371,3 +379,35 @@ class ReviewResponseSerializer(serializers.ModelSerializer):
371379
class Meta:
372380
model = ReviewResponse
373381
fields = ("pk", "review", "comment", "created", "items_responses")
382+
383+
def validate(self, attrs: dict) -> dict:
384+
destruction_list = attrs["review"].destruction_list
385+
request = self.context["request"]
386+
387+
if not (
388+
request.user == destruction_list.author
389+
and destruction_list.status == ListStatus.changes_requested
390+
):
391+
raise ValidationError(
392+
_(
393+
"This user is either not allowed to update the destruction list or "
394+
"the destruction list cannot currently be updated."
395+
)
396+
)
397+
398+
return attrs
399+
400+
@transaction.atomic
401+
def create(self, validated_data: dict) -> ReviewResponse:
402+
items_responses_data = validated_data.pop("items_responses", [])
403+
items_responses = [
404+
ReviewItemResponse(**item_response)
405+
for item_response in items_responses_data
406+
]
407+
408+
review_response = ReviewResponse.objects.create(**validated_data)
409+
ReviewItemResponse.objects.bulk_create(items_responses)
410+
411+
# TODO kick off celery task to update the cases and to change the status/assignee of the destruction list
412+
413+
return review_response

backend/src/openarchiefbeheer/destruction/api/viewsets.py

+20-23
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
from django_filters.rest_framework import DjangoFilterBackend
55
from drf_spectacular.utils import OpenApiExample, extend_schema, extend_schema_view
66
from rest_framework import mixins, viewsets
7-
from rest_framework.decorators import action
87
from rest_framework.permissions import IsAuthenticated
9-
from rest_framework.response import Response
108

119
from ..models import (
1210
DestructionList,
@@ -22,11 +20,7 @@
2220
DestructionListReviewItemFilterset,
2321
ReviewResponseFilterset,
2422
)
25-
from .permissions import (
26-
CanMakeRequestedChanges,
27-
CanStartDestructionPermission,
28-
CanUpdateDestructionList,
29-
)
23+
from .permissions import CanStartDestructionPermission, CanUpdateDestructionList
3024
from .serializers import (
3125
DestructionListAPIResponseSerializer,
3226
DestructionListItemReviewSerializer,
@@ -132,13 +126,6 @@
132126
description=_("Retrieve details about a destruction list."),
133127
responses={200: DestructionListAPIResponseSerializer},
134128
),
135-
make_requested_changes=extend_schema(
136-
tags=["Destruction list"],
137-
summary=_("Make requested changes"),
138-
description=_(
139-
"Update a destruction list after a reviewer has requested changes."
140-
),
141-
),
142129
)
143130
class DestructionListViewSet(
144131
mixins.RetrieveModelMixin,
@@ -158,8 +145,6 @@ def get_permissions(self):
158145
permission_classes = [IsAuthenticated & CanStartDestructionPermission]
159146
elif self.action == "update":
160147
permission_classes = [IsAuthenticated & CanUpdateDestructionList]
161-
elif self.action == "make_requested_changes":
162-
permission_classes = [IsAuthenticated & CanMakeRequestedChanges]
163148
else:
164149
permission_classes = [IsAuthenticated]
165150
return [permission() for permission in permission_classes]
@@ -177,12 +162,6 @@ def create(self, request, *args, **kwargs):
177162
def update(self, request, *args, **kwargs):
178163
return super().update(request, *args, **kwargs)
179164

180-
@action(detail=True, methods=["patch"], name="make-requested-changes")
181-
def make_requested_changes(self, request, *args, **kwargs):
182-
# Triggers the object permissions check
183-
self.get_object()
184-
return Response("Not implemented!")
185-
186165

187166
@extend_schema_view(
188167
list=extend_schema(
@@ -253,9 +232,27 @@ class DestructionListItemReviewViewSet(mixins.ListModelMixin, viewsets.GenericVi
253232
summary=_("List review responses"),
254233
description=_("List all the responses to the reviews of a destruction list."),
255234
),
235+
create=extend_schema(
236+
tags=["Reviews"],
237+
summary=_("Create a review response"),
238+
description=_(
239+
"Create a response to a review. "
240+
"You need to be the author of a destruction list for this and you need to be assigned to it. "
241+
"The status of the destruction list must be 'changes requested'."
242+
),
243+
),
256244
)
257-
class ReviewResponseViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
245+
class ReviewResponseViewSet(
246+
mixins.ListModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet
247+
):
258248
serializer_class = ReviewResponseSerializer
259249
queryset = ReviewResponse.objects.all()
260250
filter_backends = (DjangoFilterBackend,)
261251
filterset_class = ReviewResponseFilterset
252+
253+
def get_permissions(self):
254+
if self.action == "create":
255+
permission_classes = [IsAuthenticated & CanStartDestructionPermission]
256+
else:
257+
permission_classes = [IsAuthenticated]
258+
return [permission() for permission in permission_classes]

backend/src/openarchiefbeheer/destruction/models.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import uuid as _uuid
33

44
from django.db import models
5+
from django.db.models import QuerySet
56
from django.utils import timezone
67
from django.utils.translation import gettext_lazy as _
78

@@ -324,7 +325,7 @@ def __str__(self):
324325
return f"Response to {self.review}"
325326

326327
@property
327-
def items_responses(self):
328+
def items_responses(self) -> QuerySet["ReviewItemResponse"]:
328329
return ReviewItemResponse.objects.filter(review_item__review=self.review)
329330

330331

0 commit comments

Comments
 (0)