US#1913: CSV Reports

remotes/origin/enhancement/email-actions
Jesús Espino 2015-02-19 16:51:36 +01:00 committed by David Barragán Merino
parent d984557449
commit 66e6512245
21 changed files with 443 additions and 4 deletions

View File

@ -5,6 +5,7 @@
### Features ### Features
- Added custom fields per project for user stories, tasks and issues. - Added custom fields per project for user stories, tasks and issues.
- Support of export to CSV user stories, tasks and issues.
- Allow public projects. - Allow public projects.
### Misc ### Misc

View File

@ -87,6 +87,33 @@ class ProjectViewSet(ModelCrudViewSet):
self.check_permissions(request, "stats", project) self.check_permissions(request, "stats", project)
return response.Ok(services.get_stats_for_project(project)) return response.Ok(services.get_stats_for_project(project))
def _regenerate_csv_uuid(self, project, field):
uuid_value = uuid.uuid4().hex
setattr(project, field, uuid_value)
project.save()
return uuid_value
@detail_route(methods=["POST"])
def regenerate_userstories_csv_uuid(self, request, pk=None):
project = self.get_object()
self.check_permissions(request, "regenerate_userstories_csv_uuid", project)
data = {"uuid": self._regenerate_csv_uuid(project, "userstories_csv_uuid")}
return response.Ok(data)
@detail_route(methods=["POST"])
def regenerate_issues_csv_uuid(self, request, pk=None):
project = self.get_object()
self.check_permissions(request, "regenerate_issues_csv_uuid", project)
data = {"uuid": self._regenerate_csv_uuid(project, "issues_csv_uuid")}
return response.Ok(data)
@detail_route(methods=["POST"])
def regenerate_tasks_csv_uuid(self, request, pk=None):
project = self.get_object()
self.check_permissions(request, "regenerate_tasks_csv_uuid", project)
data = {"uuid": self._regenerate_csv_uuid(project, "tasks_csv_uuid")}
return response.Ok(data)
@detail_route(methods=["GET"]) @detail_route(methods=["GET"])
def member_stats(self, request, pk=None): def member_stats(self, request, pk=None):
project = self.get_object() project = self.get_object()

View File

