weaver-work-cli 0.1.8 → 0.1.20
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/README.md +11 -11
- package/dist/cmd/action.js +76 -0
- package/dist/cmd/index.js +2 -0
- package/dist/cmd/refs/index.js +103 -0
- package/dist/cmd/register.js +31 -0
- package/dist/cmd/root.js +1 -0
- package/dist/cmd/setup/index.js +25 -5
- package/dist/cmd/skills/index.js +37 -5
- package/dist/core/connector.js +54 -0
- package/dist/core/context.js +2 -1
- package/dist/core/input.js +48 -0
- package/dist/core/output.js +298 -3
- package/dist/core/refs.js +432 -0
- package/dist/core/state.js +26 -0
- package/dist/internal/e10/auth/commands.js +2 -2
- package/dist/internal/e10/auth/session.js +14 -0
- package/dist/internal/e10/auth/xiaoe.js +116 -51
- package/dist/internal/e10/request-runtime.js +5 -0
- package/dist/internal/skills/install.js +148 -28
- package/dist/internal/skills/reader.js +12 -9
- package/dist/shortcuts/blog/continuation.js +74 -0
- package/dist/shortcuts/blog/errors.js +60 -0
- package/dist/shortcuts/blog/host.js +175 -0
- package/dist/shortcuts/blog/index.js +324 -0
- package/dist/shortcuts/blog/manifest.js +415 -0
- package/dist/shortcuts/blog/operations/comment.js +125 -0
- package/dist/shortcuts/blog/operations/comments.js +31 -0
- package/dist/shortcuts/blog/operations/edit.js +131 -0
- package/dist/shortcuts/blog/operations/export.js +46 -0
- package/dist/shortcuts/blog/operations/like.js +80 -0
- package/dist/shortcuts/blog/operations/publish.js +157 -0
- package/dist/shortcuts/blog/operations/query-user.js +58 -0
- package/dist/shortcuts/blog/operations/query.js +96 -0
- package/dist/shortcuts/blog/operations/registry.js +54 -0
- package/dist/shortcuts/blog/operations/remind.js +176 -0
- package/dist/shortcuts/blog/operations/shared.js +330 -0
- package/dist/shortcuts/blog/operations/types.js +16 -0
- package/dist/shortcuts/blog/operations.js +9 -0
- package/dist/shortcuts/caizhilian/continuation.js +70 -0
- package/dist/shortcuts/caizhilian/errors.js +53 -0
- package/dist/shortcuts/caizhilian/host.js +190 -0
- package/dist/shortcuts/caizhilian/index.js +186 -0
- package/dist/shortcuts/caizhilian/manifest.js +42 -0
- package/dist/shortcuts/caizhilian/operations/api.js +801 -0
- package/dist/shortcuts/caizhilian/operations/confirm.js +75 -0
- package/dist/shortcuts/caizhilian/operations/files.js +306 -0
- package/dist/shortcuts/caizhilian/operations/form.js +170 -0
- package/dist/shortcuts/caizhilian/operations/handlers/collab.js +611 -0
- package/dist/shortcuts/caizhilian/operations/handlers/document.js +890 -0
- package/dist/shortcuts/caizhilian/operations/handlers/file-collection.js +346 -0
- package/dist/shortcuts/caizhilian/operations/handlers/file-upload.js +192 -0
- package/dist/shortcuts/caizhilian/operations/handlers/fileops.js +570 -0
- package/dist/shortcuts/caizhilian/operations/handlers/folder.js +969 -0
- package/dist/shortcuts/caizhilian/operations/handlers/search.js +318 -0
- package/dist/shortcuts/caizhilian/operations/handlers/setting-attach.js +294 -0
- package/dist/shortcuts/caizhilian/operations/handlers/setting-backup.js +423 -0
- package/dist/shortcuts/caizhilian/operations/handlers/setting-encrypt.js +238 -0
- package/dist/shortcuts/caizhilian/operations/handlers/setting-storage.js +364 -0
- package/dist/shortcuts/caizhilian/operations/handlers/system.js +106 -0
- package/dist/shortcuts/caizhilian/operations/registry.js +151 -0
- package/dist/shortcuts/caizhilian/operations/shared.js +408 -0
- package/dist/shortcuts/caizhilian/operations/specs.js +623 -0
- package/dist/shortcuts/caizhilian/operations/types.js +57 -0
- package/dist/shortcuts/caizhilian/operations.js +21 -0
- package/dist/shortcuts/contract/continuation.js +70 -0
- package/dist/shortcuts/contract/errors.js +62 -0
- package/dist/shortcuts/contract/host.js +205 -0
- package/dist/shortcuts/contract/index.js +318 -0
- package/dist/shortcuts/contract/manifest.js +596 -0
- package/dist/shortcuts/contract/operations/clause-reference.js +78 -0
- package/dist/shortcuts/contract/operations/form-info.js +371 -0
- package/dist/shortcuts/contract/operations/read.js +118 -0
- package/dist/shortcuts/contract/operations/registry.js +43 -0
- package/dist/shortcuts/contract/operations/request.js +300 -0
- package/dist/shortcuts/contract/operations/shared.js +133 -0
- package/dist/shortcuts/contract/operations/subject.js +157 -0
- package/dist/shortcuts/contract/operations/template.js +81 -0
- package/dist/shortcuts/contract/operations/types.js +7 -0
- package/dist/shortcuts/contract/operations/workflow.js +52 -0
- package/dist/shortcuts/contract/operations/write.js +131 -0
- package/dist/shortcuts/contract/operations.js +8 -0
- package/dist/shortcuts/hrm/index.js +83 -2
- package/dist/shortcuts/hrm/operations/employee.js +160 -30
- package/dist/shortcuts/hrm/operations/org.js +17 -3
- package/dist/shortcuts/hrm/operations/position.js +18 -2
- package/dist/shortcuts/index.js +5 -1
- package/dist/shortcuts/invoice/index.js +74 -36
- package/dist/shortcuts/invoice/manifest.js +674 -4
- package/dist/shortcuts/invoice/markdown.js +172 -0
- package/dist/shortcuts/invoice/operations/add.js +3 -3
- package/dist/shortcuts/invoice/operations/delete.js +2 -2
- package/dist/shortcuts/invoice/operations/get.js +10 -2
- package/dist/shortcuts/invoice/operations/import.js +2 -2
- package/dist/shortcuts/invoice/operations/registry.js +8 -1
- package/dist/shortcuts/invoice/operations/reim-auto.js +719 -0
- package/dist/shortcuts/invoice/operations/reim.js +85 -2
- package/dist/shortcuts/invoice/operations/shared.js +75 -8
- package/dist/shortcuts/invoice/operations/update.js +2 -2
- package/dist/shortcuts/invoice/operations/upload-and-validate.js +93 -0
- package/dist/shortcuts/invoice/operations/validate-preview.js +2 -1
- package/dist/shortcuts/invoice/projection.js +328 -0
- package/dist/shortcuts/meeting/host.js +18 -1
- package/dist/shortcuts/meeting/manifest.js +30 -18
- package/dist/shortcuts/meeting/operations/eb/catalog.js +390 -0
- package/dist/shortcuts/meeting/operations/eb/conflict.js +389 -0
- package/dist/shortcuts/meeting/operations/eb/factory.js +389 -0
- package/dist/shortcuts/meeting/operations/eb/index.js +22 -0
- package/dist/shortcuts/meeting/operations/env.js +8 -1
- package/dist/shortcuts/meeting/operations/registry.js +2 -0
- package/dist/shortcuts/meeting/operations/signs.js +216 -2
- package/dist/shortcuts/workflow/endpoints.js +2 -1
- package/dist/shortcuts/workflow/errors.js +8 -2
- package/dist/shortcuts/workflow/host.js +6 -3
- package/dist/shortcuts/workflow/operations/form.js +931 -589
- package/dist/shortcuts/workflow/operations/read.js +128 -205
- package/dist/shortcuts/workflow/operations/shared.js +21 -0
- package/dist/shortcuts/workflow/operations/write.js +750 -52
- package/dist/shortcuts/workflow/operations.js +36 -10
- package/docs/_catalog.md +6 -0
- package/docs/agent-invoice.md +5 -1
- package/docs/agent-io-channel-design.md +468 -0
- package/docs/agent-skill-install.md +9 -4
- package/docs/blog.md +123 -0
- package/docs/caizhilian.md +304 -0
- package/docs/contract.md +91 -0
- package/docs/e10-auth.md +2 -2
- package/docs/hrm.md +19 -9
- package/docs/invoice.md +5 -1
- package/docs/meeting.md +1 -1
- package/docs/operation-manual.md +15 -3
- package/docs/skill-review-2026-09-19.md +2 -2
- package/package.json +2 -2
- package/scripts/package-skill.mjs +32 -20
- package/skill-template/business-info.json +113 -14
- package/skill-template/domains/blog.md +24 -0
- package/skill-template/domains/caizhilian.md +22 -0
- package/skill-template/domains/jinchengda.md +23 -0
- package/skill-template/domains/meeting.md +1 -1
- package/skill-template/domains/workflow.md +1 -1
- package/skill-template/skill-template.md +1 -1
- package/skills/weaver-e10-blog/SKILL.md +111 -0
- package/skills/weaver-e10-blog/references/blog-comment.md +51 -0
- package/skills/weaver-e10-blog/references/blog-comments.md +39 -0
- package/skills/weaver-e10-blog/references/blog-default-permission.md +38 -0
- package/skills/weaver-e10-blog/references/blog-disabled-capabilities.md +11 -0
- package/skills/weaver-e10-blog/references/blog-edit.md +51 -0
- package/skills/weaver-e10-blog/references/blog-export.md +42 -0
- package/skills/weaver-e10-blog/references/blog-like.md +50 -0
- package/skills/weaver-e10-blog/references/blog-publish.md +52 -0
- package/skills/weaver-e10-blog/references/blog-query-user.md +45 -0
- package/skills/weaver-e10-blog/references/blog-query.md +49 -0
- package/skills/weaver-e10-blog/references/blog-remind.md +51 -0
- package/skills/weaver-e10-blog/references/blog-resolve-users.md +38 -0
- package/skills/weaver-e10-blog/references/source-manifest.json +1540 -0
- package/skills/weaver-e10-caizhilian/SKILL.md +216 -0
- package/skills/weaver-e10-caizhilian/references/agent-entry.md +106 -0
- package/skills/weaver-e10-caizhilian/references/collaboration.md +112 -0
- package/skills/weaver-e10-caizhilian/references/document.md +111 -0
- package/skills/weaver-e10-caizhilian/references/file-collection.md +136 -0
- package/skills/weaver-e10-caizhilian/references/file-upload.md +309 -0
- package/skills/weaver-e10-caizhilian/references/files.md +120 -0
- package/skills/weaver-e10-caizhilian/references/folder.md +118 -0
- package/skills/weaver-e10-caizhilian/references/org-browser.md +104 -0
- package/skills/weaver-e10-caizhilian/references/setting-attach.md +410 -0
- package/skills/weaver-e10-caizhilian/references/setting-backup.md +372 -0
- package/skills/weaver-e10-caizhilian/references/setting-encrypt.md +399 -0
- package/skills/weaver-e10-caizhilian/references/setting-storage.md +603 -0
- package/skills/weaver-e10-caizhilian/references/source-manifest.json +5079 -0
- package/skills/weaver-e10-caizhilian/references/withheld.md +93 -0
- package/skills/weaver-e10-caizhilian/references/write-protocol.md +120 -0
- package/skills/weaver-e10-calendar/SKILL.md +4 -3
- package/skills/weaver-e10-ebuilder-form/SKILL.md +4 -9
- package/skills/weaver-e10-ebuilder-form/references/context-routing.md +0 -9
- package/skills/weaver-e10-ebuilder-form/references/custom-api.md +1 -5
- package/skills/weaver-e10-ebuilder-form/references/fields-browser.md +1 -5
- package/skills/weaver-e10-ebuilder-form/references/list-nlist.md +1 -5
- package/skills/weaver-e10-ebuilder-form/references/openapi-read.md +1 -5
- package/skills/weaver-e10-ebuilder-form/references/openapi-write.md +1 -5
- package/skills/weaver-e10-esb/SKILL.md +2 -2
- package/skills/weaver-e10-esb/references/source-manifest.json +9 -9
- package/skills/weaver-e10-hrm/SKILL.md +54 -6
- package/skills/weaver-e10-hrm/references/employee.md +89 -15
- package/skills/weaver-e10-hrm/references/org.md +7 -4
- package/skills/weaver-e10-hrm/references/position.md +14 -7
- package/skills/weaver-e10-hrm/references/source-manifest.json +1 -1
- package/skills/weaver-e10-jinchengda/SKILL.md +166 -0
- package/skills/weaver-e10-jinchengda/references/contract-agent-entry.md +82 -0
- package/skills/weaver-e10-jinchengda/references/contract-clause-recommender.md +69 -0
- package/skills/weaver-e10-jinchengda/references/contract-clause-reference-save.md +78 -0
- package/skills/weaver-e10-jinchengda/references/contract-disabled-capabilities.md +27 -0
- package/skills/weaver-e10-jinchengda/references/contract-request-status.md +71 -0
- package/skills/weaver-e10-jinchengda/references/contract-request-write.md +94 -0
- package/skills/weaver-e10-jinchengda/references/contract-signing-subjects.md +89 -0
- package/skills/weaver-e10-jinchengda/references/contract-subject-create.md +77 -0
- package/skills/weaver-e10-jinchengda/references/contract-template-selector.md +66 -0
- package/skills/weaver-e10-jinchengda/references/contract-workflow-discovery.md +94 -0
- package/skills/weaver-e10-jinchengda/references/source-manifest.json +259 -0
- package/skills/weaver-e10-jiuchuanhui/SKILL.md +5 -11
- package/skills/weaver-e10-jucailin/SKILL.md +4 -3
- package/skills/weaver-e10-mail/SKILL.md +4 -11
- package/skills/weaver-e10-meeting/SKILL.md +66 -32
- package/skills/weaver-e10-meeting/references/meeting-change.md +5 -2
- package/skills/weaver-e10-meeting/references/meeting-create.md +2 -1
- package/skills/weaver-e10-meeting/references/meeting-eb.md +114 -0
- package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +9 -8
- package/skills/weaver-e10-meeting/references/meeting-receipts-signs.md +35 -7
- package/skills/weaver-e10-meeting/references/meeting-update.md +1 -1
- package/skills/weaver-e10-okr/SKILL.md +6 -11
- package/skills/weaver-e10-okr/references/source-manifest.json +3 -3
- package/skills/weaver-e10-plan/SKILL.md +3 -3
- package/skills/weaver-e10-plan/references/plan-collect-and-compose.md +1 -1
- package/skills/weaver-e10-plan/references/plan-overview-and-routing.md +1 -1
- package/skills/weaver-e10-plan/references/source-manifest.json +13 -13
- package/skills/weaver-e10-qiyecheng/SKILL.md +4 -10
- package/skills/weaver-e10-qiyecheng/references/source-manifest.json +9 -9
- package/skills/weaver-e10-shared/SKILL.md +36 -25
- package/skills/weaver-e10-shared/references/e10-auth-and-session.md +10 -31
- package/skills/weaver-e10-shared/references/json-output-contract.md +20 -11
- package/skills/weaver-e10-shijingran/SKILL.md +2 -1
- package/skills/weaver-e10-shijingran/references/source-manifest.json +9 -9
- package/skills/weaver-e10-skill-maker/SKILL.md +4 -10
- package/skills/weaver-e10-skill-maker/references/business-skill-generation.md +5 -3
- package/skills/weaver-e10-skill-maker/references/module-cli-generation.md +12 -27
- package/skills/weaver-e10-skill-maker/references/module-gap-audit-and-repair.md +17 -5
- package/skills/weaver-e10-skill-maker/references/source-update-detection.md +4 -27
- package/skills/weaver-e10-wenshuding/SKILL.md +5 -16
- package/skills/weaver-e10-wenshuding/references/source-manifest.json +7 -7
- package/skills/weaver-e10-workflow/SKILL.md +32 -37
- package/skills/weaver-e10-workflow/references/source-manifest.json +39 -75
- package/skills/weaver-e10-workflow/references/workflow-batch.md +90 -29
- package/skills/weaver-e10-workflow/references/workflow-create.md +79 -109
- package/skills/weaver-e10-workflow/references/workflow-memory.md +19 -9
- package/skills/weaver-e10-workflow/references/workflow-operate.md +2 -2
- package/skills/weaver-e10-workflow/references/workflow-query.md +38 -20
- package/skills/weaver-e10-workflow/references/workflow-share.md +18 -2
- package/skills/weaver-e10-workflow/references/workflow-view.md +3 -4
- package/skills/weaver-e10-yepiaotong/SKILL.md +75 -39
- package/skills/weaver-e10-yepiaotong/references/invoice-detail.md +22 -1
- package/skills/weaver-e10-yepiaotong/references/invoice-enterprise-list.md +3 -1
- package/skills/weaver-e10-yepiaotong/references/invoice-output-view.md +135 -0
- package/skills/weaver-e10-yepiaotong/references/invoice-personal-list.md +15 -3
- package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +1 -1
- package/skills/weaver-e10-yepiaotong/references/invoice-summarize.py +217 -0
- package/skills/weaver-e10-yepiaotong/references/invoice-upload-and-validate.md +88 -0
- package/skills/weaver-e10-yepiaotong/references/invoice-validation-preview.md +7 -2
- package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +89 -9
- package/skills/weaver-e10-yepiaotong/references/reim-examples.md +1 -0
- package/skills/weaver-e10-yepiaotong/references/reim-expense-subject-rules.md +70 -49
- package/skills/weaver-e10-yepiaotong/references/reim-fast-path.md +119 -0
- package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +55 -36
- package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +4 -0
- package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +149 -0
- package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +125 -5
- package/skills/weaver-e10-yepiaotong/references/source-manifest.json +430 -63
- package/skills/weaver-e10-yimiaoban/SKILL.md +4 -12
- package/skills/weaver-e10-yimiaoban/references/source-manifest.json +3 -3
- package/skills/weaver-e10-ziguanjia/SKILL.md +2 -1
- package/skills/weaver-e10-ziguanjia/references/ziguanjia-agent-entry.md +3 -3
- package/tools/weaver-skill-detector-1.0.13/SKILL.md +9 -9
- package/tools/weaver-skill-detector-1.0.13/references/checklist.md +3 -3
- package/tools/weaver-skill-detector-1.0.13/scripts/__pycache__/validate_skill.cpython-313.pyc +0 -0
- package/tools/weaver-skill-detector-1.0.13/scripts/validate_skill.py +98 -91
- package/scripts/sync-connector-skills.mjs +0 -172
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# 发票输出投影与渲染(--format / --view / --fields)
|
|
2
|
+
|
|
3
|
+
## 什么时候读取
|
|
4
|
+
|
|
5
|
+
用户要**查询票夹、看发票清单、按条件筛票**,或者需要把发票列表交给用户阅读时读取本文件。
|
|
6
|
+
|
|
7
|
+
不读本文件的场景:写操作(导入/新增/编辑/删除/报销填单)——这些按各自 reference 处理;单张发票详情见 `invoice-detail.md`。
|
|
8
|
+
|
|
9
|
+
## 三层出口:渲染档 / 语义视图 / 点路径投影
|
|
10
|
+
|
|
11
|
+
| 出口 | 用途 | 输出形态 |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `--format markdown` | **要在对话里展示给用户时首选** | markdown 文本(表格/卡片),非 JSON |
|
|
14
|
+
| `--view summary`(列表)/ `--view detail`(`invoice.get`) | 要给程序消费的语义化数据 | JSON envelope,字段口径已固化 |
|
|
15
|
+
| `--fields a,b.c` | 精确控制字段或用于无视图的 operation | JSON envelope,保持原嵌套 |
|
|
16
|
+
|
|
17
|
+
三者的取舍:**给人看 → `--format markdown`;给下游代码看 → `--view`;只在特殊字段需求下才用 `--fields`。**
|
|
18
|
+
|
|
19
|
+
## 为什么需要投影
|
|
20
|
+
|
|
21
|
+
`invoice.list` / `invoice.enterprise.list` 的默认输出是**面向程序的完整包络**:单条发票 40+ 字段(`custom_field_*`、`oa`、`suser`、`rb`、`agricultural_*` 等),10 条约 35KB,而真正要看的只有 8 个字段(约 3KB)。
|
|
22
|
+
|
|
23
|
+
**不要**因此自己现写解析脚本,也不要把完整 JSON 贴给用户。CLI 已原生提供上面三层出口。
|
|
24
|
+
|
|
25
|
+
## 首选展示:`--format markdown`
|
|
26
|
+
|
|
27
|
+
一次调用直接得到可读表格,列顺序、千分位、票种简称、挂单状态都已内置:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
weaver-work-cli invoice list --format markdown
|
|
31
|
+
weaver-work-cli invoice get --fid 1310817108299735054 --format markdown
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
票夹列表渲染为标题行(票夹口径 + 总数 + 合计金额)+ 8 列表格;发票详情渲染为「标头 + 字段表」(含附件、费用说明、开票人、查验标记)。
|
|
35
|
+
|
|
36
|
+
规则:
|
|
37
|
+
|
|
38
|
+
- **自带字段口径**,不必也不能再传 `--view`(`invoice.list` 固定 summary、`invoice.get` 固定 detail);传了不一致的视图返回 `validation/input_conflict`
|
|
39
|
+
- **与 `--fields` 互斥**(要自定义字段就用 `--fields` 出 JSON)
|
|
40
|
+
- **与全局 `--json` 互斥**:markdown 是渲染档不是数据档,同时传返回 `validation/input_conflict`,提示去掉 `--json`
|
|
41
|
+
- 只支持 `invoice.list` / `invoice.enterprise.list` / `invoice.get`;其他 operation 返回 `validation/format_unsupported`
|
|
42
|
+
- 仍要自行拼表时用下面的 `--view`,不要退回完整 JSON
|
|
43
|
+
|
|
44
|
+
### 拿到输出后怎么展示:贴进正文,别包代码围栏
|
|
45
|
+
|
|
46
|
+
`--format markdown` 产出的是 **markdown 源码字符串**,表格、加粗、可点链接都要靠消费端的 markdown 渲染器解析。因此 Agent 拿到后要把它**作为消息正文原样输出**:
|
|
47
|
+
|
|
48
|
+
- **不要用代码围栏(三个反引号)包裹**:围栏的语义是「原样照录、不解析」,包上就退化成等宽纯文本 —— 发票号码的链接变死文本、表格散架,等于把渲染档降级回 plaintext。
|
|
49
|
+
- **不要改写、不要重新拼表**:CLI 给的就是成品,转录要保真;别自行加反斜杠转义(把 `*` 写成 `\*`)、别调整字符或列顺序。
|
|
50
|
+
- 在终端里直接执行只能看到源码,这属正常;要预览渲染效果,用支持 markdown 的客户端(浏览器、聊天界面),或在本地用 markdown 渲染器(如 `glow`、`mdcat`)。
|
|
51
|
+
|
|
52
|
+
## 语义视图:`--view summary`(列表)/ `--view detail`(详情)
|
|
53
|
+
|
|
54
|
+
`--view summary` 给出语义平表,字段口径与 `invoice.reim.candidates.list` 的 items 一致。
|
|
55
|
+
|
|
56
|
+
字段集(**省略空值**,所以某条票可能少几个键):
|
|
57
|
+
|
|
58
|
+
| 字段 | 含义 |
|
|
59
|
+
|---|---|
|
|
60
|
+
| `fid` | 发票主键,也是详情页跳转参数 |
|
|
61
|
+
| `number` / `code` | 发票号码 / 代码 |
|
|
62
|
+
| `typeName` | 票种名称,如"电子发票(增值税专用发票)" |
|
|
63
|
+
| `date` | 开票日期 |
|
|
64
|
+
| `amount` / `total` / `taxAmount` | 不含税金额 / 价税合计 / 税额 |
|
|
65
|
+
| `buyer` / `buyerTaxNo` | 购买方名称 / 税号 |
|
|
66
|
+
| `payer` / `payerTaxNo` | 销售方名称 / 税号 |
|
|
67
|
+
| `valid` | 查验状态原始值(`1`=已查验) |
|
|
68
|
+
| `status` | 发票状态原始值 |
|
|
69
|
+
| `reimState` | 票面 `comm_info.pro.sreim` 原始值,**语义未定义,不要自行解读** |
|
|
70
|
+
| `reimRequests` | 关联报销单名称数组,空数组表示未挂报销单 |
|
|
71
|
+
| `fileName` | 附件文件名 |
|
|
72
|
+
| `detailUrl` | 发票详情页链接,展示时必须转成可点击超链接 |
|
|
73
|
+
|
|
74
|
+
列表级字段:`total`(票夹总数)、`totalAmount`(价税合计)、`totalAmountExcludingTax`、`hasMore`、`scope`、`itemCount`(本次返回张数)。
|
|
75
|
+
|
|
76
|
+
`--view summary` 只对 `invoice.list` 与 `invoice.enterprise.list` 生效;`invoice.get` 用 `--view detail`(见 `invoice-detail.md`,在 summary 字段上多出 `attachments` / `expenseNote` / `issuer` / `checkState`)。对其他 operation 传视图参数会返回 `validation/view_unsupported`,此时改用 `--fields`、`--format markdown`(若该 operation 有模板)或默认完整输出。
|
|
77
|
+
|
|
78
|
+
## 备用:`--fields` 点路径投影
|
|
79
|
+
|
|
80
|
+
需要精确控制字段(例如只要号码和金额),或用于非列表 operation 时使用。点路径按**原始 JSON 结构**书写,输出保持原嵌套形状。
|
|
81
|
+
|
|
82
|
+
- 作用于 `data.items` 数组时逐项投影,列表级汇总字段(`total` / `hasMore` 等)原样保留
|
|
83
|
+
- 作用于其他 operation 时投影 `data` 本身
|
|
84
|
+
- 未命中的路径出现在 `meta.projection.missingFields`;**全部**未命中时返回 `validation/field_not_found`
|
|
85
|
+
- 与 `--view` **互斥**,同时传返回 `validation/input_conflict`
|
|
86
|
+
|
|
87
|
+
> ⚠️ **`--fields` 里不要写裸 `total` 取金额。** 发票对象顶层的 `total` 是 E10 的独立字段(实测恒为 `0`),**价税合计在 `comm_info.price.total`**,不含税金额在 `comm_info.price.amount`,税额在 `comm_info.price.dtax`。要金额就用 `--fields comm_info.price.total`,或直接用 `--view summary`(那里的 `total` 已是价税合计)。
|
|
88
|
+
|
|
89
|
+
三个参数都不属于 operation 的 `inputSchema`,它们只裁剪/渲染输出、不改变任何请求参数,因此不违反"列表查询不支持字段"的白名单校验。
|
|
90
|
+
参数错误会在**发起业务请求之前**就返回(`view_unsupported` / `view_invalid` / `format_unsupported` / `format_invalid` / `input_conflict`),不会先打一次网络请求;只有 `field_not_found` 需要拿到结果才能判断。
|
|
91
|
+
|
|
92
|
+
## 回执:`meta.projection`
|
|
93
|
+
|
|
94
|
+
投影过的响应会在 `meta.projection` 里说明本次裁剪:
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"meta": {
|
|
99
|
+
"status": "COMPLETE",
|
|
100
|
+
"projection": { "view": "summary", "omittedEmpty": true }
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
出现 `missingFields` 说明字段名写错了,按提示改正后重试,不要在缺失字段上继续加逻辑。
|
|
106
|
+
|
|
107
|
+
## 兜底:CLI 版本低于 0.1.17
|
|
108
|
+
|
|
109
|
+
旧版 CLI 没有 `--view` / `--fields` / `--format`(可用 `weaver-work-cli --version` 确认)。此时用随本 reference 提供的脚本 `invoice-summarize.py`,字段口径与 `--view summary` 完全一致:
|
|
110
|
+
|
|
111
|
+
macOS/Linux(bash/zsh):
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
weaver-work-cli --json invoice list > list.json
|
|
115
|
+
python3 ~/.workbuddy/skills/weaver-e10-yepiaotong/references/invoice-summarize.py list.json
|
|
116
|
+
python3 ~/.workbuddy/skills/weaver-e10-yepiaotong/references/invoice-summarize.py list.json --format table
|
|
117
|
+
weaver-work-cli --json invoice list | python3 ~/.workbuddy/skills/weaver-e10-yepiaotong/references/invoice-summarize.py -
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Windows PowerShell:
|
|
121
|
+
|
|
122
|
+
```powershell
|
|
123
|
+
weaver-work-cli --json invoice list | Out-File -Encoding UTF8 list.json
|
|
124
|
+
python "$env:USERPROFILE\.workbuddy\skills\weaver-e10-yepiaotong\references\invoice-summarize.py" list.json
|
|
125
|
+
python "$env:USERPROFILE\.workbuddy\skills\weaver-e10-yepiaotong\references\invoice-summarize.py" list.json --format table
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
脚本要求 Python 3,只用标准库;输入接受完整 envelope、`data` 对象、`{items:[...]}` 或 E10 原生 `{infos:[...]}`;`--format table` 输出 markdown 表格,适合直接贴给用户。
|
|
129
|
+
|
|
130
|
+
## 注意事项
|
|
131
|
+
|
|
132
|
+
- **发票号码必须用 `detailUrl` 渲染成可点击超链接**,格式为 `[号码](detailUrl)`;`--view summary` 已保留该字段,`--fields` 时记得把它列进字段表,否则详情链接会丢失。
|
|
133
|
+
- 需要完整票面字段(`ext` 里的商品明细、`flist` 附件列表等)时不要用投影,走 `invoice.get`。
|
|
134
|
+
- 统计金额以 `totalAmount` / `totalAmountExcludingTax` 为准,不要用单条 `total` 相加去"复核"服务端汇总——两者口径可能不同(作废票、红冲票的处理方式未在契约中定义)。
|
|
135
|
+
- `reimState` 与列表筛选参数 `sreim` **不是同一套语义**:`sreim` 是筛选入参(`"0"`=全部、`"1"`=报销中、`"2"`=报销完成、`"3"`=未报销、`"4"`=不可报销),而票面 `comm_info.pro.sreim` 的取值含义未在 CLI 契约里定义,只能原样呈现。
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
|
|
17
17
|
- `page_size`、`start_pos`
|
|
18
18
|
- `content`
|
|
19
|
-
- `date_begin`、`date_end
|
|
20
|
-
- `create_tm_begin`、`create_tm_end
|
|
19
|
+
- `date_begin`、`date_end`(开票日期含当日)
|
|
20
|
+
- `create_tm_begin`、`create_tm_end`(创建时间含当日)
|
|
21
21
|
- `payer_company`、`buyer_company`
|
|
22
22
|
- `payer_taxno`、`buyer_taxno`
|
|
23
23
|
- `code`、`number`
|
|
@@ -39,6 +39,8 @@ Windows PowerShell:
|
|
|
39
39
|
weaver-work-cli --json invoice run invoice.list --input-json '{"page_size":10,"start_pos":0,"content":"滴滴"}'
|
|
40
40
|
|
|
41
41
|
weaver-work-cli --json invoice run invoice.list --input-json '{"page_size":10,"start_pos":0,"sreim":"2"}'
|
|
42
|
+
|
|
43
|
+
weaver-work-cli --json invoice run invoice.list --input-json '{"page_size":10,"start_pos":0,"date_begin":"2026-09-01","date_end":"2026-09-30"}'
|
|
42
44
|
```
|
|
43
45
|
|
|
44
46
|
macOS/Linux(bash/zsh):
|
|
@@ -47,12 +49,22 @@ macOS/Linux(bash/zsh):
|
|
|
47
49
|
weaver-work-cli --json invoice run invoice.list --input-json '{"page_size":10,"start_pos":0,"content":"滴滴"}'
|
|
48
50
|
|
|
49
51
|
weaver-work-cli --json invoice run invoice.list --input-json '{"page_size":10,"start_pos":0,"sreim":"2"}'
|
|
52
|
+
|
|
53
|
+
weaver-work-cli --json invoice run invoice.list --input-json '{"page_size":10,"start_pos":0,"date_begin":"2026-09-01","date_end":"2026-09-30"}'
|
|
50
54
|
```
|
|
51
55
|
|
|
52
56
|
## 返回
|
|
53
57
|
|
|
54
|
-
返回 `items`、`total`、`totalAmount`、`totalAmountExcludingTax`、`hasMore` 和 `scope="personal"
|
|
58
|
+
返回 `items`、`total`、`totalAmount`、`totalAmountExcludingTax`、`hasMore` 和 `scope="personal"`。每条 item 包含 `detailUrl`(如 `https://xxx/sp/inc/incDetail?fid=<fid>`)。分页时递增 `start_pos`,保持筛选条件和排序不变。
|
|
59
|
+
|
|
60
|
+
向用户展示发票列表时,**发票号码必须用 markdown 链接格式** `[号码](detailUrl)` 展示,让用户点击直接打开发票详情页。
|
|
55
61
|
|
|
56
62
|
## 注意
|
|
57
63
|
|
|
58
64
|
不要在输入里传 `flag`;即使传入也会被 CLI 忽略并固定为个人票夹。空筛选条件直接省略,不要把空字符串传给 integer 字段。除非用户明确要求全部或某个报销状态,否则不要传 `sreim`;除非用户明确要求凭证,否则不要传 `bill_type`。
|
|
65
|
+
|
|
66
|
+
**时间字段两种写法都接受**(0.1.15 起):`date_begin`/`date_end`/`create_tm_begin`/`create_tm_end` 既可以传 `"YYYY-MM-DD"`(按东八区零点换算),也可以传秒级时间戳 integer(E10 `/api/inc/sync` 的原生格式)。CLI 会在本地归一,非法值直接报 `validation/input_invalid`,不会再透传到 E10 变成不透明的 `400 系统错误`。`page_size`/`start_pos`/`req_type`/`mask`/`mext` 同样会归一:数字串(如 `"20"`)可以,`"abc"`、`-1`、`1.5` 会被本地拦下。
|
|
67
|
+
|
|
68
|
+
> 0.1.14 及更早:CLI 不做本地归一,字符串日期会一路透传到 E10 并返回 `api/business_error`/`400 系统错误`。用 `doctor --e10` 的 package 字段确认版本。
|
|
69
|
+
|
|
70
|
+
> `invoice.reim.candidates.list` 的 `date_begin`/`date_end` 同样接受 `YYYY-MM-DD` 或秒级时间戳,与 `invoice.list` 口径一致。
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
3. 用 `invoice.reim.requests.list` 获取事前申请,再按时间、费用类型和标题做匹配;原始 ID、日期、金额必须逐字符保留。
|
|
26
26
|
4. 用 `invoice.reim.workflow.resolve` 得到报销工作流,必要时按工作流分组。
|
|
27
27
|
5. 对每组并行读取 `invoice.reim.form.structure`、`invoice.reim.row-info` 和 `invoice.reim.employee-superiors`;只有需要用户修正关联字段时才用 `invoice.reim.field.search`。
|
|
28
|
-
6. Agent 按表单结构组装报销单 JSON,先调用 `invoice.reim.flow.create.prepare`,展示标题、主表字段数、明细行数、发票和风险;用户明确确认后再调用 `.apply
|
|
28
|
+
6. Agent 按表单结构组装报销单 JSON,先调用 `invoice.reim.flow.create.prepare`,展示标题、主表字段数、明细行数、发票和风险;用户明确确认后再调用 `.apply`。命中「话费补贴标准审批流程」或「话费报销」时,必须先读 [`reim-phone-subsidy-rules.md`](reim-phone-subsidy-rules.md),按月度标准核算实报金额,不能直接用发票金额填单。
|
|
29
29
|
7. 报销单创建成功后,后续修正使用 `invoice.reim.flow.update.prepare/apply`,不要重复创建同一组发票的报销单。
|
|
30
30
|
|
|
31
31
|
## 命令
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""把 weaver-work-cli 发票查询的完整 JSON envelope 裁成语义摘要。
|
|
3
|
+
|
|
4
|
+
为什么需要它
|
|
5
|
+
------------
|
|
6
|
+
`invoice.list` / `invoice.enterprise.list` 的原始输出里,单条发票有 40+ 字段
|
|
7
|
+
(`custom_field_*`、`rb`、`oa`、`suser`、`agricultural_*` 等对调用方无用),
|
|
8
|
+
10 条就是 35KB 左右。要拿到"号码 / 金额 / 购销方"就得先解析一遍。
|
|
9
|
+
|
|
10
|
+
优先用 CLI 原生能力
|
|
11
|
+
------------------
|
|
12
|
+
CLI 0.1.17 起支持 `--view summary`(语义平表)与 `--fields a,b.c`(点路径投影),
|
|
13
|
+
Agent 应当优先用它们,不必写脚本:
|
|
14
|
+
|
|
15
|
+
weaver-work-cli --json invoice list --view summary
|
|
16
|
+
|
|
17
|
+
本脚本用于以下兜底场景:
|
|
18
|
+
1. 目标机器上的 CLI 版本低于 0.1.17,没有 `--view summary`
|
|
19
|
+
2. 需要把结果整理成 markdown 表格直接贴给用户
|
|
20
|
+
3. 需要在多份导出文件之间做汇总核对
|
|
21
|
+
|
|
22
|
+
用法
|
|
23
|
+
----
|
|
24
|
+
weaver-work-cli --json invoice run invoice.list --input-json '{"page_size":10}' > list.json
|
|
25
|
+
python invoice-summarize.py list.json
|
|
26
|
+
python invoice-summarize.py list.json --format table
|
|
27
|
+
weaver-work-cli --json invoice list | python invoice-summarize.py -
|
|
28
|
+
|
|
29
|
+
输入可以是:完整 envelope、`data` 对象、`{items:[...]}`,或 E10 原生 `{infos:[...]}` 响应。
|
|
30
|
+
|
|
31
|
+
字段口径与 CLI `--view summary` 保持一致(见 references/invoice-output-view.md)。
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
from __future__ import annotations
|
|
35
|
+
|
|
36
|
+
import argparse
|
|
37
|
+
import json
|
|
38
|
+
import sys
|
|
39
|
+
|
|
40
|
+
# 与 src/shortcuts/invoice/projection.ts 的 SUMMARY_ITEM_FIELDS 保持同序同义
|
|
41
|
+
SUMMARY_FIELDS = [
|
|
42
|
+
"fid",
|
|
43
|
+
"number",
|
|
44
|
+
"code",
|
|
45
|
+
"typeName",
|
|
46
|
+
"date",
|
|
47
|
+
"amount",
|
|
48
|
+
"total",
|
|
49
|
+
"taxAmount",
|
|
50
|
+
"buyer",
|
|
51
|
+
"buyerTaxNo",
|
|
52
|
+
"payer",
|
|
53
|
+
"payerTaxNo",
|
|
54
|
+
"valid",
|
|
55
|
+
"status",
|
|
56
|
+
"reimState",
|
|
57
|
+
"reimRequests",
|
|
58
|
+
"fileName",
|
|
59
|
+
"detailUrl",
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
TABLE_COLUMNS = [
|
|
63
|
+
("number", "发票号码"),
|
|
64
|
+
("typeName", "类型"),
|
|
65
|
+
("date", "开票日期"),
|
|
66
|
+
("total", "价税合计"),
|
|
67
|
+
("payer", "销方"),
|
|
68
|
+
("buyer", "购方"),
|
|
69
|
+
("reimRequests", "关联报销单"),
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def as_dict(value: object) -> dict:
|
|
74
|
+
return value if isinstance(value, dict) else {}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def as_text(value: object) -> str:
|
|
78
|
+
if value is None:
|
|
79
|
+
return ""
|
|
80
|
+
return str(value).lstrip("\ufeff").strip()
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def as_int(value: object) -> int | None:
|
|
84
|
+
if isinstance(value, bool):
|
|
85
|
+
return None
|
|
86
|
+
if isinstance(value, int):
|
|
87
|
+
return value
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def summarize_item(item: dict) -> dict:
|
|
92
|
+
"""把一条原始发票对象裁成语义摘要;空值省键,票面自带的 '0' 保留。"""
|
|
93
|
+
comm = as_dict(item.get("comm_info"))
|
|
94
|
+
pro = as_dict(comm.get("pro"))
|
|
95
|
+
price = as_dict(comm.get("price"))
|
|
96
|
+
buyer = as_dict(comm.get("buyer"))
|
|
97
|
+
payer = as_dict(comm.get("payer"))
|
|
98
|
+
modify = as_dict(item.get("modify_info"))
|
|
99
|
+
oreim = as_dict(item.get("oreim"))
|
|
100
|
+
reim_list = oreim.get("list_reim") if isinstance(oreim.get("list_reim"), list) else []
|
|
101
|
+
|
|
102
|
+
summary = {
|
|
103
|
+
"fid": as_text(item.get("fid") or item.get("id")),
|
|
104
|
+
"number": as_text(item.get("number")),
|
|
105
|
+
"code": as_text(item.get("code")),
|
|
106
|
+
"typeName": as_text(pro.get("cname")),
|
|
107
|
+
"date": as_text(pro.get("date")),
|
|
108
|
+
"amount": as_text(price.get("amount")),
|
|
109
|
+
"total": as_text(price.get("total")),
|
|
110
|
+
"taxAmount": as_text(price.get("dtax")),
|
|
111
|
+
"buyer": as_text(buyer.get("company")),
|
|
112
|
+
"buyerTaxNo": as_text(buyer.get("tcode")),
|
|
113
|
+
"payer": as_text(payer.get("company")),
|
|
114
|
+
"payerTaxNo": as_text(payer.get("tcode")),
|
|
115
|
+
"valid": as_int(pro.get("valid")),
|
|
116
|
+
"status": as_int(pro.get("status")),
|
|
117
|
+
"reimState": as_int(pro.get("sreim")),
|
|
118
|
+
"reimRequests": [as_text(as_dict(entry).get("name")) for entry in reim_list if as_text(as_dict(entry).get("name"))],
|
|
119
|
+
"fileName": as_text(modify.get("fname")),
|
|
120
|
+
"detailUrl": as_text(item.get("detailUrl")),
|
|
121
|
+
}
|
|
122
|
+
return {key: value for key, value in summary.items() if value not in ("", None, [])}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def extract_items(payload: object) -> tuple[list, dict]:
|
|
126
|
+
"""兼容 envelope / data / items / E10 原生 infos 四种输入形状。"""
|
|
127
|
+
root = as_dict(payload)
|
|
128
|
+
data = as_dict(root.get("data")) or root
|
|
129
|
+
for key in ("items", "infos"):
|
|
130
|
+
candidate = data.get(key)
|
|
131
|
+
if isinstance(candidate, list):
|
|
132
|
+
return candidate, data
|
|
133
|
+
if isinstance(payload, list):
|
|
134
|
+
return payload, {}
|
|
135
|
+
return [], data
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def summarize_payload(payload: object) -> dict:
|
|
139
|
+
items, data = extract_items(payload)
|
|
140
|
+
summary = {}
|
|
141
|
+
for key in ("total", "totalAmount", "totalAmountExcludingTax", "hasMore", "scope"):
|
|
142
|
+
if data.get(key) is not None:
|
|
143
|
+
summary[key] = data[key]
|
|
144
|
+
summary["items"] = [summarize_item(as_dict(item)) for item in items]
|
|
145
|
+
summary["itemCount"] = len(summary["items"])
|
|
146
|
+
return summary
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def render_cell(item: dict, key: str) -> str:
|
|
150
|
+
value = item.get(key)
|
|
151
|
+
if key == "reimRequests":
|
|
152
|
+
names = value if isinstance(value, list) else []
|
|
153
|
+
if not names:
|
|
154
|
+
return "-"
|
|
155
|
+
return names[0] if len(names) == 1 else f"{names[0]} 等 {len(names)} 笔"
|
|
156
|
+
return str(value) if value is not None else ""
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def render_table(summary: dict) -> str:
|
|
160
|
+
lines = []
|
|
161
|
+
header = "| " + " | ".join(label for _, label in TABLE_COLUMNS) + " |"
|
|
162
|
+
divider = "|" + "---|" * len(TABLE_COLUMNS)
|
|
163
|
+
lines.append(header)
|
|
164
|
+
lines.append(divider)
|
|
165
|
+
for item in summary["items"]:
|
|
166
|
+
cells = [render_cell(item, key) for key, _ in TABLE_COLUMNS]
|
|
167
|
+
lines.append("| " + " | ".join(cells) + " |")
|
|
168
|
+
|
|
169
|
+
parts = [f"共 {summary.get('itemCount', 0)} 张"]
|
|
170
|
+
if summary.get("total") is not None:
|
|
171
|
+
parts.append(f"票夹总数 {summary['total']}")
|
|
172
|
+
if summary.get("totalAmount") is not None:
|
|
173
|
+
parts.append(f"价税合计 {summary['totalAmount']}")
|
|
174
|
+
if summary.get("hasMore"):
|
|
175
|
+
parts.append("还有更多(hasMore=true)")
|
|
176
|
+
lines.append("")
|
|
177
|
+
lines.append(";".join(parts))
|
|
178
|
+
lines.append("")
|
|
179
|
+
lines.append("注:`reimState`(票面 `comm_info.pro.sreim`)的取值语义未在 CLI 契约中定义,只能原样呈现,不要自行解读成已报销/未报销。")
|
|
180
|
+
return "\n".join(lines)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def main(argv: list[str]) -> int:
|
|
184
|
+
parser = argparse.ArgumentParser(
|
|
185
|
+
description="把 weaver-work-cli 发票查询的完整 JSON 输出裁成语义摘要(CLI --view summary 的兜底方案)",
|
|
186
|
+
)
|
|
187
|
+
parser.add_argument("path", help="JSON 文件路径,或 - 表示从标准输入读取")
|
|
188
|
+
parser.add_argument("--format", choices=["json", "table"], default="json", help="json=摘要对象(默认),table=markdown 表格")
|
|
189
|
+
parser.add_argument("--indent", type=int, default=1, help="json 格式的缩进,默认 1")
|
|
190
|
+
args = parser.parse_args(argv)
|
|
191
|
+
|
|
192
|
+
if args.path == "-":
|
|
193
|
+
raw = sys.stdin.read()
|
|
194
|
+
else:
|
|
195
|
+
try:
|
|
196
|
+
with open(args.path, encoding="utf-8-sig") as handle:
|
|
197
|
+
raw = handle.read()
|
|
198
|
+
except OSError as error:
|
|
199
|
+
print(f"无法读取 {args.path}:{error}", file=sys.stderr)
|
|
200
|
+
return 1
|
|
201
|
+
|
|
202
|
+
try:
|
|
203
|
+
payload = json.loads(raw.lstrip("\ufeff"))
|
|
204
|
+
except json.JSONDecodeError as error:
|
|
205
|
+
print(f"{args.path} 不是合法 JSON:{error}", file=sys.stderr)
|
|
206
|
+
return 1
|
|
207
|
+
|
|
208
|
+
summary = summarize_payload(payload)
|
|
209
|
+
if args.format == "table":
|
|
210
|
+
print(render_table(summary))
|
|
211
|
+
else:
|
|
212
|
+
print(json.dumps(summary, ensure_ascii=False, indent=args.indent))
|
|
213
|
+
return 0
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
if __name__ == "__main__":
|
|
217
|
+
raise SystemExit(main(sys.argv[1:]))
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# 一站式上传+OCR+查验
|
|
2
|
+
|
|
3
|
+
## 什么时候读取
|
|
4
|
+
|
|
5
|
+
用户要求上传发票附件并完成查验(上传→识别→查验一步到位)时读取本文件。
|
|
6
|
+
如果用户只需要单独上传或单独 OCR,请分别参阅 `invoice-file-upload.md` 或 `invoice-import.md`。
|
|
7
|
+
|
|
8
|
+
## Operation
|
|
9
|
+
|
|
10
|
+
| Operation | 说明 |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| `invoice.upload-and-validate` | 上传发票文件 → OCR 识别 → 逐张查验,合并为单条命令 |
|
|
13
|
+
|
|
14
|
+
## 输入参数
|
|
15
|
+
|
|
16
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
17
|
+
| --- | --- | --- | --- |
|
|
18
|
+
| `file` | string | 与 url 二选一 | 本地文件路径 |
|
|
19
|
+
| `url` | string | 与 file 二选一 | 可访问的文件 URL |
|
|
20
|
+
| `scope` | string | ✅ | `personal`(个人票夹)或 `enterprise`(企业票夹) |
|
|
21
|
+
|
|
22
|
+
文件来源支持扩展名:`pdf`、`ofd`、`xml`、`png`、`jpg`、`jpeg`。
|
|
23
|
+
本地文件必须存在、非空且不超过 25 MiB。URL 只允许 `http/https`,不能包含账号密码。
|
|
24
|
+
|
|
25
|
+
## 示例
|
|
26
|
+
|
|
27
|
+
Windows PowerShell:
|
|
28
|
+
|
|
29
|
+
```powershell
|
|
30
|
+
weaver-work-cli --json invoice run invoice.upload-and-validate --input-json '{"file":"./invoice.pdf","scope":"personal"}'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
macOS/Linux(bash/zsh):
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
weaver-work-cli --json invoice run invoice.upload-and-validate --input-json '{"file":"./invoice.pdf","scope":"personal"}'
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 返回
|
|
40
|
+
|
|
41
|
+
```jsonc
|
|
42
|
+
{
|
|
43
|
+
"status": "COMPLETE",
|
|
44
|
+
"data": {
|
|
45
|
+
"upload": { /* upload 对象:id, ids, fileType, fileName, totalPages … */ },
|
|
46
|
+
"ocrCount": 1, // OCR 识别出的发票数量
|
|
47
|
+
"invoices": [ /* OCR 识别出的发票列表(原始 info) */ ],
|
|
48
|
+
"validations": [ // 每张发票的查验结果
|
|
49
|
+
{
|
|
50
|
+
"fid": "751293486469988353",
|
|
51
|
+
"code": "031001900311",
|
|
52
|
+
"number": "00188205",
|
|
53
|
+
"date": "2024-11-25",
|
|
54
|
+
"total": "200.00",
|
|
55
|
+
"buyer": "...",
|
|
56
|
+
"payer": "...",
|
|
57
|
+
"scope": "personal",
|
|
58
|
+
"validation": 1, // 查验结果:1=真 0=假/未查验
|
|
59
|
+
"invoiceStatus": 0,
|
|
60
|
+
"saved": false
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
"validationErrors": [], // 查验失败的发票 [{fid, error}]
|
|
64
|
+
"results": [ /* OCR 原始返回 */ ],
|
|
65
|
+
"workflow": { "workflow": "invoice.upload-and-validate", "version": 1, "state": "COMPLETE" }
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 部分失败
|
|
71
|
+
|
|
72
|
+
- 上传失败:直接报错。
|
|
73
|
+
- OCR 失败:返回 `partialData`(含 upload 对象),状态为 `OCR_FAILED`。
|
|
74
|
+
- 单张查验失败:不中断整体流程,失败项记入 `validationErrors`,其余成功项正常返回 `validations`。
|
|
75
|
+
|
|
76
|
+
## 与分步操作的关系
|
|
77
|
+
|
|
78
|
+
本命令等价于依次执行:
|
|
79
|
+
|
|
80
|
+
1. `invoice.upload`(上传文件获取 upload 对象)
|
|
81
|
+
2. `invoice.ocr.preview`(OCR 识别所有页面)
|
|
82
|
+
3. `invoice.validate.preview`(逐张查验)
|
|
83
|
+
|
|
84
|
+
如需更细粒度的控制(例如只上传不查验、或重复 OCR),请使用上述分步命令。
|
|
85
|
+
|
|
86
|
+
## 注意
|
|
87
|
+
|
|
88
|
+
上传前必须先提醒用户:发票附件/图片/文件内容可能被上传到 E10 业票通,并可能进入当前大模型上下文用于理解和处理;只有用户明确确认后才执行。用户仅提供文件路径或文件名不等于同意上传。
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 查验预览(仅限已在票夹中的发票)
|
|
2
2
|
|
|
3
3
|
## 什么时候读取
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
用户要查验**已在票夹中的发票**(已有 `fid`),但没有明确要求把查验结果回写票夹时读取本文件。
|
|
6
|
+
|
|
7
|
+
## ⚠️ 路由判断
|
|
8
|
+
|
|
9
|
+
- 如果用户提供的是**文件路径或 URL**(还没上传到票夹),**不要**使用本命令 → 应改用 `invoice.upload-and-validate`(一站式上传+OCR+查验)
|
|
10
|
+
- 本命令**仅适用于票夹中已存在的发票**,必须已有 `fid`
|
|
6
11
|
|
|
7
12
|
## Operation
|
|
8
13
|
|
|
@@ -104,8 +104,8 @@ CLI 已固定 `flag`(个人票夹=0 / 企业票夹=6),默认 `sreim="3"`
|
|
|
104
104
|
| --- | --- | --- | --- |
|
|
105
105
|
| `page_size` | Integer | 否 | 每页条数,默认 `10`,建议不超过 `20` |
|
|
106
106
|
| `start_pos` | Integer | 否 | 分页起始位置,默认 `0` |
|
|
107
|
-
| `date_begin` / `date_end` | Integer | 否 |
|
|
108
|
-
| `create_tm_begin` / `create_tm_end` | Integer | 否 |
|
|
107
|
+
| `date_begin` / `date_end` | Integer \| String | 否 | 开票日期范围。可传秒级时间戳,也可直接传 `"YYYY-MM-DD"`(0.1.15 起 CLI 按东八区零点换算)。用户未指定日期时,默认最近一周 |
|
|
108
|
+
| `create_tm_begin` / `create_tm_end` | Integer \| String | 否 | 录入/创建日期范围,写法同上。仅用户明确说录入/创建日期时使用 |
|
|
109
109
|
| `content` | String | 否 | 消费内容关键词(如 `"滴滴"`、`"住宿"`) |
|
|
110
110
|
| `number` | String | 否 | 发票号码精确匹配 |
|
|
111
111
|
| `types` | Array\<Integer\> | 否 | 发票类型 ID 数组(见下方映射表) |
|
|
@@ -115,6 +115,7 @@ CLI 已固定 `flag`(个人票夹=0 / 企业票夹=6),默认 `sreim="3"`
|
|
|
115
115
|
### 时间戳计算
|
|
116
116
|
|
|
117
117
|
> **所有日期参数的秒级时间戳由 AI 按内联公式直接计算(UTC+8 时区)。**
|
|
118
|
+
> 0.1.15 起 `date_begin` / `date_end` / `create_tm_begin` / `create_tm_end` 也直接接受 `"YYYY-MM-DD"`(CLI 按东八区零点换算),日期区间不跨时区歧义时优先写 `"YYYY-MM-DD"`,更省一次心算;需要精确到时分秒的边界(如 `23:59:59`)时才用秒级时间戳。
|
|
118
119
|
> 完整公式和 Fallback 见 [reim-workflow.md - 时间戳内联计算](reim-workflow.md#时间戳内联计算零工具调用)。
|
|
119
120
|
|
|
120
121
|
示例(最近一周,只传必要字段):
|
|
@@ -427,6 +428,7 @@ weaver-work-cli --json invoice run invoice.reim.requests.list --input-json '{"pa
|
|
|
427
428
|
|
|
428
429
|
- `cusCreateDateEnd` = 最晚发票 invoiceDate(事前申请不会晚于开票日期)
|
|
429
430
|
- `cusCreateDateStart` = 最早发票 invoiceDate 往前推 90 天(合理的事前申请窗口期)
|
|
431
|
+
- **话费报销例外**:话费补贴事前申请可能在很早以前审批,`cusCreateDateStart` 需往前推 **1095 天(3 年)**,并加 `requestname="话费"` 缩小结果。详见 [reim-phone-subsidy-rules.md](reim-phone-subsidy-rules.md)。
|
|
430
432
|
|
|
431
433
|
### 返回示例
|
|
432
434
|
|
|
@@ -869,14 +871,18 @@ weaver-work-cli --json invoice run invoice.reim.employee-superiors --input-json
|
|
|
869
871
|
"id": "1201729946891231232",
|
|
870
872
|
"name": "后端开发111"
|
|
871
873
|
},
|
|
874
|
+
"directSuperior": {
|
|
875
|
+
"id": "1201729946891231233",
|
|
876
|
+
"name": "直属主管王五"
|
|
877
|
+
},
|
|
872
878
|
"allSuperiors": [
|
|
873
879
|
{
|
|
874
880
|
"id": "1201729946891231111",
|
|
875
|
-
"name": "
|
|
881
|
+
"name": "分管领导熊总"
|
|
876
882
|
},
|
|
877
883
|
{
|
|
878
|
-
"id": "
|
|
879
|
-
"name": "
|
|
884
|
+
"id": "1201729946891231233",
|
|
885
|
+
"name": "直属主管王五"
|
|
880
886
|
}
|
|
881
887
|
]
|
|
882
888
|
},
|
|
@@ -890,16 +896,16 @@ weaver-work-cli --json invoice run invoice.reim.employee-superiors --input-json
|
|
|
890
896
|
| --- | --- |
|
|
891
897
|
| `currentEmployee.id` | 当前人员 ID(**字符串**,避免雪花 ID 超过 JS 安全整数精度) |
|
|
892
898
|
| `currentEmployee.name` | 当前人员名称 |
|
|
893
|
-
| `allSuperiors` |
|
|
894
|
-
| `allSuperiors[0]`
|
|
899
|
+
| `allSuperiors` | 所有上级列表(直接上级 + 间接上级,按层级从高到低排列),每项含 `id` 和 `name` |
|
|
900
|
+
| `directSuperior` | **直接上级**(对象,含 `id` 和 `name`)。⚠️ **与 `allSuperiors[0]` 不是同一人**:`allSuperiors[0]` 是上级链中最高层(如分管领导),直接上级必须取 `directSuperior` |
|
|
895
901
|
| `allSuperiors[].id` | 上级人员 ID(**字符串**) |
|
|
896
902
|
|
|
897
903
|
### 填单字段对应关系
|
|
898
904
|
|
|
899
905
|
| 表单字段 | 取值方式 |
|
|
900
906
|
| --- | --- |
|
|
901
|
-
| 报销人上级 | `
|
|
902
|
-
| 承担人直接上级 | `
|
|
907
|
+
| 报销人上级 | `directSuperior.id`(直接上级 ID,直接赋值;**不是 `allSuperiors[0]`**) |
|
|
908
|
+
| 承担人直接上级 | `directSuperior.id`(同上) |
|
|
903
909
|
| 承担人所有上级 | `allSuperiors` 中所有 `id` 用逗号拼接(如 `"id1,id2,id3"`) |
|
|
904
910
|
|
|
905
911
|
---
|
|
@@ -969,6 +975,80 @@ weaver-work-cli --json invoice run invoice.reim.row-info --input-json '{"invoice
|
|
|
969
975
|
|
|
970
976
|
---
|
|
971
977
|
|
|
978
|
+
## 5.6b 批量获取发票预填信息(0.1.19 新增)
|
|
979
|
+
|
|
980
|
+
CLI operation:`invoice.reim.row-info-batch`
|
|
981
|
+
|
|
982
|
+
一次调用获取多张发票的预填信息,内部并行处理(并发度 4),避免 Agent 逐张串行调用 `invoice.reim.row-info` 导致 N-1 次额外 CLI 启动与网络往返。
|
|
983
|
+
|
|
984
|
+
### 入参
|
|
985
|
+
|
|
986
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
987
|
+
| --- | --- | --- | --- |
|
|
988
|
+
| `invoiceIds` | Array\<String\> | 是 | 发票 ID 列表,1-100 个 |
|
|
989
|
+
| `requestid` | String | 否 | 事前申请流程 ID(无可不传或留空) |
|
|
990
|
+
| `cdzt` | String | 否 | 当前用户/人员 ID,不传则 CLI 使用当前登录用户 |
|
|
991
|
+
|
|
992
|
+
### 命令
|
|
993
|
+
|
|
994
|
+
macOS/Linux(bash/zsh):
|
|
995
|
+
|
|
996
|
+
```bash
|
|
997
|
+
weaver-work-cli --json invoice run invoice.reim.row-info-batch --input-json '{"invoiceIds":["1297093330645237792","1297093330645237793"]}'
|
|
998
|
+
```
|
|
999
|
+
|
|
1000
|
+
Windows PowerShell:
|
|
1001
|
+
|
|
1002
|
+
```powershell
|
|
1003
|
+
weaver-work-cli --json invoice run invoice.reim.row-info-batch --input-json '{"invoiceIds":["1297093330645237792","1297093330645237793"]}'
|
|
1004
|
+
```
|
|
1005
|
+
|
|
1006
|
+
### 返回示例
|
|
1007
|
+
|
|
1008
|
+
```json
|
|
1009
|
+
{
|
|
1010
|
+
"results": [
|
|
1011
|
+
{
|
|
1012
|
+
"invoiceId": "1297093330645237792",
|
|
1013
|
+
"status": "success",
|
|
1014
|
+
"data": {
|
|
1015
|
+
"date": "2026-07-29",
|
|
1016
|
+
"fysm": "交通运输服务",
|
|
1017
|
+
"itinerary": "1298798990831518001",
|
|
1018
|
+
"subjectId": "100502270000000006"
|
|
1019
|
+
}
|
|
1020
|
+
},
|
|
1021
|
+
{
|
|
1022
|
+
"invoiceId": "1297093330645237793",
|
|
1023
|
+
"status": "fail",
|
|
1024
|
+
"error": "获取发票 1297093330645237793 行预填失败"
|
|
1025
|
+
}
|
|
1026
|
+
],
|
|
1027
|
+
"succeeded": 1,
|
|
1028
|
+
"failed": 1,
|
|
1029
|
+
"total": 2,
|
|
1030
|
+
"workflow": { "workflow": "invoice.reim.row-info-batch", "version": 1, "state": "PARTIAL" }
|
|
1031
|
+
}
|
|
1032
|
+
```
|
|
1033
|
+
|
|
1034
|
+
### 返回字段说明
|
|
1035
|
+
|
|
1036
|
+
| 字段 | 说明 |
|
|
1037
|
+
| --- | --- |
|
|
1038
|
+
| `results[].invoiceId` | 对应的发票 ID |
|
|
1039
|
+
| `results[].status` | `"success"` 或 `"fail"` |
|
|
1040
|
+
| `results[].data` | 成功时返回,结构与单张 `row-info` 一致(`date`、`fysm`、`itinerary`、`subjectId`) |
|
|
1041
|
+
| `results[].error` | 失败时返回错误信息 |
|
|
1042
|
+
| `succeeded` / `failed` / `total` | 成功/失败/总数统计 |
|
|
1043
|
+
|
|
1044
|
+
### 使用场景
|
|
1045
|
+
|
|
1046
|
+
- **手工组装报销单时**(Step 3.5),用 `row-info-batch` 替代 N 次 `row-info` 调用
|
|
1047
|
+
- 部分失败不影响其他发票,失败的回退到 AI 推断逻辑
|
|
1048
|
+
- 快速路径(`template.build`/`auto-prepare`)内部已自带批量获取,无需额外调用
|
|
1049
|
+
|
|
1050
|
+
---
|
|
1051
|
+
|
|
972
1052
|
## 5.7 获取发票详情(交通类发票行程信息)
|
|
973
1053
|
|
|
974
1054
|
CLI operation:`invoice.get`
|