Added due_date to taks, us and issues
parent
8b76b5787b
commit
c2149ef6a5
|
@ -0,0 +1,28 @@
|
||||||
|
# Copyright (C) 2018 Miguel González <migonzalvar@gmail.com>
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
|
class DueDateMixin(models.Model):
|
||||||
|
due_date = models.DateField(
|
||||||
|
blank=True, null=True, default=None, verbose_name=_('due date'),
|
||||||
|
)
|
||||||
|
due_date_reason = models.TextField(
|
||||||
|
null=False, blank=True, default='', verbose_name=_('reason for the due date'),
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
|
@ -0,0 +1,39 @@
|
||||||
|
# Copyright (C) 2018 Miguel González <migonzalvar@gmail.com>
|
||||||
|
# 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 datetime as dt
|
||||||
|
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
|
from taiga.base.api import serializers
|
||||||
|
from taiga.base.fields import Field, MethodField
|
||||||
|
|
||||||
|
|
||||||
|
class DueDateSerializerMixin(serializers.LightSerializer):
|
||||||
|
due_date = Field()
|
||||||
|
due_date_reason = Field()
|
||||||
|
due_date_status = MethodField()
|
||||||
|
|
||||||
|
THRESHOLD = 3
|
||||||
|
|
||||||
|
def get_due_date_status(self, obj):
|
||||||
|
if obj.due_date is None:
|
||||||
|
return 'not_set'
|
||||||
|
elif obj.status.is_closed:
|
||||||
|
return 'no_longer_applicable'
|
||||||
|
elif timezone.now().date() > obj.due_date:
|
||||||
|
return 'past_due'
|
||||||
|
elif (timezone.now().date() + dt.timedelta(days=self.THRESHOLD)) >= obj.due_date:
|
||||||
|
return 'due_soon'
|
||||||
|
else:
|
||||||
|
return 'set'
|
|
@ -357,6 +357,8 @@ def userstory_freezer(us) -> dict:
|
||||||
"blocked_note_html": mdrender(us.project, us.blocked_note),
|
"blocked_note_html": mdrender(us.project, us.blocked_note),
|
||||||
"custom_attributes": extract_user_story_custom_attributes(us),
|
"custom_attributes": extract_user_story_custom_attributes(us),
|
||||||
"tribe_gig": us.tribe_gig,
|
"tribe_gig": us.tribe_gig,
|
||||||
|
"due_date": str(us.due_date),
|
||||||
|
"due_date_reason": str(us.due_date_reason),
|
||||||
}
|
}
|
||||||
|
|
||||||
return snapshot
|
return snapshot
|
||||||
|
@ -381,6 +383,8 @@ def issue_freezer(issue) -> dict:
|
||||||
"blocked_note": issue.blocked_note,
|
"blocked_note": issue.blocked_note,
|
||||||
"blocked_note_html": mdrender(issue.project, issue.blocked_note),
|
"blocked_note_html": mdrender(issue.project, issue.blocked_note),
|
||||||
"custom_attributes": extract_issue_custom_attributes(issue),
|
"custom_attributes": extract_issue_custom_attributes(issue),
|
||||||
|
"due_date": str(issue.due_date),
|
||||||
|
"due_date_reason": str(issue.due_date_reason),
|
||||||
}
|
}
|
||||||
|
|
||||||
return snapshot
|
return snapshot
|
||||||
|
@ -406,6 +410,8 @@ def task_freezer(task) -> dict:
|
||||||
"blocked_note": task.blocked_note,
|
"blocked_note": task.blocked_note,
|
||||||
"blocked_note_html": mdrender(task.project, task.blocked_note),
|
"blocked_note_html": mdrender(task.project, task.blocked_note),
|
||||||
"custom_attributes": extract_task_custom_attributes(task),
|
"custom_attributes": extract_task_custom_attributes(task),
|
||||||
|
"due_date": str(task.due_date),
|
||||||
|
"due_date_reason": str(task.due_date_reason),
|
||||||
}
|
}
|
||||||
|
|
||||||
return snapshot
|
return snapshot
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.2 on 2018-04-09 09:06
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('issues', '0007_auto_20160614_1201'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='issue',
|
||||||
|
name='due_date',
|
||||||
|
field=models.DateField(blank=True, default=None, null=True, verbose_name='due date'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='issue',
|
||||||
|
name='due_date_reason',
|
||||||
|
field=models.TextField(blank=True, default='', verbose_name='reason for the due date'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -24,13 +24,14 @@ from django.utils import timezone
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from taiga.projects.due_dates.models import DueDateMixin
|
||||||
from taiga.projects.occ import OCCModelMixin
|
from taiga.projects.occ import OCCModelMixin
|
||||||
from taiga.projects.notifications.mixins import WatchedModelMixin
|
from taiga.projects.notifications.mixins import WatchedModelMixin
|
||||||
from taiga.projects.mixins.blocked import BlockedMixin
|
from taiga.projects.mixins.blocked import BlockedMixin
|
||||||
from taiga.projects.tagging.models import TaggedMixin
|
from taiga.projects.tagging.models import TaggedMixin
|
||||||
|
|
||||||
|
|
||||||
class Issue(OCCModelMixin, WatchedModelMixin, BlockedMixin, TaggedMixin, models.Model):
|
class Issue(OCCModelMixin, WatchedModelMixin, BlockedMixin, TaggedMixin, DueDateMixin, models.Model):
|
||||||
ref = models.BigIntegerField(db_index=True, null=True, blank=True, default=None,
|
ref = models.BigIntegerField(db_index=True, null=True, blank=True, default=None,
|
||||||
verbose_name=_("ref"))
|
verbose_name=_("ref"))
|
||||||
owner = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, default=None,
|
owner = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, default=None,
|
||||||
|
|
|
@ -21,6 +21,7 @@ from taiga.base.fields import Field, MethodField
|
||||||
from taiga.base.neighbors import NeighborsSerializerMixin
|
from taiga.base.neighbors import NeighborsSerializerMixin
|
||||||
|
|
||||||
from taiga.mdrender.service import render as mdrender
|
from taiga.mdrender.service import render as mdrender
|
||||||
|
from taiga.projects.due_dates.serializers import DueDateSerializerMixin
|
||||||
from taiga.projects.mixins.serializers import OwnerExtraInfoSerializerMixin
|
from taiga.projects.mixins.serializers import OwnerExtraInfoSerializerMixin
|
||||||
from taiga.projects.mixins.serializers import ProjectExtraInfoSerializerMixin
|
from taiga.projects.mixins.serializers import ProjectExtraInfoSerializerMixin
|
||||||
from taiga.projects.mixins.serializers import AssignedToExtraInfoSerializerMixin
|
from taiga.projects.mixins.serializers import AssignedToExtraInfoSerializerMixin
|
||||||
|
@ -33,7 +34,8 @@ from taiga.projects.votes.mixins.serializers import VoteResourceSerializerMixin
|
||||||
class IssueListSerializer(VoteResourceSerializerMixin, WatchedResourceSerializer,
|
class IssueListSerializer(VoteResourceSerializerMixin, WatchedResourceSerializer,
|
||||||
OwnerExtraInfoSerializerMixin, AssignedToExtraInfoSerializerMixin,
|
OwnerExtraInfoSerializerMixin, AssignedToExtraInfoSerializerMixin,
|
||||||
StatusExtraInfoSerializerMixin, ProjectExtraInfoSerializerMixin,
|
StatusExtraInfoSerializerMixin, ProjectExtraInfoSerializerMixin,
|
||||||
TaggedInProjectResourceSerializer, serializers.LightSerializer):
|
DueDateSerializerMixin, TaggedInProjectResourceSerializer,
|
||||||
|
serializers.LightSerializer):
|
||||||
id = Field()
|
id = Field()
|
||||||
ref = Field()
|
ref = Field()
|
||||||
severity = Field(attr="severity_id")
|
severity = Field(attr="severity_id")
|
||||||
|
|
|
@ -82,7 +82,7 @@ def issues_to_csv(project, queryset):
|
||||||
"sprint_estimated_finish", "owner", "owner_full_name", "assigned_to",
|
"sprint_estimated_finish", "owner", "owner_full_name", "assigned_to",
|
||||||
"assigned_to_full_name", "status", "severity", "priority", "type",
|
"assigned_to_full_name", "status", "severity", "priority", "type",
|
||||||
"is_closed", "attachments", "external_reference", "tags", "watchers",
|
"is_closed", "attachments", "external_reference", "tags", "watchers",
|
||||||
"voters", "created_date", "modified_date", "finished_date"]
|
"voters", "created_date", "modified_date", "finished_date", "due_date"]
|
||||||
|
|
||||||
custom_attrs = project.issuecustomattributes.all()
|
custom_attrs = project.issuecustomattributes.all()
|
||||||
for custom_attr in custom_attrs:
|
for custom_attr in custom_attrs:
|
||||||
|
@ -125,6 +125,7 @@ def issues_to_csv(project, queryset):
|
||||||
"created_date": issue.created_date,
|
"created_date": issue.created_date,
|
||||||
"modified_date": issue.modified_date,
|
"modified_date": issue.modified_date,
|
||||||
"finished_date": issue.finished_date,
|
"finished_date": issue.finished_date,
|
||||||
|
"due_date": issue.due_date,
|
||||||
}
|
}
|
||||||
|
|
||||||
for custom_attr in custom_attrs:
|
for custom_attr in custom_attrs:
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.2 on 2018-04-09 09:06
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('tasks', '0011_auto_20160928_0755'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='task',
|
||||||
|
name='due_date',
|
||||||
|
field=models.DateField(blank=True, default=None, null=True, verbose_name='due date'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='task',
|
||||||
|
name='due_date_reason',
|
||||||
|
field=models.TextField(blank=True, default='', verbose_name='reason for the due date'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -24,13 +24,14 @@ from django.utils import timezone
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from taiga.base.utils.time import timestamp_ms
|
from taiga.base.utils.time import timestamp_ms
|
||||||
|
from taiga.projects.due_dates.models import DueDateMixin
|
||||||
from taiga.projects.occ import OCCModelMixin
|
from taiga.projects.occ import OCCModelMixin
|
||||||
from taiga.projects.notifications.mixins import WatchedModelMixin
|
from taiga.projects.notifications.mixins import WatchedModelMixin
|
||||||
from taiga.projects.mixins.blocked import BlockedMixin
|
from taiga.projects.mixins.blocked import BlockedMixin
|
||||||
from taiga.projects.tagging.models import TaggedMixin
|
from taiga.projects.tagging.models import TaggedMixin
|
||||||
|
|
||||||
|
|
||||||
class Task(OCCModelMixin, WatchedModelMixin, BlockedMixin, TaggedMixin, models.Model):
|
class Task(OCCModelMixin, WatchedModelMixin, BlockedMixin, TaggedMixin, DueDateMixin, models.Model):
|
||||||
user_story = models.ForeignKey("userstories.UserStory", null=True, blank=True,
|
user_story = models.ForeignKey("userstories.UserStory", null=True, blank=True,
|
||||||
related_name="tasks", verbose_name=_("user story"))
|
related_name="tasks", verbose_name=_("user story"))
|
||||||
ref = models.BigIntegerField(db_index=True, null=True, blank=True, default=None,
|
ref = models.BigIntegerField(db_index=True, null=True, blank=True, default=None,
|
||||||
|
|
|
@ -22,6 +22,7 @@ from taiga.base.neighbors import NeighborsSerializerMixin
|
||||||
|
|
||||||
from taiga.mdrender.service import render as mdrender
|
from taiga.mdrender.service import render as mdrender
|
||||||
from taiga.projects.attachments.serializers import BasicAttachmentsInfoSerializerMixin
|
from taiga.projects.attachments.serializers import BasicAttachmentsInfoSerializerMixin
|
||||||
|
from taiga.projects.due_dates.serializers import DueDateSerializerMixin
|
||||||
from taiga.projects.mixins.serializers import OwnerExtraInfoSerializerMixin
|
from taiga.projects.mixins.serializers import OwnerExtraInfoSerializerMixin
|
||||||
from taiga.projects.mixins.serializers import ProjectExtraInfoSerializerMixin
|
from taiga.projects.mixins.serializers import ProjectExtraInfoSerializerMixin
|
||||||
from taiga.projects.mixins.serializers import AssignedToExtraInfoSerializerMixin
|
from taiga.projects.mixins.serializers import AssignedToExtraInfoSerializerMixin
|
||||||
|
@ -36,7 +37,8 @@ class TaskListSerializer(VoteResourceSerializerMixin, WatchedResourceSerializer,
|
||||||
OwnerExtraInfoSerializerMixin, AssignedToExtraInfoSerializerMixin,
|
OwnerExtraInfoSerializerMixin, AssignedToExtraInfoSerializerMixin,
|
||||||
StatusExtraInfoSerializerMixin, ProjectExtraInfoSerializerMixin,
|
StatusExtraInfoSerializerMixin, ProjectExtraInfoSerializerMixin,
|
||||||
BasicAttachmentsInfoSerializerMixin, TaggedInProjectResourceSerializer,
|
BasicAttachmentsInfoSerializerMixin, TaggedInProjectResourceSerializer,
|
||||||
TotalCommentsSerializerMixin, serializers.LightSerializer):
|
TotalCommentsSerializerMixin, DueDateSerializerMixin,
|
||||||
|
serializers.LightSerializer):
|
||||||
|
|
||||||
id = Field()
|
id = Field()
|
||||||
user_story = Field(attr="user_story_id")
|
user_story = Field(attr="user_story_id")
|
||||||
|
|
|
@ -122,7 +122,7 @@ def tasks_to_csv(project, queryset):
|
||||||
"sprint_estimated_finish", "owner", "owner_full_name", "assigned_to",
|
"sprint_estimated_finish", "owner", "owner_full_name", "assigned_to",
|
||||||
"assigned_to_full_name", "status", "is_iocaine", "is_closed", "us_order",
|
"assigned_to_full_name", "status", "is_iocaine", "is_closed", "us_order",
|
||||||
"taskboard_order", "attachments", "external_reference", "tags", "watchers", "voters",
|
"taskboard_order", "attachments", "external_reference", "tags", "watchers", "voters",
|
||||||
"created_date", "modified_date", "finished_date"]
|
"created_date", "modified_date", "finished_date", "due_date"]
|
||||||
|
|
||||||
custom_attrs = project.taskcustomattributes.all()
|
custom_attrs = project.taskcustomattributes.all()
|
||||||
for custom_attr in custom_attrs:
|
for custom_attr in custom_attrs:
|
||||||
|
@ -167,6 +167,7 @@ def tasks_to_csv(project, queryset):
|
||||||
"created_date": task.created_date,
|
"created_date": task.created_date,
|
||||||
"modified_date": task.modified_date,
|
"modified_date": task.modified_date,
|
||||||
"finished_date": task.finished_date,
|
"finished_date": task.finished_date,
|
||||||
|
"due_date": task.due_date,
|
||||||
}
|
}
|
||||||
for custom_attr in custom_attrs:
|
for custom_attr in custom_attrs:
|
||||||
value = task.custom_attributes_values.attributes_values.get(str(custom_attr.id), None)
|
value = task.custom_attributes_values.attributes_values.get(str(custom_attr.id), None)
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.2 on 2018-04-09 09:06
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('userstories', '0014_auto_20160928_0540'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='userstory',
|
||||||
|
name='due_date',
|
||||||
|
field=models.DateField(blank=True, default=None, null=True, verbose_name='due date'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='userstory',
|
||||||
|
name='due_date_reason',
|
||||||
|
field=models.TextField(blank=True, default='', verbose_name='reason for the due date'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -26,6 +26,7 @@ from django.utils import timezone
|
||||||
from picklefield.fields import PickledObjectField
|
from picklefield.fields import PickledObjectField
|
||||||
|
|
||||||
from taiga.base.utils.time import timestamp_ms
|
from taiga.base.utils.time import timestamp_ms
|
||||||
|
from taiga.projects.due_dates.models import DueDateMixin
|
||||||
from taiga.projects.tagging.models import TaggedMixin
|
from taiga.projects.tagging.models import TaggedMixin
|
||||||
from taiga.projects.occ import OCCModelMixin
|
from taiga.projects.occ import OCCModelMixin
|
||||||
from taiga.projects.notifications.mixins import WatchedModelMixin
|
from taiga.projects.notifications.mixins import WatchedModelMixin
|
||||||
|
@ -57,7 +58,7 @@ class RolePoints(models.Model):
|
||||||
return self.user_story.project
|
return self.user_story.project
|
||||||
|
|
||||||
|
|
||||||
class UserStory(OCCModelMixin, WatchedModelMixin, BlockedMixin, TaggedMixin, models.Model):
|
class UserStory(OCCModelMixin, WatchedModelMixin, BlockedMixin, TaggedMixin, DueDateMixin, models.Model):
|
||||||
ref = models.BigIntegerField(db_index=True, null=True, blank=True, default=None,
|
ref = models.BigIntegerField(db_index=True, null=True, blank=True, default=None,
|
||||||
verbose_name=_("ref"))
|
verbose_name=_("ref"))
|
||||||
milestone = models.ForeignKey("milestones.Milestone", null=True, blank=True,
|
milestone = models.ForeignKey("milestones.Milestone", null=True, blank=True,
|
||||||
|
|
|
@ -22,6 +22,7 @@ from taiga.base.neighbors import NeighborsSerializerMixin
|
||||||
|
|
||||||
from taiga.mdrender.service import render as mdrender
|
from taiga.mdrender.service import render as mdrender
|
||||||
from taiga.projects.attachments.serializers import BasicAttachmentsInfoSerializerMixin
|
from taiga.projects.attachments.serializers import BasicAttachmentsInfoSerializerMixin
|
||||||
|
from taiga.projects.due_dates.serializers import DueDateSerializerMixin
|
||||||
from taiga.projects.mixins.serializers import AssignedToExtraInfoSerializerMixin
|
from taiga.projects.mixins.serializers import AssignedToExtraInfoSerializerMixin
|
||||||
from taiga.projects.mixins.serializers import OwnerExtraInfoSerializerMixin
|
from taiga.projects.mixins.serializers import OwnerExtraInfoSerializerMixin
|
||||||
from taiga.projects.mixins.serializers import ProjectExtraInfoSerializerMixin
|
from taiga.projects.mixins.serializers import ProjectExtraInfoSerializerMixin
|
||||||
|
@ -49,7 +50,7 @@ class UserStoryListSerializer(ProjectExtraInfoSerializerMixin,
|
||||||
OwnerExtraInfoSerializerMixin, AssignedToExtraInfoSerializerMixin,
|
OwnerExtraInfoSerializerMixin, AssignedToExtraInfoSerializerMixin,
|
||||||
StatusExtraInfoSerializerMixin, BasicAttachmentsInfoSerializerMixin,
|
StatusExtraInfoSerializerMixin, BasicAttachmentsInfoSerializerMixin,
|
||||||
TaggedInProjectResourceSerializer, TotalCommentsSerializerMixin,
|
TaggedInProjectResourceSerializer, TotalCommentsSerializerMixin,
|
||||||
serializers.LightSerializer):
|
DueDateSerializerMixin, serializers.LightSerializer):
|
||||||
|
|
||||||
id = Field()
|
id = Field()
|
||||||
ref = Field()
|
ref = Field()
|
||||||
|
|
|
@ -197,7 +197,7 @@ def userstories_to_csv(project, queryset):
|
||||||
"created_date", "modified_date", "finish_date",
|
"created_date", "modified_date", "finish_date",
|
||||||
"client_requirement", "team_requirement", "attachments",
|
"client_requirement", "team_requirement", "attachments",
|
||||||
"generated_from_issue", "external_reference", "tasks",
|
"generated_from_issue", "external_reference", "tasks",
|
||||||
"tags", "watchers", "voters"]
|
"tags", "watchers", "voters", "due_date"]
|
||||||
|
|
||||||
custom_attrs = project.userstorycustomattributes.all()
|
custom_attrs = project.userstorycustomattributes.all()
|
||||||
for custom_attr in custom_attrs:
|
for custom_attr in custom_attrs:
|
||||||
|
@ -249,7 +249,8 @@ def userstories_to_csv(project, queryset):
|
||||||
"tasks": ",".join([str(task.ref) for task in us.tasks.all()]),
|
"tasks": ",".join([str(task.ref) for task in us.tasks.all()]),
|
||||||
"tags": ",".join(us.tags or []),
|
"tags": ",".join(us.tags or []),
|
||||||
"watchers": us.watchers,
|
"watchers": us.watchers,
|
||||||
"voters": us.total_voters
|
"voters": us.total_voters,
|
||||||
|
"due_date": us.due_date,
|
||||||
}
|
}
|
||||||
|
|
||||||
us_role_points_by_role_id = {us_rp.role.id: us_rp.points.value for us_rp in us.role_points.all()}
|
us_role_points_by_role_id = {us_rp.role.id: us_rp.points.value for us_rp in us.role_points.all()}
|
||||||
|
|
|
@ -591,9 +591,9 @@ def test_custom_fields_csv_generation():
|
||||||
data.seek(0)
|
data.seek(0)
|
||||||
reader = csv.reader(data)
|
reader = csv.reader(data)
|
||||||
row = next(reader)
|
row = next(reader)
|
||||||
assert row[23] == attr.name
|
assert row[24] == attr.name
|
||||||
row = next(reader)
|
row = next(reader)
|
||||||
assert row[23] == "val1"
|
assert row[24] == "val1"
|
||||||
|
|
||||||
|
|
||||||
def test_api_validator_assigned_to_when_update_issues(client):
|
def test_api_validator_assigned_to_when_update_issues(client):
|
||||||
|
|
|
@ -574,9 +574,9 @@ def test_custom_fields_csv_generation():
|
||||||
data.seek(0)
|
data.seek(0)
|
||||||
reader = csv.reader(data)
|
reader = csv.reader(data)
|
||||||
row = next(reader)
|
row = next(reader)
|
||||||
assert row[24] == attr.name
|
assert row[25] == attr.name
|
||||||
row = next(reader)
|
row = next(reader)
|
||||||
assert row[24] == "val1"
|
assert row[25] == "val1"
|
||||||
|
|
||||||
|
|
||||||
def test_get_tasks_including_attachments(client):
|
def test_get_tasks_including_attachments(client):
|
||||||
|
|
|
@ -899,9 +899,9 @@ def test_custom_fields_csv_generation():
|
||||||
data.seek(0)
|
data.seek(0)
|
||||||
reader = csv.reader(data)
|
reader = csv.reader(data)
|
||||||
row = next(reader)
|
row = next(reader)
|
||||||
assert row[28] == attr.name
|
assert row[29] == attr.name
|
||||||
row = next(reader)
|
row = next(reader)
|
||||||
assert row[28] == "val1"
|
assert row[29] == "val1"
|
||||||
|
|
||||||
|
|
||||||
def test_update_userstory_respecting_watchers(client):
|
def test_update_userstory_respecting_watchers(client):
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import datetime as dt
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
|
from taiga.projects.due_dates.serializers import DueDateSerializerMixin
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('due_date, is_closed, expected', [
|
||||||
|
(None, False, 'not_set'),
|
||||||
|
(dt.date(2100, 1, 1), True, 'no_longer_applicable'),
|
||||||
|
(dt.date(2100, 12, 31), False, 'set'),
|
||||||
|
(dt.date(2000, 1, 1), False, 'past_due'),
|
||||||
|
(timezone.now().date(), False, 'due_soon'),
|
||||||
|
])
|
||||||
|
def test_due_date_status(due_date, is_closed, expected):
|
||||||
|
serializer = DueDateSerializerMixin()
|
||||||
|
obj_status = mock.MagicMock(is_closed=is_closed)
|
||||||
|
obj = mock.MagicMock(due_date=due_date, status=obj_status)
|
||||||
|
status = serializer.get_due_date_status(obj)
|
||||||
|
assert status == expected
|
Loading…
Reference in New Issue