@ -16,7 +16,7 @@
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.db.models import Q from django.db.models import Q
from django.http import Http404 from django.http import Http404, HttpResponse
from taiga.base import filters from taiga.base import filters
from taiga.base import exceptions as exc from taiga.base import exceptions as exc
@ -24,7 +24,6 @@ from taiga.base import response
from taiga.base.decorators import detail_route, list_route from taiga.base.decorators import detail_route, list_route
from taiga.base.api import ModelCrudViewSet, ModelListViewSet from taiga.base.api import ModelCrudViewSet, ModelListViewSet
from taiga.base.api.utils import get_object_or_404 from taiga.base.api.utils import get_object_or_404
from taiga.base import tags
from taiga.users.models import User from taiga.users.models import User
@ -163,6 +162,19 @@ class IssueViewSet(OCCResourceMixin, HistoryResourceMixin, WatchedResourceMixin,
issue = get_object_or_404(models.Issue, ref=ref, project_id=project_id) issue = get_object_or_404(models.Issue, ref=ref, project_id=project_id)
return self.retrieve(request, pk=issue.pk) return self.retrieve(request, pk=issue.pk)
@list_route(methods=["GET"])
def csv(self, request):
uuid = request.QUERY_PARAMS.get("uuid", None)
if uuid is None:
return response.NotFound()
project = get_object_or_404(Project, issues_csv_uuid=uuid)
queryset = project.issues.all().order_by('ref')
data = services.issues_to_csv(queryset)
csv_response = HttpResponse(data.getvalue(), content_type='application/csv')
csv_response['Content-Disposition'] = 'attachment; filename="issues.csv"'
return csv_response
@list_route(methods=["POST"]) @list_route(methods=["POST"])
def bulk_create(self, request, **kwargs): def bulk_create(self, request, **kwargs):
serializer = serializers.IssuesBulkSerializer(data=request.DATA) serializer = serializers.IssuesBulkSerializer(data=request.DATA)

View File

@ -28,6 +28,7 @@ class IssuePermission(TaigaResourcePermission):
update_perms = HasProjectPerm('modify_issue') update_perms = HasProjectPerm('modify_issue')
destroy_perms = HasProjectPerm('delete_issue') destroy_perms = HasProjectPerm('delete_issue')
list_perms = AllowAny() list_perms = AllowAny()
csv_perms = AllowAny()
upvote_perms = IsAuthenticated() & HasProjectPerm('vote_issues') upvote_perms = IsAuthenticated() & HasProjectPerm('vote_issues')
downvote_perms = IsAuthenticated() & HasProjectPerm('vote_issues') downvote_perms = IsAuthenticated() & HasProjectPerm('vote_issues')
bulk_create_perms = HasProjectPerm('add_issue') bulk_create_perms = HasProjectPerm('add_issue')

View File

@ -14,6 +14,9 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import io
import csv
from taiga.base.utils import db, text from taiga.base.utils import db, text
from . import models from . import models
@ -58,3 +61,33 @@ def update_issues_order_in_bulk(bulk_data):
issue_ids.append(issue_id) issue_ids.append(issue_id)
new_order_values.append({"order": new_order_value}) new_order_values.append({"order": new_order_value})
db.update_in_bulk_with_ids(issue_ids, new_order_values, model=models.Issue) db.update_in_bulk_with_ids(issue_ids, new_order_values, model=models.Issue)
def issues_to_csv(queryset):
csv_data = io.StringIO()
fieldnames = ["ref", "subject", "description", "milestone", "owner",
"owner_full_name", "assigned_to", "assigned_to_full_name",
"status", "severity", "priority", "type", "is_closed",
"attachments", "external_reference"]
writer = csv.DictWriter(csv_data, fieldnames=fieldnames)
writer.writeheader()
for issue in queryset:
writer.writerow({
"ref": issue.ref,
"subject": issue.subject,
"description": issue.description,
"milestone": issue.milestone.name if issue.milestone else None,
"owner": issue.owner.username,
"owner_full_name": issue.owner.get_full_name(),
"assigned_to": issue.assigned_to.username if issue.assigned_to else None,
"assigned_to_full_name": issue.assigned_to.get_full_name() if issue.assigned_to else None,
"status": issue.status.name,
"severity": issue.severity.name,
"priority": issue.priority.name,
"type": issue.type.name,
"is_closed": issue.is_closed,
"attachments": issue.attachments.count(),
"external_reference": issue.external_reference,
})
return csv_data

View File

@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('projects', '0016_fix_json_field_not_null'),
]
operations = [
migrations.AddField(
model_name='project',
name='issues_csv_uuid',
field=models.CharField(editable=False, max_length=32, default=None, null=True, db_index=True, blank=True),
preserve_default=True,
),
migrations.AddField(
model_name='project',
name='tasks_csv_uuid',
field=models.CharField(editable=False, max_length=32, default=None, null=True, db_index=True, blank=True),
preserve_default=True,
),
migrations.AddField(
model_name='project',
name='userstories_csv_uuid',
field=models.CharField(editable=False, max_length=32, default=None, null=True, db_index=True, blank=True),
preserve_default=True,
),
]

View File

