Add csv for Epics
parent
79eeccf379
commit
0a5ba7b3ae
|
@ -33,6 +33,9 @@ urls = {
|
|||
|
||||
"project": "/project/{0}", # project.slug
|
||||
|
||||
"epics": "/project/{0}/epics/", # project.slug
|
||||
"epic": "/project/{0}/epic/{1}", # project.slug, epic.ref
|
||||
|
||||
"backlog": "/project/{0}/backlog/", # project.slug
|
||||
"taskboard": "/project/{0}/taskboard/{1}", # project.slug, milestone.slug
|
||||
"kanban": "/project/{0}/kanban/", # project.slug
|
||||
|
|
|
@ -243,6 +243,20 @@ class ProjectViewSet(LikedResourceMixin, HistoryResourceMixin,
|
|||
services.remove_user_from_project(request.user, project)
|
||||
return response.Ok()
|
||||
|
||||
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_epics_csv_uuid(self, request, pk=None):
|
||||
project = self.get_object()
|
||||
self.check_permissions(request, "regenerate_epics_csv_uuid", project)
|
||||
self.pre_conditions_on_save(project)
|
||||
data = {"uuid": self._regenerate_csv_uuid(project, "epics_csv_uuid")}
|
||||
return response.Ok(data)
|
||||
|
||||
@detail_route(methods=["POST"])
|
||||
def regenerate_userstories_csv_uuid(self, request, pk=None):
|
||||
project = self.get_object()
|
||||
|
@ -251,14 +265,6 @@ class ProjectViewSet(LikedResourceMixin, HistoryResourceMixin,
|
|||
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)
|
||||
self.pre_conditions_on_save(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()
|
||||
|
@ -267,6 +273,14 @@ class ProjectViewSet(LikedResourceMixin, HistoryResourceMixin,
|
|||
data = {"uuid": self._regenerate_csv_uuid(project, "tasks_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)
|
||||
self.pre_conditions_on_save(project)
|
||||
data = {"uuid": self._regenerate_csv_uuid(project, "issues_csv_uuid")}
|
||||
return response.Ok(data)
|
||||
|
||||
@list_route(methods=["GET"])
|
||||
def by_slug(self, request, *args, **kwargs):
|
||||
slug = request.QUERY_PARAMS.get("slug", None)
|
||||
|
@ -293,12 +307,6 @@ class ProjectViewSet(LikedResourceMixin, HistoryResourceMixin,
|
|||
self.check_permissions(request, "stats", 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=["GET"])
|
||||
def member_stats(self, request, pk=None):
|
||||
project = self.get_object()
|
||||
|
|
|
@ -154,18 +154,18 @@ class EpicViewSet(OCCResourceMixin, VotedResourceMixin, HistoryResourceMixin,
|
|||
|
||||
return self.retrieve(request, **retrieve_kwargs)
|
||||
|
||||
#@list_route(methods=["GET"])
|
||||
#def csv(self, request):
|
||||
# uuid = request.QUERY_PARAMS.get("uuid", None)
|
||||
# if uuid is None:
|
||||
# return response.NotFound()
|
||||
@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, epics_csv_uuid=uuid)
|
||||
# queryset = project.epics.all().order_by('ref')
|
||||
# data = services.epics_to_csv(project, queryset)
|
||||
# csv_response = HttpResponse(data.getvalue(), content_type='application/csv; charset=utf-8')
|
||||
# csv_response['Content-Disposition'] = 'attachment; filename="epics.csv"'
|
||||
# return csv_response
|
||||
project = get_object_or_404(Project, epics_csv_uuid=uuid)
|
||||
queryset = project.epics.all().order_by('ref')
|
||||
data = services.epics_to_csv(project, queryset)
|
||||
csv_response = HttpResponse(data.getvalue(), content_type='application/csv; charset=utf-8')
|
||||
csv_response['Content-Disposition'] = 'attachment; filename="epics.csv"'
|
||||
return csv_response
|
||||
|
||||
@list_route(methods=["POST"])
|
||||
def bulk_create(self, request, **kwargs):
|
||||
|
|
|
@ -105,66 +105,57 @@ def snapshot_epics_in_bulk(bulk_data, user):
|
|||
#####################################################
|
||||
# CSV
|
||||
#####################################################
|
||||
#
|
||||
#def epics_to_csv(project, queryset):
|
||||
# csv_data = io.StringIO()
|
||||
# fieldnames = ["ref", "subject", "description", "user_story", "sprint", "sprint_estimated_start",
|
||||
# "sprint_estimated_finish", "owner", "owner_full_name", "assigned_to",
|
||||
# "assigned_to_full_name", "status", "is_iocaine", "is_closed", "us_order",
|
||||
# "epicboard_order", "attachments", "external_reference", "tags", "watchers", "voters",
|
||||
# "created_date", "modified_date", "finished_date"]
|
||||
#
|
||||
# custom_attrs = project.epiccustomattributes.all()
|
||||
# for custom_attr in custom_attrs:
|
||||
# fieldnames.append(custom_attr.name)
|
||||
#
|
||||
# queryset = queryset.prefetch_related("attachments",
|
||||
# "custom_attributes_values")
|
||||
# queryset = queryset.select_related("milestone",
|
||||
# "owner",
|
||||
# "assigned_to",
|
||||
# "status",
|
||||
# "project")
|
||||
#
|
||||
# queryset = attach_total_voters_to_queryset(queryset)
|
||||
# queryset = attach_watchers_to_queryset(queryset)
|
||||
#
|
||||
# writer = csv.DictWriter(csv_data, fieldnames=fieldnames)
|
||||
# writer.writeheader()
|
||||
# for epic in queryset:
|
||||
# epic_data = {
|
||||
# "ref": epic.ref,
|
||||
# "subject": epic.subject,
|
||||
# "description": epic.description,
|
||||
# "user_story": epic.user_story.ref if epic.user_story else None,
|
||||
# "sprint": epic.milestone.name if epic.milestone else None,
|
||||
# "sprint_estimated_start": epic.milestone.estimated_start if epic.milestone else None,
|
||||
# "sprint_estimated_finish": epic.milestone.estimated_finish if epic.milestone else None,
|
||||
# "owner": epic.owner.username if epic.owner else None,
|
||||
# "owner_full_name": epic.owner.get_full_name() if epic.owner else None,
|
||||
# "assigned_to": epic.assigned_to.username if epic.assigned_to else None,
|
||||
# "assigned_to_full_name": epic.assigned_to.get_full_name() if epic.assigned_to else None,
|
||||
# "status": epic.status.name if epic.status else None,
|
||||
# "is_iocaine": epic.is_iocaine,
|
||||
# "is_closed": epic.status is not None and epic.status.is_closed,
|
||||
# "us_order": epic.us_order,
|
||||
# "epicboard_order": epic.epicboard_order,
|
||||
# "attachments": epic.attachments.count(),
|
||||
# "external_reference": epic.external_reference,
|
||||
# "tags": ",".join(epic.tags or []),
|
||||
# "watchers": epic.watchers,
|
||||
# "voters": epic.total_voters,
|
||||
# "created_date": epic.created_date,
|
||||
# "modified_date": epic.modified_date,
|
||||
# "finished_date": epic.finished_date,
|
||||
# }
|
||||
# for custom_attr in custom_attrs:
|
||||
# value = epic.custom_attributes_values.attributes_values.get(str(custom_attr.id), None)
|
||||
# epic_data[custom_attr.name] = value
|
||||
#
|
||||
# writer.writerow(epic_data)
|
||||
#
|
||||
# return csv_data
|
||||
|
||||
def epics_to_csv(project, queryset):
|
||||
csv_data = io.StringIO()
|
||||
fieldnames = ["ref", "subject", "description", "owner", "owner_full_name", "assigned_to",
|
||||
"assigned_to_full_name", "status", "epics_order", "client_requirement",
|
||||
"team_requirement", "attachments", "tags", "watchers", "voters",
|
||||
"created_date", "modified_date"]
|
||||
|
||||
custom_attrs = project.epiccustomattributes.all()
|
||||
for custom_attr in custom_attrs:
|
||||
fieldnames.append(custom_attr.name)
|
||||
|
||||
queryset = queryset.prefetch_related("attachments",
|
||||
"custom_attributes_values")
|
||||
queryset = queryset.select_related("owner",
|
||||
"assigned_to",
|
||||
"status",
|
||||
"project")
|
||||
|
||||
queryset = attach_total_voters_to_queryset(queryset)
|
||||
queryset = attach_watchers_to_queryset(queryset)
|
||||
|
||||
writer = csv.DictWriter(csv_data, fieldnames=fieldnames)
|
||||
writer.writeheader()
|
||||
for epic in queryset:
|
||||
epic_data = {
|
||||
"ref": epic.ref,
|
||||
"subject": epic.subject,
|
||||
"description": epic.description,
|
||||
"owner": epic.owner.username if epic.owner else None,
|
||||
"owner_full_name": epic.owner.get_full_name() if epic.owner else None,
|
||||
"assigned_to": epic.assigned_to.username if epic.assigned_to else None,
|
||||
"assigned_to_full_name": epic.assigned_to.get_full_name() if epic.assigned_to else None,
|
||||
"status": epic.status.name if epic.status else None,
|
||||
"epics_order": epic.epics_order,
|
||||
"client_requirement": epic.client_requirement,
|
||||
"team_requirement": epic.team_requirement,
|
||||
"attachments": epic.attachments.count(),
|
||||
"tags": ",".join(epic.tags or []),
|
||||
"watchers": epic.watchers,
|
||||
"voters": epic.total_voters,
|
||||
"created_date": epic.created_date,
|
||||
"modified_date": epic.modified_date,
|
||||
}
|
||||
for custom_attr in custom_attrs:
|
||||
value = epic.custom_attributes_values.attributes_values.get(str(custom_attr.id), None)
|
||||
epic_data[custom_attr.name] = value
|
||||
|
||||
writer.writerow(epic_data)
|
||||
|
||||
return csv_data
|
||||
|
||||
|
||||
#####################################################
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.2 on 2016-07-20 17:57
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('projects', '0049_auto_20160629_1443'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='project',
|
||||
name='epics_csv_uuid',
|
||||
field=models.CharField(blank=True, db_index=True, default=None, editable=False, max_length=32, null=True),
|
||||
),
|
||||
]
|
|
@ -202,6 +202,8 @@ class Project(ProjectDefaults, TaggedMixin, TagsColorsdMixin, models.Model):
|
|||
looking_for_people_note = models.TextField(default="", null=False, blank=True,
|
||||
verbose_name=_("loking for people note"))
|
||||
|
||||
epics_csv_uuid = models.CharField(max_length=32, editable=False, null=True,
|
||||
blank=True, default=None, db_index=True)
|
||||
userstories_csv_uuid = models.CharField(max_length=32, editable=False,
|
||||
null=True, blank=True,
|
||||
default=None, db_index=True)
|
||||
|
|
|
@ -62,6 +62,7 @@ class ProjectPermission(TaigaResourcePermission):
|
|||
stats_perms = HasProjectPerm('view_project')
|
||||
member_stats_perms = HasProjectPerm('view_project')
|
||||
issues_stats_perms = HasProjectPerm('view_project')
|
||||
regenerate_epics_csv_uuid_perms = IsProjectAdmin()
|
||||
regenerate_userstories_csv_uuid_perms = IsProjectAdmin()
|
||||
regenerate_issues_csv_uuid_perms = IsProjectAdmin()
|
||||
regenerate_tasks_csv_uuid_perms = IsProjectAdmin()
|
||||
|
|
|
@ -373,9 +373,10 @@ class ProjectDetailSerializer(ProjectSerializer):
|
|||
# Admin fields
|
||||
is_private_extra_info = MethodField()
|
||||
max_memberships = MethodField()
|
||||
issues_csv_uuid = Field()
|
||||
tasks_csv_uuid = Field()
|
||||
epics_csv_uuid = Field()
|
||||
userstories_csv_uuid = Field()
|
||||
tasks_csv_uuid = Field()
|
||||
issues_csv_uuid = Field()
|
||||
transfer_token = Field()
|
||||
milestones = MethodField()
|
||||
|
||||
|
@ -404,8 +405,8 @@ class ProjectDetailSerializer(ProjectSerializer):
|
|||
ret = super().to_value(instance)
|
||||
|
||||
admin_fields = [
|
||||
"is_private_extra_info", "max_memberships", "issues_csv_uuid",
|
||||
"tasks_csv_uuid", "userstories_csv_uuid", "transfer_token"
|
||||
"epics_csv_uuid", "userstories_csv_uuid", "tasks_csv_uuid", "issues_csv_uuid",
|
||||
"is_private_extra_info", "max_memberships", "transfer_token",
|
||||
]
|
||||
|
||||
is_admin_user = False
|
||||
|
|
|
@ -59,29 +59,29 @@ def data():
|
|||
m.public_project = f.ProjectFactory(is_private=False,
|
||||
anon_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)),
|
||||
public_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)),
|
||||
owner=m.project_owner)
|
||||
#epics_csv_uuid=uuid.uuid4().hex)
|
||||
owner=m.project_owner,
|
||||
epics_csv_uuid=uuid.uuid4().hex)
|
||||
m.public_project = attach_project_extra_info(Project.objects.all()).get(id=m.public_project.id)
|
||||
|
||||
m.private_project1 = f.ProjectFactory(is_private=True,
|
||||
anon_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)),
|
||||
public_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)),
|
||||
owner=m.project_owner)
|
||||
#epics_csv_uuid=uuid.uuid4().hex)
|
||||
owner=m.project_owner,
|
||||
epics_csv_uuid=uuid.uuid4().hex)
|
||||
m.private_project1 = attach_project_extra_info(Project.objects.all()).get(id=m.private_project1.id)
|
||||
|
||||
m.private_project2 = f.ProjectFactory(is_private=True,
|
||||
anon_permissions=[],
|
||||
public_permissions=[],
|
||||
owner=m.project_owner)
|
||||
#epics_csv_uuid=uuid.uuid4().hex)
|
||||
owner=m.project_owner,
|
||||
epics_csv_uuid=uuid.uuid4().hex)
|
||||
m.private_project2 = attach_project_extra_info(Project.objects.all()).get(id=m.private_project2.id)
|
||||
|
||||
m.blocked_project = f.ProjectFactory(is_private=True,
|
||||
anon_permissions=[],
|
||||
public_permissions=[],
|
||||
owner=m.project_owner,
|
||||
#epics_csv_uuid=uuid.uuid4().hex,
|
||||
epics_csv_uuid=uuid.uuid4().hex,
|
||||
blocked_code=project_choices.BLOCKED_BY_STAFF)
|
||||
m.blocked_project = attach_project_extra_info(Project.objects.all()).get(id=m.blocked_project.id)
|
||||
|
||||
|
@ -873,29 +873,29 @@ def test_epic_watchers_retrieve(client, data):
|
|||
assert results == [401, 403, 403, 200, 200]
|
||||
|
||||
|
||||
#def test_epics_csv(client, data):
|
||||
# url = reverse('epics-csv')
|
||||
# csv_public_uuid = data.public_project.epics_csv_uuid
|
||||
# csv_private1_uuid = data.private_project1.epics_csv_uuid
|
||||
# csv_private2_uuid = data.private_project1.epics_csv_uuid
|
||||
# csv_blocked_uuid = data.blocked_project.epics_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]
|
||||
#
|
||||
# results = helper_test_http_method(client, 'get', "{}?uuid={}".format(url, csv_blocked_uuid), None, users)
|
||||
# assert results == [200, 200, 200, 200, 200]
|
||||
def test_epics_csv(client, data):
|
||||
url = reverse('epics-csv')
|
||||
csv_public_uuid = data.public_project.epics_csv_uuid
|
||||
csv_private1_uuid = data.private_project1.epics_csv_uuid
|
||||
csv_private2_uuid = data.private_project1.epics_csv_uuid
|
||||
csv_blocked_uuid = data.blocked_project.epics_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]
|
||||
|
||||
results = helper_test_http_method(client, 'get', "{}?uuid={}".format(url, csv_blocked_uuid), None, users)
|
||||
assert results == [200, 200, 200, 200, 200]
|
||||
|
|
|
@ -486,6 +486,31 @@ def test_invitations_retrieve(client, data):
|
|||
assert results == [200, 200, 200, 200]
|
||||
|
||||
|
||||
def test_regenerate_epics_csv_uuid(client, data):
|
||||
public_url = reverse('projects-regenerate-epics-csv-uuid', kwargs={"pk": data.public_project.pk})
|
||||
private1_url = reverse('projects-regenerate-epics-csv-uuid', kwargs={"pk": data.private_project1.pk})
|
||||
private2_url = reverse('projects-regenerate-epics-csv-uuid', kwargs={"pk": data.private_project2.pk})
|
||||
blocked_url = reverse('projects-regenerate-epics-csv-uuid', kwargs={"pk": data.blocked_project.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]
|
||||
|
||||
results = helper_test_http_method(client, 'post', blocked_url, None, users)
|
||||
assert results == [404, 404, 403, 451]
|
||||
|
||||
|
||||
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})
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2014-2016 Andrey Antukh <niwi@niwi.nz>
|
||||
# Copyright (C) 2014-2016 Jesús Espino <jespinog@gmail.com>
|
||||
# Copyright (C) 2014-2016 David Barragán <bameda@dbarragan.com>
|
||||
# Copyright (C) 2014-2016 Alejandro Alonso <alejandro.alonso@kaleidos.net>
|
||||
# Copyright (C) 2014-2016 Anler Hernández <hello@anler.me>
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
import uuid
|
||||
import csv
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from taiga.base.utils import json
|
||||
from taiga.projects.epics import services
|
||||
|
||||
from .. import factories as f
|
||||
|
||||
import pytest
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
||||
def test_get_invalid_csv(client):
|
||||
url = reverse("epics-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("epics-csv")
|
||||
project = f.ProjectFactory.create(epics_csv_uuid=uuid.uuid4().hex)
|
||||
|
||||
response = client.get("{}?uuid={}".format(url, project.epics_csv_uuid))
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_custom_fields_csv_generation():
|
||||
project = f.ProjectFactory.create(epics_csv_uuid=uuid.uuid4().hex)
|
||||
attr = f.EpicCustomAttributeFactory.create(project=project, name="attr1", description="desc")
|
||||
epic = f.EpicFactory.create(project=project)
|
||||
attr_values = epic.custom_attributes_values
|
||||
attr_values.attributes_values = {str(attr.id):"val1"}
|
||||
attr_values.save()
|
||||
queryset = project.epics.all()
|
||||
data = services.epics_to_csv(project, queryset)
|
||||
data.seek(0)
|
||||
reader = csv.reader(data)
|
||||
row = next(reader)
|
||||
assert row[17] == attr.name
|
||||
row = next(reader)
|
||||
assert row[17] == "val1"
|
Loading…
Reference in New Issue