feat: init commint
This commit is contained in:
@@ -108,6 +108,13 @@ class Ticket(models.Model):
|
||||
on_delete=models.SET_NULL,
|
||||
related_name="created_tickets",
|
||||
)
|
||||
follow_up_of = models.ForeignKey(
|
||||
"self",
|
||||
null=True,
|
||||
blank=True,
|
||||
on_delete=models.SET_NULL,
|
||||
related_name="follow_up_tickets",
|
||||
)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
resolved_at = models.DateTimeField(null=True, blank=True)
|
||||
@@ -286,6 +293,8 @@ class TicketDraft(models.Model):
|
||||
message_timeline = models.JSONField(default=list)
|
||||
missing_fields = models.JSONField(default=list)
|
||||
questions = models.JSONField(default=list)
|
||||
blocking_missing_fields = models.JSONField(default=list)
|
||||
blocking_questions = models.JSONField(default=list)
|
||||
guided_rounds = models.PositiveSmallIntegerField(default=0)
|
||||
latest_agent_run = models.ForeignKey(
|
||||
"agents.AgentRun",
|
||||
@@ -549,6 +558,7 @@ class TicketSupportAnalysis(models.Model):
|
||||
query = models.TextField()
|
||||
references = models.JSONField(default=list)
|
||||
retrieval_policy = models.JSONField(default=dict)
|
||||
result_mode = models.CharField(max_length=24, default="trusted")
|
||||
automation_decision = models.JSONField(default=dict, blank=True)
|
||||
applied_solution = models.ForeignKey(
|
||||
"solutions.Solution",
|
||||
@@ -665,6 +675,131 @@ class CustomerReplyRevision(models.Model):
|
||||
]
|
||||
|
||||
|
||||
class TicketAutomationRunStatus(models.TextChoices):
|
||||
QUEUED = "queued", "Queued"
|
||||
RUNNING = "running", "Running"
|
||||
WAITING_INPUT = "waiting_input", "Waiting input"
|
||||
WAITING_APPROVAL = "waiting_approval", "Waiting approval"
|
||||
WAITING_DELIVERY = "waiting_delivery", "Waiting delivery"
|
||||
WAITING_CUSTOMER = "waiting_customer", "Waiting customer"
|
||||
COMPLETED = "completed", "Completed"
|
||||
FAILED = "failed", "Failed"
|
||||
CANCELLED = "cancelled", "Cancelled"
|
||||
|
||||
|
||||
class TicketAutomationRun(models.Model):
|
||||
"""工单端到端自动处理的持久化编排状态。"""
|
||||
|
||||
public_id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
|
||||
ticket = models.ForeignKey(
|
||||
Ticket,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="automation_runs",
|
||||
)
|
||||
status = models.CharField(
|
||||
max_length=32,
|
||||
choices=TicketAutomationRunStatus.choices,
|
||||
default=TicketAutomationRunStatus.QUEUED,
|
||||
)
|
||||
current_step = models.CharField(max_length=48, default="intake")
|
||||
policy_snapshot = models.JSONField(default=dict, blank=True)
|
||||
blocking_missing_fields = models.JSONField(default=list, blank=True)
|
||||
blocking_questions = models.JSONField(default=list, blank=True)
|
||||
retry_count = models.PositiveSmallIntegerField(default=0)
|
||||
last_error_code = models.CharField(max_length=80, blank=True)
|
||||
last_error_message = models.TextField(blank=True)
|
||||
next_action_at = models.DateTimeField(null=True, blank=True)
|
||||
support_analysis = models.ForeignKey(
|
||||
TicketSupportAnalysis,
|
||||
null=True,
|
||||
blank=True,
|
||||
on_delete=models.SET_NULL,
|
||||
related_name="automation_runs",
|
||||
)
|
||||
reply_task = models.ForeignKey(
|
||||
CustomerReplyTask,
|
||||
null=True,
|
||||
blank=True,
|
||||
on_delete=models.SET_NULL,
|
||||
related_name="automation_runs",
|
||||
)
|
||||
initiated_by = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
null=True,
|
||||
blank=True,
|
||||
on_delete=models.SET_NULL,
|
||||
related_name="initiated_ticket_automation_runs",
|
||||
)
|
||||
approved_by = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
null=True,
|
||||
blank=True,
|
||||
on_delete=models.SET_NULL,
|
||||
related_name="approved_ticket_automation_runs",
|
||||
)
|
||||
approved_at = models.DateTimeField(null=True, blank=True)
|
||||
started_at = models.DateTimeField(null=True, blank=True)
|
||||
finished_at = models.DateTimeField(null=True, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ["-created_at"]
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=["ticket"],
|
||||
condition=models.Q(
|
||||
status__in=[
|
||||
TicketAutomationRunStatus.QUEUED,
|
||||
TicketAutomationRunStatus.RUNNING,
|
||||
TicketAutomationRunStatus.WAITING_INPUT,
|
||||
TicketAutomationRunStatus.WAITING_APPROVAL,
|
||||
TicketAutomationRunStatus.WAITING_DELIVERY,
|
||||
TicketAutomationRunStatus.WAITING_CUSTOMER,
|
||||
]
|
||||
),
|
||||
name="unique_active_ticket_automation_run",
|
||||
)
|
||||
]
|
||||
indexes = [
|
||||
models.Index(
|
||||
fields=["ticket", "status", "created_at"],
|
||||
name="tickets_tic_ticket__f9dbaf_idx",
|
||||
),
|
||||
models.Index(
|
||||
fields=["status", "next_action_at"],
|
||||
name="tickets_tic_status_9ef355_idx",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
class TicketAutomationEvent(models.Model):
|
||||
run = models.ForeignKey(
|
||||
TicketAutomationRun,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="events",
|
||||
)
|
||||
sequence = models.PositiveIntegerField()
|
||||
event_type = models.CharField(max_length=80)
|
||||
payload = models.JSONField(default=dict, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ["sequence"]
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=["run", "sequence"],
|
||||
name="unique_ticket_automation_event_sequence",
|
||||
)
|
||||
]
|
||||
indexes = [
|
||||
models.Index(
|
||||
fields=["run", "sequence"],
|
||||
name="tickets_tic_run_id_d6464b_idx",
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
# Kept temporarily for imports owned by stage 2.1 integrations.
|
||||
TicketDraftImage = TicketDraftMaterial
|
||||
|
||||
|
||||
Reference in New Issue
Block a user