From 0d50c16ed48ecd7784b1f7a8a990b248aa481bc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lex=20Hermida?= Date: Thu, 15 Nov 2018 17:27:13 +0100 Subject: [PATCH] Add update issue milestone in bulk --- taiga/projects/issues/api.py | 17 ++++++++++++++ taiga/projects/issues/permissions.py | 1 + taiga/projects/issues/services.py | 30 ++++++++++++++++++++++++ taiga/projects/issues/validators.py | 34 ++++++++++++++++++++++++++++ taiga/projects/tasks/services.py | 1 - 5 files changed, 82 insertions(+), 1 deletion(-) diff --git a/taiga/projects/issues/api.py b/taiga/projects/issues/api.py index f6f132b3..17d4acfe 100644 --- a/taiga/projects/issues/api.py +++ b/taiga/projects/issues/api.py @@ -28,6 +28,7 @@ from taiga.base.api.mixins import BlockedByProjectMixin from taiga.base.api.utils import get_object_or_404 from taiga.projects.history.mixins import HistoryResourceMixin +from taiga.projects.milestones.models import Milestone from taiga.projects.mixins.by_ref import ByRefMixin from taiga.projects.models import Project, IssueStatus, Severity, Priority, IssueType from taiga.projects.notifications.mixins import AssignedToSignalMixin @@ -252,6 +253,22 @@ class IssueViewSet(AssignedToSignalMixin, OCCResourceMixin, VotedResourceMixin, return response.BadRequest(validator.errors) + @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_issues"], milestone) + + return response.Ok(ret) + class IssueVotersViewSet(VotersViewSetMixin, ModelListViewSet): permission_classes = (permissions.IssueVotersPermission,) diff --git a/taiga/projects/issues/permissions.py b/taiga/projects/issues/permissions.py index 6218e8e6..bd4ff5ec 100644 --- a/taiga/projects/issues/permissions.py +++ b/taiga/projects/issues/permissions.py @@ -35,6 +35,7 @@ class IssuePermission(TaigaResourcePermission): filters_data_perms = AllowAny() csv_perms = AllowAny() bulk_create_perms = HasProjectPerm('add_issue') + bulk_update_milestone_perms = HasProjectPerm('modify_issue') delete_comment_perms= HasProjectPerm('modify_issue') upvote_perms = IsAuthenticated() & HasProjectPerm('view_issues') downvote_perms = IsAuthenticated() & HasProjectPerm('view_issues') diff --git a/taiga/projects/issues/services.py b/taiga/projects/issues/services.py index e0dacd9a..c371e319 100644 --- a/taiga/projects/issues/services.py +++ b/taiga/projects/issues/services.py @@ -26,6 +26,9 @@ from django.db import connection from django.utils.translation import ugettext as _ from taiga.base.utils import db, text +from taiga.events import events + +from taiga.projects.history.services import take_snapshot from taiga.projects.issues.apps import ( connect_issues_signals, disconnect_issues_signals) @@ -72,6 +75,33 @@ def create_issues_in_bulk(bulk_data, callback=None, precall=None, **additional_f return issues +def snapshot_issues_in_bulk(bulk_data, user): + for issue_data in bulk_data: + try: + issue = models.Issue.objects.get(pk=issue_data['issue_id']) + take_snapshot(issue, user=user) + except models.Issue.DoesNotExist: + pass + + +def update_tasks_milestone_in_bulk(bulk_data: list, milestone: object): + """ + Update the milestone some issues adding + `bulk_data` should be a list of dicts with the following format: + [{'task_id': }, ...] + """ + issue_milestones = {e["issue_id"]: milestone.id for e in bulk_data} + issue_ids = issue_milestones.keys() + + events.emit_event_for_ids(ids=issue_ids, + content_type="issues.issues", + projectid=milestone.project.pk) + + db.update_attr_in_bulk_for_ids(issue_milestones, "milestone_id", + model=models.Issue) + + return issue_milestones + ##################################################### # CSV ##################################################### diff --git a/taiga/projects/issues/validators.py b/taiga/projects/issues/validators.py index 882559a0..8a3cd59e 100644 --- a/taiga/projects/issues/validators.py +++ b/taiga/projects/issues/validators.py @@ -18,7 +18,9 @@ from taiga.base.api import serializers from taiga.base.api import validators +from taiga.base.exceptions import ValidationError from taiga.base.fields import PgArrayField +from taiga.projects.milestones.models import Milestone from taiga.projects.mixins.validators import AssignedToValidator from taiga.projects.notifications.mixins import EditableWatchedResourceSerializer from taiga.projects.notifications.validators import WatchersValidator @@ -43,3 +45,35 @@ class IssuesBulkValidator(ProjectExistsValidator, validators.Validator): project_id = serializers.IntegerField() milestone_id = serializers.IntegerField(required=False) bulk_issues = serializers.CharField() + + +# Milestone bulk validators + +class _IssueMilestoneBulkValidator(validators.Validator): + issue_id = serializers.IntegerField() + + +class UpdateMilestoneBulkValidator(ProjectExistsValidator, validators.Validator): + project_id = serializers.IntegerField() + milestone_id = serializers.IntegerField() + bulk_issues = _IssueMilestoneBulkValidator(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": [issue["issue_id"] for issue in attrs[source]] + } + + if models.Issue.objects.filter(**filters).count() != len(filters["id__in"]): + raise ValidationError(_("All the issues must be from the same project")) + + return attrs diff --git a/taiga/projects/tasks/services.py b/taiga/projects/tasks/services.py index e23a8c22..cea16a42 100644 --- a/taiga/projects/tasks/services.py +++ b/taiga/projects/tasks/services.py @@ -120,7 +120,6 @@ def update_tasks_milestone_in_bulk(bulk_data: list, milestone: object): [{'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: