from django.core.cache import cache
from django.db import models
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from ferrosoft.apps.ferrobase.models import LocalUser, CommonLimit, UUIDModel
from ferrosoft.apps.ticketing.api.service import generate_comment_hash
[docs]
class TicketType(models.TextChoices):
BUG = "B", _("Bug")
SUPPORT = "S", _("Support")
FEATURE_REQUEST = "F", _("Feature Request")
[docs]
class TicketPriority(models.TextChoices):
NORMAL = "N", _("Normal")
High = "H", _("High")
[docs]
class Settings(UUIDModel):
name = models.CharField(
max_length=100,
default="Ticketing Settings",
unique=True,
editable=False,
verbose_name=_("Settings Name"),
)
[docs]
@classmethod
def get_instance(cls):
instance = cls.objects.first() or cls.objects.create()
return instance
[docs]
def get_ticket_type_options(self, ticket_type: str) -> "TicketTypeProjectOption":
return self.ticket_type_projects.filter(ticket_type=ticket_type).first()
def __str__(self):
return self.name
[docs]
class TaigaProject(UUIDModel):
name = models.CharField(
max_length=255,
verbose_name=_("Project Name"),
)
project_id = models.PositiveIntegerField(
unique=True,
verbose_name=_("Project ID"),
)
types = models.JSONField(
default=dict,
verbose_name=_("Ticket Types"),
)
priorities = models.JSONField(
default=dict,
verbose_name=_("Ticket Priorities"),
)
[docs]
def get_type_id(self, ticket_type_label: str) -> int:
return self.types.get(ticket_type_label)
[docs]
def get_priority_id(self, priority_label: str) -> int:
return self.priorities.get(priority_label)
def __str__(self):
return self.name
[docs]
class TicketTypeProjectOption(UUIDModel):
settings = models.ForeignKey(
Settings,
on_delete=models.CASCADE,
related_name="ticket_type_projects",
verbose_name=_("Settings"),
)
ticket_type = models.CharField(
max_length=1,
choices=TicketType.choices,
verbose_name=_("Ticket Type"),
)
project = models.ForeignKey(
TaigaProject,
on_delete=models.CASCADE,
related_name="ticket_type_options",
verbose_name=_("Project"),
)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["settings", "ticket_type"],
name="unique_settings_ticket_type",
)
]
[docs]
@classmethod
def create_association(cls, project_id: str, ticket_type: TicketType):
cls.objects.get_or_create(
settings=Settings.get_instance(),
ticket_type=ticket_type,
project=TaigaProject.objects.get(project_id=project_id),
)
[docs]
@classmethod
def delete_association(cls, project_id: str, ticket_type: TicketType):
try:
cls.objects.get(
settings=Settings.get_instance(),
ticket_type=ticket_type,
project__project_id=project_id,
).delete()
except cls.DoesNotExist:
return
[docs]
class Ticket(UUIDModel):
[docs]
def attachment_upload_path(instance, filename):
return f"ticket/{instance.reference}/{filename}"
reference = models.CharField(
max_length=int(CommonLimit.TINY_CHAR),
verbose_name=_("Ticket ID"),
)
created_by = models.ForeignKey(
LocalUser,
on_delete=models.CASCADE,
related_name="created_by",
verbose_name=_("Created by"),
)
foreign_id = models.CharField(
max_length=100,
unique=True,
null=True,
default=None,
verbose_name=_("Foreign ID"),
)
title = models.CharField(
max_length=int(CommonLimit.NORMAL_CHAR),
verbose_name=_("Title"),
)
description = models.TextField(
verbose_name=_("Description"),
)
created_at = models.DateTimeField(
auto_now_add=True,
verbose_name=_("Created at"),
)
type = models.CharField(
max_length=1,
choices=TicketType.choices,
verbose_name=_("Type"),
default=TicketType.BUG,
)
priority = models.CharField(
max_length=1,
choices=TicketPriority.choices,
verbose_name=_("Priority"),
default=TicketPriority.NORMAL,
)
attachment = models.FileField(
verbose_name=_("Attachment"),
upload_to=attachment_upload_path,
null=True,
)
[docs]
def get_absolute_url(self) -> str:
return reverse("ticketing:ticket_detail", kwargs={"pk": str(self.pk)})