bb-plane-fork/apps/api/plane/db/models/draft.py
sriram veeraghanta 02d0ee3e0f
chore: add copyright (#8584)
* feat: adding new copyright info on all files

* chore: adding CI
2026-01-27 13:54:22 +05:30

224 lines
7.8 KiB
Python

# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
# Django imports
from django.conf import settings
from django.db import models
from django.utils import timezone
# Module imports
from plane.utils.html_processor import strip_tags
from .workspace import WorkspaceBaseModel
class DraftIssue(WorkspaceBaseModel):
PRIORITY_CHOICES = (
("urgent", "Urgent"),
("high", "High"),
("medium", "Medium"),
("low", "Low"),
("none", "None"),
)
parent = models.ForeignKey(
"db.Issue",
on_delete=models.CASCADE,
null=True,
blank=True,
related_name="draft_parent_issue",
)
state = models.ForeignKey(
"db.State",
on_delete=models.CASCADE,
null=True,
blank=True,
related_name="state_draft_issue",
)
estimate_point = models.ForeignKey(
"db.EstimatePoint",
on_delete=models.SET_NULL,
related_name="draft_issue_estimates",
null=True,
blank=True,
)
name = models.CharField(max_length=255, verbose_name="Issue Name", blank=True, null=True)
description_json = models.JSONField(blank=True, default=dict)
description_html = models.TextField(blank=True, default="<p></p>")
description_stripped = models.TextField(blank=True, null=True)
description_binary = models.BinaryField(null=True)
priority = models.CharField(
max_length=30,
choices=PRIORITY_CHOICES,
verbose_name="Issue Priority",
default="none",
)
start_date = models.DateField(null=True, blank=True)
target_date = models.DateField(null=True, blank=True)
assignees = models.ManyToManyField(
settings.AUTH_USER_MODEL,
blank=True,
related_name="draft_assignee",
through="DraftIssueAssignee",
through_fields=("draft_issue", "assignee"),
)
labels = models.ManyToManyField("db.Label", blank=True, related_name="draft_labels", through="DraftIssueLabel")
sort_order = models.FloatField(default=65535)
completed_at = models.DateTimeField(null=True)
external_source = models.CharField(max_length=255, null=True, blank=True)
external_id = models.CharField(max_length=255, blank=True, null=True)
type = models.ForeignKey(
"db.IssueType",
on_delete=models.SET_NULL,
related_name="draft_issue_type",
null=True,
blank=True,
)
class Meta:
verbose_name = "DraftIssue"
verbose_name_plural = "DraftIssues"
db_table = "draft_issues"
ordering = ("-created_at",)
def save(self, *args, **kwargs):
if self.state is None:
try:
from plane.db.models import State
default_state = State.objects.filter(
~models.Q(is_triage=True), project=self.project, default=True
).first()
if default_state is None:
random_state = State.objects.filter(~models.Q(is_triage=True), project=self.project).first()
self.state = random_state
else:
self.state = default_state
except ImportError:
pass
else:
try:
from plane.db.models import State
if self.state.group == "completed":
self.completed_at = timezone.now()
else:
self.completed_at = None
except ImportError:
pass
if self._state.adding:
# Strip the html tags using html parser
self.description_stripped = (
None
if (self.description_html == "" or self.description_html is None)
else strip_tags(self.description_html)
)
largest_sort_order = DraftIssue.objects.filter(project=self.project, state=self.state).aggregate(
largest=models.Max("sort_order")
)["largest"]
if largest_sort_order is not None:
self.sort_order = largest_sort_order + 10000
super(DraftIssue, self).save(*args, **kwargs)
else:
# Strip the html tags using html parser
self.description_stripped = (
None
if (self.description_html == "" or self.description_html is None)
else strip_tags(self.description_html)
)
super(DraftIssue, self).save(*args, **kwargs)
def __str__(self):
"""Return name of the draft issue"""
return f"{self.name} <{self.project.name}>"
class DraftIssueAssignee(WorkspaceBaseModel):
draft_issue = models.ForeignKey(DraftIssue, on_delete=models.CASCADE, related_name="draft_issue_assignee")
assignee = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="draft_issue_assignee",
)
class Meta:
unique_together = ["draft_issue", "assignee", "deleted_at"]
constraints = [
models.UniqueConstraint(
fields=["draft_issue", "assignee"],
condition=models.Q(deleted_at__isnull=True),
name="draft_issue_assignee_unique_issue_assignee_when_deleted_at_null",
)
]
verbose_name = "Draft Issue Assignee"
verbose_name_plural = "Draft Issue Assignees"
db_table = "draft_issue_assignees"
ordering = ("-created_at",)
def __str__(self):
return f"{self.draft_issue.name} {self.assignee.email}"
class DraftIssueLabel(WorkspaceBaseModel):
draft_issue = models.ForeignKey("db.DraftIssue", on_delete=models.CASCADE, related_name="draft_label_issue")
label = models.ForeignKey("db.Label", on_delete=models.CASCADE, related_name="draft_label_issue")
class Meta:
verbose_name = "Draft Issue Label"
verbose_name_plural = "Draft Issue Labels"
db_table = "draft_issue_labels"
ordering = ("-created_at",)
def __str__(self):
return f"{self.draft_issue.name} {self.label.name}"
class DraftIssueModule(WorkspaceBaseModel):
module = models.ForeignKey("db.Module", on_delete=models.CASCADE, related_name="draft_issue_module")
draft_issue = models.ForeignKey("db.DraftIssue", on_delete=models.CASCADE, related_name="draft_issue_module")
class Meta:
unique_together = ["draft_issue", "module", "deleted_at"]
constraints = [
models.UniqueConstraint(
fields=["draft_issue", "module"],
condition=models.Q(deleted_at__isnull=True),
name="module_draft_issue_unique_issue_module_when_deleted_at_null",
)
]
verbose_name = "Draft Issue Module"
verbose_name_plural = "Draft Issue Modules"
db_table = "draft_issue_modules"
ordering = ("-created_at",)
def __str__(self):
return f"{self.module.name} {self.draft_issue.name}"
class DraftIssueCycle(WorkspaceBaseModel):
"""
Draft Issue Cycles
"""
draft_issue = models.ForeignKey("db.DraftIssue", on_delete=models.CASCADE, related_name="draft_issue_cycle")
cycle = models.ForeignKey("db.Cycle", on_delete=models.CASCADE, related_name="draft_issue_cycle")
class Meta:
unique_together = ["draft_issue", "cycle", "deleted_at"]
constraints = [
models.UniqueConstraint(
fields=["draft_issue", "cycle"],
condition=models.Q(deleted_at__isnull=True),
name="draft_issue_cycle_when_deleted_at_null",
)
]
verbose_name = "Draft Issue Cycle"
verbose_name_plural = "Draft Issue Cycles"
db_table = "draft_issue_cycles"
ordering = ("-created_at",)
def __str__(self):
return f"{self.cycle}"