From 947642919b286cedf1e5608b33aebcff074a75ab Mon Sep 17 00:00:00 2001 From: selfrelease Date: Sun, 19 Jul 2026 12:05:33 +0800 Subject: [PATCH] =?UTF-8?q?feat(data):=20=E5=AE=8C=E6=95=B4=E6=BC=94?= =?UTF-8?q?=E7=A4=BA=E7=A7=8D=E5=AD=90=E6=95=B0=E6=8D=AE=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=20=E2=80=94=2022=20=E5=BC=A0=E8=A1=A8=20119=20=E6=9D=A1?= =?UTF-8?q?=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 租户:远见资本(VC) - 用户 7 个:admin/gp/lead/mgr/founder_a/founder_b/founder_c - 企业 5 家:智链科技/云栈数据/深瞳智能/量子芯微/光合生物 - 覆盖全模型:财务数据/月报/健康度/风险/弱信号/任务/OKR/里程碑/ 协同/决策前哨/助推/重大事项/协议/董事会/BML假设/AAR/团队/人才/审计 - 运行:cd backend && python -m scripts.seed_demo_data - 登录密码均为 demo123456 --- backend/scripts/__init__.py | 0 backend/scripts/seed_demo_data.py | 637 ++++++++++++++++++++++++++++++ 2 files changed, 637 insertions(+) create mode 100644 backend/scripts/__init__.py create mode 100644 backend/scripts/seed_demo_data.py diff --git a/backend/scripts/__init__.py b/backend/scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/scripts/seed_demo_data.py b/backend/scripts/seed_demo_data.py new file mode 100644 index 0000000..4e6d762 --- /dev/null +++ b/backend/scripts/seed_demo_data.py @@ -0,0 +1,637 @@ +"""演示种子数据 — 按 5 个业务场景生成完整示例数据。 + +覆盖模型:Tenant / User / Company / MonthlyReport / HealthScore / RiskEvent / +WeakSignal / Task / OKR / MilestoneTree / SynergyOpportunity / DecisionSentinel / +NudgeRecord / MajorEvent / InvestmentAgreement / BoardMeeting / FinancialData / +Hypothesis / AARRecord / TeamMember / TalentProfile / AuditLog。 + +运行方式: + cd backend && python -m scripts.seed_demo_data +""" + +import asyncio +import json +from datetime import datetime, timedelta, timezone + +from sqlalchemy import text +from sqlalchemy.ext.asyncio import AsyncSession + +from app.core.database import async_session_factory, engine, Base +from app.core.security import hash_password +from app.models import ( + AARRecord, AuditLog, BoardMeeting, Company, FinancialData, HealthScore, + Hypothesis, InvestmentAgreement, MajorEvent, MilestoneTree, MonthlyReport, + NudgeRecord, OKR, RiskEvent, SynergyOpportunity, Task, TalentProfile, + TeamMember, Tenant, User, WeakSignal, DecisionSentinel, +) + +UTC = timezone.utc + +# ─── 固定 ID(方便跨表引用) ────────────────────────────────────────── +TENANT_ID = "00000000-0000-0000-0000-000000000001" +ADMIN_ID = "00000000-0000-0000-0000-000000000002" +GP_ID = "00000000-0000-0000-0000-000000000003" +LEAD_ID = "00000000-0000-0000-0000-000000000004" +MGR_ID = "00000000-0000-0000-0000-000000000005" +FOUNDER_A = "00000000-0000-0000-0000-000000000006" +FOUNDER_B = "00000000-0000-0000-0000-000000000007" +FOUNDER_C = "00000000-0000-0000-0000-000000000008" + +COMP_A = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa1" +COMP_B = "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbb2" +COMP_C = "cccccccc-cccc-cccc-cccc-ccccccccccc3" +COMP_D = "dddddddd-dddd-dddd-dddd-ddddddddddd4" +COMP_E = "eeeeeeee-eeee-eeee-eeee-eeeeeeeeeee5" + +NOW = datetime.now(UTC) +D = lambda days: NOW - timedelta(days=days) # noqa: E731 + + +async def seed() -> None: + """生成全部演示数据。""" + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.drop_all) + await conn.run_sync(Base.metadata.create_all) + + async with async_session_factory() as db: + await _seed_tenant_users(db) + await _seed_companies(db) + await _seed_financial(db) + await _seed_reports(db) + await _seed_health(db) + await _seed_risks(db) + await _seed_weak_signals(db) + await _seed_tasks(db) + await _seed_okrs(db) + await _seed_milestones(db) + await _seed_synergies(db) + await _seed_sentinels(db) + await _seed_nudges(db) + await _seed_events(db) + await _seed_agreements(db) + await _seed_boards(db) + await _seed_hypotheses(db) + await _seed_aars(db) + await _seed_team_members(db) + await _seed_talents(db) + await _seed_audit_logs(db) + await db.commit() + + print("✅ 演示数据生成完成") + print(f" 租户: {TENANT_ID}") + print(f" 用户: admin/gp/lead/mgr/founder_a/founder_b/founder_c") + print(f" 企业: 智链科技/云栈数据/深瞳智能/量子芯微/光合生物") + print(" 登录密码均为: demo123456") + + +# ─── 租户 + 用户 ─────────────────────────────────────────────────────── +async def _seed_tenant_users(db: AsyncSession) -> None: + tenant = Tenant( + id=TENANT_ID, + name="远见资本", + type="vc", + config_json={"fund_name": "远见三期", "fund_size": "5亿人民币"}, + ) + db.add(tenant) + + users = [ + User(id=ADMIN_ID, tenant_id=TENANT_ID, email="admin@demo.com", password_hash=hash_password("demo123456"), name="系统管理员", role="admin", is_active=True), + User(id=GP_ID, tenant_id=TENANT_ID, email="gp@demo.com", password_hash=hash_password("demo123456"), name="张远见", role="gp", is_active=True), + User(id=LEAD_ID, tenant_id=TENANT_ID, email="lead@demo.com", password_hash=hash_password("demo123456"), name="李投后", role="post_invest_lead", is_active=True), + User(id=MGR_ID, tenant_id=TENANT_ID, email="mgr@demo.com", password_hash=hash_password("demo123456"), name="王经理", role="investor", is_active=True), + User(id=FOUNDER_A, tenant_id=TENANT_ID, email="founder_a@demo.com", password_hash=hash_password("demo123456"), name="陈智链", role="founder", is_active=True), + User(id=FOUNDER_B, tenant_id=TENANT_ID, email="founder_b@demo.com", password_hash=hash_password("demo123456"), name="刘云栈", role="founder", is_active=True), + User(id=FOUNDER_C, tenant_id=TENANT_ID, email="founder_c@demo.com", password_hash=hash_password("demo123456"), name="赵深瞳", role="founder", is_active=True), + ] + for u in users: + db.add(u) + await db.flush() + print(" ✓ 租户 + 7 用户") + + +# ─── 企业 ────────────────────────────────────────────────────────────── +async def _seed_companies(db: AsyncSession) -> None: + companies = [ + Company(id=COMP_A, tenant_id=TENANT_ID, name="智链科技有限公司", industry="AI/供应链", stage="b", + description="利用大模型优化供应链决策,服务制造业客户。", + founded_at=datetime(2021, 3, 1, tzinfo=UTC), total_funding="1.2亿人民币", website="https://zhilian.example.com"), + Company(id=COMP_B, tenant_id=TENANT_ID, name="云栈数据科技", industry="AI/数据平台", stage="a", + description="企业级数据治理与 AI 训练数据管理平台。", + founded_at=datetime(2022, 1, 1, tzinfo=UTC), total_funding="5000万人民币", website="https://yunzhan.example.com"), + Company(id=COMP_C, tenant_id=TENANT_ID, name="深瞳智能", industry="AI/计算机视觉", stage="b", + description="工业质检视觉 AI,服务半导体和新能源行业。", + founded_at=datetime(2020, 6, 1, tzinfo=UTC), total_funding="2亿人民币", website="https://shentong.example.com"), + Company(id=COMP_D, tenant_id=TENANT_ID, name="量子芯微电子", industry="芯片/AI算力", stage="seed", + description="AI 推理芯片设计,边缘端低功耗 NPU。", + founded_at=datetime(2023, 9, 1, tzinfo=UTC), total_funding="1500万人民币", website="https://quantumchip.example.com"), + Company(id=COMP_E, tenant_id=TENANT_ID, name="光合生物医疗", industry="AI/医疗", stage="a", + description="AI 辅助药物发现,聚焦小分子靶点筛选。", + founded_at=datetime(2022, 9, 1, tzinfo=UTC), total_funding="8000万人民币", website="https://guanghe.example.com"), + ] + for c in companies: + db.add(c) + await db.flush() + print(" ✓ 5 企业") + + +# ─── 财务数据 ────────────────────────────────────────────────────────── +async def _seed_financial(db: AsyncSession) -> None: + """每家企业生成近 3 个月利润表 + 现金流。""" + for comp_id, revenue, burn, cash in [ + (COMP_A, 800, 350, 4200), # 月营收350万, 消耗120万, 现金4200万 + (COMP_B, 150, 120, 1800), + (COMP_C, 1200, 480, 6500), + (COMP_D, 0, 80, 600), + (COMP_E, 80, 200, 2400), + ]: + for i in range(3): + y, m = (NOW.year, NOW.month - i) if NOW.month - i > 0 else (NOW.year - 1, 12 + NOW.month - i) + db.add(FinancialData( + company_id=comp_id, period_year=y, period_month=m, + statement_type="income", + data_json={"revenue": revenue, "cogs": int(revenue * 0.4), "gross_profit": int(revenue * 0.6), "opex": burn, "net_income": revenue - burn - int(revenue * 0.4)}, + source="monthly_report", credibility_score=85.0 - i * 5, + )) + db.add(FinancialData( + company_id=comp_id, period_year=y, period_month=m, + statement_type="cash_flow", + data_json={"operating_cf": revenue - burn, "investing_cf": -50, "financing_cf": 0, "net_cf": revenue - burn - 50, "cash_balance": cash - i * burn}, + source="monthly_report", credibility_score=85.0 - i * 5, + )) + await db.flush() + print(" ✓ 财务数据 (5 企业 x 3 月)") + + +# ─── 月报 ────────────────────────────────────────────────────────────── +async def _seed_reports(db: AsyncSession) -> None: + reports = [ + # 智链科技 — 已提交 + AI 解析 + MonthlyReport(company_id=COMP_A, period_year=NOW.year, period_month=NOW.month - 1 if NOW.month > 1 else 12, + status="ai_parsed", submitted_by=FOUNDER_A, submitted_at=D(10), + raw_content="本月营收800万,环比增长15%。新签客户3家,流失1家。团队新增5人。AI模型推理成本降低12%。", + structured_data={"revenue": 800, "mom_growth": 0.15, "new_customers": 3, "churned": 1, "headcount": 45, "ai_cost_reduction": 0.12}, + ai_summary="智链科技本月表现良好,营收增长15%,AI推理成本优化显著。客户净增2家,团队扩张至45人。", + ai_concerns=[{"level": "medium", "item": "客户流失率环比上升", "detail": "本月流失1家年合同客户"}, {"level": "low", "item": "现金Runway 12个月", "detail": "按当前消耗速度可维持12个月"}]), + # 云栈数据 — 已提交 + MonthlyReport(company_id=COMP_B, period_year=NOW.year, period_month=NOW.month - 1 if NOW.month > 1 else 12, + status="ai_parsed", submitted_by=FOUNDER_B, submitted_at=D(8), + raw_content="本月营收150万,环比持平。完成数据治理平台v2.0发布。新签1家金融客户。", + structured_data={"revenue": 150, "mom_growth": 0.0, "new_customers": 1, "churned": 0, "headcount": 22}, + ai_summary="云栈数据营收持平,产品迭代正常。金融客户拓展是亮点。", + ai_concerns=[{"level": "high", "item": "营收增长停滞", "detail": "连续2个月环比0%增长"}, {"level": "medium", "item": "现金Runway 15个月", "detail": "需关注融资节奏"}]), + # 深瞳智能 — 已提交 + MonthlyReport(company_id=COMP_C, period_year=NOW.year, period_month=NOW.month - 1 if NOW.month > 1 else 12, + status="reviewed", submitted_by=FOUNDER_C, submitted_at=D(12), reviewed_by=MGR_ID, reviewed_at=D(5), + raw_content="本月营收1200万,环比增长22%。半导体客户占比提升至60%。新增专利2项。", + structured_data={"revenue": 1200, "mom_growth": 0.22, "new_customers": 2, "churned": 0, "headcount": 68, "patents": 2}, + ai_summary="深瞳智能强劲增长,半导体行业渗透加深。专利积累构建技术壁垒。", + ai_concerns=[{"level": "low", "item": "客户集中度风险", "detail": "半导体行业占比60%"}]), + # 量子芯微 — 草稿 + MonthlyReport(company_id=COMP_D, period_year=NOW.year, period_month=NOW.month - 1 if NOW.month > 1 else 12, + status="draft", submitted_by=None, + raw_content="", structured_data=None, ai_summary=None, ai_concerns=None), + # 光合生物 — 延迟提交 + MonthlyReport(company_id=COMP_E, period_year=NOW.year, period_month=NOW.month - 2 if NOW.month > 2 else 11, + status="ai_parsed", submitted_by=FOUNDER_A, submitted_at=D(40), + raw_content="本月营收80万,来自2个合作药企里程碑付款。研发进展:3个靶点进入先导化合物阶段。", + structured_data={"revenue": 80, "milestone_payment": 80, "targets": 3, "headcount": 18}, + ai_summary="光合生物收入来自里程碑付款,研发管线推进正常。", + ai_concerns=[{"level": "high", "item": "月报延迟提交", "detail": "延迟20天"}, {"level": "medium", "item": "现金消耗快", "detail": "月消耗200万,Runway 12月"}]), + ] + for r in reports: + db.add(r) + await db.flush() + print(" ✓ 月报 (5 份)") + + +# ─── 健康度评分 ──────────────────────────────────────────────────────── +async def _seed_health(db: AsyncSession) -> None: + scores = [ + # 智链科技 — 良好 + HealthScore(company_id=COMP_A, total_score=78.5, financial_score=82, operational_score=75, ai_commercial_score=80, ai_cost_score=85, + org_talent_score=72, product_tech_score=80, market_compete_score=78, governance_score=75, financing_score=80, + trend="up", evidence_json={"financial": "营收增长15%,现金流健康", "ai_cost": "推理成本降低12%"}, + recommendations_json={"action": "关注客户流失率", "owner": MGR_ID, "review_at": D(-30).isoformat()}), + # 云栈数据 — 中等 + HealthScore(company_id=COMP_B, total_score=62.0, financial_score=55, operational_score=68, ai_commercial_score=60, ai_cost_score=65, + org_talent_score=70, product_tech_score=72, market_compete_score=58, governance_score=65, financing_score=50, + trend="stable", evidence_json={"financial": "营收持平,需突破", "financing": "Runway 15月,需启动融资"}, + recommendations_json={"action": "加速融资节奏", "owner": LEAD_ID, "review_at": D(-14).isoformat()}), + # 深瞳智能 — 优秀 + HealthScore(company_id=COMP_C, total_score=85.5, financial_score=88, operational_score=85, ai_commercial_score=90, ai_cost_score=82, + org_talent_score=83, product_tech_score=88, market_compete_score=86, governance_score=82, financing_score=85, + trend="up", evidence_json={"financial": "营收增长22%", "market": "半导体渗透加深"}, + recommendations_json={"action": "关注客户集中度", "owner": MGR_ID, "review_at": D(-30).isoformat()}), + # 量子芯微 — 早期风险 + HealthScore(company_id=COMP_D, total_score=48.0, financial_score=35, operational_score=50, ai_commercial_score=45, ai_cost_score=55, + org_talent_score=52, product_tech_score=60, market_compete_score=42, governance_score=55, financing_score=40, + trend="down", evidence_json={"financial": "无营收,现金紧张", "financing": "Runway 7月"}, + recommendations_json={"action": "紧急启动天使+轮融资", "owner": GP_ID, "review_at": D(-7).isoformat()}), + # 光合生物 — 中等偏上 + HealthScore(company_id=COMP_E, total_score=68.5, financial_score=60, operational_score=72, ai_commercial_score=70, ai_cost_score=65, + org_talent_score=68, product_tech_score=75, market_compete_score=65, governance_score=70, financing_score=62, + trend="stable", evidence_json={"financial": "里程碑收入稳定", "product": "3靶点推进中"}, + recommendations_json={"action": "月报提交及时性改善", "owner": MGR_ID, "review_at": D(-30).isoformat()}), + ] + for s in scores: + s.calculated_at = D(5) + db.add(s) + await db.flush() + print(" ✓ 健康度评分 (5 企业)") + + +# ─── 风险事件 ────────────────────────────────────────────────────────── +async def _seed_risks(db: AsyncSession) -> None: + risks = [ + RiskEvent(company_id=COMP_A, type="operational", severity="medium", status="in_progress", + title="客户流失率环比上升", description="本月流失1家年合同客户,流失率从2%升至4%", + evidence_json={"metric": "churn_rate", "current": 0.04, "previous": 0.02, "threshold": 0.03}, + suggested_action="联系流失客户了解原因,加强客户成功团队", assigned_to=MGR_ID, due_at=D(-7)), + RiskEvent(company_id=COMP_B, type="financial", severity="high", status="assigned", + title="营收增长停滞", description="连续2个月环比0%增长,未达预期", + evidence_json={"metric": "revenue_growth", "current": 0.0, "expected": 0.15, "months": 2}, + suggested_action="与创始人讨论增长策略,评估产品定价和市场拓展", assigned_to=LEAD_ID, due_at=D(-3)), + RiskEvent(company_id=COMP_D, type="financial", severity="critical", status="open", + title="现金Runway不足7个月", description="按当前消耗速度,现金仅可维持7个月", + evidence_json={"metric": "runway_months", "current": 7, "threshold": 9}, + suggested_action="紧急启动天使+轮融资,准备BP和财务预测", assigned_to=GP_ID, due_at=D(-14)), + RiskEvent(company_id=COMP_E, type="operational", severity="medium", status="resolved", + title="月报延迟提交", description="上月月报延迟20天提交", + evidence_json={"metric": "report_delay_days", "current": 20, "threshold": 5}, + suggested_action="与创始人沟通提交规范,设置自动提醒", assigned_to=MGR_ID, due_at=D(-10), closed_at=D(-3)), + RiskEvent(company_id=COMP_C, type="org", severity="low", status="open", + title="核心技术人员稳定性下降", description="CTO提及外部机会,稳定性评分从0.85降至0.65", + evidence_json={"metric": "cto_stability", "current": 0.65, "previous": 0.85}, + suggested_action="了解CTO诉求,评估股权激励调整", assigned_to=LEAD_ID), + RiskEvent(company_id=COMP_A, type="ai_specific", severity="low", status="closed", + title="AI模型推理成本超标", description="上月推理成本占营收比12%,超10%阈值", + evidence_json={"metric": "ai_cost_ratio", "current": 0.12, "threshold": 0.10}, + suggested_action="优化模型量化策略", assigned_to=MGR_ID, closed_at=D(-5)), + ] + for r in risks: + r.identified_at = D(15) + db.add(r) + await db.flush() + print(" ✓ 风险事件 (6 条)") + + +# ─── 弱信号 ──────────────────────────────────────────────────────────── +async def _seed_weak_signals(db: AsyncSession) -> None: + signals = [ + WeakSignal(company_id=COMP_B, signal_type="market", source="行业论坛", content="竞品发布类似数据治理产品,定价低30%", + confidence=0.72, risk_probability=0.65, status="alerted", + correlation_result={"related_signals": 2, "pattern": "竞品压力增加"}), + WeakSignal(company_id=COMP_C, signal_type="org", source="LinkedIn", content="CTO 更新简历,标注'开放看机会'", + confidence=0.85, risk_probability=0.78, status="alerted", + correlation_result={"related_signals": 1, "pattern": "核心人员流失风险"}), + WeakSignal(company_id=COMP_D, signal_type="technical", source="GitHub", content="核心开源依赖库停止维护,需迁移", + confidence=0.68, risk_probability=0.45, status="correlated"), + WeakSignal(company_id=COMP_A, signal_type="sentiment", source="客户反馈", content="大客户提及预算削减计划", + confidence=0.60, risk_probability=0.55, status="new"), + WeakSignal(company_id=COMP_E, signal_type="market", source="FDA新闻", content="同类靶点药物获FDA快速审批", + confidence=0.75, risk_probability=0.30, status="new"), + ] + for s in signals: + s.detected_at = D(7) + db.add(s) + await db.flush() + print(" ✓ 弱信号 (5 条)") + + +# ─── 任务 ────────────────────────────────────────────────────────────── +async def _seed_tasks(db: AsyncSession) -> None: + tasks = [ + Task(tenant_id=TENANT_ID, company_id=COMP_A, title="联系流失客户进行回访", description="了解客户流失原因,制定挽留方案", + status="in_progress", priority="high", assigned_to=MGR_ID, source_type="risk", due_at=D(-3)), + Task(tenant_id=TENANT_ID, company_id=COMP_B, title="与云栈数据创始人讨论增长策略", description="评估产品定价和市场拓展方案", + status="todo", priority="high", assigned_to=LEAD_ID, source_type="risk", due_at=D(-1)), + Task(tenant_id=TENANT_ID, company_id=COMP_D, title="准备天使+轮BP", description="包含财务预测和产品路线图", + status="todo", priority="urgent", assigned_to=GP_ID, source_type="risk", due_at=D(-14)), + Task(tenant_id=TENANT_ID, company_id=COMP_C, title="评估CTO股权激励调整方案", description="了解CTO诉求,设计retention package", + status="todo", priority="medium", assigned_to=LEAD_ID, source_type="manual", due_at=D(-7)), + Task(tenant_id=TENANT_ID, company_id=COMP_A, title="审阅智链科技本月月报", description="关注AI成本降低和客户流失", + status="done", priority="medium", assigned_to=MGR_ID, source_type="report", completed_at=D(-3)), + Task(tenant_id=TENANT_ID, company_id=COMP_E, title="跟进光合生物月报提交及时性", description="设置自动提醒,沟通提交规范", + status="done", priority="medium", assigned_to=MGR_ID, source_type="manual", completed_at=D(-2)), + ] + for t in tasks: + db.add(t) + await db.flush() + print(" ✓ 任务 (6 条)") + + +# ─── OKR ─────────────────────────────────────────────────────────────── +async def _seed_okrs(db: AsyncSession) -> None: + okrs = [ + OKR(company_id=COMP_A, quarter=f"{NOW.year}-Q{(NOW.month - 1) // 3 + 1}", + objective="实现季度营收3000万,客户净增8家", + key_results=[{"kr": "季度营收达3000万", "current": 2400, "target": 3000, "progress": 0.80}, + {"kr": "新签客户8家", "current": 5, "target": 8, "progress": 0.625}, + {"kr": "客户流失率<3%", "current": 0.04, "target": 0.03, "progress": 0.75}], + alignment_score=82.0, status="active", + deviation_alerts=[{"kr": "客户流失率", "current": "4%", "target": "<3%", "severity": "medium"}]), + OKR(company_id=COMP_B, quarter=f"{NOW.year}-Q{(NOW.month - 1) // 3 + 1}", + objective="完成A+轮融资,营收突破500万/月", + key_results=[{"kr": "月营收达500万", "current": 150, "target": 500, "progress": 0.30}, + {"kr": "完成A+轮融资", "current": 0, "target": 1, "progress": 0.0}, + {"kr": "签约3家金融客户", "current": 1, "target": 3, "progress": 0.33}], + alignment_score=55.0, status="active", + deviation_alerts=[{"kr": "月营收", "current": "150万", "target": "500万", "severity": "high"}, + {"kr": "融资进度", "current": "未启动", "target": "完成", "severity": "high"}]), + OKR(company_id=COMP_C, quarter=f"{NOW.year}-Q{(NOW.month - 1) // 3 + 1}", + objective="半导体行业营收占比70%,新增专利5项", + key_results=[{"kr": "半导体营收占比70%", "current": 0.60, "target": 0.70, "progress": 0.857}, + {"kr": "新增专利5项", "current": 2, "target": 5, "progress": 0.40}], + alignment_score=88.0, status="active", deviation_alerts=[]), + ] + for o in okrs: + db.add(o) + await db.flush() + print(" ✓ OKR (3 条)") + + +# ─── 里程碑 ──────────────────────────────────────────────────────────── +async def _seed_milestones(db: AsyncSession) -> None: + # 智链科技里程碑树 + m1 = MilestoneTree(company_id=COMP_A, name="B轮融资", is_current=True, status="in_progress", target_date=D(-90), description="B轮1亿人民币,估值8亿") + db.add(m1); await db.flush() + m2 = MilestoneTree(company_id=COMP_A, name="产品v3.0发布", parent_id=m1.id, is_current=True, status="completed", actual_date=D(-20), description="多模态供应链决策引擎") + m3 = MilestoneTree(company_id=COMP_A, name="客户数突破50", parent_id=m1.id, is_current=True, status="in_progress", target_date=D(-60)) + m4 = MilestoneTree(company_id=COMP_A, name="海外市场拓展", parent_id=m1.id, is_current=False, status="planned", target_date=D(-180), description="东南亚试点 — 备选路径", + ai_analysis={"risk": "海外合规成本高", "opportunity": "市场先发优势"}) + for m in [m2, m3, m4]: + db.add(m) + + # 云栈数据里程碑 + m5 = MilestoneTree(company_id=COMP_B, name="A+轮融资", is_current=True, status="in_progress", target_date=D(-45), description="A+轮3000万人民币") + db.add(m5); await db.flush() + m6 = MilestoneTree(company_id=COMP_B, name="数据治理平台v2.0", parent_id=m5.id, is_current=True, status="completed", actual_date=D(-10)) + m7 = MilestoneTree(company_id=COMP_B, name="金融行业突破", parent_id=m5.id, is_current=True, status="in_progress", target_date=D(-30)) + for m in [m6, m7]: + db.add(m) + + await db.flush() + print(" ✓ 里程碑 (7 节点)") + + +# ─── 协同机会 ────────────────────────────────────────────────────────── +async def _seed_synergies(db: AsyncSession) -> None: + synergies = [ + SynergyOpportunity(tenant_id=TENANT_ID, type="customer", company_a_id=COMP_A, company_b_id=COMP_C, + title="智链科技 → 深瞳智能:制造业客户共享", + description="智链科技的3家制造业客户有质检需求,可引荐深瞳智能。", + match_reason="AI分析:客户行业重叠度高,需求互补", + status="confirmed", authorized=True), + SynergyOpportunity(tenant_id=TENANT_ID, type="tech", company_a_id=COMP_B, company_b_id=COMP_D, + title="云栈数据 → 量子芯微:数据平台支持芯片设计仿真", + description="云栈数据平台可处理量子芯微的仿真数据集。", + match_reason="技术栈匹配,数据平台可降低芯片仿真IT成本40%", + status="discovered", authorized=False), + SynergyOpportunity(tenant_id=TENANT_ID, type="talent", company_a_id=COMP_C, company_b_id=COMP_E, + title="深瞳智能 → 光合生物:AI算法人才推荐", + description="深瞳智能有CV算法人才储备,光合生物需AI药物筛选算法工程师。", + match_reason="技能匹配度85%,工作地点同城", + status="executing", authorized=True, + effect_result={"candidates_referred": 3, "interviewed": 2, "offered": 1}), + ] + for s in synergies: + db.add(s) + await db.flush() + print(" ✓ 协同机会 (3 条)") + + +# ─── 决策前哨 ────────────────────────────────────────────────────────── +async def _seed_sentinels(db: AsyncSession) -> None: + sentinels = [ + DecisionSentinel(company_id=COMP_B, decision_type="funding", + title="A+轮融资时机选择:现在 vs 等待产品验证", + description="营收增长停滞,但产品v2.0刚发布。是否现在融资还是等Q2数据验证后融资?", + signals=[{"source": "月报", "signal": "营收停滞2月"}, {"source": "市场", "signal": "竞品定价低30%"}], + scenarios={"A": {"name": "现在融资", "pros": "现金充裕", "cons": "估值可能偏低", "probability": 0.6}, + "B": {"name": "等待Q2验证", "pros": "估值更高", "cons": "现金Runway风险", "probability": 0.4}}, + status="analyzed"), + DecisionSentinel(company_id=COMP_C, decision_type="hiring", + title="CTO retention:股权激励 vs 替换", + description="CTO稳定性下降,需决定加大股权激励还是提前寻找替代者。", + signals=[{"source": "LinkedIn", "signal": "CTO更新简历"}, {"source": "弱信号", "signal": "稳定性评分0.65"}], + scenarios={"A": {"name": "加大股权激励", "pros": "保留技术连续性", "cons": "股权稀释", "probability": 0.7}, + "B": {"name": "启动替换搜索", "pros": "降低单点风险", "cons": "过渡期风险", "probability": 0.3}}, + status="identified"), + DecisionSentinel(company_id=COMP_D, decision_type="funding", + title="天使+轮 vs Pre-A:融资策略选择", + description="现金Runway 7月,需快速融资。天使+轮快但金额小,Pre-A慢但可支撑更长。", + signals=[{"source": "财务", "signal": "Runway 7月"}, {"source": "产品", "signal": "NPU原型流片在即"}], + scenarios={"A": {"name": "天使+轮 1500万", "pros": "3个月内close", "cons": "只够6月", "probability": 0.55}, + "B": {"name": "Pre-A 5000万", "pros": "支撑18月", "cons": "需6月", "probability": 0.45}}, + status="acted"), + ] + for s in sentinels: + s.identified_at = D(10) + db.add(s) + await db.flush() + print(" ✓ 决策前哨 (3 条)") + + +# ─── 行为助推 ────────────────────────────────────────────────────────── +async def _seed_nudges(db: AsyncSession) -> None: + nudges = [ + NudgeRecord(company_id=COMP_A, nudge_type="anchoring", + context="月报审阅 — 客户流失率", + message="同类AI供应链企业平均客户流失率为2.5%,智链科技本月4%高于基准。", + target_user_id=MGR_ID, accepted=True, + effect_result={"action": "联系流失客户", "result": "挽留1家"}), + NudgeRecord(company_id=COMP_B, nudge_type="loss_aversion", + context="融资时机提醒", + message="如果不启动A+轮融资,预计6个月后现金耗尽,错失产品验证窗口。", + target_user_id=LEAD_ID, accepted=True, + effect_result={"action": "约见创始人讨论融资", "result": "启动BP准备"}), + NudgeRecord(company_id=COMP_D, nudge_type="social_proof", + context="融资策略", + message="Portfolio中3家类似阶段企业选择了Pre-A路线,平均估值高于天使+轮2倍。", + target_user_id=GP_ID, accepted=False, + effect_result={"action": "选择天使+轮", "result": "快速close"}), + NudgeRecord(company_id=COMP_C, nudge_type="timing", + context="CTO稳定性", + message="融资前是关键人才挽留的最佳时机,建议在B+轮前完成CTO股权激励调整。", + target_user_id=LEAD_ID, accepted=True, + effect_result={"action": "设计retention package", "result": "进行中"}), + ] + for n in nudges: + db.add(n) + await db.flush() + print(" ✓ 行为助推 (4 条)") + + +# ─── 重大事项 ────────────────────────────────────────────────────────── +async def _seed_events(db: AsyncSession) -> None: + events = [ + MajorEvent(company_id=COMP_A, event_type="product", title="产品v3.0多模态引擎发布", severity="high", + description="支持文本+图像+时序数据的多模态供应链决策引擎上线", + source="monthly_report", status="addressed", occurred_at=D(20)), + MajorEvent(company_id=COMP_C, event_type="personnel", title="CTO更新简历", severity="high", + description="CTO在LinkedIn更新简历,标注'开放看机会'", + source="weak_signal", status="confirmed", occurred_at=D(7)), + MajorEvent(company_id=COMP_D, event_type="funding", title="天使+轮融资启动", severity="critical", + description="现金Runway不足7月,启动天使+轮融资", + source="manual", status="addressed", occurred_at=D(3)), + MajorEvent(company_id=COMP_E, event_type="product", title="3个靶点进入先导化合物阶段", severity="medium", + description="AI药物筛选管线推进,3个靶点通过虚拟筛选进入实验验证", + source="monthly_report", status="confirmed", occurred_at=D(15)), + ] + for e in events: + db.add(e) + await db.flush() + print(" ✓ 重大事项 (4 条)") + + +# ─── 投资协议 ────────────────────────────────────────────────────────── +async def _seed_agreements(db: AsyncSession) -> None: + agreements = [ + InvestmentAgreement(company_id=COMP_A, title="B轮投资协议", signed_at=datetime(2023, 6, 1, tzinfo=UTC), + key_clauses={"valuation": "8亿人民币", "investment": "1亿", "board_seat": "1席", "anti_dilution": "加权平均", "liquidation_pref": "1x非参与"}, + monitoring_rules=[{"clause": "反稀释", "trigger": "下一轮估值低于8亿", "action": "通知GP"}], + status="active"), + InvestmentAgreement(company_id=COMP_B, title="A轮投资协议", signed_at=datetime(2023, 3, 1, tzinfo=UTC), + key_clauses={"valuation": "3亿", "investment": "5000万", "board_seat": "1席", "redemption_right": "5年后可要求回购"}, + monitoring_rules=[{"clause": "回购权", "trigger": "2028-03-01", "action": "提前6月提醒"}], + status="active"), + InvestmentAgreement(company_id=COMP_C, title="B轮投资协议", signed_at=datetime(2022, 12, 1, tzinfo=UTC), + key_clauses={"valuation": "10亿", "investment": "2亿", "board_seat": "1席", "info_rights": "月报+季度财务"}, + monitoring_rules=[{"clause": "信息权", "trigger": "月报延迟>5天", "action": "通知投后负责人"}], + status="active"), + ] + for a in agreements: + db.add(a) + await db.flush() + print(" ✓ 投资协议 (3 份)") + + +# ─── 董事会 ──────────────────────────────────────────────────────────── +async def _seed_boards(db: AsyncSession) -> None: + boards = [ + BoardMeeting(company_id=COMP_A, title="2025年Q2董事会", meeting_at=D(-7), status="scheduled", + agenda=[{"item": "Q2经营汇报", "duration": "30min"}, {"item": "B轮融资进展", "duration": "20min"}, {"item": "客户流失分析", "duration": "15min"}], + materials_summary="AI摘要:Q2营收2400万(完成80%),客户净增5家但流失率上升,B轮估值预期8-10亿。", + questions=[{"q": "客户流失率上升的原因是什么?", "priority": "high"}, {"q": "B轮预计何时close?", "priority": "medium"}]), + BoardMeeting(company_id=COMP_C, title="2025年Q2董事会", meeting_at=D(-14), status="completed", + agenda=[{"item": "Q2经营汇报", "duration": "30min"}, {"item": "半导体行业拓展", "duration": "20min"}], + minutes="Q2营收3600万超预期,半导体占比60%。专利新增2项。CTO稳定性需关注。", + resolutions=[{"item": "批准CTO股权激励调整方案", "status": "执行中"}, {"item": "Q3启动半导体行业专项销售", "status": "已启动"}]), + ] + for b in boards: + db.add(b) + await db.flush() + print(" ✓ 董事会 (2 场)") + + +# ─── BML 假设 ────────────────────────────────────────────────────────── +async def _seed_hypotheses(db: AsyncSession) -> None: + hypotheses = [ + Hypothesis(company_id=COMP_A, hypothesis="降低定价10%可提升客户签约率30%", + experiment="对3家潜在客户提供10%折扣试用", + data={"customers_tested": 3, "signed": 2, "conversion_rate": 0.67}, + conclusion="部分验证:签约率提升67%(超预期30%),但需观察折扣结束后续约率", + status="validated"), + Hypothesis(company_id=COMP_B, hypothesis="金融行业客户愿意为数据合规功能支付20%溢价", + experiment="向2家金融客户展示合规模块并报价溢价20%", + data={"customers_tested": 2, "interested": 1, "signed": 0}, + conclusion="待验证:1家表示感兴趣但需内部审批,尚未签约", + status="measuring"), + Hypothesis(company_id=COMP_C, hypothesis="半导体客户对边缘端质检需求年增长50%", + experiment="调研5家半导体客户未来12月质检预算", + data={"surveyed": 3, "budget_increase_avg": 0.35}, + conclusion="未达预期:平均预算增长35%低于50%假设,但基础需求强劲", + status="learning"), + ] + for h in hypotheses: + db.add(h) + await db.flush() + print(" ✓ BML 假设 (3 条)") + + +# ─── AAR 复盘 ────────────────────────────────────────────────────────── +async def _seed_aars(db: AsyncSession) -> None: + aars = [ + AARRecord(company_id=COMP_A, trigger_event="Q1客户流失率升至4%", + original_plan="Q1客户流失率控制在2%以内", + actual_result="Q1流失率4%,流失2家年合同客户", + gap_analysis="客户成功团队响应延迟,流失客户反馈'技术支持不够及时'。竞品以低价策略抢客。", + lessons={"what_expected": "流失率2%", "what_happened": "4%", "why_gap": "客户成功人手不足+竞品低价", "what_learned": "需主动客户健康度监控", "what_to_change": "增加客户成功HC,建立预警机制"}, + improvements=[{"action": "增加2名客户成功经理", "status": "已完成", "owner": "创始人"}, {"action": "建立客户健康度周报", "status": "进行中", "owner": "投资经理"}]), + AARRecord(company_id=COMP_C, trigger_event="CTO稳定性下降", + original_plan="核心技术团队稳定,无关键人员流失", + actual_result="CTO更新简历,稳定性评分0.65", + gap_analysis="CTO反馈股权激励不足,技术路线存在分歧。", + lessons={"what_expected": "CTO长期稳定", "what_happened": "稳定性下降", "why_gap": "股权激励未随估值增长调整", "what_learned": "关键人才激励需动态调整", "what_to_change": "建立定期激励review机制"}, + improvements=[{"action": "CTO股权激励调整方案", "status": "设计中", "owner": "投后负责人"}]), + ] + for a in aars: + db.add(a) + await db.flush() + print(" ✓ AAR 复盘 (2 条)") + + +# ─── 团队成员 ────────────────────────────────────────────────────────── +async def _seed_team_members(db: AsyncSession) -> None: + members = [ + TeamMember(company_id=COMP_A, name="陈智链", role="CEO/创始人", is_key_person=True, joined_at=datetime(2021, 3, 1, tzinfo=UTC), stability_score=0.92), + TeamMember(company_id=COMP_A, name="张技术", role="CTO", is_key_person=True, joined_at=datetime(2021, 4, 1, tzinfo=UTC), stability_score=0.85), + TeamMember(company_id=COMP_A, name="李销售", role="VP销售", is_key_person=True, joined_at=datetime(2022, 1, 1, tzinfo=UTC), stability_score=0.80), + TeamMember(company_id=COMP_C, name="赵深瞳", role="CEO/创始人", is_key_person=True, joined_at=datetime(2020, 6, 1, tzinfo=UTC), stability_score=0.90), + TeamMember(company_id=COMP_C, name="孙算法", role="CTO", is_key_person=True, joined_at=datetime(2020, 7, 1, tzinfo=UTC), stability_score=0.65), + TeamMember(company_id=COMP_C, name="周产品", role="产品总监", is_key_person=False, joined_at=datetime(2021, 3, 1, tzinfo=UTC), stability_score=0.78), + TeamMember(company_id=COMP_B, name="刘云栈", role="CEO/创始人", is_key_person=True, joined_at=datetime(2022, 1, 1, tzinfo=UTC), stability_score=0.88), + ] + for m in members: + db.add(m) + await db.flush() + print(" ✓ 团队成员 (7 人)") + + +# ─── 人才画像 ────────────────────────────────────────────────────────── +async def _seed_talents(db: AsyncSession) -> None: + talents = [ + TalentProfile(tenant_id=TENANT_ID, name="孙算法", current_role="CTO", current_company="深瞳智能", + skills=["计算机视觉", "PyTorch", "团队管理", "边缘计算"], experience_years=12, + performance_rating=4.5, potential_rating=4.0, nine_box="star", + flow_prediction={"probability": 0.65, "timeline": "3-6月", "triggers": ["股权激励不足", "技术路线分歧"]}, + status="active"), + TalentProfile(tenant_id=TENANT_ID, name="李销售", current_role="VP销售", current_company="智链科技", + skills=["B2B销售", "制造业客户", "团队管理"], experience_years=10, + performance_rating=4.2, potential_rating=3.8, nine_box="high_potential", + flow_prediction={"probability": 0.20, "timeline": "12月+", "triggers": []}, + status="active"), + TalentProfile(tenant_id=TENANT_ID, name="吴架构", current_role="首席架构师", current_company="云栈数据", + skills=["分布式系统", "数据治理", "Kubernetes"], experience_years=15, + performance_rating=4.8, potential_rating=4.5, nine_box="star", + flow_prediction={"probability": 0.15, "timeline": "稳定", "triggers": []}, + status="active"), + ] + for t in talents: + db.add(t) + await db.flush() + print(" ✓ 人才画像 (3 人)") + + +# ─── 审计日志 ────────────────────────────────────────────────────────── +async def _seed_audit_logs(db: AsyncSession) -> None: + logs = [ + AuditLog(tenant_id=TENANT_ID, user_id=MGR_ID, action="login", resource_type="auth", ip="192.168.1.100", created_at=D(0)), + AuditLog(tenant_id=TENANT_ID, user_id=MGR_ID, action="view", resource_type="company", resource_id=COMP_A, ip="192.168.1.100", created_at=D(0)), + AuditLog(tenant_id=TENANT_ID, user_id=MGR_ID, action="view", resource_type="report", resource_id="report_001", ip="192.168.1.100", created_at=D(0)), + AuditLog(tenant_id=TENANT_ID, user_id=LEAD_ID, action="view", resource_type="risk", resource_id="risk_001", ip="192.168.1.101", created_at=D(1)), + AuditLog(tenant_id=TENANT_ID, user_id=LEAD_ID, action="update", resource_type="risk", resource_id="risk_001", detail_json={"field": "status", "old": "open", "new": "assigned"}, ip="192.168.1.101", created_at=D(1)), + AuditLog(tenant_id=TENANT_ID, user_id=GP_ID, action="view", resource_type="dashboard", ip="192.168.1.102", created_at=D(2)), + AuditLog(tenant_id=TENANT_ID, user_id=GP_ID, action="ai_call", resource_type="weekly_brief", detail_json={"tokens": 3500, "model": "qwen-max"}, ip="192.168.1.102", created_at=D(2)), + AuditLog(tenant_id=TENANT_ID, user_id=ADMIN_ID, action="view", resource_type="audit_logs", ip="192.168.1.103", created_at=D(3)), + AuditLog(tenant_id=TENANT_ID, user_id=FOUNDER_A, action="create", resource_type="monthly_report", detail_json={"company": "智链科技", "period": f"{NOW.year}-{NOW.month-1}"}, ip="10.0.0.50", created_at=D(10)), + AuditLog(tenant_id=TENANT_ID, user_id=FOUNDER_B, action="create", resource_type="monthly_report", detail_json={"company": "云栈数据", "period": f"{NOW.year}-{NOW.month-1}"}, ip="10.0.0.51", created_at=D(8)), + ] + for l in logs: + db.add(l) + await db.flush() + print(" ✓ 审计日志 (10 条)") + + +if __name__ == "__main__": + asyncio.run(seed())