Merge pull request #609 from taigaio/status-and-default_status-can-be-None
Status and default status can be Noneremotes/origin/issue/4795/notification_even_they_are_disabled
commit
010fcfa635
|
@ -266,7 +266,7 @@ def userstory_freezer(us) -> dict:
|
||||||
snapshot = {
|
snapshot = {
|
||||||
"ref": us.ref,
|
"ref": us.ref,
|
||||||
"owner": us.owner_id,
|
"owner": us.owner_id,
|
||||||
"status": us.status_id,
|
"status": us.status.id if us.status else None,
|
||||||
"is_closed": us.is_closed,
|
"is_closed": us.is_closed,
|
||||||
"finish_date": str(us.finish_date),
|
"finish_date": str(us.finish_date),
|
||||||
"backlog_order": us.backlog_order,
|
"backlog_order": us.backlog_order,
|
||||||
|
@ -297,7 +297,7 @@ def issue_freezer(issue) -> dict:
|
||||||
snapshot = {
|
snapshot = {
|
||||||
"ref": issue.ref,
|
"ref": issue.ref,
|
||||||
"owner": issue.owner_id,
|
"owner": issue.owner_id,
|
||||||
"status": issue.status_id,
|
"status": issue.status.id if issue.status else None,
|
||||||
"priority": issue.priority_id,
|
"priority": issue.priority_id,
|
||||||
"severity": issue.severity_id,
|
"severity": issue.severity_id,
|
||||||
"type": issue.type_id,
|
"type": issue.type_id,
|
||||||
|
@ -321,7 +321,7 @@ def task_freezer(task) -> dict:
|
||||||
snapshot = {
|
snapshot = {
|
||||||
"ref": task.ref,
|
"ref": task.ref,
|
||||||
"owner": task.owner_id,
|
"owner": task.owner_id,
|
||||||
"status": task.status_id,
|
"status": task.status.id if task.status else None,
|
||||||
"milestone": task.milestone_id,
|
"milestone": task.milestone_id,
|
||||||
"subject": task.subject,
|
"subject": task.subject,
|
||||||
"description": task.description,
|
"description": task.description,
|
||||||
|
|
|
@ -98,4 +98,4 @@ class Issue(OCCModelMixin, WatchedModelMixin, BlockedMixin, TaggedMixin, models.
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_closed(self):
|
def is_closed(self):
|
||||||
return self.status.is_closed
|
return self.status is not None and self.status.is_closed
|
||||||
|
|
|
@ -117,7 +117,7 @@ def issues_to_csv(project, queryset):
|
||||||
"owner_full_name": issue.owner.get_full_name() if issue.owner else None,
|
"owner_full_name": issue.owner.get_full_name() if issue.owner else None,
|
||||||
"assigned_to": issue.assigned_to.username if issue.assigned_to else None,
|
"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,
|
"assigned_to_full_name": issue.assigned_to.get_full_name() if issue.assigned_to else None,
|
||||||
"status": issue.status.name,
|
"status": issue.status.name if issue.status else None,
|
||||||
"severity": issue.severity.name,
|
"severity": issue.severity.name,
|
||||||
"priority": issue.priority.name,
|
"priority": issue.priority.name,
|
||||||
"type": issue.type.name,
|
"type": issue.type.name,
|
||||||
|
|
|
@ -23,6 +23,8 @@ from django.utils import timezone
|
||||||
####################################
|
####################################
|
||||||
|
|
||||||
def set_finished_date_when_edit_issue(sender, instance, **kwargs):
|
def set_finished_date_when_edit_issue(sender, instance, **kwargs):
|
||||||
|
if instance.status is None:
|
||||||
|
return
|
||||||
if instance.status.is_closed and not instance.finished_date:
|
if instance.status.is_closed and not instance.finished_date:
|
||||||
instance.finished_date = timezone.now()
|
instance.finished_date = timezone.now()
|
||||||
elif not instance.status.is_closed and instance.finished_date:
|
elif not instance.status.is_closed and instance.finished_date:
|
||||||
|
|
|
@ -23,7 +23,7 @@ from . import models
|
||||||
|
|
||||||
def calculate_milestone_is_closed(milestone):
|
def calculate_milestone_is_closed(milestone):
|
||||||
return (milestone.user_stories.all().count() > 0 and
|
return (milestone.user_stories.all().count() > 0 and
|
||||||
all([task.status.is_closed for task in milestone.tasks.all()]) and
|
all([task.status is not None and task.status.is_closed for task in milestone.tasks.all()]) and
|
||||||
all([user_story.is_closed for user_story in milestone.user_stories.all()]))
|
all([user_story.is_closed for user_story in milestone.user_stories.all()]))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ def get_stats_for_project_issues(project):
|
||||||
)
|
)
|
||||||
for issue in issues:
|
for issue in issues:
|
||||||
project_issues_stats['total_issues'] += 1
|
project_issues_stats['total_issues'] += 1
|
||||||
if issue.status.is_closed:
|
if issue.status is not None and issue.status.is_closed:
|
||||||
project_issues_stats['closed_issues'] += 1
|
project_issues_stats['closed_issues'] += 1
|
||||||
else:
|
else:
|
||||||
project_issues_stats['opened_issues'] += 1
|
project_issues_stats['opened_issues'] += 1
|
||||||
|
|
|
@ -68,7 +68,7 @@ class TaskSerializer(WatchersValidator, VoteResourceSerializerMixin, EditableWat
|
||||||
return mdrender(obj.project, obj.description)
|
return mdrender(obj.project, obj.description)
|
||||||
|
|
||||||
def get_is_closed(self, obj):
|
def get_is_closed(self, obj):
|
||||||
return obj.status.is_closed
|
return obj.status is not None and obj.status.is_closed
|
||||||
|
|
||||||
|
|
||||||
class TaskListSerializer(TaskSerializer):
|
class TaskListSerializer(TaskSerializer):
|
||||||
|
|
|
@ -129,9 +129,9 @@ def tasks_to_csv(project, queryset):
|
||||||
"owner_full_name": task.owner.get_full_name() if task.owner else None,
|
"owner_full_name": task.owner.get_full_name() if task.owner else None,
|
||||||
"assigned_to": task.assigned_to.username if task.assigned_to else None,
|
"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,
|
"assigned_to_full_name": task.assigned_to.get_full_name() if task.assigned_to else None,
|
||||||
"status": task.status.name,
|
"status": task.status.name if task.status else None,
|
||||||
"is_iocaine": task.is_iocaine,
|
"is_iocaine": task.is_iocaine,
|
||||||
"is_closed": task.status.is_closed,
|
"is_closed": task.status is not None and task.status.is_closed,
|
||||||
"us_order": task.us_order,
|
"us_order": task.us_order,
|
||||||
"taskboard_order": task.taskboard_order,
|
"taskboard_order": task.taskboard_order,
|
||||||
"attachments": task.attachments.count(),
|
"attachments": task.attachments.count(),
|
||||||
|
|
|
@ -100,6 +100,8 @@ def _try_to_close_milestone_when_delete_task(instance):
|
||||||
####################################
|
####################################
|
||||||
|
|
||||||
def set_finished_date_when_edit_task(sender, instance, **kwargs):
|
def set_finished_date_when_edit_task(sender, instance, **kwargs):
|
||||||
|
if instance.status is None:
|
||||||
|
return
|
||||||
if instance.status.is_closed and not instance.finished_date:
|
if instance.status.is_closed and not instance.finished_date:
|
||||||
instance.finished_date = timezone.now()
|
instance.finished_date = timezone.now()
|
||||||
elif not instance.status.is_closed and instance.finished_date:
|
elif not instance.status.is_closed and instance.finished_date:
|
||||||
|
|
|
@ -106,9 +106,9 @@ def calculate_userstory_is_closed(user_story):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if user_story.tasks.count() == 0:
|
if user_story.tasks.count() == 0:
|
||||||
return user_story.status.is_closed
|
return user_story.status is not None and user_story.status.is_closed
|
||||||
|
|
||||||
if all([task.status.is_closed for task in user_story.tasks.all()]):
|
if all([task.status is not None and task.status.is_closed for task in user_story.tasks.all()]):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -179,7 +179,7 @@ def userstories_to_csv(project,queryset):
|
||||||
"owner_full_name": us.owner.get_full_name() if us.owner else None,
|
"owner_full_name": us.owner.get_full_name() if us.owner else None,
|
||||||
"assigned_to": us.assigned_to.username if us.assigned_to else None,
|
"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,
|
"assigned_to_full_name": us.assigned_to.get_full_name() if us.assigned_to else None,
|
||||||
"status": us.status.name,
|
"status": us.status.name if us.status else None,
|
||||||
"is_closed": us.is_closed,
|
"is_closed": us.is_closed,
|
||||||
"backlog_order": us.backlog_order,
|
"backlog_order": us.backlog_order,
|
||||||
"sprint_order": us.sprint_order,
|
"sprint_order": us.sprint_order,
|
||||||
|
|
|
@ -71,6 +71,27 @@ def test_create_issue_without_status(client):
|
||||||
assert response.data['type'] == project.default_issue_type.id
|
assert response.data['type'] == project.default_issue_type.id
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_issue_without_status_in_project_without_default_values(client):
|
||||||
|
user = f.UserFactory.create()
|
||||||
|
project = f.ProjectFactory.create(owner=user,
|
||||||
|
default_issue_status=None,
|
||||||
|
default_priority=None,
|
||||||
|
default_severity=None,
|
||||||
|
default_issue_type = None)
|
||||||
|
|
||||||
|
f.MembershipFactory.create(project=project, user=user, is_owner=True)
|
||||||
|
url = reverse("issues-list")
|
||||||
|
|
||||||
|
data = {"subject": "Test user story", "project": project.id}
|
||||||
|
client.login(user)
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
assert response.status_code == 201
|
||||||
|
assert response.data['status'] == None
|
||||||
|
assert response.data['severity'] == None
|
||||||
|
assert response.data['priority'] == None
|
||||||
|
assert response.data['type'] == None
|
||||||
|
|
||||||
|
|
||||||
def test_api_create_issues_in_bulk(client):
|
def test_api_create_issues_in_bulk(client):
|
||||||
project = f.create_project()
|
project = f.create_project()
|
||||||
f.MembershipFactory(project=project, user=project.owner, is_owner=True)
|
f.MembershipFactory(project=project, user=project.owner, is_owner=True)
|
||||||
|
|
|
@ -53,6 +53,19 @@ def test_create_task_without_status(client):
|
||||||
assert response.data['status'] == project.default_task_status.id
|
assert response.data['status'] == project.default_task_status.id
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_task_without_default_values(client):
|
||||||
|
user = f.UserFactory.create()
|
||||||
|
project = f.ProjectFactory.create(owner=user, default_task_status=None)
|
||||||
|
f.MembershipFactory.create(project=project, user=user, is_owner=True)
|
||||||
|
url = reverse("tasks-list")
|
||||||
|
|
||||||
|
data = {"subject": "Test user story", "project": project.id}
|
||||||
|
client.login(user)
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
assert response.status_code == 201
|
||||||
|
assert response.data['status'] == None
|
||||||
|
|
||||||
|
|
||||||
def test_api_update_task_tags(client):
|
def test_api_update_task_tags(client):
|
||||||
project = f.ProjectFactory.create()
|
project = f.ProjectFactory.create()
|
||||||
task = f.create_task(project=project, status__project=project, milestone=None, user_story=None)
|
task = f.create_task(project=project, status__project=project, milestone=None, user_story=None)
|
||||||
|
|
|
@ -79,6 +79,19 @@ def test_create_userstory_without_status(client):
|
||||||
assert response.data['status'] == project.default_us_status.id
|
assert response.data['status'] == project.default_us_status.id
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_userstory_without_default_values(client):
|
||||||
|
user = f.UserFactory.create()
|
||||||
|
project = f.ProjectFactory.create(owner=user, default_us_status=None)
|
||||||
|
f.MembershipFactory.create(project=project, user=user, is_owner=True)
|
||||||
|
url = reverse("userstories-list")
|
||||||
|
|
||||||
|
data = {"subject": "Test user story", "project": project.id}
|
||||||
|
client.login(user)
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
assert response.status_code == 201
|
||||||
|
assert response.data['status'] == None
|
||||||
|
|
||||||
|
|
||||||
def test_api_delete_userstory(client):
|
def test_api_delete_userstory(client):
|
||||||
us = f.UserStoryFactory.create()
|
us = f.UserStoryFactory.create()
|
||||||
f.MembershipFactory.create(project=us.project, user=us.owner, is_owner=True)
|
f.MembershipFactory.create(project=us.project, user=us.owner, is_owner=True)
|
||||||
|
|
Loading…
Reference in New Issue