@ -15,6 +15,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import itertools import itertools
import uuid
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models from django.db import models
@ -163,6 +165,15 @@ class Project(ProjectDefaults, TaggedMixin, models.Model):
is_private = models.BooleanField(default=True, null=False, blank=True, is_private = models.BooleanField(default=True, null=False, blank=True,
verbose_name=_("is private")) verbose_name=_("is private"))
userstories_csv_uuid = models.CharField(max_length=32, editable=False,
null=True, blank=True,
default=None, db_index=True)
tasks_csv_uuid = models.CharField(max_length=32, editable=False, null=True,
blank=True, default=None, db_index=True)
issues_csv_uuid = models.CharField(max_length=32, editable=False,
null=True, blank=True, default=None,
db_index=True)
tags_colors = TextArrayField(dimension=2, null=False, blank=True, verbose_name=_("tags colors"), default=[]) tags_colors = TextArrayField(dimension=2, null=False, blank=True, verbose_name=_("tags colors"), default=[])
_importing = None _importing = None
@ -181,6 +192,15 @@ class Project(ProjectDefaults, TaggedMixin, models.Model):
return "<Project {0}>".format(self.id) return "<Project {0}>".format(self.id)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if not self._importing and not self.userstories_csv_uuid:
self.userstories_csv_uuid = uuid.uuid4().hex
if not self._importing and not self.tasks_csv_uuid:
self.tasks_csv_uuid = uuid.uuid4().hex
if not self._importing and not self.issues_csv_uuid:
self.issues_csv_uuid = uuid.uuid4().hex
if not self._importing or not self.modified_date: if not self._importing or not self.modified_date:
self.modified_date = timezone.now() self.modified_date = timezone.now()

View File

@ -54,6 +54,9 @@ class ProjectPermission(TaigaResourcePermission):
list_perms = AllowAny() list_perms = AllowAny()
stats_perms = HasProjectPerm('view_project') stats_perms = HasProjectPerm('view_project')
member_stats_perms = HasProjectPerm('view_project') member_stats_perms = HasProjectPerm('view_project')
regenerate_userstories_csv_uuid_perms = IsProjectOwner()
regenerate_issues_csv_uuid_perms = IsProjectOwner()
regenerate_tasks_csv_uuid_perms = IsProjectOwner()
star_perms = IsAuthenticated() star_perms = IsAuthenticated()
unstar_perms = IsAuthenticated() unstar_perms = IsAuthenticated()
issues_stats_perms = HasProjectPerm('view_project') issues_stats_perms = HasProjectPerm('view_project')

View File

