Add US duedates configuration

remotes/origin/endpoint-for-estimation-system-new
Álex Hermida 2018-06-05 12:30:00 +02:00 committed by Alex Hermida
parent 4dd525972b
commit 758109ac22
8 changed files with 145 additions and 1 deletions

View File

@ -585,6 +585,21 @@ class PointsViewSet(MoveOnDestroyMixin, BlockedByProjectMixin,
return super().create(request, *args, **kwargs) return super().create(request, *args, **kwargs)
class UserStoryDueDateViewSet(BlockedByProjectMixin, ModelCrudViewSet):
model = models.UserStoryDueDate
serializer_class = serializers.UserStoryDueDateSerializer
validator_class = validators.UserStoryDueDateValidator
permission_classes = (permissions.UserStoryDueDatePermission,)
filter_backends = (filters.CanViewProjectFilterBackend,)
filter_fields = ('project',)
def create(self, request, *args, **kwargs):
project_id = request.DATA.get("project", 0)
with advisory_lock("user-story-duedate-creation-{}".format(project_id)):
return super().create(request, *args, **kwargs)
class TaskStatusViewSet(MoveOnDestroyMixin, BlockedByProjectMixin, class TaskStatusViewSet(MoveOnDestroyMixin, BlockedByProjectMixin,
ModelCrudViewSet, BulkUpdateOrderMixin): ModelCrudViewSet, BulkUpdateOrderMixin):

View File

@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.2 on 2018-06-05 10:42
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('projects', '0059_auto_20170116_1633'),
]
operations = [
migrations.CreateModel(
name='UserStoryDueDate',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='name')),
('slug', models.SlugField(blank=True, max_length=255, verbose_name='slug')),
('order', models.IntegerField(default=10, verbose_name='order')),
('by_default', models.BooleanField(default=False, verbose_name='by default')),
('color', models.CharField(default='#999999', max_length=20, verbose_name='color')),
('days_to_due', models.IntegerField(blank=True, default=None, null=True, verbose_name='days to due')),
('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='us_duedates', to='projects.Project', verbose_name='project')),
],
options={
'verbose_name': 'user story due date',
'verbose_name_plural': 'user story due dates',
'ordering': ['project', 'order', 'name'],
},
),
migrations.AddField(
model_name='project',
name='default_us_duedate',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='projects.UserStoryDueDate', verbose_name='default US duedate'),
),
migrations.AlterUniqueTogether(
name='userstoryduedate',
unique_together=set([('project', 'slug'), ('project', 'name')]),
),
]

View File

