feat(regulatory): 增加mock通知留痕

This commit is contained in:
2026-06-07 09:35:24 +08:00
parent d88d642f6a
commit d39e3fe2d5
4 changed files with 152 additions and 1 deletions

View File

@@ -75,6 +75,13 @@ def build_markdown_report(batch: RegulatoryReviewBatch) -> str:
passed = sum(1 for item in items if item.get("status") == RegulatoryIssue.Status.REVIEW_PASSED)
failed = sum(1 for item in items if item.get("status") == RegulatoryIssue.Status.REVIEW_FAILED)
lines.append(f"| {record.get('file_summary_batch_no')} | {len(items)} | {passed} | {failed} |")
notifications = _notification_records(batch)
if notifications:
lines.extend(["", "## 通知记录", "", "| 渠道 | 对象 | 状态 | 问题 |", "| --- | --- | --- | --- |"])
for record in notifications:
lines.append(
f"| {record['channel']} | {record['target'] or '-'} | {record['status']} | {record['payload'].get('title', '-')} |"
)
return "\n".join(lines)
@@ -99,6 +106,7 @@ def build_result_payload(batch: RegulatoryReviewBatch) -> dict[str, object]:
for issue in batch.issues.order_by("id")
],
"review_records": _review_records(batch),
"notifications": _notification_records(batch),
}
@@ -159,7 +167,7 @@ def _create_excel_export(batch: RegulatoryReviewBatch, path: Path) -> ExportedSu
workbook = Workbook()
sheet = workbook.active
sheet.title = "法规问题清单"
sheet.append(["等级", "类别", "规则", "问题", "状态", "建议", "法规依据"])
sheet.append(["等级", "类别", "规则", "问题", "状态", "建议", "法规依据", "通知记录"])
for issue in batch.issues.order_by("id"):
sheet.append(
[
@@ -170,6 +178,7 @@ def _create_excel_export(batch: RegulatoryReviewBatch, path: Path) -> ExportedSu
issue.status,
issue.suggestion,
"; ".join(str(item.get("source", "")) for item in issue.citations),
_notification_summary_for_issue(batch, issue.pk),
]
)
workbook.save(path)
@@ -192,3 +201,25 @@ def _review_records(batch: RegulatoryReviewBatch) -> list[dict[str, object]]:
except (OSError, json.JSONDecodeError):
continue
return records
def _notification_records(batch: RegulatoryReviewBatch) -> list[dict[str, object]]:
return [
{
"channel": record.channel,
"target": record.target,
"status": record.status,
"payload": record.payload,
"sent_at": record.sent_at.isoformat() if record.sent_at else "",
}
for record in batch.notifications.order_by("created_at", "id")
]
def _notification_summary_for_issue(batch: RegulatoryReviewBatch, issue_id: int) -> str:
records = [
record
for record in batch.notifications.all()
if isinstance(record.payload, dict) and record.payload.get("issue_id") == issue_id
]
return "; ".join(f"{record.channel}:{record.status}" for record in records)

View File

@@ -0,0 +1,39 @@
from __future__ import annotations
from django.utils import timezone
from review_agent.models import RegulatoryNotificationRecord, RegulatoryReviewBatch
NOTIFIABLE_SEVERITIES = {"blocking", "high", "medium"}
def create_mock_notifications(batch: RegulatoryReviewBatch) -> list[RegulatoryNotificationRecord]:
records = []
existing_issue_ids = {
item.get("issue_id")
for item in RegulatoryNotificationRecord.objects.filter(batch=batch, channel=RegulatoryNotificationRecord.Channel.MOCK).values_list(
"payload", flat=True
)
if isinstance(item, dict)
}
for issue in batch.issues.order_by("id"):
if issue.severity not in NOTIFIABLE_SEVERITIES or issue.pk in existing_issue_ids:
continue
records.append(
RegulatoryNotificationRecord.objects.create(
batch=batch,
channel=RegulatoryNotificationRecord.Channel.MOCK,
target="法规整改负责人",
status=RegulatoryNotificationRecord.Status.SENT,
sent_at=timezone.now(),
payload={
"issue_id": issue.pk,
"rule_code": issue.rule_code,
"severity": issue.severity,
"title": issue.title,
"suggestion": issue.suggestion,
},
)
)
return records

View File

@@ -20,6 +20,7 @@ from review_agent.models import (
from review_agent.regulatory_review.services.completeness_check import run_completeness_check
from review_agent.regulatory_review.services.consistency_check import run_consistency_check
from review_agent.regulatory_review.services.export import build_assistant_summary, export_review_results
from review_agent.regulatory_review.services.feishu_notifier import create_mock_notifications
from review_agent.regulatory_review.services.info_extract import detect_regulatory_condition_candidates
from review_agent.regulatory_review.services.risk_assess import persist_findings
from review_agent.regulatory_review.services.rule_loader import load_rule_file
@@ -195,6 +196,7 @@ class RegulatoryWorkflowExecutor:
return
if node_code == "risk_assess":
issues = persist_findings(self.batch, self.findings)
create_mock_notifications(self.batch)
save_artifact(
self.batch,
name="rag_result_json.json",