@ -22,6 +22,7 @@ from taiga.base import exceptions as exc
from taiga.base.decorators import list_route from taiga.base.decorators import list_route
from taiga.base.api import ModelCrudViewSet from taiga.base.api import ModelCrudViewSet
from taiga.projects.models import Project from taiga.projects.models import Project
from django.http import HttpResponse
from taiga.projects.notifications.mixins import WatchedResourceMixin from taiga.projects.notifications.mixins import WatchedResourceMixin
from taiga.projects.history.mixins import HistoryResourceMixin from taiga.projects.history.mixins import HistoryResourceMixin
@ -71,6 +72,19 @@ class TaskViewSet(OCCResourceMixin, HistoryResourceMixin, WatchedResourceMixin,
task = get_object_or_404(models.Task, ref=ref, project_id=project_id) task = get_object_or_404(models.Task, ref=ref, project_id=project_id)
return self.retrieve(request, pk=task.pk) return self.retrieve(request, pk=task.pk)
@list_route(methods=["GET"])
def csv(self, request):
uuid = request.QUERY_PARAMS.get("uuid", None)
if uuid is None:
return response.NotFound()
project = get_object_or_404(Project, tasks_csv_uuid=uuid)
queryset = project.tasks.all().order_by('ref')
data = services.tasks_to_csv(queryset)
csv_response = HttpResponse(data.getvalue(), content_type='application/csv')
csv_response['Content-Disposition'] = 'attachment; filename="tasks.csv"'
return csv_response
@list_route(methods=["POST"]) @list_route(methods=["POST"])
def bulk_create(self, request, **kwargs): def bulk_create(self, request, **kwargs):
serializer = serializers.TasksBulkSerializer(data=request.DATA) serializer = serializers.TasksBulkSerializer(data=request.DATA)
@ -98,8 +112,8 @@ class TaskViewSet(OCCResourceMixin, HistoryResourceMixin, WatchedResourceMixin,
self.check_permissions(request, "bulk_update_order", project) self.check_permissions(request, "bulk_update_order", project)
services.update_tasks_order_in_bulk(data["bulk_tasks"], services.update_tasks_order_in_bulk(data["bulk_tasks"],
project=project, project=project,
field=order_field) field=order_field)
services.snapshot_tasks_in_bulk(data["bulk_tasks"], request.user) services.snapshot_tasks_in_bulk(data["bulk_tasks"], request.user)
return response.NoContent() return response.NoContent()

View File

@ -26,5 +26,6 @@ class TaskPermission(TaigaResourcePermission):
update_perms = HasProjectPerm('modify_task') update_perms = HasProjectPerm('modify_task')
destroy_perms = HasProjectPerm('delete_task') destroy_perms = HasProjectPerm('delete_task')
list_perms = AllowAny() list_perms = AllowAny()
csv_perms = AllowAny()
bulk_create_perms = HasProjectPerm('add_task') bulk_create_perms = HasProjectPerm('add_task')
bulk_update_order_perms = HasProjectPerm('modify_task') bulk_update_order_perms = HasProjectPerm('modify_task')

View File

@ -14,6 +14,9 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import io
import csv
from taiga.base.utils import db, text from taiga.base.utils import db, text
from taiga.projects.history.services import take_snapshot from taiga.projects.history.services import take_snapshot
from taiga.events import events from taiga.events import events
@ -75,3 +78,34 @@ def snapshot_tasks_in_bulk(bulk_data, user):
take_snapshot(task, user=user) take_snapshot(task, user=user)
except models.UserStory.DoesNotExist: except models.UserStory.DoesNotExist:
pass pass
def tasks_to_csv(queryset):
csv_data = io.StringIO()
fieldnames = ["ref", "subject", "description", "user_story", "milestone", "owner",
"owner_full_name", "assigned_to", "assigned_to_full_name",
"status", "is_iocaine", "is_closed", "us_order",
"taskboard_order", "attachments", "external_reference"]
writer = csv.DictWriter(csv_data, fieldnames=fieldnames)
writer.writeheader()
for task in queryset:
writer.writerow({
"ref": task.ref,
"subject": task.subject,
"description": task.description,
"user_story": task.user_story.ref if task.user_story else None,
"milestone": task.milestone.name if task.milestone else None,
"owner": task.owner.username,
"owner_full_name": task.owner.get_full_name(),
"assigned_to": task.assigned_to.username if task.assigned_to else None,
"assigned_to_full_name": task.assigned_to.get_full_name() if task.assigned_to else None,
"status": task.status.name,
"is_iocaine": task.is_iocaine,
"is_closed": task.status.is_closed,
"us_order": task.us_order,
"taskboard_order": task.taskboard_order,
"attachments": task.attachments.count(),
"external_reference": task.external_reference,
})
return csv_data

View File

@ -22,6 +22,7 @@ from django.apps import apps
from django.db import transaction from django.db import transaction
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpResponse
from taiga.base import filters from taiga.base import filters
from taiga.base import exceptions as exc from taiga.base import exceptions as exc
@ -102,6 +103,19 @@ class UserStoryViewSet(OCCResourceMixin, HistoryResourceMixin, WatchedResourceMi
userstory = get_object_or_404(models.UserStory, ref=ref, project_id=project_id) userstory = get_object_or_404(models.UserStory, ref=ref, project_id=project_id)
return self.retrieve(request, pk=userstory.pk) return self.retrieve(request, pk=userstory.pk)
@list_route(methods=["GET"])
def csv(self, request):
uuid = request.QUERY_PARAMS.get("uuid", None)
if uuid is None:
return response.NotFound()
project = get_object_or_404(Project, userstories_csv_uuid=uuid)
queryset = project.user_stories.all().order_by('ref')
data = services.userstories_to_csv(project, queryset)
csv_response = HttpResponse(data.getvalue(), content_type='application/csv')
csv_response['Content-Disposition'] = 'attachment; filename="userstories.csv"'
return csv_response
@list_route(methods=["POST"]) @list_route(methods=["POST"])
def bulk_create(self, request, **kwargs): def bulk_create(self, request, **kwargs):
serializer = serializers.UserStoriesBulkSerializer(data=request.DATA) serializer = serializers.UserStoriesBulkSerializer(data=request.DATA)

View File

@ -25,5 +25,6 @@ class UserStoryPermission(TaigaResourcePermission):
update_perms = HasProjectPerm('modify_us') update_perms = HasProjectPerm('modify_us')
destroy_perms = HasProjectPerm('delete_us') destroy_perms = HasProjectPerm('delete_us')
list_perms = AllowAny() list_perms = AllowAny()
csv_perms = AllowAny()
bulk_create_perms = IsAuthenticated() & (HasProjectPerm('add_us_to_project') | HasProjectPerm('add_us')) bulk_create_perms = IsAuthenticated() & (HasProjectPerm('add_us_to_project') | HasProjectPerm('add_us'))
bulk_update_order_perms = HasProjectPerm('modify_us') bulk_update_order_perms = HasProjectPerm('modify_us')

View File

@ -14,6 +14,9 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import csv
import io
from django.utils import timezone from django.utils import timezone
from taiga.base.utils import db, text from taiga.base.utils import db, text
@ -104,3 +107,57 @@ def open_userstory(us):
us.is_closed = False us.is_closed = False
us.finish_date = None us.finish_date = None
us.save(update_fields=["is_closed", "finish_date"]) us.save(update_fields=["is_closed", "finish_date"])
def userstories_to_csv(project,queryset):
csv_data = io.StringIO()
fieldnames = ["ref", "subject", "description", "milestone", "owner",
"owner_full_name", "assigned_to", "assigned_to_full_name",
"status", "is_closed"]
for role in project.roles.filter(computable=True).order_by('name'):
fieldnames.append("{}-points".format(role.slug))
fieldnames.append("total-points")
fieldnames += ["backlog_order", "sprint_order", "kanban_order",
"created_date", "modified_date", "finish_date",
"client_requirement", "team_requirement", "attachments",
"generated_from_issue", "external_reference", "tasks"]
writer = csv.DictWriter(csv_data, fieldnames=fieldnames)
writer.writeheader()
for us in queryset:
row = {
"ref": us.ref,
"subject": us.subject,
"description": us.description,
"milestone": us.milestone.name if us.milestone else None,
"owner": us.owner.username,
"owner_full_name": us.owner.get_full_name(),
"assigned_to": us.assigned_to.username if us.assigned_to else None,
"assigned_to_full_name": us.assigned_to.get_full_name() if us.assigned_to else None,
"status": us.status.name,
"is_closed": us.is_closed,
"backlog_order": us.backlog_order,
"sprint_order": us.sprint_order,
"kanban_order": us.kanban_order,
"created_date": us.created_date,
"modified_date": us.modified_date,
"finish_date": us.finish_date,
"client_requirement": us.client_requirement,
"team_requirement": us.team_requirement,
"attachments": us.attachments.count(),
"generated_from_issue": us.generated_from_issue.ref if us.generated_from_issue else None,
"external_reference": us.external_reference,
"tasks": ",".join([str(task.ref) for task in us.tasks.all()]),
}
for role in us.project.roles.filter(computable=True).order_by('name'):
if us.role_points.filter(role_id=role.id).count() == 1:
row["{}-points".format(role.slug)] = us.role_points.get(role_id=role.id).points.value
else:
row["{}-points".format(role.slug)] = 0
row['total-points'] = us.get_total_points()
writer.writerow(row)
return csv_data

View File

@ -437,3 +437,27 @@ def test_issue_voters_retrieve(client, data):
results = helper_test_http_method(client, 'get', private_url2, None, users) results = helper_test_http_method(client, 'get', private_url2, None, users)
assert results == [401, 403, 403, 200, 200] assert results == [401, 403, 403, 200, 200]
def test_issues_csv(client, data):
url = reverse('issues-csv')
csv_public_uuid = data.public_project.issues_csv_uuid
csv_private1_uuid = data.private_project1.issues_csv_uuid
csv_private2_uuid = data.private_project1.issues_csv_uuid
users = [
None,
data.registered_user,
data.project_member_without_perms,
data.project_member_with_perms,
data.project_owner
]
results = helper_test_http_method(client, 'get', "{}?uuid={}".format(url, csv_public_uuid), None, users)
assert results == [200, 200, 200, 200, 200]
results = helper_test_http_method(client, 'get', "{}?uuid={}".format(url, csv_private1_uuid), None, users)
assert results == [200, 200, 200, 200, 200]
results = helper_test_http_method(client, 'get', "{}?uuid={}".format(url, csv_private2_uuid), None, users)
assert results == [200, 200, 200, 200, 200]

View File

@ -369,3 +369,66 @@ def test_invitations_retrieve(client, data):
] ]
results = helper_test_http_method(client, 'get', url, None, users) results = helper_test_http_method(client, 'get', url, None, users)
assert results == [200, 200, 200, 200] assert results == [200, 200, 200, 200]
def test_regenerate_userstories_csv_uuid(client, data):
public_url = reverse('projects-regenerate-userstories-csv-uuid', kwargs={"pk": data.public_project.pk})
private1_url = reverse('projects-regenerate-userstories-csv-uuid', kwargs={"pk": data.private_project1.pk})
private2_url = reverse('projects-regenerate-userstories-csv-uuid', kwargs={"pk": data.private_project2.pk})
users = [
None,
data.registered_user,
data.project_member_with_perms,
data.project_owner
]
results = helper_test_http_method(client, 'post', public_url, None, users)
assert results == [401, 403, 403, 200]
results = helper_test_http_method(client, 'post', private1_url, None, users)
assert results == [401, 403, 403, 200]
results = helper_test_http_method(client, 'post', private2_url, None, users)
assert results == [404, 404, 403, 200]
def test_regenerate_tasks_csv_uuid(client, data):
public_url = reverse('projects-regenerate-tasks-csv-uuid', kwargs={"pk": data.public_project.pk})
private1_url = reverse('projects-regenerate-tasks-csv-uuid', kwargs={"pk": data.private_project1.pk})
private2_url = reverse('projects-regenerate-tasks-csv-uuid', kwargs={"pk": data.private_project2.pk})
users = [
None,
data.registered_user,
data.project_member_with_perms,
data.project_owner
]
results = helper_test_http_method(client, 'post', public_url, None, users)
assert results == [401, 403, 403, 200]
results = helper_test_http_method(client, 'post', private1_url, None, users)
assert results == [401, 403, 403, 200]
results = helper_test_http_method(client, 'post', private2_url, None, users)
assert results == [404, 404, 403, 200]
def test_regenerate_issues_csv_uuid(client, data):
public_url = reverse('projects-regenerate-issues-csv-uuid', kwargs={"pk": data.public_project.pk})
private1_url = reverse('projects-regenerate-issues-csv-uuid', kwargs={"pk": data.private_project1.pk})
private2_url = reverse('projects-regenerate-issues-csv-uuid', kwargs={"pk": data.private_project2.pk})
users = [
None,
data.registered_user,
data.project_member_with_perms,
data.project_owner
]
results = helper_test_http_method(client, 'post', public_url, None, users)
assert results == [401, 403, 403, 200]
results = helper_test_http_method(client, 'post', private1_url, None, users)
assert results == [401, 403, 403, 200]
results = helper_test_http_method(client, 'post', private2_url, None, users)
assert results == [404, 404, 403, 200]

View File

@ -307,3 +307,27 @@ def test_task_action_bulk_create(client, data):
}) })
results = helper_test_http_method(client, 'post', url, bulk_data, users) results = helper_test_http_method(client, 'post', url, bulk_data, users)
assert results == [401, 403, 403, 200, 200] assert results == [401, 403, 403, 200, 200]
def test_tasks_csv(client, data):
url = reverse('tasks-csv')
csv_public_uuid = data.public_project.tasks_csv_uuid
csv_private1_uuid = data.private_project1.tasks_csv_uuid
csv_private2_uuid = data.private_project1.tasks_csv_uuid
users = [
None,
data.registered_user,
data.project_member_without_perms,
data.project_member_with_perms,
data.project_owner
]
results = helper_test_http_method(client, 'get', "{}?uuid={}".format(url, csv_public_uuid), None, users)
assert results == [200, 200, 200, 200, 200]
results = helper_test_http_method(client, 'get', "{}?uuid={}".format(url, csv_private1_uuid), None, users)
assert results == [200, 200, 200, 200, 200]
results = helper_test_http_method(client, 'get', "{}?uuid={}".format(url, csv_private2_uuid), None, users)
assert results == [200, 200, 200, 200, 200]

