vps-work 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vps-work",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "VPS Work CLI - tenant-aware domain shortcuts and bundled agent skills for Cursor / Claude Code / Trae.",
5
5
  "license": "MIT",
6
6
  "author": "he-linyan",
@@ -47,10 +47,10 @@
47
47
  "dev": "tsx src/bin/vps-work.ts",
48
48
  "build": "tsup && node scripts/build-office.mjs",
49
49
  "lint": "eslint \"src/**/*.ts\" \"tests/**/*.ts\"",
50
- "typecheck": "tsc --noEmit",
50
+ "typecheck": "tsc -p tsconfig.cli.json && tsc -p tsconfig.integration-tests.json",
51
51
  "test": "vitest run",
52
52
  "test:watch": "vitest",
53
- "prepublishOnly": "npm test && npm run build",
53
+ "prepublishOnly": "npm run typecheck && npm run lint && npm test && npm run build",
54
54
  "pretest": "node scripts/build-office.mjs"
55
55
  },
56
56
  "dependencies": {
@@ -69,7 +69,7 @@ Shortcut 是对常用销售经营查询的高级封装(`vps-work sales +<verb>
69
69
 
70
70
  - 用户提到“经销商订单 / 经销商销售单 / JXSD 单号”时必须用 `+dealer-orders`,不要用普通 `+orders`;两者数据模型和金额口径不同。
71
71
  - `+dealer-orders` 默认本月,订单号、经销商、商品或 VSN 筛选后仍需检查 `filter.order_prefix=JXSD`、`filter.access` 和分页状态。
72
- - 用户问“经销商库存数量/金额”时用 `+dealer-inventory`;这是经销商默认仓库专用口径,不用通用商品库存替代。
72
+ - 用户问“经销商库存数量/金额”时用 `+dealer-inventory`;这是经销商默认仓库专用口径,不用通用商品库存替代。查询逐件商品、VSN、IMEI1/IMEI2、仓库和库位时,使用同一命令加 `--params '{"detail":true,"page":1,"page_size":100}'`,按 `pagination.total_rows` 翻页;现有 CLI 无需升级。
73
73
  - 用户问“经销商终销/五件套客户类型”时用 `+dealer-final-sales`;用户问终销单内的客户背景、年龄或购买原因时用 `+dealer-customer-portrait`。两个终销入口默认本月,必须说明只含 `JXSD + done + so + 非退货明细`。
74
74
  - 用户问“代理商 Sell-in/Sell-out 对比”时用 `+agent-sell-in-out`,追明细用 `+agent-sell-in-out-details`。Sell-in 来自国内代理部门子树销售业绩;Sell-out 来自国内经销商已完成销售单。此处为 `vps-ep` 个性化看板口径,不额外限制 `JXSD` 或 `doc_type=so`。
75
75
  - 用户问“代理商五件套/五大来源/来源完成率”时用 `+agent-five-source`;问半年结构时用 `+agent-five-source-half-year`;问自然进店订单时用 `+agent-walkin`。
@@ -25,12 +25,14 @@
25
25
  ## 参数
26
26
 
27
27
  - 时间使用共享的 `--period`、`--start-date`、`--end-date`;半年度命令未传日期时可传 `--year`、`--month` 决定 H1/H2。
28
- - `--agent-name <完整名称>` 标准化中英文括号后精确匹配,同时传给 Sell-in、Sell-out 和目标表。
28
+ - Sell-in/out、明细、Walk-in、五件套来源/半年/完成率支持 `--dealer-id <ID>`(execute 参数 `dealer_id`),优先于名称,按同一主体过滤所有销售数据。
29
+ - 以上查询的 `--agent-name <完整名称>` 标准化中英文括号后匹配主体名称或原伙伴名称(含门店后缀)。名称对应多个主体时返回 409 并列出候选 ID,必须选择 ID;不存在的 ID 返回 404,非法 ID 返回 400。目标按所选主体的原伙伴名称读取,保留门店后缀。
30
+ - 其他代理商业绩、产品和提货命令仍使用原有完整客户名称筛选,暂不支持 `--dealer-id`。
29
31
  - `--dealer <名称>` 是兼容参数。新代理商看板查询应优先使用 `--agent-name`,旧库存、订单、终销查询仍可用 `--dealer` 模糊匹配。
30
32
 
31
33
  ## 口径
32
34
 
33
- - Sell-in:直接查询 `销售订单明细`,范围为国内代理部门 ID `2234` 及其完整子树,按客户名称汇总实际金额和数量;不用会脱敏客户名的公共销售行构造器,否则无法精确筛选代理商。
35
+ - Sell-in:直接查询 `销售订单明细`,范围为国内代理部门 ID `2234` 及其完整子树。优先通过销售单号关联原销售单的客户伙伴 ID,再匹配代理商主体(直接伙伴优先于商业父主体)。只有找不到原销售单的历史行才允许按唯一主体/伙伴名称匹配;同名或多订单身份歧义单列待核实。按 `dealer_id` 汇总实际金额和数量,不用会脱敏客户名的公共销售行构造器。
34
36
  - Sell-out:与 `vps-ep` 个性化看板一致,取 `dealer_sale_order` 中 `state=done + dealer_nature=domestic`,不额外限制 `JXSD` 或 `doc_type=so`;汇总金额取订单 `total`。
35
37
  - `+dealer-final-sales` 是另一套严格终销口径,仍限制 `JXSD + done + so + 非退货明细`,不要与代理商个性化看板 Sell-out 混用。
36
38
  - 五件套真实业绩按经销商订单客户类型映射:自然进店→`walk in`、老客户存量→`存量`、线上渠道:官网+社媒→`原线上`、商场线下:异业销售推荐→`下线`、招聘:新员工自带客户转化→`AI招聘`。
@@ -42,6 +44,18 @@
42
44
  - `线下代理OKR` 目标严格按请求日期范围读取;当前期无记录时返回 `0`,不自动沿用最近月份。回答时应说明目标缺失,不把 `0` 表述为已配置的零目标。
43
45
  - 普通用户沿用 ERP 经销商记录规则;汇总与目标也必须检查返回的 `filter.access`。
44
46
 
47
+ ## 代理商与员工身份
48
+
49
+ 名单同时返回 `partner_name`(原伙伴名称),供同名主体的门店区分与展示。
50
+
51
+ - `agent_list.agents` 顶层只返回当前启用的国内代理商主体,名单来自 `res_dealer_information`,不再从销售客户名称或员工账号拼名单;无当期销售的已登记代理商也会出现。时间参数不决定主体是否存在。
52
+ - 每个主体含 `dealer_id`(ERP `res.dealer.information.id`)、`name`、`entity_type: dealer`。下属员工位于该项的 `employees`,包含 `dealer_id`、`employee_id`(ERP `hr.employee.id`)、`user_id`(ERP `res.users.id`)、`name` 和 `entity_type: dealer_employee`。不能把嵌套员工当作独立代理商计数。
53
+ - Sell-out 先使用订单保存的 `dealer_id`;旧单为空时使用账号 `dealer_id`,最后仅允许唯一的企业伙伴关联。订单的 `dealer_name` 原字段实际是 `res.users` 外键,不能把其伙伴姓名当成代理商名称,也不能用订单买家的 `partner_id` 作为售出方主体。
54
+ - 汇总 `rows` 以 `dealer_id` 合并,`dealers` 兼容字段提供 `dealerId`、`dealerName`、`entityType`。同名但不同 ID 的主体保持独立;员工产生的金额归入其订单主体。
55
+ - Sell-out 明细和 Walk-in 同时提供 `dealer_id/dealer_name`、`dealer_user_id`、`dealer_employee_id`、`dealer_employee_name`,兼容字段为对应 camelCase。`salesperson` 是原订单填写的销售员文本,与登录账号身份分开保留。`entity_type` 区分 `dealer_employee`、无唯一员工档案的 `dealer_account`、无法核实主体的 `unresolved`。
56
+ - 无法唯一归属的记录不进入代理商汇总行,单列 `attribution_issues` 和 `unattributed`。整体金额仍包含这部分,`summary.attribution_complete=false` 表示需要核对;代理商行合计与整体合计的差额见 `unattributed`,不得据姓名猜测归属或静默丢弃金额。
57
+ - `identity_contract: dealer_subject_v1` 标识以上返回契约。此调整需要更新 VPS 服务端;仅更新 CLI 不会改变已部署接口的数据归属。
58
+
45
59
  ## 示例
46
60
 
47
61
  ```powershell
@@ -47,3 +47,20 @@ vps-work sales +dealer-inventory --nature domestic
47
47
  vps-work sales +dealer-final-sales --period this_year --dealer "太原拍得丽"
48
48
  vps-work sales +dealer-customer-portrait --start-date 2026-07-01 --end-date 2026-07-31
49
49
  ```
50
+
51
+ ## 逐件库存明细(兼容现有 CLI)
52
+
53
+ 服务端支持 `dealer_inventory_summary` 的 `detail=true` 模式;旧 CLI 使用已有的 `--params` 透传,无需升级 npm 包。默认不传 `detail` 时保持原汇总响应。
54
+
55
+ ```bash
56
+ vps-work sales +dealer-inventory --dealer "经销商名称" --params '{"detail":true,"page":1,"page_size":100}'
57
+ # 完整名称精确匹配,避免名称包含匹配查到多个经销商
58
+ vps-work sales +dealer-inventory --agent-name "经销商完整名称" --params '{"detail":true,"page":2,"page_size":100}'
59
+ ```
60
+
61
+ - 返回经销商、经销商性质、商品编码、商品名称、VSN、IMEI1、IMEI2、仓库、完整库位和库存数量。
62
+ - 每行对应一条正库存记录,同一 VSN 在不同库位可能有多行;数量取真实库存数量,不强制为 1。缺少 VSN 或 IMEI 时返回 `null`。
63
+ - IMEI 来自 `vsn_index` 中对应 VSN 的最新记录,每个 VSN 只关联一行,避免重复索引放大库存。
64
+ - `pagination` 返回 `page`、`page_size`、`total_rows`;默认每页 100,最大 1000。`summary` 的数量和经销商数覆盖全部匹配库存,不仅是当前页。空页仍返回总数。
65
+ - 沿用本页既有默认仓库、内部库位、序列号追踪商品口径及全部权限控制;`--dealer`、`--agent-name`、`--nature` 和 `--product` 均继续生效。
66
+ - HTTP 仍走现有执行接口,以 `skill_key=vps-daily-sales-report`、`script_key=dealer_inventory_summary`、`params.detail=true` 调用,继续要求 `sales.headline_kpi:read`。
@@ -18,3 +18,15 @@ metadata:
18
18
  | [`+my-submitted`](../vps-pending-approval-assistant/reference.md) | 同上 |
19
19
  | [`+my-approved`](../vps-pending-approval-assistant/reference.md) | 同上 |
20
20
  | [`+pass` / `+refuse` / `+logs`](../vps-pending-approval-assistant/SKILL.md) | 内建 AI tool |
21
+
22
+ 新版 VPS 及 ERP 历史付款申请只读查询复用现有 `exec`,不新增命令:
23
+
24
+ ```sh
25
+ vps-work exec --skill vps-pending-approval-assistant --script payment_applications --param start_date=2026-10-01 --param end_date=2026-10-15
26
+ vps-work exec --skill vps-pending-approval-assistant --script payment_applications --param operation=detail --param document_number=FK20261015-01
27
+ vps-work exec --skill vps-pending-approval-assistant --script payment_applications --param source=erp --param start_date=2026-01-01
28
+ ```
29
+
30
+ 必须显式授予 `approvals.payment.all:read`;默认查询当前企业全部新版 VPS 及 ERP 历史付款申请,可指定 `source=vps/erp`。普通审批权限和管理员通配权限不代替此授权。合并列表以 `next_cursor` 传 `cursor` 续查,单来源以 `next_offset` 传 `offset`(`limit` 最大100)。支持 `status`、`applicant_user_id`、`keyword`、精确 `document_number`;VPS 用户筛选历史时通过来源关联映射,不能直接混用编号。详情也可用 `submission_id` 或 `erp_id`;两边同号需明确来源。不支持发起、审批、编辑、撤回或付款,不改变原 ERP 审批队列的 ACL。
31
+
32
+ 新版及 ERP 历史付款查询可直接展示返回的来源、单号、申请人、金额、币种、明细行、审批进度和附件名称,无需转交其他技能;原有队列“仅展示类型与数量”的限制不适用于该查询。字段、日期、状态和附件目录说明见上表引用的 `reference.md`。
@@ -49,6 +49,8 @@ vps-work creative +video --model <id> --prompt "..." --wait --wait-timeout 600
49
49
 
50
50
  ## 返回说明
51
51
 
52
+ - 云电脑沙箱通过当前账号网关访问素材。需要检查、预览或加工生成文件时,使用 `vps-work creative +download --storage-key '<返回的 storage_key>' --output './图片.png'`,再读取本地图片。也支持 `--url '<VPS /v1/creative/oss?key=... 地址>'`。不要直接用 curl 访问公网素材地址,也不要因公网 DNS 被隔离就判定图片不可下载;返回的 `attachments[].download_command` 提供完整命令参数。该命令沿用当前账号素材权限,不覆盖已有文件。
53
+
52
54
  - 生图 `image_url`、生视频 `video_url`、语音/音乐 `url` 都是站内受控 OSS 直链,可直接作为可下载附件链接回给用户。
53
55
  - 生图/语音会返回 `billing`(预扣/实扣积分),生成类操作会消耗当前登录用户的画布积分;积分不足返回 402 类错误,需引导用户到画布前台充值。
54
56
  - `+models` 返回的 `billing` 字段(unit/credits/ratio/min)用于预估消耗,`display_name` 用于回显模型名。
@@ -28,11 +28,13 @@ metadata:
28
28
 
29
29
  用户明确说“每日应填但未提交”时使用 `+missing-daily-reports`。用户说“打卡但未交”时使用 `+checkin-missing`;后者不会把请假、出差未打卡、离职等本来不应提交的人混入。
30
30
 
31
+ `+missing-daily-reports` 使用 VPS 原生 `/v1/daily-report/missing`,复用业务审计权限及系统考勤“应工作”判定、免报白名单和离职截止规则。返回 `partial=true` 时必须说明存在未映射或无法判定人员,不能把结果当作完整名单。原生接口未上线而返回 404 时提示服务端版本不匹配,不回退旧 `/api/v1/tasks/...` 地址;CLI 与 VPS 服务端需配套发布,沙箱不需要变更。
32
+
31
33
  ## 命令清单
32
34
 
33
35
  | 命令 | 服务接口 | 说明 |
34
36
  |------|----------|------|
35
- | `+missing-daily-reports --date YYYY-MM-DD` | `GET /api/v1/tasks/tasks/export-missing-daily-reports` | 每日应填但未提交日报名单 |
37
+ | `+missing-daily-reports --date YYYY-MM-DD` | `GET /v1/daily-report/missing` | 每日应填但未提交日报名单 |
36
38
  | `+checkin-missing --date YYYY-MM-DD` | 日报查询脚本 `checkin_missing` | 打卡但未提交日报名单;可选 `--department-id` `--limit` |
37
39
  | `+mine --user-id N --start-time YYYY-MM-DD --end-time YYYY-MM-DD` | `GET /v1/daily-report/mine` | 统一日报列表;省略 `--user-id` 时查当前登录用户,日期省略默认今天 |
38
40
  | `+department --date YYYY-MM-DD --limit 500` | `GET /v1/daily-report/department` | 默认查当前用户部门树;`--department-path` 需要指定部门权限,`--all-departments` 需要全公司权限 |
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: vps-finance-ledger
3
+ description: 通过已登记的 VPS 只读入口查询合作伙伴与科目余额、已过账往来明细、科目余额及合作伙伴基础资料,并导出含勾稽的 Excel。用于往来分析和对账;不用于账务写入、审批或付款。
4
+ ---
5
+
6
+ 先查询 `vps-work catalog --domain finance`。需要独立 `finance.ledger:read` 和当前内部成员的公司、会计日期范围、有效期授权。缺少授权时说明所缺范围,不使用管理员身份、数据库直连或其他业务入口绕过。
7
+
8
+ 查询复用现有 exec,无需新增 CLI 命令或升级客户端。已发布 vps-work 2.3.0 可直接调用,执行不依赖本机已安装本技能。旧版本 auth check 可能把管理员权限误判为业务权限,须查看 auth scopes 返回的 userScopes 是否含精确 finance.ledger:read,并以实际查询验证公司/期间范围。
9
+
10
+ ```sh
11
+ vps-work exec --skill vps-finance-ledger --script partner_balance --param company_id=<已授权公司ID> --param start_date=2025-06-30 --param end_date=2025-09-30
12
+ ```
13
+
14
+ 脚本:`partner_balance`(合作伙伴→科目→原币币种,本位币余额)、`ledger_detail`(分录)、`account_balance`(登记往来科目余额)、`partners`(基础资料)、`export`(完整 xlsx,含小计、合计和勾稽)。所有脚本必须传 company_id、start_date、end_date。公司 ID 来自已核实授权,不能按名称猜测。查询返回 next_offset 时继续分页,未拉完不能称为全量。
15
+
16
+ 可选筛选:partner_id、currency_id、account_codes(登记编码,逗号分隔且精确匹配)。查询 limit 最大 1000。export 不接受分页参数,超过 25000 行会拒绝,缩小日期范围重试,不输出截断报表。
17
+
18
+ ```powershell
19
+ $companyId = Read-Host '输入已核实的授权公司ID'
20
+ $report = vps-work exec --skill vps-finance-ledger --script export --param "company_id=$companyId" --param start_date=2025-06-30 --param end_date=2025-09-30 | ConvertFrom-Json
21
+ if ($LASTEXITCODE -ne 0 -or -not $report.file.content) { throw '导出失败,未生成文件' }
22
+ $output = Join-Path $PWD '财务往来账.xlsx'
23
+ if (Test-Path -LiteralPath $output) { throw '文件已存在,请更换文件名' }
24
+ [IO.File]::WriteAllBytes($output, [Convert]::FromBase64String($report.file.content))
25
+ ```
26
+
27
+ 导出前核对公司名称、期间和本位币。金额 JSON 保留十进制文本;余额均按本位币借正贷负。期初为起始日前已过账行的累计,期末 = 期初 + 期间借 − 期间贷。保留无往来单位行和同名不同编码,不擅自合并身份。原币不能跨币种相加。当前核销状态不能冒充历史截止日未核销余额;查询结果不包含个人联系方式或银行账号。科目余额仅覆盖登记往来科目,不能称为全科目试算平衡表。
28
+
29
+ 返回 checks 不通过时明确报告差异,附输出文件供核查,不得宣称账账核对通过。集团公司标记仅来自公司主体对应 partner_id,其他标为 unclassified,不能推断为集团外。
@@ -0,0 +1,8 @@
1
+ import { readFile, writeFile } from 'node:fs/promises';
2
+ const [input,output]=process.argv.slice(2);
3
+ if(!input||!output)throw new Error('Usage: node save-export.mjs report.json output.xlsx');
4
+ const json=JSON.parse((await readFile(input,'utf8')).replace(/^\uFEFF/,''));
5
+ const result=json.result??json;
6
+ if(result.file?.encoding!=='base64'||result.file?.content_type!=='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'||!result.file?.content)throw new Error('No complete XLSX export in result');
7
+ await writeFile(output,Buffer.from(result.file.content,'base64'),{flag:'wx'});
8
+ console.log(JSON.stringify({output,company:result.company,start_date:result.start_date,end_date:result.end_date,checks:result.checks}));
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: vps-hr-compensation-documents
3
3
  description: |
4
- 员工月度工资条只读查询(VPS 原生 HR,vps_tenant_payslips)。本人可查本人已发放工资条,企业管理员可查本企业成员。取数通过 `vps-work hr +payslip`。
4
+ 员工月度工资条只读查询(VPS 原生 HR,vps_tenant_payslips)。本人可查本人已发放工资条,查他人需要薪酬管理组及有效薪酬访问凭证,管理员不豁免。取数通过 `vps-work hr +payslip`。
5
5
  metadata:
6
6
  requires:
7
7
  bins: ["vps-work"]
@@ -32,7 +32,8 @@ vps-work hr +payslip --name "孔健" --salary-month 2026-04
32
32
 
33
33
  - 工资条只来自 VPS 原生 HR,**不再**读取 `employee.salary` / `human.resource.salary`,也不要走 `vps-work` 通道查工资
34
34
  - 只返回 `status=published` 的工资条;草稿、已撤回不可见
35
- - 查他人需要企业管理员(owner / manager)身份,否则服务端返回 403,不要绕行
35
+ - 查他人需要当前薪酬管理组成员资格及有效的薪酬访问凭证;企业管理员、平台管理员和 Agent Key 均不能绕过。403/423 时停止查询,请用户在人事助手中授权查看,不要在对话中索要密码、猜测密码或使用共享密钥绕行
36
+ - 薪酬权限群组配置只能由服务端指定配置人读取/修改,不能通过对话委托给其他身份,也不能把“可配置”当成“可查看全员薪酬”
36
37
  - 取数走 CLI 封装:`vps-work hr +payslip`,不要自行拼 SQL 或调用其它接口
37
38
  - 禁止 `skills/**/scripts/*.py`
38
39
 
@@ -13,9 +13,10 @@
13
13
  | 查询对象 | 要求 |
14
14
  |----------|------|
15
15
  | 本人(`--my` 或不指定) | 任意企业成员 |
16
- | 他人(`--employee-id` / `--name`) | 企业管理员(`membership_role` 为 owner / manager) |
16
+ | 他人(`--employee-id` / `--name`) | 当前薪酬管理组成员 + 服务端验证的薪酬访问凭证;管理员不豁免 |
17
17
 
18
18
  只返回 `status = published` 的工资条;草稿 / 已撤回对成员不可见。服务级 API Key 无企业上下文,返回 403。
19
+ 跨人员访问凭证只取请求头 `X-Compensation-Access`,不采信查询参数中的角色、成员身份、密码或伪造凭证。CLI/专属小V没有凭证时应停止并引导在人事助手中查看,不在聊天中索要访问密码。配置群组的权限不自动授予薪酬数据访问权。
19
20
 
20
21
  ## 3. 参数
21
22
 
@@ -61,7 +62,8 @@
61
62
  | 状态 | 含义 |
62
63
  |------|------|
63
64
  | 400 | `salary_month` 格式错误 |
64
- | 403 | 查他人但非企业管理员;或当前会话无企业身份 |
65
+ | 403 | 查他人但无薪酬组权限;或当前会话无有效企业身份 |
66
+ | 423 | 未解锁薪酬访问,或凭证过期/失效 |
65
67
  | 404 | `employee_id` / `name` 未匹配到企业成员 |
66
68
  | 409 | `name` 匹配多人 |
67
69
 
@@ -17,12 +17,12 @@
17
17
  # 本人工资条(--salary-month 可写 2026-04,自动归一到当月)
18
18
  vps-work hr +payslip --my --salary-month 2026-04
19
19
 
20
- # 企业管理员查成员
20
+ # 查他人需要薪酬管理组和有效访问凭证;无凭证时请在人事助手中查看
21
21
  vps-work hr +payslip --employee-id 4726 --salary-month 2026-04-01
22
22
  vps-work hr +payslip --name "孔健" --salary-month 2026-04
23
23
  ```
24
24
 
25
- 无行时先确认该月工资条是否已发布;403 表示无权查他人,不要绕行。
25
+ 无行时先确认该月工资条是否已发布;403 表示无权查他人,423 表示缺少有效薪酬访问凭证,均不要绕行或在对话中索要访问密码。
26
26
 
27
27
  ## 员工定位
28
28
 
@@ -3,7 +3,7 @@
3
3
  ## 数据路径
4
4
 
5
5
  本 skill 查数统一走 **`vps-work hr +payslip`** → vps-service `execute(vps-hr-compensation-documents/payslip)` → VPS 原生 `vps_tenant_payslips`。
6
- 访问控制在服务端:本人可查;查他人需企业管理员。
6
+ 访问控制在服务端:本人可查;查他人需当前薪酬管理组成员资格及有效薪酬访问凭证。企业管理员和专属小V不豁免;无凭证时引导在人事助手中查看,不通过聊天索要密码或使用共享身份。
7
7
 
8
8
  ## 仓库约束
9
9
 
@@ -53,6 +53,7 @@ vps-work mail +send-email --mailbox-id '<department-uuid>' \
53
53
  发送必须提供 `--to`、`--subject`、`--body` 或 `--body-file`、8–128 字符的 `--request-id`。
54
54
  `--to`、`--cc`、`--bcc` 支持重复或逗号分隔的纯邮箱地址,`--attachment-id` 可重复;显示名写法不支持。
55
55
  `--body` 与 `--body-file` 互斥。需要别名发件时,从 `+identities` 获取 `--identity-id`,不能任意伪造 From。
56
+ 可同时提供 `--body-html-file <UTF-8文件>` 发送带点击链接及二维码等内容的 HTML 正文;仍须提供 `--body` 或 `--body-file` 作为纯文本后备。发送前可用 `--dry-run` 核对两种正文。
56
57
 
57
58
  先准备好全部附件和内容,再用固定的业务请求编号发送。网络超时后保持同一邮箱、请求编号、正文、收件人、身份和附件 ID 重试;不要重新上传附件或生成新编号。不要并发重试或把 processing 状态当作送达。
58
59
  服务器对同一编号校验内容一致性;客户端不自动重试发送。若服务返回失败或长时间 processing,保留编号排查,不盲目重发。
@@ -1,14 +1,14 @@
1
1
  ---
2
2
  name: vps-pending-approval-assistant
3
3
  description: |
4
- 提供 VPS 审批相关能力:`vps-work approval +wait` / `+pending` / `+my-submitted` / `+my-approved` 拉取本人、部门或全员待办与历史视图,`+logs` 看单证轨迹,`+pass` / `+refuse` 在明确意图下操作当前步骤。在用户查看待我审批、审批流、签核历史、我提交的审批、我已批过的单子、同意或驳回、统计待办类型或整理审批队列时使用。业务单据金额/明细等结构化取数由对应业务域 skill 负责,本技能不下钻业务表。
4
+ 提供 VPS 审批相关能力:`vps-work approval +wait` / `+pending` / `+my-submitted` / `+my-approved` 拉取本人、部门或全员待办与历史视图,`+logs` 看单证轨迹,`+pass` / `+refuse` 在明确意图下操作当前步骤。新版 VPS 及 ERP 历史付款申请列表、金额明细和审批进度复用现有 exec 的 payment_applications 只读查询,需独立全量查询权限。在用户查看待我审批、付款申请单、ERP 历史付款、审批流、签核历史、我提交的审批、我已批过的单子、同意或驳回、统计待办类型或整理审批队列时使用。其他业务单据结构化取数由对应业务域 skill 负责,不拼接业务表查询。
5
5
  ---
6
6
 
7
7
  # 审批助手
8
8
 
9
9
  ## 何时使用
10
10
 
11
- 用户需要审批相关能力:查看待我审批、我提交的审批、我已批过的单子、某单的审批轨迹,或在明确意图下通过/拒绝当前步骤。业务单据的金额/明细等结构化取数由对应业务域 skill 负责,本技能不下钻业务表。
11
+ 用户需要审批相关能力:查看待我审批、我提交的审批、我已批过的单子、某单的审批轨迹、新版及 ERP 历史付款申请列表和详情,或在明确意图下通过/拒绝原有审批步骤。付款查询仅支持下述只读能力;其他业务单据的金额/明细等取数仍交给对应业务域 skill。
12
12
 
13
13
  ## 工作流
14
14
 
@@ -18,27 +18,32 @@ description: |
18
18
  2. **历史审批** — **`vps-work approval +my-submitted`** / **`+my-approved`**。用户未区分时两条都跑
19
19
  3. **审批轨迹** — `vps-work approval +logs --res-model <m> --res-id <id>`
20
20
  4. **通过/拒绝** — 仅在用户明确表态后调用 `vps-work approval +pass` / `refuse`,带 res_model + res_id
21
- 5. **下钻业务正文** — 用户要看"具体是哪些单子 / 单据金额 / 申请人 / 明细"等:交给对应 `res_model` 的业务域 skill;本技能不在内部对业务模型拼 `--fields` / `--domain` 绕路。若无对应专项 skill,则说明该明细暂不提供。
21
+ 5. **付款申请查询** — `vps-work exec --skill vps-pending-approval-assistant --script payment_applications`,需显式 `approvals.payment.all:read`。默认合并本企业新版 VPS 及 ERP 历史付款申请,可用 `--param source=vps` 或 `--param source=erp` 单独查询。支持日期、状态、申请人、单号和关键词筛选;详情使用 `--param operation=detail --param document_number=<完整单号>`。合并结果以 `next_cursor` 传 `cursor` 续查,单来源按 `next_offset` 传 `offset`。筛选及标识规则见 [reference.md](reference.md),无发起、审批或编辑能力。
22
+ 6. **其他业务正文** — 用户要看其他类型单据的金额/申请人/明细时,交给对应 `res_model` 的业务域 skill;不拼接 `--fields` / `--domain` 绕路。若无对应专项 skill,则说明该明细暂不提供。
22
23
 
23
24
  ## 硬约束
24
25
 
25
- - **下钻明细必须切技能**:用户追问业务字段(金额/伙伴/状态/申请人/明细行 等)时,交给对应业务域 skill,不在本技能里查 res_model 业务表
26
+ - **按已登记契约查询**:新版及 ERP 历史付款的业务明细只用 `payment_applications`;其他业务字段交给对应业务域 skill,不在本技能里查 `res_model` 业务表。本付款入口仅只读,禁止将查询权限当作审批或付款权限,也不得将原生付款 UUID 交给 ERP 的 `+pass/refuse/logs`。
26
27
  - **禁止盲构查询**:字段名/关系/枚举必须出现在 **skills/** 文档中;禁止 `vps-work knowledge`;禁止 `_fields` 嗅探;缺口 `POST /ai/skills/v1/feedback`
27
- - 只向用户展示 model_name 与数量,禁止展示 res_model/res_ids/原始 id 列表
28
- - web.approval.commit/approvaled 与 wait 同形,fields 完全相同
28
+ - **原有审批队列视图**(`+wait` / `+pending` / `+my-submitted` / `+my-approved`)只向用户展示 `model_name` 与数量,禁止展示 `res_model/res_ids` 或原始 id 列表。
29
+ - **付款查询例外(新版及 ERP 历史)**:已有独立权限且通过 `payment_applications` 取得数据时,可直接展示单号、申请人、部门、金额、币种、收款人、状态、明细行、审批进度和附件名称,无需转交其他技能。不展示内部附件标识或上传凭据;业务字段按名称解释,没有返回的数据不得编造。区分来源和日期口径;ERP 查询失败不能按“无历史单据”回答。
30
+ - 原有 `web.approval.commit/approvaled` 与 `wait` 同形,fields 完全相同;这条仅描述原有队列视图,不限制付款查询的输出。
29
31
  - 所有 CLI 以当前用户 ACL 执行,不提供法律/强制性建议
30
32
 
31
33
  ## 常见坑点
32
34
 
33
35
  | 现象 | 根因 | 正确做法 |
34
36
  |------|------|---------|
35
- | 用户追问"具体是哪些单子 / 金额 / 申请人" | 只看了 model_name 和 count,想在本技能里直接查业务表 | **停下,交给对应 res_model 的业务域 skill**;无对应专项 skill 则说明该明细暂不提供 |
36
- | 业务字段报错 / 返回空 | 在本技能内对业务模型自行猜字段 | 禁止盲构;交给对应域 skill 后只使用文档已列字段,无文档则 feedback |
37
- | 审批后状态未变 | 没确认审批轨迹 | 通过/拒绝后查 approval logs 验证 |
37
+ | 用户追问新版或 ERP 历史付款的单号、金额、申请人或明细 | 将原有队列的汇总限制套到付款查询 | 用 `payment_applications` 查询列表或详情,直接按返回数据展示;缺少独立权限时说明权限不足,不绕过授权 |
38
+ | 同一单号在两边都有 | 只按单号无法定位来源 | 传 `source=vps/erp`,或用对应 `submission_id/erp_id`;不得按名称或金额猜匹配 |
39
+ | 按人查历史单报关联缺失 | VPS 和 ERP 使用不同身份编号 | 不直接把 VPS 数字 ID 当 ERP 用户 ID;可明确只查新版,或使用 `source=erp` 与已知 ERP 员工 ID |
40
+ | 用户追问其他类型单据的具体单子、金额或申请人 | 只看了 model_name 和 count,想在本技能里直接查业务表 | **交给对应 res_model 的业务域 skill**;无对应专项 skill 则说明该明细暂不提供 |
41
+ | 其他类型单据的业务字段报错 / 返回空 | 在本技能内对业务模型自行猜字段 | 禁止盲构;交给对应域 skill 后只使用文档已列字段,无文档则 feedback |
42
+ | 原有审批操作后状态未变 | 没确认审批轨迹 | 通过/拒绝后查 approval logs 验证 |
38
43
 
39
44
  ## 关联技能
40
45
 
41
- - 未知字段先读对应专项 skill 文档,禁止运行时字段嗅探;下钻前读专项文档
46
+ - 新版及 ERP 历史付款按 [reference.md](reference.md) 的已登记契约直接查询和展示;其他业务下钻前读对应专项 skill 文档,未知字段禁止运行时嗅探。
42
47
  - **vps-current-user-identity** — 第一人称身份解析,审批视图已自动限定当前用户,无需额外取身份
43
48
 
44
49
  ---
@@ -10,6 +10,21 @@
10
10
  | 通过 | `vps-work approval +pass --res-model … --res-id …` | VPS 审批服务 |
11
11
  | 拒绝 | `vps-work approval +refuse …` | VPS 审批服务 |
12
12
  | 轨迹 | `vps-work approval +logs …` | VPS 审批服务 |
13
+ | 新版及 ERP 历史付款申请 | `vps-work exec --skill vps-pending-approval-assistant --script payment_applications` | 默认合并两个来源,只读,需 `approvals.payment.all:read` |
14
+
15
+ 付款查询参数:默认 `operation=list`、`source=all`,合并新版 VPS 和 ERP `cost.pay.apply` 历史申请,也可指定 `source=vps` 或 `source=erp`。可选 `start_date/end_date`(VPS 提交日期、ERP 申请日期,含首尾日期)、`status`、`applicant_user_id`、`keyword`、`document_number`。`limit` 默认50、最大100;合并结果原样传回 `next_cursor` 到 `cursor`,不能与 `offset` 同传或更改筛选条件;单来源按 `next_offset` 传 `offset` 续查。合并列表先按 VPS 提交时间 / ERP 申请日上海零点降序,同一时刻先 VPS,各来源内部再按 ID 降序;两库分别为只读快照,翻页期间源数据变化可能影响列表位置。
16
+
17
+ `operation=detail` 必须且只能传 `submission_id`(VPS UUID)、`erp_id`(ERP 正整数 ID)或完整 `document_number`;带对应 ID 时自动确定来源。只传单号时默认在两边精确查找;两边同号或 ERP 内同号多条均报冲突,应指定来源或精确 ID,不能按金额/姓名猜匹配。仅有当前企业独立权限才可查询全员,不继承普通审批或管理员通配权限,不授予任何写入操作。
18
+
19
+ `applicant_user_id` 始终是 VPS 用户 ID,历史筛选只使用当前企业账号的明确 `res.users` 来源关联;缺失/歧义时报错。历史离职员工未在 VPS 关联时,可明确 `source=erp --param erp_employee_id=<ERP员工ID>` 查询,不能和 `applicant_user_id` 同传。ERP 输出中的 `erp_employee_id/erp_applicant_user_id` 为来源标识,不当作 VPS 身份。
20
+
21
+ 新版及 ERP 历史付款都是本技能可直接展示业务明细的例外,不受原有队列“只展示类型与数量、明细切技能”的限制:列表 `items` 可展示 `source`、`document_number`、`applicant_name`、`applicant_department_path`、`amount/amount_cny`、`currency`、`payee`、`status`、`submitted_at/application_date` 及 `pending_approvers`;详情 `submission` 可展示 `values` 的表单与明细行、`approval_tasks`、`approval_history`、`comments`、`attachments` 和 `node_materials` 的业务信息。新版按冻结 `fields` 解读,ERP 的 `fields` 是已登记的原字段标签。无需转交其他技能,不展示内部标识或上传凭据。
22
+
23
+ ERP `source_status` 保留原始状态:`draft→draft`、`approval→in_progress`、`finished→approved`,用于统一筛选;`finished` 表示 ERP 流程完成,不能据此断言已打款,应结合 `payment_date` 和原始历史。ERP `application_date` 是业务申请日,`submitted_at=null`,不能伪造成实际提交时刻。ERP 费用、发票、付款阶段、固定资产、分摊明细分别在 `values.payment_expense_lines/payment_invoice_lines/payment_stage_lines/payment_asset_lines/payment_allocation_lines`,完整返回,未设原审批卡片的8行展示上限。VPS 回写 ERP 的镜像按 `vps_request_id/vps_tenant_id` 明确标记排除,不按单号或金额去重。任一数据源不可用时合并查询报错;可明确 `source=vps` 单独查新版,不能把错误当作历史单据数量0。
24
+
25
+ `attachments` 是表单附件与旧附件表的合并目录,含 `file_name/content_type/size_bytes`、来源 `source`(`form_values` 或 `legacy`)及位置 `field_key/field_path`;明细行位置如 `["payment_expense_lines",0,"evidence"]` 中行号从0开始,向用户说“第1行”。相同文件在不同字段或行内的引用保留,不按文件名去重。原表单未记录上传时间时 `created_at=null`,不能用提交时间代替。`id` 仅供程序识别,目录不提供原文件下载能力;审批节点材料仍在 `node_materials` 中单列。
26
+
27
+ ERP 附件目录还包含 `erp_form_values/erp_attachment` 来源:主表发票、结算单、付款凭证、行政发票 JSON 附件、发票行附件及旧 `ir_attachment`/关系表附件;不复制附件 URL、访问令牌或二进制内容到目录。无法解析的原附件通过 `attachment_issues` 标明字段位置和原因,不能把它描述成“没有附件”。ERP 办理附件包含在此目录,没有单独的 VPS 节点材料表,`node_materials=[]`。
13
28
 
14
29
  ## 三种视图的通用查询
15
30
 
@@ -33,9 +48,9 @@
33
48
  - **`vps-work approval +logs`**:`res_model`、`res_id`。
34
49
  - **`vps-work approval +pass` / `+refuse`**:`res_model`、`res_id`;`+pass` 可选 `proposal`。
35
50
 
36
- ## 下钻明细必须切技能
51
+ ## 其他类型单据下钻明细必须切技能
37
52
 
38
- 用户从"审批待办/历史"进入"具体是哪些单子 / 金额多少 / 谁提交的 / 明细行" 这一步时,**本技能就到此为止**:
53
+ 除上述新版及 ERP 历史付款查询外,用户从原有"审批待办/历史"进入其他类型单据的"具体是哪些单子 / 金额多少 / 谁提交的 / 明细行" 这一步时,切换到对应技能:
39
54
 
40
55
  1. **交给对应 `res_model` 的业务域 skill** —— 由它负责业务模型取数;若无对应专项 skill,则说明该明细暂不提供。
41
56
  2. 匹配 **Features** 中与 `res_model` 对应的专项 skill,读其 `reference.md` / `references/*.md` 中的字段与 domain 示例。
@@ -49,7 +64,8 @@
49
64
 
50
65
  ## 输出结构(对用户)
51
66
 
52
- 1. 待办/历史:仅文档类型标签 + 数量。
67
+ 1. 原有队列待办/历史:仅文档类型标签 + 数量。
53
68
  2. 轨迹:时间顺序叙述,无内部 id。
54
- 3. 其他业务信息:经数据技能路径取数后,用业务语言转述。
55
- 4. 可给简短核对建议,不编造数据。
69
+ 3. 新版及 ERP 历史付款:直接展示已授权查询返回的来源、单号、申请人、金额、明细行、进度及附件名称。
70
+ 4. 其他业务信息:经数据技能路径取数后,用业务语言转述。
71
+ 5. 可给简短核对建议,不编造数据。
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: vps-purchase
3
+ description: "只读查询 VPS 原生采购申请及明细、ERP 采购订单及订单行。适用于采购单、办公采购申请、供应商订单、采购数量、单价、收货及开票数量查询。必须使用当前身份的独立采购只读权限。"
4
+ ---
5
+
6
+ # 采购只读查询
7
+
8
+ 开始前读取 [vps-shared](../vps-shared/SKILL.md)。先用 `vps-work catalog --domain purchase` 检查当前企业可见能力。
9
+
10
+ ## 权限和来源
11
+
12
+ - `purchase.requests.all:read`:本内部企业全部 **VPS 原生**采购申请及明细。
13
+ - `purchase.orders.all:read`:内部企业 ERP 业务库的全部采购订单及明细,可按公司筛选。
14
+ - 两项独立,沿用 VPS 角色 → 权限组 → 权限项配置;管理员、普通审批权限、付款权限均不自动获得。无权限应说明权限不足,不切换身份或绕过授权。
15
+ - ERP 订单查询要求企业开通 ERP;企业停用 ERP 不影响原生采购申请。
16
+ - 本入口不读取 ERP 历史 `cost.procure.apply`,不将 VPS 采购申请当成采购订单;不存在申请到 ERP 订单的推定关联。
17
+
18
+ ## 命令
19
+
20
+ ```bash
21
+ vps-work purchase +requests --start-date 2026-10-01 --end-date 2026-10-28 --limit 50
22
+ vps-work purchase +request-detail --id <VPS申请UUID>
23
+ vps-work purchase +request-lines --document-number <完整申请单号> --limit 50 --offset 0
24
+ vps-work purchase +orders --company-id 1 --status purchase --keyword <关键词>
25
+ vps-work purchase +order-detail --id <ERP订单整数ID>
26
+ vps-work purchase +order-lines --id <ERP订单整数ID> --limit 50 --offset 0
27
+ ```
28
+
29
+ 已有 CLI 可通过通用 `exec` 使用相同能力,无需等待快捷命令发布:
30
+
31
+ ```bash
32
+ vps-work exec --skill vps-purchase --script requests --param operation=list
33
+ vps-work exec --skill vps-purchase --script orders --param operation=lines --param id=123
34
+ ```
35
+
36
+ ## 查询契约
37
+
38
+ 脚本为 `requests` 或 `orders`,参数以 catalog 为准。`operation` 支持 `list`(默认)、`detail`、`lines`。
39
+
40
+ - 详情和明细必须提供一个标识:申请用 `submission_id`(快捷命令 `--id`),订单用整数 `id`,或二者都可用 `document_number` 精确匹配完整单号。多个同号记录返回冲突,改用 ID。
41
+ - 列表支持 `status`、`keyword`、`company_id`、`start_date`、`end_date`、完整单号;条件取交集。日期均按上海时区且包含两端,申请按提交日期,订单按订单日期。未提交日期为空的申请不进入日期筛选结果。
42
+ - 列表和明细分页:`limit` 1–100,默认 50;用响应 `next_offset` 继续,直到 `has_more=false`。不能把一页当作完整清单。详情不接受分页参数。
43
+ - 申请详情含 `details.purchase_lines`;订单详情返回 `line_count` 和 `lines_query`,另用 `lines` 分页取明细,避免静默截断。
44
+ - ERP 金额和数量按十进制字符串返回。申请明细区分预计数量/单价与实际采购数量/单价/金额。不同币种不得直接相加。
45
+ - `erp_buyer_user_id` 是 ERP 用户 ID,不是 VPS 用户 ID,不用姓名匹配身份。
46
+ - 仅返回固定业务字段,不返回附件 URL、上传凭据或审批操作能力。禁止任意模型、字段、SQL、domain、租户参数和写入动作。
47
+ - ERP 失败必须报告不可用,不得回答“没有订单”;申请查询不会依赖 ERP 在线校验。
@@ -60,6 +60,19 @@ description: |
60
60
  | `+tc-okr-options` | 当前用户可绑定的正式 OKR/KR;可选 `--period YYYY-MM`、`--owner-type`、`--owner-id` |
61
61
  | `+my-okr` | 个人或团队 OKR(`--type mine|team`,默认 mine;`--period YYYY-MM` 省略=当前周期) |
62
62
 
63
+ ## 简单日期查询的快速路径
64
+
65
+ “我明天的任务是什么”只查询当前用户在所问日期的事项,不默认扩展到其他部门、研发 MCP、品牌增长、审批、考勤或整周日历。用户明确要求跨系统时再扩展;“工作安排/日程”才增加本人日历查询。
66
+
67
+ 当前 CLI 提供 `--start-time YYYY-MM-DD --end-time YYYY-MM-DD --date-field deadline|start_date`(待办不支持 start_date),日期范围含首尾两天。先在宿主当前 CLI 的帮助中确认这些参数可用;旧版本没有这些参数时不要猜测或声称已经按日期筛选。
68
+
69
+ - 当前用户身份已通过本轮认证上下文确认后复用,不重复查询身份。
70
+ - 第一次列表查询就传本人 `--owner-user-id <当前用户ID>` 和 `--no-include-department`,不要先读取全部门再筛选。
71
+ - 并行读取本人当天 `deadline` 到期任务、`start_date` 计划开始任务,以及 `deadline` 到期待办;日期按业务时区解释。任务 UUID 去重,不能把没有到期项说成“当天没有工作”。
72
+ - `has_more=true` 时继续翻页:任务 `--offset` 从 0 开始递增实际页长度;待办 `--page` 从 1 开始递增。没有完整读完不能声称零项或给出全量数量。
73
+ - 查询成功且范围内无结果就返回明确范围,不通过扫描无关系统“凑答案”。失败说明失败,不当作空结果。
74
+ - 实时语音优先先给结论和最多五条必要事项;不要生成长表格或顺带扩展任务。
75
+
63
76
  ## 工作流
64
77
 
65
78
  1. 判断用户是查询还是写操作;任务/待办/项目都走 `+tc-*`。