diff --git a/backend/apps/knowledge/distillation.py b/backend/apps/knowledge/distillation.py index c930075..463ed98 100644 --- a/backend/apps/knowledge/distillation.py +++ b/backend/apps/knowledge/distillation.py @@ -146,7 +146,7 @@ def start_ticket_knowledge_distillation( """从可信解决结果启动幂等蒸馏运行,并冻结工单输入快照。""" ticket = ( - Ticket.objects.select_for_update() + Ticket.objects.select_for_update(of=("self",)) .select_related("category", "resolution") .get(id=ticket.id) ) @@ -255,7 +255,7 @@ def process_knowledge_distillation_result( if run.definition.code != KNOWLEDGE_DISTILLATION_AGENT_CODE or run.status != "succeeded": return None distillation = ( - TicketKnowledgeDistillation.objects.select_for_update() + TicketKnowledgeDistillation.objects.select_for_update(of=("self",)) .select_related("ticket__category", "ticket__resolution", "run__created_by") .get(run=run) ) diff --git a/backend/apps/tickets/draft_services.py b/backend/apps/tickets/draft_services.py index e867737..770a474 100644 --- a/backend/apps/tickets/draft_services.py +++ b/backend/apps/tickets/draft_services.py @@ -671,7 +671,7 @@ def _auto_create_ticket( # Agent/Celery 重试可能并发进入;锁定受理记录后再判断是否已经完成建单。 draft = ( - TicketDraft.objects.select_for_update() + TicketDraft.objects.select_for_update(of=("self",)) .select_related("created_by", "confirmed_ticket") .prefetch_related("materials") .get(id=draft_id) @@ -944,7 +944,7 @@ def cancel_draft_analysis( user, ) -> TicketDraft: draft = ( - TicketDraft.objects.select_for_update() + TicketDraft.objects.select_for_update(of=("self",)) .select_related("latest_agent_run", "created_by") .get(public_id=draft_public_id, created_by=user) ) diff --git a/backend/apps/tickets/replies.py b/backend/apps/tickets/replies.py index f3c7933..fdabf85 100644 --- a/backend/apps/tickets/replies.py +++ b/backend/apps/tickets/replies.py @@ -38,7 +38,7 @@ def ensure_customer_reply_task( if not normalized: return None analysis = ( - TicketSupportAnalysis.objects.select_for_update() + TicketSupportAnalysis.objects.select_for_update(of=("self",)) .select_related("ticket", "run", "created_by") .get(id=analysis.id) ) @@ -106,7 +106,7 @@ def update_customer_reply( """使用乐观版本号修订回复,已批准或已发送版本不可被静默覆盖。""" task = ( - CustomerReplyTask.objects.select_for_update() + CustomerReplyTask.objects.select_for_update(of=("self",)) .select_related("ticket", "support_analysis") .get(id=task.id) ) @@ -162,7 +162,7 @@ def approve_customer_reply_for_channel( """批准指定回复版本进入唯一渠道会话,不在此函数直接发送消息。""" task = ( - CustomerReplyTask.objects.select_for_update() + CustomerReplyTask.objects.select_for_update(of=("self",)) .select_related("ticket", "support_analysis") .get(id=task.id) ) @@ -227,7 +227,7 @@ def confirm_customer_reply_sent( """仅在人工确认或渠道明确送达后标记回复完成并记录审计。""" task = ( - CustomerReplyTask.objects.select_for_update() + CustomerReplyTask.objects.select_for_update(of=("self",)) .select_related("ticket", "support_analysis") .get(id=task.id) ) diff --git a/backend/apps/tickets/services.py b/backend/apps/tickets/services.py index bf02a22..7c21f2c 100644 --- a/backend/apps/tickets/services.py +++ b/backend/apps/tickets/services.py @@ -493,7 +493,11 @@ def update_ticket_fields( if unknown_fields: raise TicketDataError(f"不允许修改字段: {', '.join(sorted(unknown_fields))}") - ticket = Ticket.objects.select_for_update().select_related("category").get(id=ticket.id) + ticket = ( + Ticket.objects.select_for_update(of=("self",)) + .select_related("category") + .get(id=ticket.id) + ) evidence_by_field = evidence_by_field or {} confidence_by_field = confidence_by_field or {} before: dict = {} @@ -841,7 +845,7 @@ def adopt_solution_for_ticket( if locked_solution.status != "published": raise TicketDataError("只能采纳已发布的解决方案") locked_ticket = ( - Ticket.objects.select_for_update() + Ticket.objects.select_for_update(of=("self",)) .select_related("category", "resolution") .get(id=ticket.id) ) diff --git a/backend/apps/tickets/support_analysis.py b/backend/apps/tickets/support_analysis.py index 8386d2a..b5a82ea 100644 --- a/backend/apps/tickets/support_analysis.py +++ b/backend/apps/tickets/support_analysis.py @@ -508,7 +508,7 @@ def process_support_analysis_result(run: AgentRun) -> TicketSupportAnalysis | No if run.definition.code != SUPPORT_AGENT_CODE or run.status != "succeeded": return None analysis = ( - TicketSupportAnalysis.objects.select_for_update() + TicketSupportAnalysis.objects.select_for_update(of=("self",)) .select_related( "ticket__category", "ticket__resolution", @@ -583,7 +583,11 @@ def process_support_analysis_result(run: AgentRun) -> TicketSupportAnalysis | No def start_ticket_support_analysis(ticket: Ticket, *, created_by=None) -> TicketSupportAnalysis: """为工单创建唯一活动分析并投递绑定正式 Agent 版本的运行。""" - ticket = Ticket.objects.select_for_update().select_related("category").get(id=ticket.id) + ticket = ( + Ticket.objects.select_for_update(of=("self",)) + .select_related("category") + .get(id=ticket.id) + ) if ticket.archived_at is not None: raise SupportAnalysisError("已归档工单不能启动支持分析") if ticket.status in {"resolved", "closed"}: diff --git a/backend/apps/workitems/services.py b/backend/apps/workitems/services.py index b63780d..557d86f 100644 --- a/backend/apps/workitems/services.py +++ b/backend/apps/workitems/services.py @@ -257,7 +257,7 @@ def sync_ticket_intake_failure_work_item( actor=None, ) -> WorkItem | None: draft = ( - TicketDraft.objects.select_for_update() + TicketDraft.objects.select_for_update(of=("self",)) .select_related("created_by", "latest_agent_run") .get(id=draft.id) )