View File

@ -308,3 +308,27 @@ def test_user_story_action_bulk_update_order(client, data):
}) })
results = helper_test_http_method(client, 'post', url, post_data, users) results = helper_test_http_method(client, 'post', url, post_data, users)
assert results == [401, 403, 403, 204, 204] assert results == [401, 403, 403, 204, 204]
def test_user_stories_csv(client, data):
url = reverse('userstories-csv')
csv_public_uuid = data.public_project.userstories_csv_uuid
csv_private1_uuid = data.private_project1.userstories_csv_uuid
csv_private2_uuid = data.private_project1.userstories_csv_uuid
users = [
None,
data.registered_user,
data.project_member_without_perms,
data.project_member_with_perms,
data.project_owner
]
results = helper_test_http_method(client, 'get', "{}?uuid={}".format(url, csv_public_uuid), None, users)
assert results == [200, 200, 200, 200, 200]
results = helper_test_http_method(client, 'get', "{}?uuid={}".format(url, csv_private1_uuid), None, users)
assert results == [200, 200, 200, 200, 200]
results = helper_test_http_method(client, 'get', "{}?uuid={}".format(url, csv_private2_uuid), None, users)
assert results == [200, 200, 200, 200, 200]

View File

@ -161,3 +161,21 @@ def test_api_filter_by_text_6(client):
assert response.status_code == 200 assert response.status_code == 200
assert number_of_issues == 1 assert number_of_issues == 1
def test_get_invalid_csv(client):
url = reverse("issues-csv")
response = client.get(url)
assert response.status_code == 404
response = client.get("{}?uuid={}".format(url, "not-valid-uuid"))
assert response.status_code == 404
def test_get_valid_csv(client):
url = reverse("issues-csv")
project = f.ProjectFactory.create()
response = client.get("{}?uuid={}".format(url, project.issues_csv_uuid))
assert response.status_code == 200

