Implement tasks
This commit is contained in:
285
core/models.py
285
core/models.py
@@ -1921,6 +1921,291 @@ class TranslationEventLog(models.Model):
|
||||
]
|
||||
|
||||
|
||||
class AnswerMemory(models.Model):
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="answer_memory")
|
||||
service = models.CharField(max_length=255, choices=CHANNEL_SERVICE_CHOICES)
|
||||
channel_identifier = models.CharField(max_length=255)
|
||||
question_fingerprint = models.CharField(max_length=128)
|
||||
question_text = models.TextField(blank=True, default="")
|
||||
answer_message = models.ForeignKey(
|
||||
Message,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="answer_memory_rows",
|
||||
)
|
||||
answer_text = models.TextField(blank=True, default="")
|
||||
confidence_meta = models.JSONField(default=dict, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
indexes = [
|
||||
models.Index(fields=["user", "service", "channel_identifier", "created_at"]),
|
||||
models.Index(fields=["user", "question_fingerprint", "created_at"]),
|
||||
]
|
||||
|
||||
|
||||
class AnswerSuggestionEvent(models.Model):
|
||||
STATUS_CHOICES = (
|
||||
("suggested", "Suggested"),
|
||||
("accepted", "Accepted"),
|
||||
("dismissed", "Dismissed"),
|
||||
)
|
||||
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
user = models.ForeignKey(
|
||||
User,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="answer_suggestion_events",
|
||||
)
|
||||
message = models.ForeignKey(
|
||||
Message,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="answer_suggestion_events",
|
||||
)
|
||||
status = models.CharField(max_length=32, choices=STATUS_CHOICES, default="suggested")
|
||||
candidate_answer = models.ForeignKey(
|
||||
AnswerMemory,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="suggestion_events",
|
||||
)
|
||||
score = models.FloatField(default=0.0)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
indexes = [
|
||||
models.Index(fields=["user", "status", "created_at"]),
|
||||
models.Index(fields=["message", "status"]),
|
||||
]
|
||||
|
||||
|
||||
class TaskProject(models.Model):
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="task_projects")
|
||||
name = models.CharField(max_length=255)
|
||||
external_key = models.CharField(max_length=255, blank=True, default="")
|
||||
active = models.BooleanField(default=True)
|
||||
settings = models.JSONField(default=dict, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=["user", "name"],
|
||||
name="unique_task_project_name_per_user",
|
||||
)
|
||||
]
|
||||
indexes = [models.Index(fields=["user", "active", "updated_at"])]
|
||||
|
||||
|
||||
class TaskEpic(models.Model):
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
project = models.ForeignKey(
|
||||
TaskProject,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="epics",
|
||||
)
|
||||
name = models.CharField(max_length=255)
|
||||
external_key = models.CharField(max_length=255, blank=True, default="")
|
||||
active = models.BooleanField(default=True)
|
||||
settings = models.JSONField(default=dict, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=["project", "name"],
|
||||
name="unique_task_epic_name_per_project",
|
||||
)
|
||||
]
|
||||
indexes = [models.Index(fields=["project", "active", "updated_at"])]
|
||||
|
||||
|
||||
class ChatTaskSource(models.Model):
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="chat_task_sources")
|
||||
service = models.CharField(max_length=255, choices=CHANNEL_SERVICE_CHOICES)
|
||||
channel_identifier = models.CharField(max_length=255)
|
||||
project = models.ForeignKey(
|
||||
TaskProject,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="chat_sources",
|
||||
)
|
||||
epic = models.ForeignKey(
|
||||
TaskEpic,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="chat_sources",
|
||||
)
|
||||
enabled = models.BooleanField(default=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
indexes = [
|
||||
models.Index(fields=["user", "service", "channel_identifier", "enabled"]),
|
||||
models.Index(fields=["project", "enabled"]),
|
||||
]
|
||||
|
||||
|
||||
class DerivedTask(models.Model):
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="derived_tasks")
|
||||
project = models.ForeignKey(
|
||||
TaskProject,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="derived_tasks",
|
||||
)
|
||||
epic = models.ForeignKey(
|
||||
TaskEpic,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="derived_tasks",
|
||||
)
|
||||
title = models.CharField(max_length=255)
|
||||
source_service = models.CharField(max_length=255, choices=CHANNEL_SERVICE_CHOICES)
|
||||
source_channel = models.CharField(max_length=255)
|
||||
origin_message = models.ForeignKey(
|
||||
Message,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="derived_task_origins",
|
||||
)
|
||||
reference_code = models.CharField(max_length=64, blank=True, default="")
|
||||
external_key = models.CharField(max_length=255, blank=True, default="")
|
||||
status_snapshot = models.CharField(max_length=64, blank=True, default="open")
|
||||
immutable_payload = models.JSONField(default=dict, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
indexes = [
|
||||
models.Index(fields=["user", "project", "created_at"]),
|
||||
models.Index(fields=["user", "source_service", "source_channel"]),
|
||||
models.Index(fields=["user", "reference_code"]),
|
||||
]
|
||||
|
||||
|
||||
class DerivedTaskEvent(models.Model):
|
||||
EVENT_CHOICES = (
|
||||
("created", "Created"),
|
||||
("progress", "Progress"),
|
||||
("completion_marked", "Completion Marked"),
|
||||
("synced", "Synced"),
|
||||
("sync_failed", "Sync Failed"),
|
||||
("parse_warning", "Parse Warning"),
|
||||
)
|
||||
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
task = models.ForeignKey(
|
||||
DerivedTask,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="events",
|
||||
)
|
||||
event_type = models.CharField(max_length=32, choices=EVENT_CHOICES)
|
||||
actor_identifier = models.CharField(max_length=255, blank=True, default="")
|
||||
source_message = models.ForeignKey(
|
||||
Message,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="derived_task_events",
|
||||
)
|
||||
payload = models.JSONField(default=dict, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ["created_at", "id"]
|
||||
indexes = [
|
||||
models.Index(fields=["task", "created_at"]),
|
||||
models.Index(fields=["event_type", "created_at"]),
|
||||
]
|
||||
|
||||
|
||||
class ExternalSyncEvent(models.Model):
|
||||
STATUS_CHOICES = (
|
||||
("pending", "Pending"),
|
||||
("ok", "OK"),
|
||||
("failed", "Failed"),
|
||||
("retrying", "Retrying"),
|
||||
)
|
||||
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="external_sync_events")
|
||||
task = models.ForeignKey(
|
||||
DerivedTask,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="external_sync_events",
|
||||
)
|
||||
task_event = models.ForeignKey(
|
||||
DerivedTaskEvent,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="external_sync_events",
|
||||
)
|
||||
provider = models.CharField(max_length=64, default="mock")
|
||||
idempotency_key = models.CharField(max_length=255, blank=True, default="")
|
||||
status = models.CharField(max_length=32, choices=STATUS_CHOICES, default="pending")
|
||||
payload = models.JSONField(default=dict, blank=True)
|
||||
error = models.TextField(blank=True, default="")
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
indexes = [
|
||||
models.Index(fields=["user", "provider", "status", "updated_at"]),
|
||||
models.Index(fields=["idempotency_key"]),
|
||||
]
|
||||
|
||||
|
||||
class TaskProviderConfig(models.Model):
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="task_provider_configs")
|
||||
provider = models.CharField(max_length=64, default="mock")
|
||||
enabled = models.BooleanField(default=False)
|
||||
settings = models.JSONField(default=dict, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=["user", "provider"],
|
||||
name="unique_task_provider_config_per_user",
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
class TaskCompletionPattern(models.Model):
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="task_completion_patterns")
|
||||
phrase = models.CharField(max_length=64)
|
||||
enabled = models.BooleanField(default=True)
|
||||
position = models.PositiveIntegerField(default=0)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=["user", "phrase"],
|
||||
name="unique_task_completion_phrase_per_user",
|
||||
)
|
||||
]
|
||||
indexes = [models.Index(fields=["user", "enabled", "position"])]
|
||||
|
||||
|
||||
# class Perms(models.Model):
|
||||
# class Meta:
|
||||
# permissions = (
|
||||
|
||||
Reference in New Issue
Block a user