import json from django.contrib.auth.decorators import login_required from django.conf import settings from django.http import Http404, JsonResponse from django.views.decorators.http import require_http_methods from review_agent.application_form_fill.workflow import ( create_application_form_fill_batch, find_latest_successful_summary_batch, start_application_form_fill_workflow, ) from review_agent.models import ApplicationFormFillBatch, Conversation, ExportedSummaryFile, FileSummaryBatch, WorkflowNodeRun @require_http_methods(["GET"]) def health(request): return JsonResponse({"workflow_type": "application_form_fill", "status": "available"}) @login_required @require_http_methods(["POST"]) def start(request): try: payload = json.loads(request.body.decode("utf-8") or "{}") except json.JSONDecodeError: return JsonResponse({"error": "JSON 格式错误。"}, status=400) conversation = Conversation.objects.filter(pk=payload.get("conversation_id"), user=request.user).first() if not conversation: raise Http404("对话不存在。") summary_batch = None if payload.get("file_summary_batch_id"): summary_batch = FileSummaryBatch.objects.filter( pk=payload.get("file_summary_batch_id"), conversation=conversation, user=request.user, status=FileSummaryBatch.Status.SUCCESS, ).first() if summary_batch is None: summary_batch = find_latest_successful_summary_batch(conversation) if summary_batch is None: return JsonResponse({"error": "请先上传资料并完成文件汇总。"}, status=400) batch = create_application_form_fill_batch( conversation=conversation, user=request.user, source_summary_batch=summary_batch, requested_templates=payload.get("template_codes") or [], output_types=payload.get("output_types") or None, ) start_application_form_fill_workflow(batch, async_run=getattr(settings, "APPLICATION_FORM_FILL_ASYNC", True)) return JsonResponse( { "batch_id": batch.pk, "workflow_type": "application_form_fill", "status": batch.status, "selected_templates": batch.selected_templates, } ) @login_required @require_http_methods(["GET"]) def batch_status(request, batch_id: int): batch = ApplicationFormFillBatch.objects.filter( pk=batch_id, conversation__user=request.user, is_deleted=False, ).first() if not batch: raise Http404("填表批次不存在。") exports = ExportedSummaryFile.objects.filter( workflow_type="application_form_fill", workflow_batch_id=batch.pk, ).order_by("id") return JsonResponse( { "batch": { "id": batch.pk, "workflow_type": "application_form_fill", "batch_no": batch.batch_no, "status": batch.status, "product_name": batch.product_name, "selected_templates": batch.selected_templates, "conflict_count": len(batch.conflict_summary or []), "risk_summary_text": _risk_summary_text(batch), "error_message": batch.error_message, }, "nodes": [ { "node_code": node.node_code, "node_name": node.node_name, "status": node.status, "progress": node.progress, "message": node.message, } for node in WorkflowNodeRun.objects.filter( workflow_type="application_form_fill", workflow_batch_id=batch.pk, ).order_by("id") ], "conflicts": batch.conflict_summary or [], "exports": [ { "id": export.pk, "export_type": export.export_type, "export_category": export.export_category, "file_name": export.file_name, "download_url": f"/api/review-agent/file-summary/exports/{export.pk}/download/", } for export in exports ], } ) def _risk_summary_text(batch: ApplicationFormFillBatch) -> str: parts = [] if batch.selected_templates: parts.append("模板 " + "、".join(batch.selected_templates)) if batch.conflict_summary: parts.append(f"冲突字段 {len(batch.conflict_summary)}") if batch.risk_notes: parts.append(f"提示 {len(batch.risk_notes)}") return " · ".join(parts)