@ -120,6 +120,11 @@ class ProjectDefaults(models.Model):
default_points = models.OneToOneField("projects.Points", on_delete=models.SET_NULL, default_points = models.OneToOneField("projects.Points", on_delete=models.SET_NULL,
related_name="+", null=True, blank=True, related_name="+", null=True, blank=True,
verbose_name=_("default points")) verbose_name=_("default points"))
default_us_duedate = models.OneToOneField("projects.UserStoryDueDate",
on_delete=models.SET_NULL,
related_name="+",
null=True, blank=True,
verbose_name=_("default US duedate"))
default_task_status = models.OneToOneField("projects.TaskStatus", default_task_status = models.OneToOneField("projects.TaskStatus",
on_delete=models.SET_NULL, related_name="+", on_delete=models.SET_NULL, related_name="+",
null=True, blank=True, null=True, blank=True,
@ -605,8 +610,41 @@ class Points(models.Model):
return self.name return self.name
# Tasks common models class UserStoryDueDate(models.Model):
name = models.CharField(max_length=255, null=False, blank=False,
verbose_name=_("name"))
slug = models.SlugField(max_length=255, null=False, blank=True,
verbose_name=_("slug"))
order = models.IntegerField(default=10, null=False, blank=False,
verbose_name=_("order"))
by_default = models.BooleanField(default=False, null=False, blank=True,
verbose_name=_("by default"))
color = models.CharField(max_length=20, null=False, blank=False, default="#999999",
verbose_name=_("color"))
days_to_due = models.IntegerField(null=True, blank=True, default=None,
verbose_name=_("days to due"))
project = models.ForeignKey("Project", null=False, blank=False,
related_name="us_duedates", verbose_name=_("project"))
class Meta:
verbose_name = "user story due date"
verbose_name_plural = "user story due dates"
ordering = ["project", "order", "name"]
unique_together = (("project", "name"), ("project", "slug"))
def __str__(self):
return self.name
def save(self, *args, **kwargs):
qs = self.project.us_duedates
if self.id:
qs = qs.exclude(id=self.id)
self.slug = slugify_uniquely_for_queryset(self.name, qs)
return super().save(*args, **kwargs)
# Tasks common models
class TaskStatus(models.Model): class TaskStatus(models.Model):
name = models.CharField(max_length=255, null=False, blank=False, name = models.CharField(max_length=255, null=False, blank=False,
verbose_name=_("name")) verbose_name=_("name"))

View File

@ -145,6 +145,16 @@ class UserStoryStatusPermission(TaigaResourcePermission):
bulk_update_order_perms = IsProjectAdmin() bulk_update_order_perms = IsProjectAdmin()
class UserStoryDueDatePermission(TaigaResourcePermission):
retrieve_perms = HasProjectPerm('view_project')
create_perms = IsProjectAdmin()
update_perms = IsProjectAdmin()
partial_update_perms = IsProjectAdmin()
destroy_perms = IsProjectAdmin()
list_perms = AllowAny()
bulk_update_order_perms = IsProjectAdmin()
# Tasks # Tasks
class TaskStatusPermission(TaigaResourcePermission): class TaskStatusPermission(TaigaResourcePermission):

View File

@ -67,6 +67,17 @@ class PointsSerializer(serializers.LightSerializer):
project = Field(attr="project_id") project = Field(attr="project_id")
class UserStoryDueDateSerializer(serializers.LightSerializer):
id = Field()
name = I18NField()
slug = Field()
order = Field()
by_default = Field()
days_to_due = Field()
color = Field()
project = Field(attr="project_id")
class TaskStatusSerializer(serializers.LightSerializer): class TaskStatusSerializer(serializers.LightSerializer):
id = Field() id = Field()
name = I18NField() name = I18NField()

View File

@ -84,6 +84,11 @@ class PointsValidator(DuplicatedNameInProjectValidator, validators.ModelValidato
model = models.Points model = models.Points
class UserStoryDueDateValidator(DuplicatedNameInProjectValidator, validators.ModelValidator):
class Meta:
model = models.UserStoryDueDate
class TaskStatusValidator(DuplicatedNameInProjectValidator, validators.ModelValidator): class TaskStatusValidator(DuplicatedNameInProjectValidator, validators.ModelValidator):
class Meta: class Meta:
model = models.TaskStatus model = models.TaskStatus

View File

@ -58,6 +58,7 @@ from taiga.projects.api import InvitationViewSet
from taiga.projects.api import EpicStatusViewSet from taiga.projects.api import EpicStatusViewSet
from taiga.projects.api import UserStoryStatusViewSet from taiga.projects.api import UserStoryStatusViewSet
from taiga.projects.api import PointsViewSet from taiga.projects.api import PointsViewSet
from taiga.projects.api import UserStoryDueDateViewSet
from taiga.projects.api import TaskStatusViewSet from taiga.projects.api import TaskStatusViewSet
from taiga.projects.api import IssueStatusViewSet from taiga.projects.api import IssueStatusViewSet
from taiga.projects.api import IssueTypeViewSet from taiga.projects.api import IssueTypeViewSet
@ -74,6 +75,7 @@ router.register(r"invitations", InvitationViewSet, base_name="invitations")
router.register(r"epic-statuses", EpicStatusViewSet, base_name="epic-statuses") router.register(r"epic-statuses", EpicStatusViewSet, base_name="epic-statuses")
router.register(r"userstory-statuses", UserStoryStatusViewSet, base_name="userstory-statuses") router.register(r"userstory-statuses", UserStoryStatusViewSet, base_name="userstory-statuses")
router.register(r"points", PointsViewSet, base_name="points") router.register(r"points", PointsViewSet, base_name="points")
router.register(r"userstory-due-dates", UserStoryDueDateViewSet, base_name="userstory-due-dates")
router.register(r"task-statuses", TaskStatusViewSet, base_name="task-statuses") router.register(r"task-statuses", TaskStatusViewSet, base_name="task-statuses")
router.register(r"issue-statuses", IssueStatusViewSet, base_name="issue-statuses") router.register(r"issue-statuses", IssueStatusViewSet, base_name="issue-statuses")
router.register(r"issue-types", IssueTypeViewSet, base_name="issue-types") router.register(r"issue-types", IssueTypeViewSet, base_name="issue-types")

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.2 on 2018-06-05 10:31
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0026_auto_20180514_1513'),
]
operations = [
migrations.AlterField(
model_name='user',
name='read_new_terms',
field=models.BooleanField(default=False, verbose_name='new terms read'),
),
]