from django.db import models
from django.db.models import Q
from django.utils.safestring import mark_safe
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
from enumfields import Enum, EnumIntegerField
from parler.models import TranslatableModel, TranslatedFields
from shuup.core.fields import InternalIdentifierField
from shuup.utils.analog import LogEntryKind, define_log_model
from shuup.utils.django_compat import force_text
[docs]
class TaskStatus(Enum):
NEW = 1
IN_PROGRESS = 2
COMPLETED = 3
DELETED = 4
class Labels:
NEW = _("New")
IN_PROGRESS = _("In progress")
COMPLETED = _("Completed")
DELETED = _("Deleted")
[docs]
class TaskType(TranslatableModel):
identifier = InternalIdentifierField(unique=False, blank=True, null=True, editable=True)
shop = models.ForeignKey(
on_delete=models.CASCADE,
to="shuup.Shop",
verbose_name=_("shop"),
related_name="task_types",
)
translations = TranslatedFields(name=models.TextField(verbose_name=_("name")))
class Meta:
unique_together = ("shop", "identifier")
verbose_name = _("task type")
verbose_name_plural = _("task types")
def __str__(self):
return self.name
[docs]
class TaskQuerySet(models.QuerySet):
[docs]
def completed(self):
return self.filter(status=TaskStatus.COMPLETED)
[docs]
def in_progress(self):
return self.filter(status=TaskStatus.IN_PROGRESS)
[docs]
def is_new(self):
return self.filter(tatus=TaskStatus.NEW)
[docs]
def for_shop(self, shop):
return self.filter(shop=shop)
[docs]
def delete(self):
self.update(status=TaskStatus.DELETED)
[docs]
def assigned_to(self, contact):
return self.filter(assigned_to=contact)
[docs]
class Task(models.Model):
shop = models.ForeignKey(
on_delete=models.CASCADE,
to="shuup.Shop",
verbose_name=_("shop"),
related_name="tasks",
)
name = models.CharField(verbose_name=_("name"), max_length=60)
type = models.ForeignKey(
on_delete=models.CASCADE,
to=TaskType,
verbose_name=_("task type"),
related_name="tasks",
)
status = EnumIntegerField(TaskStatus, default=TaskStatus.NEW, verbose_name=_("status"))
priority = models.PositiveIntegerField(default=0, verbose_name=_("priority"), db_index=True)
creator = models.ForeignKey(
on_delete=models.CASCADE,
to="shuup.Contact",
blank=True,
null=True,
related_name="creted_tasks",
verbose_name=_("creator"),
)
assigned_to = models.ForeignKey(
on_delete=models.CASCADE,
to="shuup.Contact",
blank=True,
null=True,
related_name="assigned_tasks",
verbose_name=_("assigned to"),
)
completed_by = models.ForeignKey(
on_delete=models.CASCADE,
to="shuup.Contact",
blank=True,
null=True,
related_name="completed_tasks",
verbose_name=_("completed by"),
)
completed_on = models.DateTimeField(verbose_name=_("completed on"), null=True, blank=True)
created_on = models.DateTimeField(auto_now_add=True, editable=False, db_index=True, verbose_name=_("created on"))
modified_on = models.DateTimeField(auto_now=True, editable=False, db_index=True, verbose_name=_("modified on"))
objects = TaskQuerySet.as_manager()
def __str__(self):
return self.name
[docs]
def assign(self, user):
self.assigned_to = user
self.status = TaskStatus.IN_PROGRESS
self.save()
[docs]
def delete(self):
self.status = TaskStatus.DELETED
self.save(update_fields=["status"])
self.add_log_entry("Success! Deleted (soft).", kind=LogEntryKind.DELETION)
[docs]
def set_in_progress(self):
self.status = TaskStatus.IN_PROGRESS
self.add_log_entry("Info! In progress.", kind=LogEntryKind.EDIT)
self.save()
[docs]
def set_completed(self, contact):
self.completed_by = contact
self.completed_on = now()
self.status = TaskStatus.COMPLETED
self.add_log_entry("Success! Completed.", kind=LogEntryKind.EDIT)
self.save()
[docs]
def get_completion_time(self):
if self.completed_on:
return self.completed_on - self.created_on
TaskLogEntry = define_log_model(Task)