diff --git a/apiserver/plane/db/migrations/0074_projectissuetype_alter_issuetype_options_and_more.py b/apiserver/plane/db/migrations/0074_projectissuetype_alter_issuetype_options_and_more.py new file mode 100644 index 000000000..191a42f65 --- /dev/null +++ b/apiserver/plane/db/migrations/0074_projectissuetype_alter_issuetype_options_and_more.py @@ -0,0 +1,176 @@ +# Generated by Django 4.2.11 on 2024-08-13 16:21 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('db', '0073_alter_commentreaction_unique_together_and_more'), + ] + + operations = [ + migrations.CreateModel( + name="ProjectIssueType", + fields=[ + ( + "created_at", + models.DateTimeField( + auto_now_add=True, verbose_name="Created At" + ), + ), + ( + "updated_at", + models.DateTimeField( + auto_now=True, verbose_name="Last Modified At" + ), + ), + ( + "deleted_at", + models.DateTimeField( + blank=True, null=True, verbose_name="Deleted At" + ), + ), + ( + "id", + models.UUIDField( + db_index=True, + default=uuid.uuid4, + editable=False, + primary_key=True, + serialize=False, + unique=True, + ), + ), + ("level", models.PositiveIntegerField(default=0)), + ("is_default", models.BooleanField(default=False)), + ], + options={ + "verbose_name": "Project Issue Type", + "verbose_name_plural": "Project Issue Types", + "db_table": "project_issue_types", + "ordering": ("project", "issue_type"), + }, + ), + migrations.AlterModelOptions( + name="issuetype", + options={ + "verbose_name": "Issue Type", + "verbose_name_plural": "Issue Types", + }, + ), + migrations.RemoveConstraint( + model_name="issuetype", + name="issue_type_unique_name_project_when_deleted_at_null", + ), + migrations.AlterUniqueTogether( + name="issuetype", + unique_together=set(), + ), + migrations.AlterField( + model_name="issuetype", + name="workspace", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="issue_types", + to="db.workspace", + ), + ), + migrations.AlterUniqueTogether( + name="issuetype", + unique_together={("workspace", "name", "deleted_at")}, + ), + migrations.AddConstraint( + model_name="issuetype", + constraint=models.UniqueConstraint( + condition=models.Q(("deleted_at__isnull", True)), + fields=("name", "workspace"), + name="issue_type_unique_name_workspace_when_deleted_at_null", + ), + ), + migrations.AddField( + model_name="projectissuetype", + name="created_by", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="%(class)s_created_by", + to=settings.AUTH_USER_MODEL, + verbose_name="Created By", + ), + ), + migrations.AddField( + model_name="projectissuetype", + name="issue_type", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="project_issue_types", + to="db.issuetype", + ), + ), + migrations.AddField( + model_name="projectissuetype", + name="project", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="project_%(class)s", + to="db.project", + ), + ), + migrations.AddField( + model_name="projectissuetype", + name="updated_by", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="%(class)s_updated_by", + to=settings.AUTH_USER_MODEL, + verbose_name="Last Modified By", + ), + ), + migrations.AddField( + model_name="projectissuetype", + name="workspace", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="workspace_%(class)s", + to="db.workspace", + ), + ), + migrations.RemoveField( + model_name="issuetype", + name="is_default", + ), + migrations.RemoveField( + model_name="issuetype", + name="project", + ), + migrations.RemoveField( + model_name="issuetype", + name="sort_order", + ), + migrations.RemoveField( + model_name="issuetype", + name="weight", + ), + migrations.AddConstraint( + model_name="projectissuetype", + constraint=models.UniqueConstraint( + condition=models.Q(("deleted_at__isnull", True)), + fields=("project", "issue_type"), + name="project_issue_type_unique_project_issue_type_when_deleted_at_null", + ), + ), + migrations.AlterUniqueTogether( + name="projectissuetype", + unique_together={("project", "issue_type", "deleted_at")}, + ), + migrations.AddField( + model_name="issuetype", + name="is_default", + field=models.BooleanField(default=False), + ), + ] diff --git a/apiserver/plane/db/models/issue_type.py b/apiserver/plane/db/models/issue_type.py index 0b61a5772..334b199f2 100644 --- a/apiserver/plane/db/models/issue_type.py +++ b/apiserver/plane/db/models/issue_type.py @@ -3,43 +3,61 @@ from django.db import models from django.db.models import Q # Module imports -from .workspace import WorkspaceBaseModel +from .project import ProjectBaseModel +from .base import BaseModel -class IssueType(WorkspaceBaseModel): +class IssueType(BaseModel): + workspace = models.ForeignKey( + "db.Workspace", + related_name="issue_types", + on_delete=models.CASCADE, + ) name = models.CharField(max_length=255) description = models.TextField(blank=True) logo_props = models.JSONField(default=dict) - sort_order = models.FloatField(default=65535) is_default = models.BooleanField(default=False) - weight = models.PositiveIntegerField(default=0) is_active = models.BooleanField(default=True) class Meta: - unique_together = ["project", "name", "deleted_at"] + unique_together = ["workspace", "name", "deleted_at"] constraints = [ models.UniqueConstraint( - fields=["name", "project"], + fields=["name", "workspace"], condition=Q(deleted_at__isnull=True), - name="issue_type_unique_name_project_when_deleted_at_null", + name="issue_type_unique_name_workspace_when_deleted_at_null", ) ] verbose_name = "Issue Type" verbose_name_plural = "Issue Types" db_table = "issue_types" - ordering = ("sort_order",) def __str__(self): return self.name - def save(self, *args, **kwargs): - # If we are adding a new issue type, we need to set the sort order - if self._state.adding: - # Get the largest sort order for the project - largest_sort_order = IssueType.objects.filter( - project=self.project - ).aggregate(largest=models.Max("sort_order"))["largest"] - # If there are issue types, set the sort order to the largest + 10000 - if largest_sort_order is not None: - self.sort_order = largest_sort_order + 10000 - super(IssueType, self).save(*args, **kwargs) + +class ProjectIssueType(ProjectBaseModel): + issue_type = models.ForeignKey( + "db.IssueType", + related_name="project_issue_types", + on_delete=models.CASCADE, + ) + level = models.PositiveIntegerField(default=0) + is_default = models.BooleanField(default=False) + + class Meta: + unique_together = ["project", "issue_type", "deleted_at"] + constraints = [ + models.UniqueConstraint( + fields=["project", "issue_type"], + condition=Q(deleted_at__isnull=True), + name="project_issue_type_unique_project_issue_type_when_deleted_at_null", + ) + ] + verbose_name = "Project Issue Type" + verbose_name_plural = "Project Issue Types" + db_table = "project_issue_types" + ordering = ("project", "issue_type") + + def __str__(self): + return f"{self.project} - {self.issue_type}"