View File

@ -110,3 +110,21 @@ def test_api_update_order_in_bulk(client):
assert response1.status_code == 204, response1.data assert response1.status_code == 204, response1.data
assert response2.status_code == 204, response2.data assert response2.status_code == 204, response2.data
def test_get_invalid_csv(client):
url = reverse("tasks-csv")
response = client.get(url)
assert response.status_code == 404
response = client.get("{}?uuid={}".format(url, "not-valid-uuid"))
assert response.status_code == 404
def test_get_valid_csv(client):
url = reverse("tasks-csv")
project = f.ProjectFactory.create()
response = client.get("{}?uuid={}".format(url, project.tasks_csv_uuid))
assert response.status_code == 200

View File

@ -241,3 +241,21 @@ def test_get_total_points(client):
f.RolePointsFactory.create(user_story=us_mixed, role=role2, points=points2) f.RolePointsFactory.create(user_story=us_mixed, role=role2, points=points2)
assert us_mixed.get_total_points() == 1.0 assert us_mixed.get_total_points() == 1.0
def test_get_invalid_csv(client):
url = reverse("userstories-csv")
response = client.get(url)
assert response.status_code == 404
response = client.get("{}?uuid={}".format(url, "not-valid-uuid"))
assert response.status_code == 404
def test_get_valid_csv(client):
url = reverse("userstories-csv")
project = f.ProjectFactory.create()
response = client.get("{}?uuid={}".format(url, project.userstories_csv_uuid))
assert response.status_code == 200