feat(regulatory): 增加mock通知留痕
This commit is contained in:
@@ -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)
|
||||
|
||||
39
review_agent/regulatory_review/services/feishu_notifier.py
Normal file
39
review_agent/regulatory_review/services/feishu_notifier.py
Normal 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
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user