| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- """
- 完整端到端测试:
- 1. 生成模拟决策数据
- 2. 发送飞书审批(个人 + 项目群)
- 3. 验证权限设置(anyone_editable)
- 4. 检查表格格式和表头
- """
- import asyncio
- import sys
- from pathlib import Path
- from datetime import datetime
- import pandas as pd
- sys.path.insert(0, str(Path(__file__).parent.parent.parent))
- from dotenv import load_dotenv
- load_dotenv()
- from agent.tools.models import ToolContext
- from config import FEISHU_OPERATOR_OPEN_ID, FEISHU_AD_PROJECT_CHAT_ID
- # 导入审批工具
- from tools.im_approval import send_approval_request
- async def main():
- print("=" * 70)
- print(" 完整端到端测试:审批流程 + 飞书在线表格")
- print("=" * 70)
- print()
- print("配置验证:")
- print(f" 个人 Open ID: {FEISHU_OPERATOR_OPEN_ID}")
- print(f" 项目群聊 ID: {FEISHU_AD_PROJECT_CHAT_ID}")
- print()
- if not FEISHU_OPERATOR_OPEN_ID or not FEISHU_AD_PROJECT_CHAT_ID:
- print("❌ 错误:配置缺失")
- return
- # 步骤1:生成模拟决策数据(验证后的决策CSV)
- print("步骤 1/4:生成模拟决策数据")
- print("-" * 70)
- # 创建模拟数据(包含所有审批表头字段)
- mock_data = [
- {
- "ad_id": 12345678,
- "account_id": 80769799,
- "ad_name": "R500_测试广告_1_小程序引流",
- "audience_tier": "R500",
- "ad_age_days": 15,
- "bid_amount": 15000, # 150元(单位:分)
- "cost_7d_avg": 850.5,
- "cost_7d_total": 5953.5,
- "revenue_7d_total": 8930.25,
- "动态ROI_7日均值": 1.50,
- "final_action": "pause",
- "action": "pause",
- "dimension": "ROI低于同类",
- "reason": "动态ROI为1.5,低于R500组中位数2.8的46%;消耗稳定但ROI持续偏低,建议关停",
- "recommended_change_pct": 0.0,
- "configured_status": "AD_STATUS_NORMAL",
- "tier": 2, # Tier 2需要审批
- },
- {
- "ad_id": 12345679,
- "account_id": 80769799,
- "ad_name": "R500_测试广告_2_小程序引流",
- "audience_tier": "R500",
- "ad_age_days": 20,
- "bid_amount": 18000,
- "cost_7d_avg": 1200.8,
- "cost_7d_total": 8405.6,
- "revenue_7d_total": 20170.44,
- "动态ROI_7日均值": 2.40,
- "final_action": "bid_down",
- "action": "bid_down",
- "dimension": "ROI低于同类",
- "reason": "动态ROI为2.4,低于R500组中位数2.8的14%;裂变率0.52低于同类均值0.62的16%;7日均消耗1200元,建议降价3%",
- "recommended_change_pct": 0.03,
- "configured_status": "AD_STATUS_NORMAL",
- "tier": 2,
- },
- {
- "ad_id": 12345680,
- "account_id": 80769799,
- "ad_name": "R330_测试广告_1_小程序引流",
- "audience_tier": "R330",
- "ad_age_days": 12,
- "bid_amount": 12000,
- "cost_7d_avg": 680.2,
- "cost_7d_total": 4761.4,
- "revenue_7d_total": 8094.38,
- "动态ROI_7日均值": 1.70,
- "final_action": "bid_down",
- "action": "bid_down",
- "dimension": "ROI低于同类",
- "reason": "动态ROI为1.7,低于R330组中位数2.0的15%;裂变率0.48低于同类均值0.55的13%;7日均消耗680元,建议降价5%",
- "recommended_change_pct": 0.05,
- "configured_status": "AD_STATUS_NORMAL",
- "tier": 3, # Tier 3需要审批
- },
- ]
- df = pd.DataFrame(mock_data)
- # 保存为验证后的CSV
- outputs_dir = Path("outputs/reports")
- outputs_dir.mkdir(parents=True, exist_ok=True)
- validated_csv = outputs_dir / "validated_decisions_test_e2e.csv"
- df.to_csv(validated_csv, index=False, encoding="utf-8-sig")
- print(f"✅ 生成 {len(df)} 条模拟决策数据")
- print(f" 文件: {validated_csv}")
- print(f" 内容: {len(df[df['tier'] >= 2])} 条需审批(Tier 2/3)")
- print()
- # 步骤2:发送飞书审批
- print("步骤 2/4:发送飞书审批")
- print("-" * 70)
- ctx = ToolContext()
- try:
- result = await send_approval_request(
- ctx=ctx,
- validated_csv=str(validated_csv),
- wait_for_reply=False, # 非阻塞模式,仅发送不等待回复
- timeout_minutes=5,
- )
- print("✅ 审批请求发送成功!")
- print()
- print(f"标题: {result.title}")
- print(f"输出: {result.output}")
- print()
- if result.metadata:
- request_id = result.metadata.get("request_id")
- print(f"请求ID: {request_id}")
- print(f"发送状态: {result.metadata.get('feishu_sent', False)}")
- print()
- except Exception as e:
- print(f"❌ 发送失败: {e}")
- import traceback
- traceback.print_exc()
- return
- # 步骤3:验证结果
- print("步骤 3/4:验证检查项")
- print("-" * 70)
- print()
- print("请手动验证以下项目:")
- print()
- print("✅ 1. 个人飞书消息")
- print(f" 检查 {FEISHU_OPERATOR_OPEN_ID} 是否收到:")
- print(" - 审批文本消息(包含'请回复通过或拒绝')")
- print(" - 在线表格链接(或文件附件)")
- print()
- print("✅ 2. 项目群聊消息")
- print(f" 检查群聊 {FEISHU_AD_PROJECT_CHAT_ID} 是否收到:")
- print(" - 相同的审批文本消息")
- print(" - 相同的在线表格链接(或文件附件)")
- print()
- print("✅ 3. 在线表格权限")
- print(" 打开表格链接,检查:")
- print(" - 是否能直接打开(无需权限申请)")
- print(" - 是否有\"编辑\"按钮(anyone_editable)")
- print(" - 尝试修改单元格内容,确认可编辑")
- print()
- print("✅ 4. 表格表头和格式")
- print(" 检查表格是否包含以下列:")
- for i, col in enumerate([
- "approval_date", "account_id", "ad_id", "cost_7d_avg", "action",
- "ad_name", "audience_tier", "ad_age_days", "bid_amount",
- "动态ROI_7日均值", "cost_7d_total", "revenue_7d_total",
- "dimension", "reason", "recommended_change_pct"
- ], 1):
- print(f" {i:2d}. {col}")
- print()
- print("✅ 5. E1黄色高亮")
- print(" 检查单元格 E1(action列标题)是否有黄色背景")
- print()
- # 步骤4:回复测试提示
- print("步骤 4/4:回复测试")
- print("-" * 70)
- print()
- print("现在可以测试回复功能:")
- print(" 1. 在个人私聊中回复 '通过'")
- print(" 或")
- print(" 2. 在项目群聊中回复 '通过'")
- print()
- print("系统应该能识别任一处的回复。")
- print()
- print("=" * 70)
- print(" 测试完成")
- print("=" * 70)
- print()
- print("📋 总结:")
- print(" ✅ 模拟数据生成完成")
- print(" ✅ 飞书审批发送完成")
- print(" ⏳ 等待手动验证")
- print()
- if __name__ == "__main__":
- asyncio.run(main())
|