from __future__ import annotations import json from django.conf import settings from django.http import Http404, JsonResponse from django.views.decorators.http import require_http_methods from django.contrib.auth.decorators import login_required from review_agent.models import RegulatoryReviewBatch, WorkflowNodeRun from review_agent.regulatory_review.events import record_event from review_agent.regulatory_review.workflow import start_regulatory_review_workflow @require_http_methods(["GET"]) @login_required def batch_status(request, batch_id: int): batch = RegulatoryReviewBatch.objects.filter(pk=batch_id, user=request.user).first() if not batch: raise Http404("批次不存在。") nodes = WorkflowNodeRun.objects.filter( workflow_type="regulatory_review", workflow_batch_id=batch.pk, ).order_by("id") return JsonResponse( { "batch": { "id": batch.pk, "workflow_type": "regulatory_review", "batch_no": batch.batch_no, "status": batch.status, "source_summary_batch_id": batch.source_summary_batch_id, "risk_summary": batch.risk_summary, "risk_summary_text": _format_risk_summary(batch.risk_summary or {}), "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 nodes ], } ) @require_http_methods(["POST"]) @login_required def confirm_conditions(request, batch_id: int): batch = RegulatoryReviewBatch.objects.filter(pk=batch_id, user=request.user).first() if not batch: raise Http404("批次不存在。") try: payload = json.loads(request.body.decode("utf-8") or "{}") except json.JSONDecodeError: return JsonResponse({"error": "请求体不是有效 JSON。"}, status=400) conditions = payload.get("conditions") if not isinstance(conditions, dict): return JsonResponse({"error": "conditions 必须是对象。"}, status=400) batch.condition_json = { **(batch.condition_json or {}), "confirmed": True, "confirmed_conditions": _normalize_conditions(conditions), } batch.status = RegulatoryReviewBatch.Status.RUNNING batch.save(update_fields=["condition_json", "status"]) WorkflowNodeRun.objects.filter( workflow_type="regulatory_review", workflow_batch_id=batch.pk, node_code="condition_confirm", ).update( status=WorkflowNodeRun.Status.SUCCESS, progress=100, message="适用条件已确认", ) record_event( batch, "condition_confirmed", {"conditions": batch.condition_json["confirmed_conditions"], "resume_from": "rule_scope"}, ) start_regulatory_review_workflow( batch, async_run=getattr(settings, "REGULATORY_REVIEW_ASYNC", True), ) batch.refresh_from_db() return JsonResponse( { "batch": { "id": batch.pk, "workflow_type": "regulatory_review", "batch_no": batch.batch_no, "status": batch.status, "condition_json": batch.condition_json, } } ) def _format_risk_summary(risk_summary: dict) -> str: labels = [ ("blocking", "阻断项"), ("high", "高风险"), ("medium", "中风险"), ("low", "低风险"), ("info", "提示"), ] return " · ".join( f"{label} {int(risk_summary.get(key) or 0)}" for key, label in labels if int(risk_summary.get(key) or 0) ) def _normalize_conditions(conditions: dict) -> dict[str, str]: allowed = [ "product_category", "registration_type", "clinical_evaluation_path", "product_name", "model_spec", "intended_use", ] return {key: str(conditions.get(key) or "").strip() for key in allowed}