@youzan-cloud/zan-saas-cli 0.1.0-beta.7 → 0.1.0-beta.8
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/internal/registry/manifest.json +21 -17
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/skills/zan-saas-order/SKILL.md +12 -1
- package/skills/zan-saas-order/references/branch-counts.md +45 -0
- package/skills/zan-saas-order/references/order-get.md +2 -0
- package/skills/zan-saas-order/references/order-list.md +2 -0
- package/skills/zan-saas-order/references/order-scan.md +2 -0
- package/skills/zan-saas-org/SKILL.md +2 -0
- package/skills/zan-saas-org/references/unit-list.md +2 -0
- package/skills/zan-saas-shared/SKILL.md +4 -0
- package/skills/zan-saas-shared/references/gateway-errors.md +29 -0
- package/skills/zan-saas-shared/references/shop-context.md +3 -1
- package/skills/zan-saas-valuecard/SKILL.md +8 -2
- package/skills/zan-saas-valuecard/references/transaction-list.md +25 -0
- package/skills/zan-saas-valuecard/references/transaction-scan.md +23 -0
- package/src/cli/context-help.js +3 -1
- package/src/commands/native/access/commands.index.json +1 -1
- package/src/commands/native/access/role/list/command.js +4 -32
- package/src/commands/native/order/commands.index.json +3 -3
- package/src/commands/native/order/order/get/command.js +14 -9
- package/src/commands/native/order/order/get/schema.json +197 -41
- package/src/commands/native/order/order/list/command.js +9 -6
- package/src/commands/native/order/order/list/schema.json +140 -10
- package/src/commands/native/order/order/scan/command.js +8 -5
- package/src/commands/native/order/order/scan/scan.js +1 -1
- package/src/commands/native/order/order/scan/schema.json +135 -8
- package/src/commands/native/order/shared/query.js +57 -9
- package/src/commands/native/order/shared/search.js +1 -1
- package/src/commands/native/org/commands.index.json +4 -4
- package/src/commands/native/valuecard/commands.index.json +20 -2
- package/src/commands/native/valuecard/domain.json +1 -1
- package/src/commands/native/valuecard/transaction/list/command.js +110 -0
- package/src/commands/native/valuecard/transaction/list/projection.js +71 -0
- package/src/commands/native/valuecard/transaction/list/schema.json +888 -0
- package/src/commands/native/valuecard/transaction/scan/command.js +130 -0
- package/src/commands/native/valuecard/transaction/scan/projection.js +58 -0
- package/src/commands/native/valuecard/transaction/scan/scan.js +70 -0
- package/src/commands/native/valuecard/transaction/scan/schema.json +954 -0
- package/src/commands/system/shop-contracts.js +35 -4
- package/src/execution/error-details.js +13 -18
- package/src/execution/gateway-guidance.js +43 -0
- package/src/execution/shop-query.js +6 -3
- package/src/identity/shop-location.js +18 -13
- package/src/identity/unit-membership.js +42 -0
- package/src/transport/api.js +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 6,
|
|
3
|
-
"businessCommandCount":
|
|
3
|
+
"businessCommandCount": 61,
|
|
4
4
|
"domains": [
|
|
5
5
|
{
|
|
6
6
|
"name": "access",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"indexFile": "access/commands.index.json",
|
|
11
11
|
"commandCount": 2,
|
|
12
12
|
"indexSize": 652,
|
|
13
|
-
"indexSha256": "
|
|
13
|
+
"indexSha256": "0021c5c1d4c6d7fdab26a07e79554f35ee8240a0f8691392d0c2fad252f65334"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
"name": "aftersale",
|
|
@@ -96,21 +96,21 @@
|
|
|
96
96
|
"name": "order",
|
|
97
97
|
"description": "订单:交易订单、商品行与售后履约摘要",
|
|
98
98
|
"skill": "zan-saas-order",
|
|
99
|
-
"fingerprint": "
|
|
99
|
+
"fingerprint": "6ecb777d56afd57f2bebd0a2ce76c8da81921d8b4e34635cde767a152efdb35b",
|
|
100
100
|
"indexFile": "order/commands.index.json",
|
|
101
101
|
"commandCount": 3,
|
|
102
102
|
"indexSize": 918,
|
|
103
|
-
"indexSha256": "
|
|
103
|
+
"indexSha256": "c179adeefb4b6dd8d14794bd5a5bd7aec7ac68001daf6221d06bd170f956388b"
|
|
104
104
|
},
|
|
105
105
|
{
|
|
106
106
|
"name": "org",
|
|
107
107
|
"description": "组织:组织资料、员工与角色关联",
|
|
108
108
|
"skill": "zan-saas-org",
|
|
109
|
-
"fingerprint": "
|
|
109
|
+
"fingerprint": "9dd00cde0a08ee2f4632f4f3f89a29b8bc9fe9f962cf1c7a86ff1159ab352503",
|
|
110
110
|
"indexFile": "org/commands.index.json",
|
|
111
111
|
"commandCount": 4,
|
|
112
112
|
"indexSize": 1185,
|
|
113
|
-
"indexSha256": "
|
|
113
|
+
"indexSha256": "e0ecd80d3a8eb49cab3d0a940a69f26413a189c49fdbf46deca54387890ef581"
|
|
114
114
|
},
|
|
115
115
|
{
|
|
116
116
|
"name": "points",
|
|
@@ -144,13 +144,13 @@
|
|
|
144
144
|
},
|
|
145
145
|
{
|
|
146
146
|
"name": "valuecard",
|
|
147
|
-
"description": "
|
|
147
|
+
"description": "储值卡:余额卡与礼品卡的资产、余额、单页流水及有界精确查找",
|
|
148
148
|
"skill": "zan-saas-valuecard",
|
|
149
|
-
"fingerprint": "
|
|
149
|
+
"fingerprint": "f2e3dbd0efeb343ab32bfa3e290348e5b9ddbfa5f6aaa9ddbbf945b04cdfb96d",
|
|
150
150
|
"indexFile": "valuecard/commands.index.json",
|
|
151
|
-
"commandCount":
|
|
152
|
-
"indexSize":
|
|
153
|
-
"indexSha256": "
|
|
151
|
+
"commandCount": 4,
|
|
152
|
+
"indexSize": 1256,
|
|
153
|
+
"indexSha256": "4bbce743893a7f62962874b73a7cf21c6a7427f805fd30b6332c587d3790a338"
|
|
154
154
|
}
|
|
155
155
|
],
|
|
156
156
|
"skills": [
|
|
@@ -175,10 +175,11 @@
|
|
|
175
175
|
"files": [
|
|
176
176
|
"SKILL.md",
|
|
177
177
|
"references/authentication.md",
|
|
178
|
+
"references/gateway-errors.md",
|
|
178
179
|
"references/shop-context.md",
|
|
179
180
|
"references/value-processing.md"
|
|
180
181
|
],
|
|
181
|
-
"fingerprint": "
|
|
182
|
+
"fingerprint": "f9f150a5ff6aa79f574d96a783079ec3adf2bec720ed83d9610aea187edc4421"
|
|
182
183
|
},
|
|
183
184
|
{
|
|
184
185
|
"name": "zan-saas-access",
|
|
@@ -339,11 +340,12 @@
|
|
|
339
340
|
],
|
|
340
341
|
"files": [
|
|
341
342
|
"SKILL.md",
|
|
343
|
+
"references/branch-counts.md",
|
|
342
344
|
"references/order-get.md",
|
|
343
345
|
"references/order-list.md",
|
|
344
346
|
"references/order-scan.md"
|
|
345
347
|
],
|
|
346
|
-
"fingerprint": "
|
|
348
|
+
"fingerprint": "69d818a88dfb42f41163b976d6883631a26d17420d02dd06c977d7443fedde86"
|
|
347
349
|
},
|
|
348
350
|
{
|
|
349
351
|
"name": "zan-saas-org",
|
|
@@ -360,7 +362,7 @@
|
|
|
360
362
|
"references/unit-get.md",
|
|
361
363
|
"references/unit-list.md"
|
|
362
364
|
],
|
|
363
|
-
"fingerprint": "
|
|
365
|
+
"fingerprint": "769823815bbef49928da82b8f18d9379db2b6ca59230c5f8af2c1aad81559b5e"
|
|
364
366
|
},
|
|
365
367
|
{
|
|
366
368
|
"name": "zan-saas-points",
|
|
@@ -410,16 +412,18 @@
|
|
|
410
412
|
"name": "zan-saas-valuecard",
|
|
411
413
|
"type": "domain",
|
|
412
414
|
"domain": "valuecard",
|
|
413
|
-
"description": "
|
|
415
|
+
"description": "储值卡:余额卡与礼品卡的资产、余额、单页流水及有界精确查找",
|
|
414
416
|
"dependsOn": [
|
|
415
417
|
"zan-saas-shared"
|
|
416
418
|
],
|
|
417
419
|
"files": [
|
|
418
420
|
"SKILL.md",
|
|
419
421
|
"references/card-get.md",
|
|
420
|
-
"references/card-list.md"
|
|
422
|
+
"references/card-list.md",
|
|
423
|
+
"references/transaction-list.md",
|
|
424
|
+
"references/transaction-scan.md"
|
|
421
425
|
],
|
|
422
|
-
"fingerprint": "
|
|
426
|
+
"fingerprint": "46c7896371f3ea67352159502a4424d6d36584cce93d6cedfa2a6fde372e22c7"
|
|
423
427
|
}
|
|
424
428
|
]
|
|
425
429
|
}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@youzan-cloud/zan-saas-cli",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.8",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@youzan-cloud/zan-saas-cli",
|
|
9
|
-
"version": "0.1.0-beta.
|
|
9
|
+
"version": "0.1.0-beta.8",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"ajv": "8.20.0",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: zan-saas-order
|
|
3
|
-
description:
|
|
3
|
+
description: 读取交易订单、总部代查明确分店或有界分批统计分店订单数量时使用。区分交易明细、支付事实与退款到账,不提供退款或发货操作。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# 订单 order
|
|
@@ -27,6 +27,7 @@ description: 读取已知交易订单、按明确筛选查询一页订单或在
|
|
|
27
27
|
| --- | --- |
|
|
28
28
|
| 已知订单号,核对订单状态、商品行及应付/实付 | `zan-saas order order get`;需要选择关联资料时读 [单笔订单](references/order-get.md)。 |
|
|
29
29
|
| 按明确筛选读取一页交易订单 | `zan-saas order order list`;Agent 根据查看目标选择模块,不自动翻页。需要组合筛选或继续读取时读 [单页订单列表](references/order-list.md)。 |
|
|
30
|
+
| 总部代查明确分店或统计多个分店订单数量 | 仍组合已有 `get/list/scan`,无跨店汇总命令。先按下节确定本批范围,再读 [分店分批计数](references/branch-counts.md)。 |
|
|
30
31
|
| 在显式创建或支付时间和预算内跨页读取 | `zan-saas order order scan`,两轴二选一,返回订单与同轴停止位置,不承诺无遗漏。先读 [预算内订单扫描](references/order-scan.md)。 |
|
|
31
32
|
| 同时查看订单可观察的售后、交付或其他有限资料 | 同一命令用 `--include` 追加所需模块,不追加关联请求。先读所选命令的 reference 与契约。 |
|
|
32
33
|
| 查看已知订单收货资料的明文 | 详情仅支持显式选择字段;先读 [单笔订单](references/order-get.md) 和同版契约。当前员工字段授权及审计服务尚未接通,实际解密会停止,不能改用列表、导出或 Raw API 绕过。 |
|
|
@@ -35,6 +36,16 @@ description: 读取已知交易订单、按明确筛选查询一页订单或在
|
|
|
35
36
|
|
|
36
37
|
缺少订单号或明确列表筛选时先向调用方取得定位信息,不自行遍历店铺。参数以叶子 help 和对应 schema 为准;发现到领域不等于具备所有订单操作。
|
|
37
38
|
|
|
39
|
+
## 总部与分店范围
|
|
40
|
+
|
|
41
|
+
省略 `--kdt-id` 使用当前 `context.shopId`;当前是总部时只查总部本身,不含分店。用户没指定其他范围时直接查询,并在回答中说明“只统计总部本身,不包含分店”,无需重复确认。用户明确指定分店时由 Agent 根据名称及同连锁目录定位,再在原总部上下文显式传入目标;这些订单读取不会保存新位置。非总部不能直接跨店,也不扩大详情解密权限。
|
|
42
|
+
|
|
43
|
+
用户要求“所有门店”时先确定实体门店候选,不先用总部结果当连锁合计。每轮整个任务最多查询5家不同分店,默认串行;拆子调用、并行或自动开启下一批都不能绕过。目录发现使用 `org unit list`,每页最多50条、每轮最多2页,发现超过5家目标即可停止。筛选组2同时包含门店和网店,实体门店按返回角色2001选择,不将网店2002或总部混入;未读完或角色不明时说明范围未知。
|
|
44
|
+
|
|
45
|
+
已明确本批不超过5家,直接执行,不再确认。只说“所有门店”时,只有相关目录已读完且目标不超过5家,才直接查这一小批;已发现超过5家则先展示候选,让用户选择本批最多5家或收窄范围,不自动取前5家。未读完且仅发现不超过5家也只展示已发现候选及覆盖限制,等待明确本批选择,不冒充全部门店数。名称到ID由Agent映射,不要求商家抄ID。
|
|
46
|
+
|
|
47
|
+
只问数量时,每店用同一时间及状态筛选的 `order order list`,第一页、`--page-size 1`、不追加模块,只取可靠的 `data.pagination.total`。不扫描累加本页条数,不扩展金额。失败、总数缺失保持未知,只有明确返回0记零。报告本批小计、累计已查小计、已知剩余及未知范围;本批不自动进入下一批。后续等待用户明确继续或选择,保持同一截止时间和店铺去重状态。不同采集时点不声称共同快照;只有目标目录及所有批次完整覆盖且计数口径可相加时才给全范围合计。详见 [分店分批计数](references/branch-counts.md) 的停止、失败和记录规则。
|
|
48
|
+
|
|
38
49
|
## 范围与停止
|
|
39
50
|
|
|
40
51
|
必须明确目标店铺并满足所选契约的同店约束,总部位置不自动授权读取分店。跨到履约域时重新核对目标命令的标识、上下文和支持范围,不能把订单查询成功当成关联查询授权。失败按同版错误停止,不遍历组织或自动换 token。
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# 总部代查与分店分批计数
|
|
2
|
+
|
|
3
|
+
用于明确分店目标、所有实体门店数量及用户选择下一批的场景。先遵守订单正文的5店、2页上限;它是Agent跨调用流程约束,不是CLI跨进程硬限流。没有 `order +summary` 或 `--scope stores`。
|
|
4
|
+
|
|
5
|
+
## 固定本轮范围
|
|
6
|
+
|
|
7
|
+
保留已核实的总部、操作者和环境,不改持久位置。记录用户原始目标、创建或支付时间轴、起止时间、状态等同一筛选;相对时间先转换为明确北京时间截止点。后续批次不把“现在”重新计算为更晚的截止点。
|
|
8
|
+
|
|
9
|
+
目标由Agent从同连锁目录将名称映射到ID;同名或归属有歧义时提供可读名称及所属关系让用户选择。总部显式分店订单读取会自行验证总部、成员及分店基础绑定;不要将普通JSON或历史缓存当成员授权证明。无法核实的目标保持未知,不切店、不换身份或自动重试。
|
|
10
|
+
|
|
11
|
+
## 发现与选择
|
|
12
|
+
|
|
13
|
+
通过当前总部的 `org unit list --org-roles 2 --page-no 1 --page-size 50` 开始,仅在需要时读第二页,每轮最多2页。组2同时含门店及网店,按 `data.units[].orgRole` 的同版契约区分,实体门店为2001,网店为2002。不要把目录 `pagination.total` 当实体门店数量,也不要用短页或空页单独证明目录读完。以分页完整性、已返回角色及既定目标共同判断覆盖。
|
|
14
|
+
|
|
15
|
+
- 明确选择了3家或5家本批门店,直接串行查询,不重复确认。必要定位仍计入本轮目录发现预算。
|
|
16
|
+
- 用户仅要求所有门店,目录完整且仅1家或5家实体门店,可直接查询,保留目录完整性的依据。
|
|
17
|
+
- 发现6家或50家实体门店,立即列出已发现候选,等待用户选最多5家。此时不发订单请求,不自动选前5家,不为列齐全部候选继续翻页。
|
|
18
|
+
- 已读2页仍有后页,说明只是已发现候选,完整范围未知。即使只发现5家实体门店也不称全部,等待明确本批选择。
|
|
19
|
+
- 返回角色不明、目录分页矛盾或无可靠覆盖依据,说明限制并停止受影响步骤,不推测实体门店数。
|
|
20
|
+
|
|
21
|
+
总部自身与网店不自动加入实体门店统计。用户明确要包含这些范围时分别标明,只有各目标查询的范围及计数口径能相加时才合计,不将总部结果再加进分店小计造成重复。
|
|
22
|
+
|
|
23
|
+
## 查询与本地汇总
|
|
24
|
+
|
|
25
|
+
对本批去重后的目标逐店执行一条列表调用,例如:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
zan-saas order order list --kdt-id <Agent映射的目标> --created-at "2026-11-01 00:00:00..2026-11-02 00:00:00" --page-no 1 --page-size 1
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
示例时间不是默认值。实际使用用户确认的时间和状态筛选。不要自动加 `--include items,payment,buyer`,不要逐单详情、扫描、解密或金额扩展。命令自身的成员分页核验是安全前置,不是Agent继续枚举候选的授权。
|
|
32
|
+
|
|
33
|
+
检查退出码及同版输出,只把成功返回的非负安全整数 `data.pagination.total` 作为匹配数。本页数组长度、`returned`、未知总数和失败不是0。总数缺失时该店记“未知”,不得扫描补算。成功明确返回0时记“0”。
|
|
34
|
+
|
|
35
|
+
保留每店的本轮记录,包括总部、目标ID及名称、筛选、采集时点、计数或未知原因、是否发出请求。同一筛选下每店仅计一次,不用下一批重复累加已查店铺;用户明确要求重新采集时替换该店观测,不叠加。
|
|
36
|
+
|
|
37
|
+
单店失败保留该店未知及安全阶段信息,其他已知结果仍可报告。共同身份失效、总部核验失败等全局前置失败时停止剩余依赖调用,不逐店重复触发相同失败。无自动重试、自动下一批或凭证回退。
|
|
38
|
+
|
|
39
|
+
## 输出及停止
|
|
40
|
+
|
|
41
|
+
列出本批已查门店、每店已知值或未知原因、本批已知小计、累计已查小计、已知剩余和未知范围。全部失败时小计写“无可靠计数”,不写0;部分失败时明确小计仅含成功且有可靠总数的店铺。目录未完整时不提供完整门店总数;计数口径可加性未核实时只列各店值,不宣称连锁订单总量。
|
|
42
|
+
|
|
43
|
+
本批结束立即停止,等待用户明确“继续”或选择下一批。已明确完整候选的剩余小批不超过5家时,“继续”可视为选择该剩余批;剩余超过5家或目录未知时仍先选择/收窄本批,不自动取前5家。保持原截止点与去重记录,不同采集时点不是共同服务端快照。
|
|
44
|
+
|
|
45
|
+
只有目标目录完整、所有目标的各批全部有可靠计数、无重复目标且范围口径可相加,才给全范围合计。否则使用“本批已知小计”或“累计已查小计”,不能把缺店、失败店及未知店补零。
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# 单笔交易订单的选择与结果边界
|
|
2
2
|
|
|
3
|
+
总部普通读取可在原总部上下文显式指定同连锁分店,目录与基础绑定核验失败时不读取订单,也不保存位置。该能力不开放跨店解密;解密仍遵守既有同店、字段授权和审计限制。
|
|
4
|
+
|
|
3
5
|
默认订单可含订单级支付时间 `paidAt` 和原始支付标记 `isPaid`,二者独立,不从状态、金额或彼此推算。缺失表示未取得,不补false,不回退创建时间。订单级支付时间不是首笔或最后一笔资金事件;整单 `realPayment` 也不是扣退款净额或商家到账。
|
|
4
6
|
|
|
5
7
|
已知目标店铺和交易订单号、需要核对交易状态或成交商品时,选择 `zan-saas order order get`。缺少定位信息时先取得订单号,不自行搜索或遍历店铺。执行前读取叶子 help 和 `zan-saas schema order.order.get`,确认参数、默认计价币种、所需模块和授权前置;不要把默认计价口径当作逐订单币种或跨币种结算证明。
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# 单页交易订单列表
|
|
2
2
|
|
|
3
|
+
总部省略目标仍只查总部本身。明确分店时可在原总部上下文显式指定同连锁目标,命令先核实目录成员与分店绑定,不保存位置。多个分店数量使用 [分店分批计数](branch-counts.md),不把一页条数或缺失总数当匹配总数。
|
|
4
|
+
|
|
3
5
|
默认订单可含订单级支付时间 `paidAt` 和原始标记 `isPaid`,缺失表示未取得,false原样保留,不从状态或金额推算。列表 `payment` 不含详情 `realPayment`,不逐单补详情,不能用于求实付或扣退款净额;订单级支付时间不是逐笔资金事件。
|
|
4
6
|
|
|
5
7
|
用户要按明确筛选浏览一页订单时,使用 `zan-saas order order list`。先读 `zan-saas schema order.order.list`,核对支持的筛选组合、时间轴、分页窗口及所需模块。
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# 预算内交易订单扫描
|
|
2
2
|
|
|
3
|
+
总部显式分店扫描先核实总部、目录成员和分店基础绑定,所有前置共享请求及字节预算,查询不保存位置。前置尚未完成即耗尽预算时失败,不把空结果记为零。只统计多个分店数量应使用 [分店分批计数](branch-counts.md),不要用扫描条数代替可靠总数。
|
|
4
|
+
|
|
3
5
|
用户明确要求在创建或支付时间范围内跨页读取时,使用 `zan-saas order order scan`。先读 `zan-saas schema order.order.scan`,核对所选窗口、筛选、请求及结果预算。只查一页使用 `zan-saas order order list`,已知单号使用 `zan-saas order order get`。
|
|
4
6
|
|
|
5
7
|
## 范围与预算
|
|
@@ -17,6 +17,8 @@ description: 查询当前组织资料、总部下级组织、微商城单店员
|
|
|
17
17
|
|
|
18
18
|
组织角色描述组织在体系中的身份,员工角色关联描述授角事实,角色定义目录描述有哪些角色,员工权限点描述本次可读权限。四者分别判断,角色名称不能推算权限或可授予性;业务线也不证明店铺类型。
|
|
19
19
|
|
|
20
|
+
目录筛选组2同时含门店与网店,实体门店按返回角色2001选择,网店为2002;目录总数不是实体门店数。为“所有门店订单数量”发现候选时,每轮最多2页、每页最多50条,发现超过5家目标即停止并展示候选,未读完明确范围未知。订单查询批次、计数和失败汇总统一转交 `zan-saas skills read zan-saas-order`,本域不重复维护订单计算规则。
|
|
21
|
+
|
|
20
22
|
商家在连锁内说的“店铺”通常指组织单元,先核对所属连锁和组织角色。账号层店铺入口由公共 `shop list` 发现,本域读取组织事实;当前位置由公共选店机制管理。需要内部切换、临时查询其他组织,或在分店浏览同连锁下级候选时,读取 `zan-saas skills read zan-saas-shared references/shop-context.md`。
|
|
21
23
|
|
|
22
24
|
组织详情仍固定当前任务上下文;不能把下级 ID 直接代入原上下文的详情参数。准备其他组织的任务上下文后,所选叶子的产品、位置和权限限制仍适用。能够切到分店不扩大微商城单店员工入口的支持范围。
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
|
|
11
11
|
根据返回的分页信息决定是否读取下一页。短页或空页不能单独证明全局无记录;跨页没有快照保证。继续读取须由用户目标决定,并限定页数或结果预算,不自动遍历。
|
|
12
12
|
|
|
13
|
+
为订单分批统计发现候选时遵守订单域预算,每轮最多2页、每页最多50条;超过5家目标即可停止。筛选组2并非仅实体门店,返回2001为门店、2002为网店。目录未读完时只展示已发现候选,不宣称完整门店数;实际订单选择与计算转交订单域。
|
|
14
|
+
|
|
13
15
|
部门关联只表示本次摘要返回的关系,不能据此构建完整部门树。网店营业、门店营业和门店状态独立表达,不能合成统一启停状态,也不能当作组织详情的运营状态。生命周期未返回不能推断永久有效。
|
|
14
16
|
|
|
15
17
|
查询失败时保留原目标、筛选与扩展选择,先核查失败原因;不通过删除失败模块、换店或自动重试取得部分列表。本地预览不证明总部授权、员工权限或对象存在。
|
|
@@ -13,6 +13,8 @@ description: zan-saas 跨领域公共使用规则。首次调用或 CLI 版本
|
|
|
13
13
|
|
|
14
14
|
网关返回 `4204` 时表示本次请求没有操作权限;应检查当前账号的店铺权限及店铺应用的接口开放能力授权。仅凭 `4204` 不能确定是哪一项缺失,可将错误中的接口、店铺和 `trace_id` 提供给管理员排查;不要自动申请授权或换店重试。
|
|
15
15
|
|
|
16
|
+
业务错误诊断明确包含 `gatewayCode`,且遇到限流 `4101`、凭证 `4201/4202/4203`、客户标识 `4009` 或上游异常 `5001/5002` 时,读取 `zan-saas skills read zan-saas-shared references/gateway-errors.md`。按 `message`、`nextStep` 及已声明的 `recovery` 停止并排查,不自动重放。顶层同号 `businessCode` 不适用网关码指导;协议冲突、HTTP 鉴权拒绝及请求结果未知优先按实际诊断处理。
|
|
17
|
+
|
|
16
18
|
需要登录时使用 `zan-saas auth login`,本地查看已存凭证状态使用 `zan-saas auth status`;用户要求退出时使用 `zan-saas auth logout`。先读取相应 help/schema,登录需要用户在浏览器中完成授权,退出尝试撤销当前授权服务下的个人会话并清理本机凭证。
|
|
17
19
|
|
|
18
20
|
认证统一由公共入口与传输层处理,领域命令不选择凭证或决定登录、续期策略。普通使用通过 `zan-saas auth login` 保存个人登录,后续默认优先使用该个人凭证并按需续期;环境中存在 `ZAN_SAAS_USER_ACCESS_TOKEN` 不会覆盖已保存的个人登录。没有个人登录记录时才使用环境 token;受控调用明确要求环境身份时配置 `ZAN_SAAS_AUTH_SOURCE=env`。个人登录失效或续期被拒绝时重新登录,不自动切换环境身份。同一次命令从首个实际请求开始固定调用环境、凭证及来源;参数拒绝、发现及预览不会触发认证。
|
|
@@ -40,6 +42,8 @@ description: zan-saas 跨领域公共使用规则。首次调用或 CLI 版本
|
|
|
40
42
|
|
|
41
43
|
## 预览、请求与结果
|
|
42
44
|
|
|
45
|
+
省略 `--kdt-id` 默认本次有效 `context.shopId`,总部默认只查总部本身,不包含分店。查询另一分店不等于保存新位置。支持总部显式目标的订单 `get/list/scan` 可在原总部上下文核验后读取;其他领域不可据此类推。需要临时上下文或切换时读取 [会话位置](references/shop-context.md)。跨店订单计数转订单域的分批规则,不自行遍历所有门店。
|
|
46
|
+
|
|
43
47
|
`--help`、`schema`、`skills list/read` 和 `doctor` 是本地发现或诊断入口。`doctor` 不探测认证和远端业务,不以其成功报告店铺能力可用。
|
|
44
48
|
|
|
45
49
|
本地指引读取因参数写法出错时,可以按帮助或错误提示修正后重新读取。例如 `skills read <skill> [file]` 的 Skill 名称和文件路径须分开传入,不能用同一对引号包住。该修正只用于本地读取,不授权重试业务请求。入口读取失败、指引未发布、文件不存在或版本无法确认时,说明缺口并停止,不猜路径或改用其他能力。
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# 业务网关错误排查
|
|
2
|
+
|
|
3
|
+
仅当本次业务命令的安全诊断明确包含 `gatewayCode` 时,才按下表处理。顶层 `businessCode` 即使同号也不能套用,不从自由错误文本猜测码或根因。账号网关、OAuth 登录和续期错误按 [公共认证与会话](authentication.md) 排查,不套用本表。
|
|
4
|
+
|
|
5
|
+
先停止本轮后续业务请求,保留原目标范围。只使用本版 `message`、`details.category/stage/requestState`、`nextStep` 及已声明的 `recovery`;旧诊断不一定提供 recovery。协议冲突、输入或上下文错误、叶子声明的响应原因优先。HTTP 明确为鉴权或权限拒绝时,不按矛盾的限流或上游异常码推断恢复;请求结果为 unknown 时不能认为未执行。不把失败或未知状态解释为空成功。
|
|
6
|
+
|
|
7
|
+
| 网关码 | 下一步 |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| `4101` | 请求过于频繁或受限。停止本轮后续请求,核对频率、并发与可用配额。降低频率后由调用方重新决定是否发起;没有固定等待时长、恢复时间或配额承诺。持续出现时提交实际保留的安全诊断。 |
|
|
10
|
+
| `4201` | 请求凭证无效。先区分凭证来源与目标店铺、应用授权范围,核对凭证值和授权。不能仅凭此码断定密码、员工权限或某一项授权失效。 |
|
|
11
|
+
| `4202` | 请求凭证过期。个人登录按公共认证流程重新登录授权;显式环境身份由凭证提供方更新。不要自动切换来源或在业务失败后刷新并重放。 |
|
|
12
|
+
| `4203` | 请求凭证不存在。按当前来源补齐有效认证并核查受控配置。不要在聊天中索取或提交 token。 |
|
|
13
|
+
| `4204` | 同时核查当前账号的店铺权限和店铺应用的接口开放能力授权;持续拒绝时由管理员核查服务端限制。错误码不能单独确定根因,不自动申请授权、换身份或切店。 |
|
|
14
|
+
| `4009` | 客户 open_id 无法解析。核对本命令契约中的客户标识、标识类型和目标店铺;只有 help/schema 实际暴露 `--yz-open-id` 时才使用该选项。它不是登录凭证问题,也不能证明客户在所有店铺均不存在。 |
|
|
15
|
+
| `5001` / `5002` | 上游系统或业务异常,本次失败。先核对同版参数契约;参数符合且持续失败时提交安全接口、错误码和实际取得的追踪号。不要承诺稍后一定成功或修改某个参数必然修复。 |
|
|
16
|
+
|
|
17
|
+
`4008`、`4010`、`5003` 和未知码仍按本次通用诊断处理。这里没有新增错误码查询命令或自动恢复机制。
|
|
18
|
+
|
|
19
|
+
## 核对凭证来源
|
|
20
|
+
|
|
21
|
+
普通使用优先采用 `zan-saas auth login` 保存的个人登录;没有个人登录记录时才使用 `ZAN_SAAS_USER_ACCESS_TOKEN`,受控环境显式要求环境身份时配置 `ZAN_SAAS_AUTH_SOURCE=env`。环境 token 不覆盖已有个人登录,个人登录失败也不自动回退到环境身份。不要为了绕过本次拒绝更改凭证来源。
|
|
22
|
+
|
|
23
|
+
`zan-saas auth status --format json` 仅查看本地保存状态,不能验证环境 token 有效性、目标店铺匹配或业务权限。需要重新登录时,先读 `zan-saas auth login --help` 或 `zan-saas schema auth.login`,再按公共授权流程执行;环境身份由提供方更新配置。个人会话与开放平台应用 access_token 不作相同有效期承诺,不把固定七天或刷新后一小时当成本 CLI 会话规则。
|
|
24
|
+
|
|
25
|
+
## 保留安全诊断后停止
|
|
26
|
+
|
|
27
|
+
用 `zan-saas schema <完整命令路径>` 或该命令 `--help` 核对同版输入与错误契约。提交诊断中实际保留的 `api`、`gatewayCode`、`businessCode`、HTTP 状态和经过校验的 `trace_id/request_id`;没有追踪号时不补造。不要提交 token、Authorization、请求 body、客户标识、私人数据或自由上游消息。
|
|
28
|
+
|
|
29
|
+
以上都是下一步指导,不自动登录、刷新、初始化应用、换店、换身份或等待重试,不自动重放。预请求正常续期仍由公共认证处理,同一命令的身份从首次实际请求开始冻结。重新认证或修正配置成功不代表原业务请求已经重试或成功;是否重新发起由调用方结合原请求状态明确决定。
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
账号下的独立店铺或连锁入口用 `shop list` 发现,切换到该入口用 `shop use`。连锁内部店铺按组织领域指引及 `org unit list` 发现;同连锁持久切换用 `shop unit use`,回总部使用已核实的根 ID。名字唯一还需所属关系与相关分页明确。
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
只有商家明确要求后续默认切换时才保存位置。用户说“查一下另一家店”时不保存:支持总部显式目标的订单普通 `get/list/scan` 在原总部上下文使用显式目标,其他命令需要临时上下文时先用 `shop resolve`。分别核对叶子契约,不把订单能力推广到所有领域。只要求本会话改变时,切换使用 `--session-only`。持久切换成功后用 `shop current` 核对实际生效位置。
|
|
18
18
|
|
|
19
19
|
同名或跨层有歧义时,用完整名称和所属关系询问,例如“你指的是 A 连锁下的杭州分店,还是独立店铺杭州店?”不询问“租户还是组织单元”,也不要求输入根组织 ID。
|
|
20
20
|
|
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
|
|
23
23
|
`shop resolve <目标ID>` 解析账号层根。解析连锁内部目标时附 `--root-kdt-id <所属根ID>`。返回的 context 只用于本次任务;它不改变当前位置或最近位置。
|
|
24
24
|
|
|
25
|
+
内部定位核实总部及其有界下级目录、按目录角色构造临时context,不依赖分店应用可用,也不初始化分店应用。定位成功不证明实际分店业务或员工权限可用,实际业务阶段仍会绑定分店并核查授权。完整目录未命中、分页未读完、字段异常与接口拒绝分别处理,失败不保存位置。
|
|
26
|
+
|
|
25
27
|
宿主把返回的四字段 context 作为每次业务调用的 `ZAN_SAAS_CONTEXT` 或程序注入值,并持续传原会话 ID。多命令任务每一步使用同一快照,不重新读取最近位置。任务结束后丢弃,无需切回原店。快照不包含 token,实际权限仍由服务端核验。
|
|
26
28
|
|
|
27
29
|
当前在分店而要浏览同连锁候选时,先 resolve 已核实的根,使用临时总部上下文执行 `org unit list`,按页读取;当前会话仍为原分店。每条业务命令仍须满足自己的位置、产品和同店限制,不能直接用目标参数绕过。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: zan-saas-valuecard
|
|
3
|
-
description:
|
|
3
|
+
description: 储值卡领域指引。查询余额卡、礼品卡的资产状态、本金和赠送金余额,浏览一页储值流水或按原始标识跨页精确查找时使用;不与会员权益卡、积分或成长值混用。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# 储值卡 valuecard
|
|
@@ -13,6 +13,8 @@ description: 储值卡领域指引。查询余额卡、礼品卡的资产状态
|
|
|
13
13
|
|
|
14
14
|
系统卡号、卡面号、兑换码、模板号和客户标识不能互换。本金和赠送金是卡余额的组成,不等于冻结、可退金额或客户资产汇总;卡状态不能单独证明某订单可以支付。
|
|
15
15
|
|
|
16
|
+
资源 `transaction` 表达店铺范围内按业务类型和业务时间读取的储值交易记录,不是当前卡资产、客户档案、充值单、支付单或退款单。流水记载的 `billCardNo` 不保证等于资产的 `cardNo`,不能拿它直接调用单卡查询;手机号不等于客户 `yzOpenId`,不通过当前持卡或手机号推断历史身份。流水交易单号 `tradeNo` 与外部支付请求号 `externalRequestNo` 分开。记录金额不代表统一余额增量,记录余额也不保证是交易前或交易后余额。
|
|
17
|
+
|
|
16
18
|
例如,假设客户甲在同一模板下有两张卡,应保留两个实例及各自余额,不能按模板合并,也不能把其中一页相加后宣称客户总余额。
|
|
17
19
|
|
|
18
20
|
权益卡的定义、持有与发放转交 `zan-saas skills read zan-saas-benefit`;客户档案转交 `zan-saas skills read zan-saas-customer`。储值资产不代替会员身份、积分或成长值。
|
|
@@ -23,10 +25,14 @@ description: 储值卡领域指引。查询余额卡、礼品卡的资产状态
|
|
|
23
25
|
| --- | --- |
|
|
24
26
|
| 已知完整系统卡号,查看这一张卡的状态和余额 | `zan-saas valuecard card get`;需要判断卡号、模板关联或未找到结果时读 [单卡查询](references/card-get.md)。 |
|
|
25
27
|
| 已知客户,查看选定状态下的一页持卡 | `zan-saas valuecard card list`;需要判断状态覆盖、空页或能否继续读取时读 [客户持卡范围](references/card-list.md)。 |
|
|
28
|
+
| 已知店铺、单个业务类型和业务发生时间,查看一页储值流水 | `zan-saas valuecard transaction list`;需要解释记录金额、关联单号或分页范围时读 [流水查询边界](references/transaction-list.md)。 |
|
|
29
|
+
| 已知流水原始手机号、流水卡号、流水号或交易单号,按一种类型和时间跨页查找 | `zan-saas valuecard transaction scan`;先读 [有界流水查找](references/transaction-scan.md),不使用系统卡号或客户 ID 猜匹配条件。 |
|
|
26
30
|
|
|
27
31
|
只知道卡号时选择单卡,不猜客户;只知道客户时选择列表,不枚举卡号。还需要模板关联时按所选契约追加模块,关联存在不证明模板可售或适用某笔订单。
|
|
28
32
|
|
|
29
|
-
|
|
33
|
+
流水 `list` 只浏览一页,`scan` 根据流水原始标识在有限范围内匹配;两者都不能证明某客户的完整交易历史。用户要查看某张卡当前余额时仍选单卡查询,不能用流水记录余额代替。
|
|
34
|
+
|
|
35
|
+
制卡、执行充值、调账或退款、余额汇总、自动余额对账及完整模板查询尚无入口,需要这些能力时说明缺口并停止。按充值或退款业务类型读流水,不代表执行充值或退款,也不证明关联单据的处理状态。
|
|
30
36
|
|
|
31
37
|
## 选定入口后
|
|
32
38
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# 储值流水查询边界
|
|
2
|
+
|
|
3
|
+
需要解释记录金额、关联单号或是否还能继续读取时,先读 `zan-saas schema valuecard.transaction.list`,再按本页判断。
|
|
4
|
+
|
|
5
|
+
## 选对对象
|
|
6
|
+
|
|
7
|
+
`zan-saas valuecard transaction list` 只读取目标店铺、一个业务类型、明确业务发生时间范围内的一页记录。它不按客户、卡号或订单筛选,不提供完整客户历史或自动余额对账。
|
|
8
|
+
|
|
9
|
+
例如,假设用户问“这张卡现在还有多少本金”,应选择 `valuecard card get` 并提供完整系统卡号。若问“本店这段时间的充值流水里本金和赠送金各是多少”,选择流水入口,但一页数据不能解释为该时间内的完整合计。
|
|
10
|
+
|
|
11
|
+
`billCardNo` 仅是流水记载的卡号,不保证与当前卡资产 `cardNo`、卡面号或汇总号相同。储值流水号、交易单号和外部支付请求号各自表示不同关联,不互相替代。手机号和昵称不作为稳定客户身份。
|
|
12
|
+
|
|
13
|
+
## 解释金额和记录
|
|
14
|
+
|
|
15
|
+
本金、赠送金及记录余额默认返回,具体字段与单位读同版 schema。`amount` 保留记录原始符号,不猜统一增减方向。`reportedBalance` 的时点未明确,不据此重建交易前后余额。
|
|
16
|
+
|
|
17
|
+
充值与充值赠送、退款与充值退款分别表达。有效性不是支付或退款处理状态,无效记录仍保留。未知类型或有效性文本只表示服务端返回了该值,不能补造业务含义。
|
|
18
|
+
|
|
19
|
+
## 范围与继续读取
|
|
20
|
+
|
|
21
|
+
按同版 schema 的分页字段判断是否有后页,保持店铺、业务类型、原时间范围和容量。短页或空页不单独证明耗尽;总数未知时也不能把当前页当作完整历史。达到页窗口后缩小时间范围,不自动分片或跨页去重,不承诺稳定排序或快照。
|
|
22
|
+
|
|
23
|
+
支持的产品范围由服务端决定。微商城单店、零售单店、连锁 D 总部及连锁 L 总部高级版在接口范围内;新储值商家可查询全部卡交易,老储值商家仅支持礼品卡交易。位置适用不授予跨店或员工权限,也不证明历史留存完整。
|
|
24
|
+
|
|
25
|
+
请求失败或超限时本次不输出部分流水。核对原店铺、时间、分页和权限后重新构造调用,不切换身份或重复发送未知结果的请求。查询成功不代表关联业务已完成。
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# 有界流水查找
|
|
2
|
+
|
|
3
|
+
用于按一种业务类型、明确的北京时间范围,寻找带原始手机号、流水卡号、流水号或有赞交易单号的储值流水。先读 `zan-saas schema valuecard.transaction.scan`。四种条件至少一个,多条件为 AND,区分大小写,保留前导零与国家码。条件只在本地精确匹配,不是服务端客户筛选。
|
|
4
|
+
|
|
5
|
+
例如,商家要找“某流水卡号在指定时间的消费”,使用 `billCardNo`,不能把当前 `card.cardNo` 或客户 `yzOpenId` 换进去。只知道系统卡号时先说明缺少原始流水标识,不能从客户当前持卡推断其历史流水归属。
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
zan-saas valuecard transaction scan --biz-type pay \
|
|
9
|
+
--occurred-at "2026-11-01 00:00:00..2026-11-11 12:00:00" \
|
|
10
|
+
--bill-card-no bill-card-demo --kdt-id 63077 --dry-run
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
实际调用需有效上下文与同店凭证。预览不读取凭证或联网,全部条件值遮盖。请求按页串行,固定最多 200 条匹配记录、21 次业务请求,包含一次店铺绑定。为完整页预留容量,可能不足 200 条即停止。不提供 `--max-items`、`--max-requests` 或其它调参入口。
|
|
14
|
+
|
|
15
|
+
新储值商家可查全部卡交易,老储值商家仅支持礼品卡流水,不能据此宣称覆盖所有储值资产。
|
|
16
|
+
|
|
17
|
+
读取 `data.transactions` 和 `data.pagination`,不把原始接口总数当成匹配总数。`scannedRecords` 包含未匹配记录。只有 `stopReason=pages_exhausted` 才表示从本次指定起始页之后走到可观察结束,不表示全历史。`max_items`、`max_requests`、`window_limit`、`total_unknown`、`inconsistent_page` 都表示未完成,匹配数组为空不能解释为没有历史。
|
|
18
|
+
|
|
19
|
+
未完成且 `nextPageNo` 非空时,保持同店、业务类型、时间、全部条件和 `pageSize`,用 `--page-no` 继续。它不是稳定游标,数据变化可能重复或遗漏;`nextPageNo=null` 不能单独证明耗尽。窗口满时缩小时间范围重查,总数漂移时建议缩小范围从第一页重查。不自动拆分时间,不存在 dump/resume 或快照保证。
|
|
20
|
+
|
|
21
|
+
结果保留无效记录、重复项及未知非空字典值。六个金额为 CNY 元两位字符串,保留源符号。`amount` 不是统一增减方向,`reportedBalance` 的时点未明确,不能用来推断交易前后余额、可支付余额或自动对账。时间为北京时间固定毫秒文本。`tradeNo` 是有赞交易单号,`externalRequestNo` 是外部支付请求号,不能互换。
|
|
22
|
+
|
|
23
|
+
单响应最多 10 MiB、累计业务响应最多 20 MiB、最终输出含换行最多 5 MiB。后页业务、网络、模型或限额错误会整体失败,不返回前页匹配记录。失败先核查原店铺、条件与授权,不能自动重试、改店、改身份或把失败当成无记录。当前命令不承诺稳定排序;即使本次观察到时间最晚记录,也不能称客户全历史上次充值。
|
package/src/cli/context-help.js
CHANGED
|
@@ -60,7 +60,9 @@ function configureContextHelp(program, state, loadDomain) {
|
|
|
60
60
|
}
|
|
61
61
|
const status = `当前位置:${positionLabels[state.context.orgType]};实际权限由服务端校验。`;
|
|
62
62
|
if (contract) {
|
|
63
|
-
|
|
63
|
+
const scopeHint = state.context.orgType === 'hq' && command.options.some(option => option.long === '--kdt-id')
|
|
64
|
+
? '\n省略 --kdt-id 只查询当前总部本身,不包含分店。显式分店目标是否支持及核验前置,以本命令 help/schema 为准。' : '';
|
|
65
|
+
return `\n${declared}${status}${scopeHint}\n${isAvailable(contract.at, state.context)
|
|
64
66
|
? '此命令适用于当前位置。'
|
|
65
67
|
: `当前组织不可使用此命令,需要${positionLabels[contract.at]}上下文。`}`;
|
|
66
68
|
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"availability": "available",
|
|
10
10
|
"at": "all",
|
|
11
11
|
"module": "access/role/list/command.js",
|
|
12
|
-
"fingerprint": "
|
|
12
|
+
"fingerprint": "9e489554a22cd27edf3fc4c22fcf53dbb820b2f26b030bb558c1df6644c25c75"
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
"path": "access.staff-perms.get",
|
|
@@ -10,19 +10,13 @@ const { readApiEnvelope, assertApiSuccess, object } = require('../../../../../ex
|
|
|
10
10
|
const { failure, bindingPath } = require('../../../../../execution/shop-query');
|
|
11
11
|
const { snapshotApiEnvironment } = require('../../../../../transport/api');
|
|
12
12
|
const schema = require('./schema.json');
|
|
13
|
+
const { organizationPath, organizationBody, maxOrganizationPages,
|
|
14
|
+
verifyMembership } = require('../../../../../identity/unit-membership');
|
|
13
15
|
|
|
14
16
|
const command = 'access.role.list';
|
|
15
|
-
const organizationPath = 'youzan.shop.chain.descendent.organization.list/1.0.1';
|
|
16
|
-
const maxOrganizationPages = 20;
|
|
17
|
-
const pageSize = 50;
|
|
18
17
|
const reject = (category, stage, scope, state, facts) =>
|
|
19
18
|
failure(command, category, stage, scope, state, facts);
|
|
20
19
|
|
|
21
|
-
function organizationBody(pageNo) {
|
|
22
|
-
return { page_num: pageNo, page_size: pageSize, with_dept_info: false,
|
|
23
|
-
with_shop_status_and_lifecycle_end_time: false, with_crm_shop: false };
|
|
24
|
-
}
|
|
25
|
-
|
|
26
20
|
function previewFor(input, context) {
|
|
27
21
|
const crossShop = context && String(input.kdtId) !== context.shopId;
|
|
28
22
|
const requests = [{ stage: 'shop-binding', method: 'POST', path: bindingPath, body: {} }];
|
|
@@ -34,29 +28,6 @@ function previewFor(input, context) {
|
|
|
34
28
|
return { scope: input, requests, maxOrganizationPages };
|
|
35
29
|
}
|
|
36
30
|
|
|
37
|
-
async function verifyMembership(read, input) {
|
|
38
|
-
const seen = new Set();
|
|
39
|
-
let total;
|
|
40
|
-
for (let pageNo = 1; pageNo <= maxOrganizationPages; pageNo += 1) {
|
|
41
|
-
const { data, facts } = await read(organizationPath, organizationBody(pageNo), 'target-membership');
|
|
42
|
-
const invalid = category => reject(category, 'target-membership', input, 'sent', facts);
|
|
43
|
-
if (!object(data) || !Array.isArray(data.organization_list) ||
|
|
44
|
-
data.page_num !== pageNo || data.page_size !== pageSize ||
|
|
45
|
-
!Number.isSafeInteger(data.total) || data.total < 0 ||
|
|
46
|
-
data.organization_list.length !== Math.min(pageSize, Math.max(0, data.total - seen.size)) ||
|
|
47
|
-
(total !== undefined && total !== data.total)) throw invalid('protocol');
|
|
48
|
-
total = data.total;
|
|
49
|
-
for (const unit of data.organization_list) {
|
|
50
|
-
if (!object(unit) || !Number.isSafeInteger(unit.kdt_id) || unit.kdt_id < 1 ||
|
|
51
|
-
!Number.isSafeInteger(unit.role) || unit.role < 0 || unit.role === 9 ||
|
|
52
|
-
seen.has(unit.kdt_id)) throw invalid('protocol');
|
|
53
|
-
seen.add(unit.kdt_id);
|
|
54
|
-
}
|
|
55
|
-
if (seen.has(input.kdtId)) return;
|
|
56
|
-
if (seen.size === total || pageNo === maxOrganizationPages) throw invalid('scope_unresolved');
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
31
|
async function execute(input, context, preview) {
|
|
61
32
|
let env;
|
|
62
33
|
try { env = await snapshotApiEnvironment(undefined, context.shopId); }
|
|
@@ -79,7 +50,8 @@ async function execute(input, context, preview) {
|
|
|
79
50
|
if (context.orgType !== 'hq' || String(binding.data.sid) !== context.hq || binding.data.role !== 1) {
|
|
80
51
|
throw reject('scope_unresolved', 'shop-binding', input, 'sent', binding.facts);
|
|
81
52
|
}
|
|
82
|
-
await verifyMembership(read, input
|
|
53
|
+
await verifyMembership(read, input.kdtId,
|
|
54
|
+
(category, stage, state, facts) => reject(category, stage, input, state, facts));
|
|
83
55
|
}
|
|
84
56
|
const request = preview.requests.at(-1);
|
|
85
57
|
const { data, facts } = await read(request.path, request.body, request.stage);
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"availability": "available",
|
|
10
10
|
"at": "all",
|
|
11
11
|
"module": "order/order/get/command.js",
|
|
12
|
-
"fingerprint": "
|
|
12
|
+
"fingerprint": "8b15ec74ec9af89adb9f82ab504a36d9404ab186ad0d7f7e9159a3668d1a7ee7"
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
"path": "order.order.list",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"availability": "available",
|
|
19
19
|
"at": "all",
|
|
20
20
|
"module": "order/order/list/command.js",
|
|
21
|
-
"fingerprint": "
|
|
21
|
+
"fingerprint": "ea68f35fc0bfe35168751b08ed46247e91a925b244642234770de0f12855907d"
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
"path": "order.order.scan",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"availability": "available",
|
|
28
28
|
"at": "all",
|
|
29
29
|
"module": "order/order/scan/command.js",
|
|
30
|
-
"fingerprint": "
|
|
30
|
+
"fingerprint": "ea25f05e8976c1f2e99e9b7e63fb35757c1b72a1298318dabc428f0ead3886fc"
|
|
31
31
|
}
|
|
32
32
|
]
|
|
33
33
|
}
|
|
@@ -10,7 +10,7 @@ const { readContext } = require('../../../../../identity/context');
|
|
|
10
10
|
const { queryDefinition, validateCommandValue } = require('../../../../../execution/command-schema');
|
|
11
11
|
const { object } = require('../../../../../execution/query-api');
|
|
12
12
|
const { discloseFields, validReason } = require('../../../../../execution/privacy');
|
|
13
|
-
const {
|
|
13
|
+
const { bindingPreview, targetScope, createOrderQuery, reject, serialize } = require('../../shared/query');
|
|
14
14
|
const projection = require('../../shared/projection');
|
|
15
15
|
const schema = require('./schema.json');
|
|
16
16
|
|
|
@@ -43,9 +43,9 @@ function normalizedInput(options, target) {
|
|
|
43
43
|
return input;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
function preview(input) {
|
|
46
|
+
function preview(input, context) {
|
|
47
47
|
const result = { requests: [
|
|
48
|
-
|
|
48
|
+
...bindingPreview(input.scope, context),
|
|
49
49
|
{ method: 'POST', path: schema.api.path, body: { tid: input.scope.orderNo } }
|
|
50
50
|
] };
|
|
51
51
|
if (input.decrypt) result.privacy = {
|
|
@@ -96,12 +96,14 @@ function createCommand({ context, privacyProvider } = {}) {
|
|
|
96
96
|
.option('--reason <text>', '仅解密时必填:1 至 200 个 Unicode 码点,无控制字符或换行,不含个人信息')
|
|
97
97
|
.addOption(new Option('--format <format>', 'json 或 pretty,仅改变缩进')
|
|
98
98
|
.choices(['json', 'pretty']).default('json'))
|
|
99
|
-
.option('--dry-run', '
|
|
99
|
+
.option('--dry-run', '纯本地校验和条件请求计划,不读凭证、不联网')
|
|
100
100
|
.addHelpText('after', `
|
|
101
101
|
固定返回 data.order、items、payment,include 只能追加模块,不能移除基础视图。
|
|
102
102
|
订单号通常为 E/V/C 开头加 23 位数字,仅供核对;不按该格式拒绝输入或响应,不改写订单号。
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
省略 --kdt-id 只查 context.shopId,总部默认只查总部本身,不含分店。非总部目标须等于 context.shopId。
|
|
104
|
+
总部普通读取可显式指定同连锁门店或网店,先核实总部sid及角色、下级目录成员,再绑定分店sid;已返回的总部字段须一致。查询不保存位置。
|
|
105
|
+
同店最多两请求;总部显式分店含总部1次、目录每页50条最多20页、分店绑定1次、详情1次,共最多23次,均计入累计响应预算。
|
|
106
|
+
目录读完未命中与预算内未读完分别拒绝;接口拒绝、字段异常与归属冲突保留实际阶段。不初始化分店应用,不重试;执行需要有效四字段上下文。
|
|
105
107
|
ID 输出十进制字符串,交易行 oid 不是商品 ID。元金额仅无损补齐两位,不再除以 100。
|
|
106
108
|
payment 是整单应付,realPayment 是实付,不扣退款或推导到账;按用户确认默认以 CNY 计价。
|
|
107
109
|
基础 order 可返回支付时间 paidAt 和支付标记 isPaid;缺失不推断,零实付不等于未支付。
|
|
@@ -123,7 +125,10 @@ payment 是整单应付,realPayment 是实付,不扣退款或推导到账;
|
|
|
123
125
|
.action(async options => {
|
|
124
126
|
const state = readContext(context);
|
|
125
127
|
const input = buildInput(options, context);
|
|
126
|
-
|
|
128
|
+
if (input.decrypt && state.status === 'ready' && input.scope.kdtId !== state.context.shopId) {
|
|
129
|
+
throw reject(command, 'permission', 'sensitive-authorization', input.scope);
|
|
130
|
+
}
|
|
131
|
+
const plan = preview(input, state.context);
|
|
127
132
|
let output = plan;
|
|
128
133
|
if (!input.dryRun) {
|
|
129
134
|
if (input.decrypt) {
|
|
@@ -142,8 +147,8 @@ payment 是整单应付,realPayment 是实付,不扣退款或推导到账;
|
|
|
142
147
|
});
|
|
143
148
|
output = disclosedOutput(result, input, state.context, sourceFacts);
|
|
144
149
|
} else {
|
|
145
|
-
const read = await createOrderQuery(input.scope, command, { shopApp: false });
|
|
146
|
-
const request = plan.requests
|
|
150
|
+
const read = await createOrderQuery(input.scope, command, { shopApp: false, context: state.context });
|
|
151
|
+
const request = plan.requests.at(-1);
|
|
147
152
|
const { data, facts } = await read(request.path, request.body);
|
|
148
153
|
output = adapt(data, input, state.context, facts);
|
|
149
154
|
}
|