diff --git a/taiga/projects/userstories/api.py b/taiga/projects/userstories/api.py index 64b9e2fa..b9ae9f5d 100644 --- a/taiga/projects/userstories/api.py +++ b/taiga/projects/userstories/api.py @@ -80,27 +80,16 @@ class UserStoryViewSet(OCCResourceMixin, HistoryResourceMixin, WatchedResourceMi @list_route(methods=["POST"]) def bulk_update_order(self, request, **kwargs): - # bulkStories should be: - # [[1,1],[23, 2], ...] + serializer = serializers.UpdateUserStoriesBulkSerializer(data=request.DATA) + if serializer.is_valid(): + data = serializer.data + project = Project.objects.get(id=data["project_id"]) + self.check_permissions(request, 'bulk_update_order', project) + # services.update_userstories_order_in_bulk(data["bulk_stories"]) - # TODO: Generate the histoy snaptshot when change the uss order in the backlog. - # Implement order with linked lists \o/. - bulk_stories = request.DATA.get("bulkStories", None) + return response.NoContent() - if bulk_stories is None: - raise exc.BadRequest(_("bulkStories parameter is mandatory")) - - project_id = request.DATA.get('projectId', None) - if project_id is None: - raise exc.BadRequest(_("projectId parameter ir mandatory")) - - project = get_object_or_404(Project, id=project_id) - - self.check_permissions(request, 'bulk_update_order', project) - - services.update_userstories_order_in_bulk(bulk_stories) - - return Response(data=None, status=status.HTTP_204_NO_CONTENT) + return response.BadRequest(serializer.errors) @transaction.atomic def create(self, *args, **kwargs): diff --git a/taiga/projects/userstories/serializers.py b/taiga/projects/userstories/serializers.py index 38ba4805..365cac13 100644 --- a/taiga/projects/userstories/serializers.py +++ b/taiga/projects/userstories/serializers.py @@ -21,6 +21,7 @@ from rest_framework import serializers from taiga.base.serializers import Serializer, PickleField, NeighborsSerializerMixin from taiga.mdrender.service import render as mdrender from taiga.projects.validators import ProjectExistsValidator, UserStoryStatusExistsValidator +from taiga.projects.userstories.validators import UserStoryExistsValidator from . import models @@ -116,3 +117,14 @@ class UserStoriesBulkSerializer(ProjectExistsValidator, UserStoryStatusExistsVal project_id = serializers.IntegerField() status_id = serializers.IntegerField(required=False) bulk_stories = serializers.CharField() + + +class UserStoryOrderBulkSerializer(UserStoryExistsValidator, Serializer): + us_id = serializers.IntegerField() + order = serializers.IntegerField() + + +class UpdateUserStoriesBulkSerializer(ProjectExistsValidator, UserStoryStatusExistsValidator, + Serializer): + project_id = serializers.IntegerField() + bulk_stories = UserStoryOrderBulkSerializer(many=True) diff --git a/taiga/projects/userstories/validators.py b/taiga/projects/userstories/validators.py index 58b7e710..b3691877 100644 --- a/taiga/projects/userstories/validators.py +++ b/taiga/projects/userstories/validators.py @@ -6,7 +6,7 @@ from . import models class UserStoryExistsValidator: - def validate_project_id(self, attrs, source): + def validate_us_id(self, attrs, source): value = attrs[source] if not models.UserStory.objects.filter(pk=value).exists(): msg = _("There's no user story with that id") diff --git a/tests/integration/resources_permissions/test_userstories_resources.py b/tests/integration/resources_permissions/test_userstories_resources.py index 54fce096..b9f564f8 100644 --- a/tests/integration/resources_permissions/test_userstories_resources.py +++ b/tests/integration/resources_permissions/test_userstories_resources.py @@ -250,15 +250,15 @@ def test_user_story_action_bulk_create(client, data): data.project_owner ] - bulk_data = json.dumps({"bulkStories": "test1\ntest2", "projectId": data.public_user_story.project.pk}) + bulk_data = json.dumps({"bulk_stories": "test1\ntest2", "projectId": data.public_user_story.project.pk}) results = helper_test_http_method(client, 'post', url, bulk_data, users) assert results == [401, 200, 200, 200, 200] - bulk_data = json.dumps({"bulkStories": "test1\ntest2", "projectId": data.private_user_story1.project.pk}) + bulk_data = json.dumps({"bulk_stories": "test1\ntest2", "projectId": data.private_user_story1.project.pk}) results = helper_test_http_method(client, 'post', url, bulk_data, users) assert results == [401, 200, 200, 200, 200] - bulk_data = json.dumps({"bulkStories": "test1\ntest2", "projectId": data.private_user_story2.project.pk}) + bulk_data = json.dumps({"bulk_stories": "test1\ntest2", "projectId": data.private_user_story2.project.pk}) results = helper_test_http_method(client, 'post', url, bulk_data, users) assert results == [401, 403, 403, 200, 200] @@ -275,22 +275,22 @@ def test_user_story_action_bulk_update_order(client, data): ] post_data = json.dumps({ - "bulkStories": [(1,2)], - "projectId": data.public_project.pk + "bulk_stories": [{"us_id": 1, "order": 2}], + "project_id": data.public_project.pk }) results = helper_test_http_method(client, 'post', url, post_data, users) assert results == [401, 403, 403, 204, 204] post_data = json.dumps({ - "bulkStories": [(1,2)], - "projectId": data.private_project1.pk + "bulk_stories": [{"id": 1, "order": 2}], + "project_id": data.private_project1.pk }) results = helper_test_http_method(client, 'post', url, post_data, users) assert results == [401, 403, 403, 204, 204] post_data = json.dumps({ - "bulkStories": [(1,2)], - "projectId": data.private_project2.pk + "bulk_stories": [{"id": 1, "order": 2}], + "project_id": data.private_project2.pk }) results = helper_test_http_method(client, 'post', url, post_data, users) assert results == [401, 403, 403, 204, 204] diff --git a/tests/integration/test_userstories.py b/tests/integration/test_userstories.py index 50ad553e..d460f546 100644 --- a/tests/integration/test_userstories.py +++ b/tests/integration/test_userstories.py @@ -80,3 +80,20 @@ def test_api_create_in_bulk_with_status(client): assert response.status_code == 200, response.data assert response.data[0]["status"] == project.default_us_status.id + + +def test_api_update_order_in_bulk(client): + project = f.create_project() + us1 = f.create_userstory(project=project) + us2 = f.create_userstory(project=project) + url = reverse("userstories-bulk-update-order") + data = { + "project_id": project.id, + "bulk_stories": [{"us_id": us1.id, "order": 1}, + {"us_id": us2.id, "order": 2}] + } + + client.login(project.owner) + response = client.json.post(url, data) + + assert response.status_code == 204, response.data