| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- """幂等种子数据只补缺失项,重启不清空业务或恢复管理员已经修改的配置。"""
- from sqlalchemy import select
- from app.domain.models import AgentConfig, AuditRule, ApprovalChain, Department, Role, User
- from app.infrastructure.security import hash_password, validate_password
- from app.shared.config import settings
- RULE_DEFAULTS = {
- "invoice_date_valid": ("发票日期", "error", {"max_age_days": 365}),
- "invoice_amount_valid": ("金额与合计", "error", {"large_amount": "100000.00"}),
- "invoice_header_valid": ("买卖方抬头", "error", {"company_name": ""}),
- "invoice_no_duplicate": ("同内容重复", "critical", {}),
- "tax_calculation_valid": ("税额计算", "warning", {"tolerance": "0.01"}),
- "tax_number_valid": ("税号长度", "warning", {"lengths": [15, 18, 20]}),
- "policy_compliance": ("政策合规", "error", {"required": True}),
- }
- AGENT_DEFAULTS = {
- "extract": ("发票提取 Agent", {"max_attempts": 3, "timeout": 20, "concurrency": 3}),
- "rule_check": ("规则校验 Agent", {}),
- "risk_detect": ("双引擎风控 Agent", {"timeout": 20, "window_days": 30, "amount_high": "50000.00", "amount_medium": "20000.00", "frequency_limit": 10, "dept_ratio_limit": 3}),
- "make_decision": ("确定性路由 Agent", {}),
- "feedback": ("人工反馈 Agent", {}),
- }
- async def latest_configs(session, model, key):
- """历史版本保留,仅取每个标识的最新配置作为下一轮输入。"""
- rows = (await session.scalars(select(model).order_by(model.version))).all()
- result = {}
- for row in rows:
- result[getattr(row, key)] = row
- return result
- async def seed(session):
- """初始化角色和规则是必需步骤,演示账号单独受 SEED_DEMO 控制。"""
- for code, name in [("employee", "员工"), ("supervisor", "主管"), ("auditor", "审核员"), ("manager", "经理"), ("admin", "管理员")]:
- if not await session.scalar(select(Role).where(Role.code == code)):
- session.add(Role(code=code, display_name=name))
- for code, (name, severity, params) in RULE_DEFAULTS.items():
- if not await session.scalar(select(AuditRule).where(AuditRule.code == code)):
- session.add(AuditRule(code=code, name=name, severity=severity, params_json=params, scope_json={}))
- for node, (name, config) in AGENT_DEFAULTS.items():
- if not await session.scalar(select(AgentConfig).where(AgentConfig.node_name == node)):
- session.add(AgentConfig(node_name=node, name=name, config_json=config))
- await session.flush()
- if not settings.seed_demo:
- return
- validate_password(settings.demo_password)
- department = await session.scalar(select(Department).where(Department.name == "演示研发部"))
- if not department:
- department = Department(name="演示研发部")
- session.add(department)
- await session.flush()
- users = {}
- for username, name, role_code in [("alice", "演示员工", "employee"), ("bob", "演示主管", "supervisor"), ("carol", "演示财务", "auditor"), ("dave", "演示经理", "manager"), ("erin", "演示管理员", "admin")]:
- user = await session.scalar(select(User).where(User.username == username))
- if not user:
- role = await session.scalar(select(Role).where(Role.code == role_code))
- user = User(username=username, real_name=name, password_hash=hash_password(settings.demo_password),
- department_id=department.id, role_id=role.id)
- session.add(user)
- await session.flush()
- users[username] = user
- # 默认链提供人工闭环;用户自己创建的链不会被启动脚本重置。
- for route, node_user, role in [("to_supervisor", "bob", "supervisor"), ("to_finance", "carol", "auditor"), ("to_manual", "carol", "auditor")]:
- if not await session.scalar(select(ApprovalChain).where(ApprovalChain.route == route)):
- session.add(ApprovalChain(name="演示审批链 · " + route, route=route,
- nodes_json=[{"approver_id": users[node_user].id, "role": role}]))
|