727 lines
16 KiB
Python
727 lines
16 KiB
Python
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import hashlib
|
||
|
|
import json
|
||
|
|
from datetime import UTC, date, datetime
|
||
|
|
from decimal import Decimal
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
from sqlalchemy import inspect, select, text
|
||
|
|
|
||
|
|
from app.core.agent_enums import (
|
||
|
|
AgentAssetContentType,
|
||
|
|
AgentAssetDomain,
|
||
|
|
AgentAssetStatus,
|
||
|
|
AgentAssetType,
|
||
|
|
AgentName,
|
||
|
|
AgentPermissionLevel,
|
||
|
|
AgentReviewStatus,
|
||
|
|
AgentRunSource,
|
||
|
|
AgentRunStatus,
|
||
|
|
AgentToolType,
|
||
|
|
)
|
||
|
|
from app.models.agent_asset import AgentAsset, AgentAssetReview, AgentAssetVersion
|
||
|
|
from app.models.agent_run import AgentRun, AgentToolCall, SemanticParseLog
|
||
|
|
from app.models.audit_log import AuditLog
|
||
|
|
from app.models.financial_record import (
|
||
|
|
AccountsPayableRecord,
|
||
|
|
AccountsReceivableRecord,
|
||
|
|
ExpenseClaim,
|
||
|
|
ExpenseClaimItem,
|
||
|
|
)
|
||
|
|
from app.services.agent_asset_rule_library import AgentAssetRuleLibraryManager
|
||
|
|
from app.services.agent_asset_spreadsheet import (
|
||
|
|
AgentAssetSpreadsheetManager,
|
||
|
|
COMPANY_COMMUNICATION_EXPENSE_RULE_CODE,
|
||
|
|
COMPANY_COMMUNICATION_EXPENSE_RULE_FILENAME,
|
||
|
|
COMPANY_TRAVEL_EXPENSE_RULE_CODE,
|
||
|
|
COMPANY_TRAVEL_EXPENSE_RULE_FILENAME,
|
||
|
|
FINANCE_RULES_LIBRARY,
|
||
|
|
RISK_RULES_LIBRARY,
|
||
|
|
)
|
||
|
|
from app.services.expense_rule_runtime import (
|
||
|
|
build_scene_submission_standard_markdown,
|
||
|
|
build_travel_risk_control_standard_markdown,
|
||
|
|
)
|
||
|
|
from app.services.agent_foundation_constants import (
|
||
|
|
ATTACHMENT_RULE_ASSET_CODE,
|
||
|
|
ATTACHMENT_RULE_RUNTIME_CONFIG,
|
||
|
|
COMPANY_COMMUNICATION_RULE_SCENARIO_JSON,
|
||
|
|
COMPANY_COMMUNICATION_RULE_VERSION,
|
||
|
|
COMPANY_TRAVEL_RULE_SCENARIO_JSON,
|
||
|
|
COMPANY_TRAVEL_RULE_VERSION,
|
||
|
|
DEMO_EXPENSE_CLAIM_SIGNATURES,
|
||
|
|
DEMO_PAYABLE_SIGNATURES,
|
||
|
|
DEMO_RECEIVABLE_SIGNATURES,
|
||
|
|
LEGACY_RULE_CODES,
|
||
|
|
PLATFORM_DESTINATION_LOCATION_RULE_FILENAME,
|
||
|
|
)
|
||
|
|
from app.core.logging import get_logger
|
||
|
|
|
||
|
|
logger = get_logger("app.services.agent_foundation")
|
||
|
|
|
||
|
|
class AgentFoundationFinancialSeedMixin:
|
||
|
|
def _seed_financial_records(self) -> None:
|
||
|
|
|
||
|
|
if self.db.scalar(select(ExpenseClaim.id).limit(1)) is not None:
|
||
|
|
|
||
|
|
return
|
||
|
|
|
||
|
|
claim_1 = ExpenseClaim(
|
||
|
|
|
||
|
|
claim_no="EXP-202605-001",
|
||
|
|
|
||
|
|
employee_name="张三",
|
||
|
|
|
||
|
|
department_name="财务共享中心",
|
||
|
|
|
||
|
|
project_code="PRJ-EXP-01",
|
||
|
|
|
||
|
|
expense_type="travel",
|
||
|
|
|
||
|
|
reason="华南客户拜访差旅报销",
|
||
|
|
|
||
|
|
location="深圳",
|
||
|
|
|
||
|
|
amount=Decimal("3280.00"),
|
||
|
|
|
||
|
|
currency="CNY",
|
||
|
|
|
||
|
|
invoice_count=3,
|
||
|
|
|
||
|
|
occurred_at=datetime(2026, 5, 6, 9, 0, tzinfo=UTC),
|
||
|
|
|
||
|
|
submitted_at=datetime(2026, 5, 7, 10, 20, tzinfo=UTC),
|
||
|
|
|
||
|
|
status="submitted",
|
||
|
|
|
||
|
|
approval_stage="finance_review",
|
||
|
|
|
||
|
|
risk_flags_json=["amount_over_limit"],
|
||
|
|
|
||
|
|
)
|
||
|
|
|
||
|
|
claim_1.items = [
|
||
|
|
|
||
|
|
ExpenseClaimItem(
|
||
|
|
|
||
|
|
item_date=date(2026, 5, 5),
|
||
|
|
|
||
|
|
item_type="hotel",
|
||
|
|
|
||
|
|
item_reason="客户拜访住宿",
|
||
|
|
|
||
|
|
item_location="深圳",
|
||
|
|
|
||
|
|
item_amount=Decimal("1880.00"),
|
||
|
|
|
||
|
|
invoice_id="INV-HOTEL-001",
|
||
|
|
|
||
|
|
),
|
||
|
|
|
||
|
|
ExpenseClaimItem(
|
||
|
|
|
||
|
|
item_date=date(2026, 5, 6),
|
||
|
|
|
||
|
|
item_type="transport",
|
||
|
|
|
||
|
|
item_reason="往返交通",
|
||
|
|
|
||
|
|
item_location="深圳",
|
||
|
|
|
||
|
|
item_amount=Decimal("1400.00"),
|
||
|
|
|
||
|
|
invoice_id="INV-TRANS-009",
|
||
|
|
|
||
|
|
),
|
||
|
|
|
||
|
|
]
|
||
|
|
|
||
|
|
claim_2 = ExpenseClaim(
|
||
|
|
|
||
|
|
claim_no="EXP-202605-002",
|
||
|
|
|
||
|
|
employee_name="李四",
|
||
|
|
|
||
|
|
department_name="华东销售部",
|
||
|
|
|
||
|
|
project_code="PRJ-SALES-02",
|
||
|
|
|
||
|
|
expense_type="meal",
|
||
|
|
|
||
|
|
reason="客户路演餐费",
|
||
|
|
|
||
|
|
location="上海",
|
||
|
|
|
||
|
|
amount=Decimal("860.00"),
|
||
|
|
|
||
|
|
currency="CNY",
|
||
|
|
|
||
|
|
invoice_count=1,
|
||
|
|
|
||
|
|
occurred_at=datetime(2026, 5, 8, 12, 0, tzinfo=UTC),
|
||
|
|
|
||
|
|
submitted_at=datetime(2026, 5, 8, 18, 30, tzinfo=UTC),
|
||
|
|
|
||
|
|
status="approved",
|
||
|
|
|
||
|
|
approval_stage="completed",
|
||
|
|
|
||
|
|
risk_flags_json=[],
|
||
|
|
|
||
|
|
)
|
||
|
|
|
||
|
|
claim_3 = ExpenseClaim(
|
||
|
|
|
||
|
|
claim_no="EXP-202605-003",
|
||
|
|
|
||
|
|
employee_name="王五",
|
||
|
|
|
||
|
|
department_name="市场品牌部",
|
||
|
|
|
||
|
|
project_code="PRJ-MKT-08",
|
||
|
|
|
||
|
|
expense_type="travel",
|
||
|
|
|
||
|
|
reason="市场活动会务差旅",
|
||
|
|
|
||
|
|
location="北京",
|
||
|
|
|
||
|
|
amount=Decimal("3280.00"),
|
||
|
|
|
||
|
|
currency="CNY",
|
||
|
|
|
||
|
|
invoice_count=2,
|
||
|
|
|
||
|
|
occurred_at=datetime(2026, 5, 6, 11, 30, tzinfo=UTC),
|
||
|
|
|
||
|
|
submitted_at=datetime(2026, 5, 8, 9, 10, tzinfo=UTC),
|
||
|
|
|
||
|
|
status="review",
|
||
|
|
|
||
|
|
approval_stage="risk_check",
|
||
|
|
|
||
|
|
risk_flags_json=["duplicate_expense"],
|
||
|
|
|
||
|
|
)
|
||
|
|
|
||
|
|
ar_records = [
|
||
|
|
|
||
|
|
AccountsReceivableRecord(
|
||
|
|
|
||
|
|
receivable_no="AR-202605-001",
|
||
|
|
|
||
|
|
customer_id="CUS-A",
|
||
|
|
|
||
|
|
customer_name="客户A",
|
||
|
|
|
||
|
|
contract_no="CTR-AR-1001",
|
||
|
|
|
||
|
|
invoice_no="INV-AR-9001",
|
||
|
|
|
||
|
|
amount_receivable=Decimal("120000.00"),
|
||
|
|
|
||
|
|
amount_received=Decimal("70000.00"),
|
||
|
|
|
||
|
|
amount_outstanding=Decimal("50000.00"),
|
||
|
|
|
||
|
|
currency="CNY",
|
||
|
|
|
||
|
|
posting_date=date(2026, 4, 1),
|
||
|
|
|
||
|
|
due_date=date(2026, 4, 30),
|
||
|
|
|
||
|
|
aging_days=11,
|
||
|
|
|
||
|
|
status="partial",
|
||
|
|
|
||
|
|
risk_flags_json=[],
|
||
|
|
|
||
|
|
),
|
||
|
|
|
||
|
|
AccountsReceivableRecord(
|
||
|
|
|
||
|
|
receivable_no="AR-202605-002",
|
||
|
|
|
||
|
|
customer_id="CUS-B",
|
||
|
|
|
||
|
|
customer_name="客户B",
|
||
|
|
|
||
|
|
contract_no="CTR-AR-1002",
|
||
|
|
|
||
|
|
invoice_no="INV-AR-9002",
|
||
|
|
|
||
|
|
amount_receivable=Decimal("88000.00"),
|
||
|
|
|
||
|
|
amount_received=Decimal("10000.00"),
|
||
|
|
|
||
|
|
amount_outstanding=Decimal("78000.00"),
|
||
|
|
|
||
|
|
currency="CNY",
|
||
|
|
|
||
|
|
posting_date=date(2026, 3, 15),
|
||
|
|
|
||
|
|
due_date=date(2026, 4, 15),
|
||
|
|
|
||
|
|
aging_days=26,
|
||
|
|
|
||
|
|
status="overdue",
|
||
|
|
|
||
|
|
risk_flags_json=["ar_overdue"],
|
||
|
|
|
||
|
|
),
|
||
|
|
|
||
|
|
]
|
||
|
|
|
||
|
|
ap_records = [
|
||
|
|
|
||
|
|
AccountsPayableRecord(
|
||
|
|
|
||
|
|
payable_no="AP-202605-001",
|
||
|
|
|
||
|
|
vendor_id="VEN-A",
|
||
|
|
|
||
|
|
vendor_name="供应商A",
|
||
|
|
|
||
|
|
invoice_no="INV-AP-5001",
|
||
|
|
|
||
|
|
amount_payable=Decimal("43000.00"),
|
||
|
|
|
||
|
|
amount_paid=Decimal("10000.00"),
|
||
|
|
|
||
|
|
amount_outstanding=Decimal("33000.00"),
|
||
|
|
|
||
|
|
currency="CNY",
|
||
|
|
|
||
|
|
posting_date=date(2026, 4, 20),
|
||
|
|
|
||
|
|
due_date=date(2026, 5, 12),
|
||
|
|
|
||
|
|
aging_days=0,
|
||
|
|
|
||
|
|
status="scheduled",
|
||
|
|
|
||
|
|
risk_flags_json=[],
|
||
|
|
|
||
|
|
),
|
||
|
|
|
||
|
|
AccountsPayableRecord(
|
||
|
|
|
||
|
|
payable_no="AP-202605-002",
|
||
|
|
|
||
|
|
vendor_id="VEN-B",
|
||
|
|
|
||
|
|
vendor_name="供应商B",
|
||
|
|
|
||
|
|
invoice_no="INV-AP-5002",
|
||
|
|
|
||
|
|
amount_payable=Decimal("96000.00"),
|
||
|
|
|
||
|
|
amount_paid=Decimal("0.00"),
|
||
|
|
|
||
|
|
amount_outstanding=Decimal("96000.00"),
|
||
|
|
|
||
|
|
currency="CNY",
|
||
|
|
|
||
|
|
posting_date=date(2026, 4, 10),
|
||
|
|
|
||
|
|
due_date=date(2026, 5, 5),
|
||
|
|
|
||
|
|
aging_days=6,
|
||
|
|
|
||
|
|
status="overdue",
|
||
|
|
|
||
|
|
risk_flags_json=["ap_overdue"],
|
||
|
|
|
||
|
|
),
|
||
|
|
|
||
|
|
]
|
||
|
|
|
||
|
|
self.db.add_all([claim_1, claim_2, claim_3, *ar_records, *ap_records])
|
||
|
|
|
||
|
|
def _purge_demo_financial_records(self) -> None:
|
||
|
|
|
||
|
|
demo_claims = list(self.db.scalars(select(ExpenseClaim)).all())
|
||
|
|
|
||
|
|
for claim in demo_claims:
|
||
|
|
|
||
|
|
signature = (
|
||
|
|
|
||
|
|
str(claim.claim_no or "").strip(),
|
||
|
|
|
||
|
|
str(claim.employee_name or "").strip(),
|
||
|
|
|
||
|
|
str(claim.reason or "").strip(),
|
||
|
|
|
||
|
|
f"{Decimal(claim.amount or 0):.2f}",
|
||
|
|
|
||
|
|
str(claim.status or "").strip(),
|
||
|
|
|
||
|
|
)
|
||
|
|
|
||
|
|
if signature in DEMO_EXPENSE_CLAIM_SIGNATURES:
|
||
|
|
|
||
|
|
self.db.delete(claim)
|
||
|
|
|
||
|
|
demo_receivables = list(self.db.scalars(select(AccountsReceivableRecord)).all())
|
||
|
|
|
||
|
|
for record in demo_receivables:
|
||
|
|
|
||
|
|
signature = (
|
||
|
|
|
||
|
|
str(record.receivable_no or "").strip(),
|
||
|
|
|
||
|
|
str(record.customer_name or "").strip(),
|
||
|
|
|
||
|
|
f"{Decimal(record.amount_outstanding or 0):.2f}",
|
||
|
|
|
||
|
|
str(record.status or "").strip(),
|
||
|
|
|
||
|
|
)
|
||
|
|
|
||
|
|
if signature in DEMO_RECEIVABLE_SIGNATURES:
|
||
|
|
|
||
|
|
self.db.delete(record)
|
||
|
|
|
||
|
|
demo_payables = list(self.db.scalars(select(AccountsPayableRecord)).all())
|
||
|
|
|
||
|
|
for record in demo_payables:
|
||
|
|
|
||
|
|
signature = (
|
||
|
|
|
||
|
|
str(record.payable_no or "").strip(),
|
||
|
|
|
||
|
|
str(record.vendor_name or "").strip(),
|
||
|
|
|
||
|
|
f"{Decimal(record.amount_outstanding or 0):.2f}",
|
||
|
|
|
||
|
|
str(record.status or "").strip(),
|
||
|
|
|
||
|
|
)
|
||
|
|
|
||
|
|
if signature in DEMO_PAYABLE_SIGNATURES:
|
||
|
|
|
||
|
|
self.db.delete(record)
|
||
|
|
|
||
|
|
def _seed_runs_and_logs(self) -> None:
|
||
|
|
|
||
|
|
if self.db.scalar(select(AgentRun.id).limit(1)) is not None:
|
||
|
|
|
||
|
|
return
|
||
|
|
|
||
|
|
task_asset = self.db.scalar(
|
||
|
|
|
||
|
|
select(AgentAsset).where(AgentAsset.code == "task.hermes.daily_risk_scan")
|
||
|
|
|
||
|
|
)
|
||
|
|
|
||
|
|
user_run = AgentRun(
|
||
|
|
|
||
|
|
run_id="run_user_20260511_001",
|
||
|
|
|
||
|
|
agent=AgentName.USER_AGENT.value,
|
||
|
|
|
||
|
|
source=AgentRunSource.USER_MESSAGE.value,
|
||
|
|
|
||
|
|
user_id="emp_001",
|
||
|
|
|
||
|
|
task_id=None,
|
||
|
|
|
||
|
|
ontology_json={"scenario": "expense", "intent": "query"},
|
||
|
|
|
||
|
|
route_json={"selected_agent": AgentName.USER_AGENT.value, "route_reason": "user query"},
|
||
|
|
|
||
|
|
permission_level=AgentPermissionLevel.READ.value,
|
||
|
|
|
||
|
|
status=AgentRunStatus.SUCCEEDED.value,
|
||
|
|
|
||
|
|
result_summary="已返回本周报销金额和风险摘要。",
|
||
|
|
|
||
|
|
started_at=datetime(2026, 5, 11, 8, 35, tzinfo=UTC),
|
||
|
|
|
||
|
|
finished_at=datetime(2026, 5, 11, 8, 35, 2, tzinfo=UTC),
|
||
|
|
|
||
|
|
)
|
||
|
|
|
||
|
|
hermes_run = AgentRun(
|
||
|
|
|
||
|
|
run_id="run_hermes_20260511_001",
|
||
|
|
|
||
|
|
agent=AgentName.HERMES.value,
|
||
|
|
|
||
|
|
source=AgentRunSource.SCHEDULE.value,
|
||
|
|
|
||
|
|
user_id=None,
|
||
|
|
|
||
|
|
task_id=task_asset.id if task_asset else None,
|
||
|
|
|
||
|
|
ontology_json={"scenario": "expense", "intent": "risk_check"},
|
||
|
|
|
||
|
|
route_json={
|
||
|
|
|
||
|
|
"selected_agent": AgentName.HERMES.value,
|
||
|
|
|
||
|
|
"route_reason": "scheduled risk scan",
|
||
|
|
|
||
|
|
},
|
||
|
|
|
||
|
|
permission_level=AgentPermissionLevel.READ.value,
|
||
|
|
|
||
|
|
status=AgentRunStatus.SUCCEEDED.value,
|
||
|
|
|
||
|
|
result_summary="Hermes 已生成今日风险巡检摘要。",
|
||
|
|
|
||
|
|
started_at=datetime(2026, 5, 11, 9, 0, tzinfo=UTC),
|
||
|
|
|
||
|
|
finished_at=datetime(2026, 5, 11, 9, 0, 4, tzinfo=UTC),
|
||
|
|
|
||
|
|
)
|
||
|
|
|
||
|
|
blocked_run = AgentRun(
|
||
|
|
|
||
|
|
run_id="run_user_20260511_002",
|
||
|
|
|
||
|
|
agent=AgentName.ORCHESTRATOR.value,
|
||
|
|
|
||
|
|
source=AgentRunSource.USER_MESSAGE.value,
|
||
|
|
|
||
|
|
user_id="emp_002",
|
||
|
|
|
||
|
|
task_id=None,
|
||
|
|
|
||
|
|
ontology_json={"scenario": "accounts_payable", "intent": "operate"},
|
||
|
|
|
||
|
|
route_json={
|
||
|
|
|
||
|
|
"selected_agent": AgentName.USER_AGENT.value,
|
||
|
|
|
||
|
|
"route_reason": "payment request",
|
||
|
|
|
||
|
|
},
|
||
|
|
|
||
|
|
permission_level=AgentPermissionLevel.APPROVAL_REQUIRED.value,
|
||
|
|
|
||
|
|
status=AgentRunStatus.BLOCKED.value,
|
||
|
|
|
||
|
|
result_summary="动作需要人工确认。",
|
||
|
|
|
||
|
|
error_message="直接付款属于高风险动作,已阻断自动执行。",
|
||
|
|
|
||
|
|
started_at=datetime(2026, 5, 11, 10, 5, tzinfo=UTC),
|
||
|
|
|
||
|
|
finished_at=datetime(2026, 5, 11, 10, 5, 1, tzinfo=UTC),
|
||
|
|
|
||
|
|
)
|
||
|
|
|
||
|
|
self.db.add_all([user_run, hermes_run, blocked_run])
|
||
|
|
|
||
|
|
self.db.flush()
|
||
|
|
|
||
|
|
self.db.add_all(
|
||
|
|
|
||
|
|
[
|
||
|
|
|
||
|
|
AgentToolCall(
|
||
|
|
|
||
|
|
run_id=user_run.run_id,
|
||
|
|
|
||
|
|
tool_type=AgentToolType.DATABASE.value,
|
||
|
|
|
||
|
|
tool_name="expense_claims.lookup",
|
||
|
|
|
||
|
|
request_json={"time_range": "this_week", "employee": "all"},
|
||
|
|
|
||
|
|
response_json={"claim_count": 3, "total_amount": "7420.00"},
|
||
|
|
|
||
|
|
status="succeeded",
|
||
|
|
|
||
|
|
duration_ms=48,
|
||
|
|
|
||
|
|
),
|
||
|
|
|
||
|
|
AgentToolCall(
|
||
|
|
|
||
|
|
run_id=hermes_run.run_id,
|
||
|
|
|
||
|
|
tool_type=AgentToolType.MCP.value,
|
||
|
|
|
||
|
|
tool_name="invoice.verify_mock",
|
||
|
|
|
||
|
|
request_json={"claim_no": "EXP-202605-003"},
|
||
|
|
|
||
|
|
response_json={
|
||
|
|
|
||
|
|
"warning": "external service degraded",
|
||
|
|
|
||
|
|
"fallback": "used mock response",
|
||
|
|
|
||
|
|
},
|
||
|
|
|
||
|
|
status="failed",
|
||
|
|
|
||
|
|
duration_ms=132,
|
||
|
|
|
||
|
|
error_message="mock upstream timeout",
|
||
|
|
|
||
|
|
),
|
||
|
|
|
||
|
|
AgentToolCall(
|
||
|
|
|
||
|
|
run_id=blocked_run.run_id,
|
||
|
|
|
||
|
|
tool_type=AgentToolType.RULE_ENGINE.value,
|
||
|
|
|
||
|
|
tool_name="permission.guard",
|
||
|
|
|
||
|
|
request_json={"action": "direct_payment"},
|
||
|
|
|
||
|
|
response_json={"requires_confirmation": True},
|
||
|
|
|
||
|
|
status="succeeded",
|
||
|
|
|
||
|
|
duration_ms=5,
|
||
|
|
|
||
|
|
),
|
||
|
|
|
||
|
|
SemanticParseLog(
|
||
|
|
|
||
|
|
run_id=user_run.run_id,
|
||
|
|
|
||
|
|
user_id="emp_001",
|
||
|
|
|
||
|
|
raw_query="查一下本周报销超标风险",
|
||
|
|
|
||
|
|
scenario="expense",
|
||
|
|
|
||
|
|
intent="risk_check",
|
||
|
|
|
||
|
|
entities_json=[],
|
||
|
|
|
||
|
|
time_range_json={"start_date": "2026-05-11", "end_date": "2026-05-17"},
|
||
|
|
|
||
|
|
metrics_json=["amount"],
|
||
|
|
|
||
|
|
constraints_json=[],
|
||
|
|
|
||
|
|
risk_flags_json=["amount_over_limit"],
|
||
|
|
|
||
|
|
permission_json={"level": AgentPermissionLevel.READ.value},
|
||
|
|
|
||
|
|
confidence=0.93,
|
||
|
|
|
||
|
|
),
|
||
|
|
|
||
|
|
SemanticParseLog(
|
||
|
|
|
||
|
|
run_id=blocked_run.run_id,
|
||
|
|
|
||
|
|
user_id="emp_002",
|
||
|
|
|
||
|
|
raw_query="帮我直接付款给供应商B",
|
||
|
|
|
||
|
|
scenario="accounts_payable",
|
||
|
|
|
||
|
|
intent="operate",
|
||
|
|
|
||
|
|
entities_json=[{"type": "vendor", "value": "供应商B"}],
|
||
|
|
|
||
|
|
time_range_json={},
|
||
|
|
|
||
|
|
metrics_json=["amount"],
|
||
|
|
|
||
|
|
constraints_json=[],
|
||
|
|
|
||
|
|
risk_flags_json=["ap_overdue"],
|
||
|
|
|
||
|
|
permission_json={"level": AgentPermissionLevel.APPROVAL_REQUIRED.value},
|
||
|
|
|
||
|
|
confidence=0.96,
|
||
|
|
|
||
|
|
),
|
||
|
|
|
||
|
|
]
|
||
|
|
|
||
|
|
)
|
||
|
|
|
||
|
|
if self.db.scalar(select(AuditLog.id).limit(1)) is None:
|
||
|
|
|
||
|
|
self.db.add_all(
|
||
|
|
|
||
|
|
[
|
||
|
|
|
||
|
|
AuditLog(
|
||
|
|
|
||
|
|
actor="系统初始化",
|
||
|
|
|
||
|
|
action="save_rule_markdown",
|
||
|
|
|
||
|
|
resource_type="rule",
|
||
|
|
|
||
|
|
resource_id=ATTACHMENT_RULE_ASSET_CODE,
|
||
|
|
|
||
|
|
before_json=None,
|
||
|
|
|
||
|
|
after_json={"version": "v1.0.0"},
|
||
|
|
|
||
|
|
request_id="seed-audit-001",
|
||
|
|
|
||
|
|
),
|
||
|
|
|
||
|
|
AuditLog(
|
||
|
|
|
||
|
|
actor="高嘉禾",
|
||
|
|
|
||
|
|
action="review_rule",
|
||
|
|
|
||
|
|
resource_type="rule",
|
||
|
|
|
||
|
|
resource_id=ATTACHMENT_RULE_ASSET_CODE,
|
||
|
|
|
||
|
|
before_json={"review_status": "pending"},
|
||
|
|
|
||
|
|
after_json={"review_status": "pending"},
|
||
|
|
|
||
|
|
request_id="seed-audit-002",
|
||
|
|
|
||
|
|
),
|
||
|
|
|
||
|
|
AuditLog(
|
||
|
|
|
||
|
|
actor="系统初始化",
|
||
|
|
|
||
|
|
action="activate_rule",
|
||
|
|
|
||
|
|
resource_type="rule",
|
||
|
|
|
||
|
|
resource_id="rule.expense.scene_submission_standard",
|
||
|
|
|
||
|
|
before_json={"status": "draft"},
|
||
|
|
|
||
|
|
after_json={"status": "active"},
|
||
|
|
|
||
|
|
request_id="seed-audit-003",
|
||
|
|
|
||
|
|
),
|
||
|
|
|
||
|
|
AuditLog(
|
||
|
|
|
||
|
|
actor="Hermes",
|
||
|
|
|
||
|
|
action="update_task_status",
|
||
|
|
|
||
|
|
resource_type="task",
|
||
|
|
|
||
|
|
resource_id="task.hermes.daily_risk_scan",
|
||
|
|
|
||
|
|
before_json={"status": "idle"},
|
||
|
|
|
||
|
|
after_json={"status": "succeeded"},
|
||
|
|
|
||
|
|
request_id="seed-audit-004",
|
||
|
|
|
||
|
|
),
|
||
|
|
|
||
|
|
]
|
||
|
|
|
||
|
|
)
|