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.
remotes/origin/enhancement/email-actions
Andrey Antukh 2014-10-15 21:25:58 +02:00
parent 154e13cc79
commit 4056d5214b
2 changed files with 39 additions and 11 deletions

View File

@ -220,22 +220,27 @@ class Project(ProjectDefaults, TaggedMixin, models.Model):
if roles.count() == 0: if roles.count() == 0:
return 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 # Iter over all project user stories and create
# role point instance for new created roles. # role point instance for new created roles.
if user_stories is None: if user_stories is None:
user_stories = self.user_stories.all() user_stories = self.user_stories.all()
for story in user_stories: # Get point instance that represent a null/undefined
story_related_roles = Role.objects.filter(role_points__in=story.role_points.all())\ # The current model allows dulplicate values. Because
.distinct() # of it, we should get all poins with None as value
new_roles = roles.exclude(id__in=story_related_roles) # and use the first one.
new_rolepoints = [RolePoints(role=role, user_story=story, points=null_points_value) # 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] for role in new_roles]
RolePoints.objects.bulk_create(new_rolepoints) RolePoints.objects.bulk_create(new_rolepoints)

View File

@ -155,6 +155,29 @@ def test_update_userstory_points(client):
assert rp == [(role1.pk, points3.pk), (role2.pk, points1.pk)] 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): def test_archived_filter(client):
user = f.UserFactory.create() user = f.UserFactory.create()
project = f.ProjectFactory.create(owner=user) project = f.ProjectFactory.create(owner=user)