Issue#2572: On status open/closed change recalc the is_closed for user stories
parent
23d7cf3cce
commit
3e8c1814d5
|
@ -53,6 +53,18 @@ def connect_projects_signals():
|
||||||
dispatch_uid="update_project_tags_when_create_or_edit_taggable_item_projects")
|
dispatch_uid="update_project_tags_when_create_or_edit_taggable_item_projects")
|
||||||
|
|
||||||
|
|
||||||
|
def connect_us_status_signals():
|
||||||
|
signals.post_save.connect(handlers.try_to_close_or_open_user_stories_when_edit_us_status,
|
||||||
|
sender=apps.get_model("projects", "UserStoryStatus"),
|
||||||
|
dispatch_uid="try_to_close_or_open_user_stories_when_edit_us_status")
|
||||||
|
|
||||||
|
|
||||||
|
def connect_task_status_signals():
|
||||||
|
signals.post_save.connect(handlers.try_to_close_or_open_user_stories_when_edit_task_status,
|
||||||
|
sender=apps.get_model("projects", "TaskStatus"),
|
||||||
|
dispatch_uid="try_to_close_or_open_user_stories_when_edit_task_status")
|
||||||
|
|
||||||
|
|
||||||
def disconnect_memberships_signals():
|
def disconnect_memberships_signals():
|
||||||
signals.pre_delete.disconnect(dispatch_uid='membership_pre_delete')
|
signals.pre_delete.disconnect(dispatch_uid='membership_pre_delete')
|
||||||
signals.post_delete.disconnect(dispatch_uid='update_watchers_on_membership_post_delete')
|
signals.post_delete.disconnect(dispatch_uid='update_watchers_on_membership_post_delete')
|
||||||
|
@ -64,6 +76,12 @@ def disconnect_projects_signals():
|
||||||
signals.pre_save.disconnect(dispatch_uid="tags_normalization_projects")
|
signals.pre_save.disconnect(dispatch_uid="tags_normalization_projects")
|
||||||
signals.pre_save.disconnect(dispatch_uid="update_project_tags_when_create_or_edit_taggable_item_projects")
|
signals.pre_save.disconnect(dispatch_uid="update_project_tags_when_create_or_edit_taggable_item_projects")
|
||||||
|
|
||||||
|
def disconnect_us_status_signals():
|
||||||
|
signals.post_save.disconnect(dispatch_uid="try_to_close_or_open_user_stories_when_edit_us_status")
|
||||||
|
|
||||||
|
def disconnect_task_status_signals():
|
||||||
|
signals.post_save.disconnect(dispatch_uid="try_to_close_or_open_user_stories_when_edit_task_status")
|
||||||
|
|
||||||
|
|
||||||
class ProjectsAppConfig(AppConfig):
|
class ProjectsAppConfig(AppConfig):
|
||||||
name = "taiga.projects"
|
name = "taiga.projects"
|
||||||
|
@ -72,3 +90,5 @@ class ProjectsAppConfig(AppConfig):
|
||||||
def ready(self):
|
def ready(self):
|
||||||
connect_memberships_signals()
|
connect_memberships_signals()
|
||||||
connect_projects_signals()
|
connect_projects_signals()
|
||||||
|
connect_us_status_signals()
|
||||||
|
connect_task_status_signals()
|
||||||
|
|
|
@ -97,3 +97,25 @@ def project_post_save(sender, instance, created, **kwargs):
|
||||||
Membership = apps.get_model("projects", "Membership")
|
Membership = apps.get_model("projects", "Membership")
|
||||||
Membership.objects.create(user=instance.owner, project=instance, role=owner_role,
|
Membership.objects.create(user=instance.owner, project=instance, role=owner_role,
|
||||||
is_owner=True, email=instance.owner.email)
|
is_owner=True, email=instance.owner.email)
|
||||||
|
|
||||||
|
|
||||||
|
def try_to_close_or_open_user_stories_when_edit_us_status(sender, instance, created, **kwargs):
|
||||||
|
from taiga.projects.userstories import services
|
||||||
|
|
||||||
|
for user_story in instance.user_stories.all():
|
||||||
|
if services.calculate_userstory_is_closed(user_story):
|
||||||
|
services.close_userstory(user_story)
|
||||||
|
else:
|
||||||
|
services.open_userstory(user_story)
|
||||||
|
|
||||||
|
|
||||||
|
def try_to_close_or_open_user_stories_when_edit_task_status(sender, instance, created, **kwargs):
|
||||||
|
from taiga.projects.userstories import services
|
||||||
|
|
||||||
|
UserStory = apps.get_model("userstories", "UserStory")
|
||||||
|
|
||||||
|
for user_story in UserStory.objects.filter(tasks__status=instance).distinct():
|
||||||
|
if services.calculate_userstory_is_closed(user_story):
|
||||||
|
services.close_userstory(user_story)
|
||||||
|
else:
|
||||||
|
services.open_userstory(user_story)
|
||||||
|
|
|
@ -45,6 +45,46 @@ def test_partially_update_project(client):
|
||||||
assert response.status_code == 400
|
assert response.status_code == 400
|
||||||
|
|
||||||
|
|
||||||
|
def test_us_status_is_closed_changed_recalc_us_is_closed(client):
|
||||||
|
us_status = f.UserStoryStatusFactory(is_closed=False)
|
||||||
|
user_story = f.UserStoryFactory.create(project=us_status.project, status=us_status)
|
||||||
|
|
||||||
|
assert user_story.is_closed is False
|
||||||
|
|
||||||
|
us_status.is_closed = True
|
||||||
|
us_status.save()
|
||||||
|
|
||||||
|
user_story = user_story.__class__.objects.get(pk=user_story.pk)
|
||||||
|
assert user_story.is_closed is True
|
||||||
|
|
||||||
|
us_status.is_closed = False
|
||||||
|
us_status.save()
|
||||||
|
|
||||||
|
user_story = user_story.__class__.objects.get(pk=user_story.pk)
|
||||||
|
assert user_story.is_closed is False
|
||||||
|
|
||||||
|
|
||||||
|
def test_task_status_is_closed_changed_recalc_us_is_closed(client):
|
||||||
|
us_status = f.UserStoryStatusFactory()
|
||||||
|
user_story = f.UserStoryFactory.create(project=us_status.project, status=us_status)
|
||||||
|
task_status = f.TaskStatusFactory.create(project=us_status.project, is_closed=False)
|
||||||
|
task = f.TaskFactory.create(project=us_status.project, status=task_status, user_story=user_story)
|
||||||
|
|
||||||
|
assert user_story.is_closed is False
|
||||||
|
|
||||||
|
task_status.is_closed = True
|
||||||
|
task_status.save()
|
||||||
|
|
||||||
|
user_story = user_story.__class__.objects.get(pk=user_story.pk)
|
||||||
|
assert user_story.is_closed is True
|
||||||
|
|
||||||
|
task_status.is_closed = False
|
||||||
|
task_status.save()
|
||||||
|
|
||||||
|
user_story = user_story.__class__.objects.get(pk=user_story.pk)
|
||||||
|
assert user_story.is_closed is False
|
||||||
|
|
||||||
|
|
||||||
def test_us_status_slug_generation(client):
|
def test_us_status_slug_generation(client):
|
||||||
us_status = f.UserStoryStatusFactory(name="NEW")
|
us_status = f.UserStoryStatusFactory(name="NEW")
|
||||||
f.MembershipFactory(user=us_status.project.owner, project=us_status.project, is_owner=True)
|
f.MembershipFactory(user=us_status.project.owner, project=us_status.project, is_owner=True)
|
||||||
|
|
Loading…
Reference in New Issue