ys-data-search - YonSuite 数据查询
定位: YS 系统业务数据查询 + 分析报表生成,支持销售/采购/生产订单、库存、客户、供应商、CRM等核心模块。
版本: v7.2(2026-06-12 HTML 输出路径变更 + query_tool 已知 Bug 记录 + 生成工作流文档)
1️⃣ 架构总览
ys-data-search/
├── SKILL.md ← 本文件(入口指引)
├── modules/ ← Layer 1: Python 库(基础 HTTP 客户端 + 各模块)
│ ├── base.py ← BaseAPIClient、重试、HTTP POST/GET
│ ├── sales.py / purchase.py / production.py / stock.py / …
│ └── __init__.py ← 统一导出
├── scripts/
│ └── query_tool.py ← Layer 1.5: 统一 CLI 工具
├── templates/ ← HTML 报表模板
├── references/
│ ├── api/ ← Layer 0: API 字段参考(按模块独立文档)
│ │ ├── sale-order-api.md
│ │ ├── purchase-order-api.md
│ │ ├── production-order-api.md
│ │ ├── stock-api.md
│ │ └── crm-api.md
│ ├── query_tool-cli-pitfalls.md ← CLI 已知 Bug(见 6.1)
│ └── *-pitfalls-*.md ← 各模块细节坑
├── config.py / exceptions.py / cache.py / models.py ← 配置/异常/缓存/模型
└── ys_client.py ← 主入口 YonSuiteClient
三层分工:
modules/*:稳定 Python API 封装,不改scripts/query_tool.py:统一 CLI,替代旧的 5 个独立脚本references/api/*:API 字段参考,供查询时查阅,避免 SKILL.md 膨胀
⚠️ 铁律:Python 脚本管理
> 2026-06-08 用户明确要求,此技能所有参与者(包括 AI agent)必须遵守:
- 禁止随意新增 Python 脚本。 创建任何新脚本前必须先获得用户明确授权。
- 优先复用现有工具。 有现成的
scripts/query_tool.py、modules/库可用时,绝不另起炉灶写新脚本。 - 用完即销毁。 经授权创建的临时/一次性脚本,执行完任务后必须立即清理删除,不得留在仓库中。
- 不提交垃圾。 备份文件、一次性迁移脚本、硬编码数据的临时跑数脚本,一律不允许提交到仓库。
违例后果: 仓库混入不可维护的垃圾脚本,增加维护成本,降低技能可信度。之前已因此清理 8 个冗余脚本(一次性临时脚本、旧版叠加生成器、备份残留),引以为戒。
2️⃣ 安装验证
ls SKILL.md ys_client.py modules/ scripts/ templates/ references/
$YONCLAW_MANAGED_PYTHON -c "import sys; sys.path.insert(0,'SKILL_DIR'); from ys_client import YonSuiteClient; print('OK')"
3️⃣ 执行前强制确认
| # | 问题 | 判断 | 下一步 |
|---|---|---|---|
| 1 | 用户指的是哪种任务? | YS 单据状态 → query_tool | 确认后继续 |
| 2 | 数据来源是哪个系统? | 默认指 YonSuite (YS) 系统数据 | YS 走 query_tool |
| 3 | 要不要生成 HTML? | 是(默认),不是等用户说了才做 | 走输出规范 |
| 4 | 要不要分析洞察? | 分析类任务必须调用 data-analysis skill | 走第 7 节流程 |
| 5 | 字段检查做了吗? | 输出前必须展示字段清单对照报告 | 必做项 |
4️⃣ 配置
本技能通过 YonSuite OpenAPI 直连认证,需要用户提供以下凭据,保存到技能目录下的 .env 文件:
YONSUITE_APP_KEY=你的AppKey
YONSUITE_APP_SECRET=你的AppSecret
YONSUITE_TENANT_ID=你的租户ID
> 缺少配置时执行查询会提示 YonSuiteConfigError,引导用户补全。
可选配置项:
| 环境变量 | 默认值 | 说明 |
|---|---|---|
YONSUITE_GATEWAY_URL |
https://c2.yonyoucloud.com/iuap-api-gateway |
API 网关地址 |
YONSUITE_TOKEN_URL |
https://c2.yonyoucloud.com/iuap-api-auth |
Token 获取地址 |
YONSUITE_LOG_LEVEL |
INFO |
日志级别 |
YONSUITE_HTTP_TIMEOUT |
30 |
HTTP 超时秒数 |
5️⃣ 核心概念
主子表结构
| 层级 | 说明 |
|---|---|
| 主表(每订单一条) | code、vouchdate、salesOrgId_name 等 |
明细表(orderDetails[]) |
skuCode、qty、oriSum 等 |
通用规则
oriSum(含税金额)、oriTaxUnitPrice(含税单价)在明细行顶层oriTax(税额)在明细行返回 null,税额由公式计算- 币种在
orderPrices.originalName(嵌套)
def get_currency(r):
op = r.get("orderPrices")
if isinstance(op, list):
return op[0].get("originalName") if op else None
if isinstance(op, dict):
return op.get("originalName")
return None
6️⃣ 查询方法
6.1 统一 CLI(推荐)
cd SKILL_DIR
$YONCLAW_MANAGED_PYTHON scripts/query_tool.py sales 2026-04
$YONCLAW_MANAGED_PYTHON scripts/query_tool.py purchase 2026-04-01
$YONCLAW_MANAGED_PYTHON scripts/query_tool.py production 2026-04
$YONCLAW_MANAGED_PYTHON scripts/query_tool.py production-detail 2026-04
$YONCLAW_MANAGED_PYTHON scripts/query_tool.py stock --warehouse 仓库名 --sku SKU编码
每个查询输出 JSON 到 output/ 目录。如需了解返回的字段明细,查阅对应 references/api/*.md。
> ⚠️ ~~已知 Bug(2026-06-12 发现)~~ ✅ 2026-06-18 已修复:根因为 if not rs: break; allr.extend(rs) 的 Python 单行缩进陷阱,allr.extend(rs) 永远无法执行。sales/purchase/production 三个函数均已修复。
6.2 代码内调用
如果需要在脚本中调用,直接用 Python 导入 ys_client:
from ys_client import YonSuiteClient
client = YonSuiteClient()
orders = client.query_sale_orders(
page_index=1,
page_size=500,
isSum=False,
date_from="2026-04-01",
date_to="2026-04-30",
)
6.3 获取 API 字段参考
查询或输出时若不确定字段名、状态映射等,先读对应 references/api/ 文档:
sale-order-api.md— 销售订单 29 字段完整清单purchase-order-api.md— 采购订单 32 字段(含 simpleVOs 日期过滤写法)production-order-api.md— 生产订单 24 字段stock-api.md— 库存 13 字段crm-api.md— CRM 商机字段
6.4 ~~YS 待办中心~~(已迁移至专用 skill)
> ~~待办功能已从 ys-data-search 中移除,迁移至专用 skill。~~
6.5 客户档案 name 字段(实测 Gotcha)
name 是嵌套 dict,不是字符串:
def _extract_name(raw):
if isinstance(raw, dict):
return raw.get("simplifiedName") or raw.get("name") or ""
return str(raw) if raw else ""
7️⃣ 标准输出流程
7.1 执行查询
$YONCLAW_MANAGED_PYTHON scripts/query_tool.py sales 2026-04
7.2 字段检查
输出 JSON 后,展示检查报告:
【字段检查】销售订单明细 29字段
✅ 已返回:27字段(表体税额由公式计算)
❌ 缺失:无
7.3 输出正文
双轨输出:
- 聊天框:Markdown 卡片摘要
- HTML:写入
~/Documents/YonSuite报告/目录(使用ditto复制,sandbox 无法直接 ls 但可以 cp)
> 中间 JSON 文件仍保留在 output/ 目录,最终 HTML 报告发布到 ~/Documents/YonSuite报告/。
> 报告工作流完整见 references/html-report-generation-workflow.md(含沙箱限制和临时脚本规范)。
> HTML 规范参考 references/sale-order-html-style.md(销售)或对应模板。
7.4 协同:同时查多模块
import concurrent.futures
with concurrent.futures.ThreadPoolExecutor() as ex:
f1 = ex.submit(
client.query_sale_orders,
date_from="2026-04-25",
date_to="2026-04-25",
isSum=False,
)
f2 = ex.submit(client.query_production_orders, page_size=500)
sales, prod = f1.result(), f2.result()
8️⃣ 分析报表流水线
> ⚠️ 分析类任务必须调用 data-analysis skill,禁止 LLM 直推。
数据来源
| 模块 | CLI 命令 | JSON 输出 |
|---|---|---|
| 销售 | query_tool sales YYYY-MM |
output/sale_order_result.json |
| 采购 | query_tool purchase YYYY-MM |
output/purchase_order_result.json |
| 生产 | query_tool production YYYY-MM |
output/production_order_result.json |
分析流程
- 加载 data-analysis skill → 读 techniques.md + decision-briefs.md
- 数据异常预检(IQR 检测)
- Python 统计分析(HHI 集中度、漏斗转化、分段对比)
- 输出 Decision Brief 写入 HTML
HTML 报告结构
Hero 区 → KPI 卡片行 → 图表区 2×2 → 决策简报(4 洞察卡片)→ 订单明细表格
模板文件: templates/sale_analysis_template.html / templates/production_analysis_template.html
踩坑自检(预读):
references/production-order-pitfalls-20260430.mdreferences/purchase-order-pitfalls-20260430.mdreferences/query_tool-cli-pitfalls.md(见第 6.1 节 query_tool 已知 Bug)
9️⃣ CPU 沙箱注意事项
execute_code 是独立沙箱,无法继承 shell 环境变量。正确做法:写临时 Python 脚本 + terminal 执行。
🔟 命名规范
| 场景 | 格式 |
|---|---|
| 销售报表 HTML | ~/Documents/YonSuite报告/本月销售分析报表_YYYY_MM.html |
| 采购报表 HTML | ~/Documents/YonSuite报告/本月采购分析报表_YYYY_MM.html |
| 生产报表 HTML | ~/Documents/YonSuite报告/本月生产分析报表_YYYY_MM.html |
| JSON 数据(中间文件) | output/{sale,purchase,production,stock}_order_result.json |
合计行过滤: 销售用 vouchdate == "合计",采购用 订单编号 == "合计",生产用 单据编号 == "合计"