[backport] Fix incorrect handling of userstory rolepoints update process.

The current implementation allows duplicate points values in one project,
and because of it, unexpected MultipleObjectsReturned can be raised with
previous update_role_points code. The new one fixes this.

Additionally, in some circumstances, the project does not have any points
with None as value, that causes also unexpected errors. The new
implementation fixes it creating a points instance with None as value
if it not exists.

Conflicts:
	tests/integration/test_userstories.py
remotes/origin/enhancement/email-actions
Andrey Antukh 2014-10-15 21:25:58 +02:00
parent fa05bf8c74
commit ae5ca20a76
2 changed files with 61 additions and 11 deletions

View File

@ -220,22 +220,27 @@ class Project(ProjectDefaults, TaggedMixin, models.Model):
if roles.count() == 0:
return
# Get point instance that represent a null/undefined
try:
null_points_value = self.points.get(value=None)
except Points.DoesNotExist:
null_points_value = None
# Iter over all project user stories and create
# role point instance for new created roles.
if user_stories is None:
user_stories = self.user_stories.all()
for story in user_stories:
story_related_roles = Role.objects.filter(role_points__in=story.role_points.all())\
.distinct()
new_roles = roles.exclude(id__in=story_related_roles)
new_rolepoints = [RolePoints(role=role, user_story=story, points=null_points_value)
# Get point instance that represent a null/undefined
# The current model allows dulplicate values. Because
# of it, we should get all poins with None as value
# and use the first one.
# In case of that not exists, creates one for avoid
# unxpected errors.
none_points = list(self.points.filter(value=None))
if none_points:
null_points_value = none_points[0]
else:
null_points_value = Points.objects.create(name="?", value=None, project=self)
for us in user_stories:
usroles = Role.objects.filter(role_points__in=us.role_points.all()).distinct()
new_roles = roles.exclude(id__in=usroles)
new_rolepoints = [RolePoints(role=role, user_story=us, points=null_points_value)
for role in new_roles]
RolePoints.objects.bulk_create(new_rolepoints)

View File

@ -155,3 +155,48 @@ def test_update_userstory_points(client):
assert rp == [(role1.pk, points3.pk), (role2.pk, points1.pk)]
def test_update_userstory_rolepoints_on_add_new_role(client):
# This test is explicitly without assertions. It simple should
# works without raising any exception.
user1 = f.UserFactory.create()
user2 = f.UserFactory.create()
project = f.ProjectFactory.create(owner=user1)
role1 = f.RoleFactory.create(project=project)
member1 = f.MembershipFactory.create(project=project, user=user1, role=role1)
points1 = f.PointsFactory.create(project=project, value=2)
us = f.UserStoryFactory.create(project=project, owner=user1)
# url = reverse("userstories-detail", args=[us.pk])
# client.login(user1)
role2 = f.RoleFactory.create(project=project, computable=True)
member2 = f.MembershipFactory.create(project=project, user=user2, role=role2)
us.save()
def test_archived_filter(client):
user = f.UserFactory.create()
project = f.ProjectFactory.create(owner=user)
f.MembershipFactory.create(project=project, user=user)
f.UserStoryFactory.create(project=project)
f.UserStoryFactory.create(is_archived=True, project=project)
client.login(user)
url = reverse("userstories-list")
data = {}
response = client.get(url, data)
assert len(json.loads(response.content)) == 2
data = {"is_archived": 0}
response = client.get(url, data)
assert len(json.loads(response.content)) == 1
data = {"is_archived": 1}
response = client.get(url, data)
assert len(json.loads(response.content)) == 1