feat: 新增预算中心本体与风险规则评分回填
后端新增预算本体解析模块和风险规则评分回填服务,优化规则 生成本体对齐和提示词构建,增强费用类型关键词和本体验证, 完善报销查询和审计接口,前端预算中心页面增加对话框和本 体工具函数,重构审计页面元数据和视图模型,补充单元测试。
This commit is contained in:
@@ -148,11 +148,12 @@ class AgentAssetRiskRuleTestingMixin:
|
||||
if not body.confirm_passed:
|
||||
raise ValueError("请确认测试通过后再保存测试报告。")
|
||||
|
||||
summary = "测试报告已确认,当前版本可提交审核。"
|
||||
summary = "测试报告已确认,当前版本可上线。"
|
||||
if scenario is None:
|
||||
summary = "快速样例测试已确认通过,真实场景试运行未执行。"
|
||||
elif not scenario.passed:
|
||||
summary = "快速样例测试已确认通过,真实场景试运行未找到可测样本。"
|
||||
self._mark_risk_rule_operation(asset, action="test", actor=actor)
|
||||
return self._create_test_run(
|
||||
asset,
|
||||
version=version,
|
||||
@@ -162,9 +163,9 @@ class AgentAssetRiskRuleTestingMixin:
|
||||
input_json={"confirm_passed": True, "note": body.note or ""},
|
||||
result_json={
|
||||
"sample_test_run_id": sample.id,
|
||||
"scenario_test_run_id": scenario.id,
|
||||
"scenario_test_run_id": scenario.id if scenario else "",
|
||||
"sample_summary": sample.summary,
|
||||
"scenario_summary": scenario.summary,
|
||||
"scenario_summary": scenario.summary if scenario else "",
|
||||
},
|
||||
actor=actor,
|
||||
request_id=request_id,
|
||||
@@ -308,6 +309,11 @@ class AgentAssetRiskRuleTestingMixin:
|
||||
|
||||
config_json = dict(asset.config_json or {})
|
||||
config_json["enabled"] = bool(enabled)
|
||||
self._set_risk_rule_status_for_online_toggle(asset, enabled=enabled, actor=actor)
|
||||
config_json["last_operation"] = self._build_last_operation(
|
||||
action="online" if enabled else "offline",
|
||||
actor=actor,
|
||||
)
|
||||
asset.config_json = config_json
|
||||
updated = self.repository.save_asset(asset)
|
||||
self.audit_service.log_action(
|
||||
@@ -321,6 +327,50 @@ class AgentAssetRiskRuleTestingMixin:
|
||||
)
|
||||
return updated
|
||||
|
||||
def _set_risk_rule_status_for_online_toggle(
|
||||
self,
|
||||
asset: AgentAsset,
|
||||
*,
|
||||
enabled: bool,
|
||||
actor: str,
|
||||
) -> None:
|
||||
if enabled:
|
||||
version = self._resolve_target_version(asset, None)
|
||||
approved_review = self.repository.get_review(
|
||||
asset.id, version, AgentReviewStatus.APPROVED.value
|
||||
)
|
||||
if approved_review is None:
|
||||
self.db.add(
|
||||
AgentAssetReview(
|
||||
asset_id=asset.id,
|
||||
version=version,
|
||||
reviewer=actor,
|
||||
review_status=AgentReviewStatus.APPROVED.value,
|
||||
review_note="直接上线风险规则。",
|
||||
reviewed_at=datetime.now(UTC),
|
||||
)
|
||||
)
|
||||
asset.published_version = version
|
||||
asset.reviewer = actor
|
||||
asset.status = AgentAssetStatus.ACTIVE.value
|
||||
return
|
||||
|
||||
asset.status = AgentAssetStatus.DISABLED.value
|
||||
|
||||
def _mark_risk_rule_operation(self, asset: AgentAsset, *, action: str, actor: str) -> None:
|
||||
config_json = dict(asset.config_json or {})
|
||||
config_json["last_operation"] = self._build_last_operation(action=action, actor=actor)
|
||||
asset.config_json = config_json
|
||||
self.db.add(asset)
|
||||
|
||||
@staticmethod
|
||||
def _build_last_operation(*, action: str, actor: str) -> dict[str, str]:
|
||||
return {
|
||||
"action": action,
|
||||
"actor": str(actor or "system").strip() or "system",
|
||||
"at": datetime.now(UTC).isoformat(),
|
||||
}
|
||||
|
||||
def _load_risk_rule_for_test(
|
||||
self, asset_id: str, version: str | None
|
||||
) -> tuple[AgentAsset, str, dict[str, Any]]:
|
||||
|
||||
Reference in New Issue
Block a user