feat: init commint
This commit is contained in:
@@ -18,6 +18,12 @@ from apps.knowledge.distillation import (
|
||||
)
|
||||
from apps.knowledge.models import TicketKnowledgeDistillation
|
||||
from apps.skills.services import SkillValidationError
|
||||
from apps.tickets.automation import (
|
||||
TicketAutomationError,
|
||||
apply_automation_action,
|
||||
approve_and_send,
|
||||
serialize_automation_run,
|
||||
)
|
||||
from apps.tickets.evaluation import build_intake_quality_metrics, record_evaluation_result
|
||||
from apps.tickets.models import (
|
||||
CustomerReplyTask,
|
||||
@@ -25,6 +31,8 @@ from apps.tickets.models import (
|
||||
SupportEvaluationCase,
|
||||
Ticket,
|
||||
TicketAttachment,
|
||||
TicketAutomationRun,
|
||||
TicketAutomationRunStatus,
|
||||
TicketCollaborator,
|
||||
TicketCollaboratorRole,
|
||||
TicketComment,
|
||||
@@ -51,6 +59,9 @@ from apps.tickets.schemas import (
|
||||
SupportQualityMetricsOut,
|
||||
TicketAttachmentIn,
|
||||
TicketAttachmentOut,
|
||||
TicketAutomationActionIn,
|
||||
TicketAutomationApproveIn,
|
||||
TicketAutomationOut,
|
||||
TicketCollaboratorIn,
|
||||
TicketCollaboratorOut,
|
||||
TicketCommentIn,
|
||||
@@ -153,6 +164,7 @@ def serialize_ticket(ticket: Ticket) -> dict:
|
||||
"current_result": ticket.current_result,
|
||||
"requester_id": ticket.requester_id,
|
||||
"assignee_id": ticket.assignee_id,
|
||||
"follow_up_of_id": ticket.follow_up_of_id,
|
||||
"requester": serialize_ticket_user(ticket.requester),
|
||||
"assignee": serialize_ticket_user(ticket.assignee),
|
||||
"problem_started_at": ticket.problem_started_at,
|
||||
@@ -265,6 +277,7 @@ def serialize_support_analysis(item: TicketSupportAnalysis) -> dict:
|
||||
"progress_message": run.progress_message,
|
||||
"query": item.query,
|
||||
"retrieval_policy": item.retrieval_policy,
|
||||
"result_mode": item.result_mode,
|
||||
"references": item.references,
|
||||
"final_output": run.final_output,
|
||||
"automation_decision": item.automation_decision,
|
||||
@@ -730,6 +743,87 @@ def confirm_customer_reply_task_sent(
|
||||
return serialize_customer_reply_task(task)
|
||||
|
||||
|
||||
@router.get("/{ticket_id}/automation", response=TicketAutomationOut | None)
|
||||
def get_ticket_automation(request, ticket_id: int):
|
||||
require_permission(request, "ticket.view")
|
||||
run = (
|
||||
TicketAutomationRun.objects.select_related("ticket")
|
||||
.filter(ticket_id=ticket_id)
|
||||
.first()
|
||||
)
|
||||
return serialize_automation_run(run) if run is not None else None
|
||||
|
||||
|
||||
@router.post("/{ticket_id}/approve-and-send", response=TicketAutomationOut)
|
||||
def approve_ticket_automation_and_send(
|
||||
request,
|
||||
ticket_id: int,
|
||||
payload: TicketAutomationApproveIn,
|
||||
):
|
||||
require_permission(request, "ticket.reply")
|
||||
require_permission(request, "ticket.resolve")
|
||||
if payload.channel_endpoint_id:
|
||||
require_permission(request, "channel.send")
|
||||
run = (
|
||||
TicketAutomationRun.objects.select_related("ticket", "reply_task")
|
||||
.filter(ticket_id=ticket_id)
|
||||
.first()
|
||||
)
|
||||
if run is None:
|
||||
raise HttpError(404, "工单自动化运行不存在")
|
||||
if run.status in {
|
||||
TicketAutomationRunStatus.WAITING_CUSTOMER,
|
||||
TicketAutomationRunStatus.COMPLETED,
|
||||
} and run.approved_at:
|
||||
return serialize_automation_run(run)
|
||||
if run.ticket.updated_at != payload.expected_ticket_updated_at:
|
||||
raise HttpError(409, "工单已被更新,请刷新后重新确认")
|
||||
try:
|
||||
run = approve_and_send(
|
||||
run,
|
||||
actor=request.user,
|
||||
expected_reply_revision=payload.expected_reply_revision,
|
||||
final_text=payload.final_text,
|
||||
resolution_text=payload.resolution_text,
|
||||
root_cause=payload.root_cause,
|
||||
solution_id=payload.solution_id,
|
||||
channel_endpoint_id=payload.channel_endpoint_id,
|
||||
external_conversation_id=payload.external_conversation_id,
|
||||
manual_delivery_confirmed=payload.manual_delivery_confirmed,
|
||||
)
|
||||
except (TicketAutomationError, CustomerReplyError) as error:
|
||||
raise HttpError(409, str(error)) from error
|
||||
return serialize_automation_run(
|
||||
TicketAutomationRun.objects.select_related("ticket").get(id=run.id)
|
||||
)
|
||||
|
||||
|
||||
@router.post("/{ticket_id}/automation/actions", response=TicketAutomationOut)
|
||||
def act_on_ticket_automation(
|
||||
request,
|
||||
ticket_id: int,
|
||||
payload: TicketAutomationActionIn,
|
||||
):
|
||||
require_permission(request, "ticket.edit")
|
||||
run = (
|
||||
TicketAutomationRun.objects.select_related("ticket")
|
||||
.filter(ticket_id=ticket_id)
|
||||
.first()
|
||||
)
|
||||
if run is None:
|
||||
raise HttpError(404, "工单自动化运行不存在")
|
||||
if payload.action == "retry" and run.current_step == "delivery_failed":
|
||||
require_permission(request, "ticket.reply")
|
||||
require_permission(request, "channel.send")
|
||||
try:
|
||||
run = apply_automation_action(run, payload.action, actor=request.user)
|
||||
except TicketAutomationError as error:
|
||||
raise HttpError(409, str(error)) from error
|
||||
return serialize_automation_run(
|
||||
TicketAutomationRun.objects.select_related("ticket").get(id=run.id)
|
||||
)
|
||||
|
||||
|
||||
@router.get("/{ticket_id}", response=TicketOut)
|
||||
def get_ticket(request, ticket_id: int):
|
||||
require_permission(request, "ticket.view")
|
||||
|
||||
Reference in New Issue
Block a user