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 AgentFoundationMarkdownMixin: def _attachment_submission_requirement_markdown( self, *, version_note: str, include_review_note: bool, ) -> str: sections = [ "# 报销附件与单据完整性规则", "", "## 模板信息", "", "- 模板键:`attachment_requirement_v1`", "- 来源文档:报销制度 / 单据与附件要求", "- 审核状态:待审核", "", "## 目标", "", "统一约束报销提交时的票据、附件与替代凭证要求,避免缺件、错件和无依据流转。", "", "## 适用范围", "", "适用于员工报销提交场景,重点覆盖差旅、住宿、交通、餐费、办公和其他费用的附件校验。", "", "## 输入字段", "", "- expense_type", "- attachments", "- invoice_count", "- reason", "", "## 判断规则", "", "- 报销提交前至少需要 1 份有效附件。", "- 金额类报销原则上应提供合法票据;特殊场景无发票时,必须补充收据与情况说明。", "- 差旅交通报销需提供行程单或等效凭证;住宿报销需提供酒店票据或等效住宿凭证。", "- 缺少必要附件时直接拦截,并提示补件后重新提交。", "", "## 输出", "", "- 风险编码:`invoice_anomaly`", "- 默认动作:`block`", "- 处理说明:附件或单据不完整时退回补充。", "", "## 来源依据", "", "- 报销制度对票据、附件、替代凭证和补件要求的统一约束。", "", "## 审核约束", "", "- 当前规则属于真实业务规则,但仍处于待审核状态。", "- 上线前需由制度管理员确认收据替代、补件时限和特殊场景豁免口径。", f"- 当前版本说明:{version_note}", "", "## 管理员备注", "", "需要结合公司正式报销制度,补充各场景附件替代口径与例外审批要求。", ] if include_review_note: sections.extend(["", "```expense-rule", json.dumps(ATTACHMENT_RULE_RUNTIME_CONFIG, ensure_ascii=False, indent=2), "```"]) return "\n".join(sections) def _scene_submission_standard_markdown(self) -> str: return self._markdown_content(build_scene_submission_standard_markdown()) def _travel_risk_control_standard_markdown(self, *, version: str = "v1.1.0") -> str: return self._markdown_content(build_travel_risk_control_standard_markdown()) @staticmethod def _markdown_content(content: str) -> str: return content @staticmethod def _json_content(content: dict[str, object]) -> str: return json.dumps(content, ensure_ascii=False, sort_keys=True, indent=2)