From 1c6d194a88341d7e9eeeb6682c678c520d512f1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lex=20Hermida?= Date: Thu, 15 Nov 2018 16:49:45 +0100 Subject: [PATCH] Add update tasks milestone in bulk --- taiga/projects/tasks/api.py | 17 +++++++++++++++ taiga/projects/tasks/permissions.py | 1 + taiga/projects/tasks/services.py | 33 +++++++++++++++++++++++++++++ taiga/projects/tasks/validators.py | 33 +++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+) diff --git a/taiga/projects/tasks/api.py b/taiga/projects/tasks/api.py index 8546c3e9..913d98e3 100644 --- a/taiga/projects/tasks/api.py +++ b/taiga/projects/tasks/api.py @@ -275,6 +275,23 @@ class TaskViewSet(AssignedToSignalMixin, OCCResourceMixin, VotedResourceMixin, return response.Ok(tasks_serialized.data) + @list_route(methods=["POST"]) + def bulk_update_milestone(self, request, **kwargs): + validator = validators.UpdateMilestoneBulkValidator(data=request.DATA) + if not validator.is_valid(): + return response.BadRequest(validator.errors) + + data = validator.data + project = get_object_or_404(Project, pk=data["project_id"]) + milestone = get_object_or_404(Milestone, pk=data["milestone_id"]) + + self.check_permissions(request, "bulk_update_milestone", project) + + ret = services.update_tasks_milestone_in_bulk(data["bulk_tasks"], milestone) + services.snapshot_tasks_in_bulk(data["bulk_tasks"], request.user) + + return response.Ok(ret) + def _bulk_update_order(self, order_field, request, **kwargs): validator = validators.UpdateTasksOrderBulkValidator(data=request.DATA) if not validator.is_valid(): diff --git a/taiga/projects/tasks/permissions.py b/taiga/projects/tasks/permissions.py index 46c6356f..b25ff6ea 100644 --- a/taiga/projects/tasks/permissions.py +++ b/taiga/projects/tasks/permissions.py @@ -35,6 +35,7 @@ class TaskPermission(TaigaResourcePermission): csv_perms = AllowAny() bulk_create_perms = HasProjectPerm('add_task') bulk_update_order_perms = HasProjectPerm('modify_task') + bulk_update_milestone_perms = HasProjectPerm('modify_task') upvote_perms = IsAuthenticated() & HasProjectPerm('view_tasks') downvote_perms = IsAuthenticated() & HasProjectPerm('view_tasks') watch_perms = IsAuthenticated() & HasProjectPerm('view_tasks') diff --git a/taiga/projects/tasks/services.py b/taiga/projects/tasks/services.py index 14fb7f8f..e23a8c22 100644 --- a/taiga/projects/tasks/services.py +++ b/taiga/projects/tasks/services.py @@ -112,6 +112,39 @@ def snapshot_tasks_in_bulk(bulk_data, user): pass +def update_tasks_milestone_in_bulk(bulk_data: list, milestone: object): + """ + Update the milestone and the milestone order of some tasks adding + the extra orders needed to keep consistency. + `bulk_data` should be a list of dicts with the following format: + [{'task_id': , 'order': }, ...] + """ + tasks = milestone.tasks.all() + print('taskss', tasks) + task_orders = {task.id: getattr(task, "taskboard_order") for task in tasks} + new_task_orders = {} + for e in bulk_data: + new_task_orders[e["task_id"]] = e["order"] + # The base orders where we apply the new orders must containg all + # the values + task_orders[e["task_id"]] = e["order"] + + apply_order_updates(task_orders, new_task_orders) + + task_milestones = {e["task_id"]: milestone.id for e in bulk_data} + task_ids = task_milestones.keys() + + events.emit_event_for_ids(ids=task_ids, + content_type="tasks.task", + projectid=milestone.project.pk) + + db.update_attr_in_bulk_for_ids(task_milestones, "milestone_id", + model=models.Task) + + db.update_attr_in_bulk_for_ids(task_orders, "taskboard_order", models.Task) + + return task_milestones + ##################################################### # CSV ##################################################### diff --git a/taiga/projects/tasks/validators.py b/taiga/projects/tasks/validators.py index 7f38f80b..61d2ff04 100644 --- a/taiga/projects/tasks/validators.py +++ b/taiga/projects/tasks/validators.py @@ -153,3 +153,36 @@ class UpdateTasksOrderBulkValidator(ProjectExistsValidator, validators.Validator "if it exists, to the same status, user story and/or milestone.")) return attrs + + +# Milestone bulk validators + +class _TaskMilestoneBulkValidator(validators.Validator): + task_id = serializers.IntegerField() + order = serializers.IntegerField() + + +class UpdateMilestoneBulkValidator(ProjectExistsValidator, validators.Validator): + project_id = serializers.IntegerField() + milestone_id = serializers.IntegerField() + bulk_tasks = _TaskMilestoneBulkValidator(many=True) + + def validate_milestone_id(self, attrs, source): + filters = { + "project__id": attrs["project_id"], + "id": attrs[source] + } + if not Milestone.objects.filter(**filters).exists(): + raise ValidationError(_("The milestone isn't valid for the project")) + return attrs + + def validate_bulk_tasks(self, attrs, source): + filters = { + "project__id": attrs["project_id"], + "id__in": [task["task_id"] for task in attrs[source]] + } + + if models.Task.objects.filter(**filters).count() != len(filters["id__in"]): + raise ValidationError(_("All the tasks must be from the same project")) + + return attrs