⚠️ 非官方声明 / Unofficial本项目是个人开发的第三方开源工具,与金蝶国际软件集团有限公司(Kingdee) 没有任何隶属、合作或授权关系。"金蝶"、"金蝶云·星空"、"K/3 Cloud"等 商标归其各自所有者所有。本工具仅通过金蝶公开的 WebAPI 与你自己的星空 系统交互,使用风险自负。
This is an independent, community-developed CLI tool. It is not affiliated with, endorsed by, or sponsored by Kingdee International Software Group. "Kingdee" and "K/3 Cloud" are trademarks of their respective owners. Use at your own risk.
金蝶云·星空(K/3 Cloud)WebAPI 命令行工具,面向财务 / 审计自动化场景: 科目余额(多期间、科目区间、核算维度钻取)、四张财务报表(自带勾稽检查)、 凭证读写(dry-run 优先)、现金流量凭证级明细、应收回款匹配。 为 AI agent 优先设计——stdout 纯数据、stderr 进度提示、JSON/CSV 输出、 写操作默认 dry-run + 显式确认。
金蝶产品线各有各的接口,本工具只适配金蝶云·星空:
| 产品 | 是否适用 | 说明 |
|---|---|---|
| 金蝶云·星空(K/3 Cloud) | ✅ | 走 ValidateUser + ExecuteBillQuery / GetSysReportData 这套 WebAPI;私有部署与公有云均可,填自己的服务器地址即可 |
| 金蝶云·苍穹 / 星瀚 | ❌ | 另一套 API 体系 |
| 金蝶云·星辰 | ❌ | 面向小微,接口不同 |
| 金蝶 K/3 WISE、KIS 系列 | ❌ | 非云架构,无此 WebAPI |
实测环境为 K/3 Cloud 8.x;更早的 7.x 未测过,接口大体兼容但请自行验证
(读类命令都是只读的,先拿 balance 试一条最省事)。
包名 k3c 取自 K/3 Cloud,命令入口 python -m k3c。
文档索引
- skills/k3c-cli-usage/SKILL.md — AI agent 用法指南(命令速查 / 口径 / 写操作机制 / 错误处理)
- docs/ARCHITECTURE.md — 模块依赖、数据流、关键技术决策
- docs/KINGDEE_API_PITFALLS.md — K3Cloud WebAPI 实测坑点集(17+ 条)
- docs/KNOWN_LIMITATIONS.md — 限制清单 + 后续迭代优先级
- config/ — 多租户配置:按账簿配业务规则 / 必填维度 / 摘要配对线索
- 二次开发 — 想接更多金蝶接口从哪下手(官方 API 文档入口 + 本项目扩展方式)
git clone https://github.com/kukubob/k3cloudy-cli.git
cd k3cloudy-cli
python3 -m k3c help主 CLI 纯 Python 标准库实现,零第三方运行时依赖(HTTP 走 urllib), Python 3.10+ 可直接源码运行,无需 pip install。跑测试才需要 pytest。
# 1. 配置你的 K3Cloud 服务器地址与数据中心 ID(也可写入 .env,见 .env.example)
export K3C_SERVER_URL="http://your-k3cloud-server/K3Cloud/"
export K3C_DB_ID="<你的数据中心ID>"
# 2. 登录(首次交互输入:用户名回显、密码隐藏不回显,验证成功后
# 凭据存入 macOS 钥匙串——之后所有命令与 2 小时会话过期自动重登
# 都静默取用,无需 .env)
python -m k3c.cli login
# 3. 查询科目余额(默认走金蝶 UI "科目余额表" 同源接口,--book 必传)
python -m k3c.cli balance --book=DEMO001 --period=2025.1初始化 prompt:不知道服务器地址和数据中心 ID 填什么?如果这台机器装过金蝶云星空 客户端,把下面这句话交给你的 AI agent,让它自动扫出来填好:
如果本机安装了金蝶云星空,可以扫描本地金蝶云星空目录获取登录地址和数据中心id
CI / 脚本等无交互终端场景的兜底:设置 K3C_USERNAME + K3C_PASSWORD
环境变量(模板见 .env.example,set -a && source .env && set +a),env
存在时优先于钥匙串。
会话与配置
| 命令 | 说明 |
|---|---|
config |
查看服务器地址、凭据来源与会话状态(密码永不显示) |
login |
登录,获取会话 Cookie(有效期约 2 小时);默认幂等(剩余 > 10 分钟跳过,--force 强制重登);无凭据时交互输入(密码不回显),成功后存 macOS 钥匙串(--no-save 跳过) |
logout |
清除登录会话;--forget 连 macOS 钥匙串保存的凭据一起删 |
books |
列出所有账簿 |
help |
显示帮助信息(各命令另有 <命令> help 子帮助) |
查询(只读)
| 命令 | 说明 |
|---|---|
balance |
科目余额表:多期间 / 科目区间 / 层级汇总 / 核算维度展开 / 维度明细账(--detail) |
report |
财务报表:资产负债表 / 利润表 / 现金流量表 / 所有者权益变动表;出数前自动跑勾稽检查 |
cashflow query |
现金流量凭证级明细(按 CI 项目下钻 / 摘要 / 科目过滤) |
account list / show |
科目档案:列末级科目、查单科目完整 model(含挂接的核算维度) |
internal list |
内部往来通知单对账数据(与金蝶「往来通知单勾稽」同源) |
ar |
应收回款匹配:Step A match/list/show + Step B pay-in import/match/list/show + payer-map(Step A 详见下文,Step B 与 payer-map 用 ar pay-in help / ar payer-map help;只读金蝶 + 写本地缓存) |
写入(默认 dry-run,需 --confirm;voucher create 是唯一例外,见下)
| 命令 | 说明 |
|---|---|
voucher |
凭证读写:list / show / create / copy / reverse(红冲)/ edit(就地改,凭证号不变)/ delete / post(过账 B→C) |
supplier create |
建供应商档案(走 Save → Submit → Audit → 分配全流程);supplier forbid 停用(金蝶不能物理删) |
customer create |
建客户档案,同上;自然人加 --person |
transferpl run |
结转损益:执行金蝶端预配置方案,生成"结转本期损益"暂存草稿 |
closing run |
总账期末结账,锁定当前会计期间(反结账不实现,见下方安全规则) |
写入类命令的安全约束见下方 凭证读写 → 安全规则:只创建暂存草稿、 不实现反审核 / 反过账 / 反结账、基础资料建档前自动查重名。
python -m k3c.cli config # 只读:显示账号配置、凭据来源 + 会话状态凭据解析优先级(k3c.credentials,2026-07 钥匙串改造):
K3C_USERNAME+K3C_PASSWORD环境变量(CI / 脚本兜底,优先级最高)- macOS 钥匙串(
login交互输入后自动存入;日常推荐,无需 .env) - 都没有 →
login终端交互输入(密码 getpass 隐藏不回显)
切换账号:login 时交互输入新账号(覆盖钥匙串),或临时用 env 覆盖。
清除保存的凭据:logout --forget。
支持的环境变量:
K3C_USERNAME/K3C_PASSWORD(可选兜底;env 同时给全两项时优先于钥匙串)K3C_SERVER_URL(默认是占位值http://k3cloud.example.com/K3Cloud/,使用前必须配置成你的服务器)K3C_DB_ID(默认是占位值1234567890abcd,使用前必须配置成你的数据中心 ID)
python -m k3c.cli balance [options]
--period=<expr> 期间表达式 (默认: 当前年月)
单期: 2026.3
范围: 2025.1-2025.12(GL_RPT 单次区间汇总一行)
跨年: 2025.10-2026.3(合法,单次调用)
13 期: 2025.13(调整期间末,年报口径)
含 13 多期: 2025.1-2025.13(GL_RPT 原生支持,无需切换通路)
--book=<业务编码> 账簿业务编码 (如 DEMO002),必传
--account=<account-code> 科目编码,三种语法
精确: 1002 / 6401.01.01(父级编码自动含子树)
前缀: 6401* (所有 6401 开头的科目)
区间: 6001..6999(金蝶原生"科目 从~至",含两端子树)
--dimension 按核算维度展开,输出 dimNumber/dimName 两列
--customer=<编码> 按客户编码筛维度(自动启用 --dimension)
编码: CUST0123 / CUST0002 / VEN00789 等
等价于金蝶 UI: 科目余额表 → 筛选客户.编码
--nonzero 只保留期末余额 != 0 的行(容差 0.005)
主通路按 endBalance 判、--detail 通路按 endDebit-endCredit
净额判,两者同一会计口径
--detail 核算维度明细账(单客户/单科目按期间逐期展开,4 列借贷)
必填 --book + --account=<精确编码> + --customer=<精确编码>
走 GL_RPT_AccountingItemsBalance,与 --dimension 互斥
输出列:year/period/dimNumber/dimName/beginDebit|Credit/debit|credit/endDebit|Credit
金额保留金蝶原样带千分位逗号字符串
--detail-group=<FormId> [--detail] 显式指定维度业务对象 FormId
未传时自动按 customer 前缀推断: VEN*→BD_Supplier, CUST*→BD_Customer
其他前缀必须显式指定
--level=<N> 按科目层级汇总(金蝶 FBALANCELEVEL,1-10)
--level=1 每个一级科目一行;树深不足 N 时落实际末级
行集不重叠、求和恒等于总账
与 --dimension / --customer / --detail 互斥
--merge-periods [--detail] 多期间合并成每维度一行(只要期末答案、
不要逐月过程时用)
--with-meta [period=13 单期 + --format=json] envelope 输出含 raw 字段
--format=<format> 输出格式: table|json|csv (默认: table)
--output=<file> 导出到文件 (csv/json 格式时生效)# 单期:甲公司 2026 年 1 月全部科目余额(默认走 GL_RPT)
python -m k3c.cli balance --book=DEMO001 --period=2026.1
# 多期区间:1-3 月一行汇总(debit/credit = 区间累计本期发生)
python -m k3c.cli balance --book=DEMO001 --period=2026.1-2026.3
# 跨年:2025.10 - 2026.3(GL_RPT 跨年合法,FDebit 正确反映区间累计)
python -m k3c.cli balance --book=DEMO001 --period=2025.10-2026.3
# 1-13 整年(含调整期间,年报口径)
python -m k3c.cli balance --book=DEMO001 --period=2025.1-2025.13
# 主营业务成本末级 + 项目维度(甲公司 2026 年 1-3 月一行汇总)
python -m k3c.cli balance --book=DEMO001 --period=2026.1-2026.3 --account=6401* --dimension
# 按客户筛应收账款(客户B在甲公司 2025 全年),GL_RPT 与金蝶 UI 同源
python -m k3c.cli balance --book=DEMO001 --account=1122* --customer=CUST0123 --period=2025.1-2025.12
# 核算维度明细账:单供应商在 2241.01 其他应付款上的逐月余额演变(甲公司 2025 全年含调整期)
python -m k3c.cli balance --book=DEMO001 --account=2241.01 --customer=VEN00123 --period=2025.1-2025.13 --detail
# --nonzero 只留期末余额非零的期,看"钱还挂着"的月份
python -m k3c.cli balance --book=DEMO001 --account=2241.01 --customer=VEN00123 --period=2025.1-2025.13 --detail --nonzero
# 导出 CSV,便于按月对账
python -m k3c.cli balance --book=DEMO002 --period=2025.1-2025.12 --account=6001* --dimension --format=csv --output=revenue_2025.csvK3Cloud 标准 WebAPI 不直接暴露 资产负债表 / 利润表 / 现金流量表。本工具通过解析金蝶 FR 报表导出的 FML 模板(XML 格式)+ 在本地评估每行公式(Acct() / AcctCash() / R[N]C[M] / 跨表引用 / 算术)取数:
Acct(...)走GL_BALANCE(资产负债表 / 利润表均用此)AcctCash(...)走GL_Rpt_CashflowQuery(现金流量表,凭证级 CI 编码明细)—— 走独立 API 而非 GL_BALANCEAcctItem(...)暂未实现(cash_flow.json row=42 / CI04 汇率变动行单元格 N/A)
# 在金蝶界面:报表 → 引入引出 → 引出 FML 格式
# 把生成的 .fml 文件复制到项目目录后:
python tools/fml_to_json.py 示例报表.fml reports/reports/ 下会生成 3 个 JSON:balance_sheet.json、profit_sheet.json、cash_flow.json。这些 JSON 已 git tracked,后续无需再跑转换工具,除非金蝶财务后台改了报表模板。
python -m k3c.cli report [options]
# 模式 1:列出报表 / 行项目
report --list 列出全部 4 张报表
report --list --name=balance_sheet 列出某张报表的全部行项目
# 模式 2:渲染整张报表
report --name=balance_sheet --period=2026.3 --book=DEMO001
# 模式 3:跨表挑行项目(可重复 --item)
report --period=2026.3 --book=DEMO001 \
--item="balance_sheet:货币资金" \
--item="profit_sheet:一、营业收入"
# 模式 4:反查某科目在哪些报表的哪些行项目(含当期金额)
report --account=1002 --period=2026.3 --book=DEMO001
# 对账模式:同时输出当前重算值与 FML snapshot 的差异
report --name=balance_sheet --period=2026.3 --book=DEMO001 --verify| 限制 | 影响范围 |
|---|---|
AcctItem()(金蝶"项目取数"函数)未实现 |
cash_flow.json 报表 row=42(CI04 汇率变动行)单元格渲染 N/A;若账簿无外币业务,N/A 与真实值 0 等效 |
IF + AY/AC 选择性合计未实现 |
应交税费、其他流动资产 行金额会偏差 |
仅在示例账簿(DEMO001)上对账过 |
其他账簿如有自定义科目体系可能要调整 |
完整清单见 docs/KNOWN_LIMITATIONS.md。后续版本会逐步补齐。
Acct(org, range, flag, dim, p5, p6, p7)第 5 参语义0或缺省 → 自然方向(贷方科目翻转为正)""空串 → 保留原始有符号值(IF 条件中使用)-1→ 上一年同期(利润表"上年同期金额"列)
- 期间标志映射 GL_BALANCE:
Y期末余额 /C上年年末(year-1,period=12)SY本月发生 /SL本年累计(自然方向取FDebit或FCredit)JF/JFL/DF/DFL借/贷方原值,不做翻转
- 父子科目处理:仅对末级科目取数(避免父+子双计),且只读
FDetailID=0行(避免合计 + 维度行双计)
凭证模块子命令:list / show / create / copy / reverse / edit / delete / post。
- CLI 不实现:反审核 / 反过账 / 反结账 / Submit / Audit。反向破坏性操作必须手动在金蝶界面完成。
- 写入只创建暂存草稿(A 状态);
post(过账)只接受已审核(B)凭证且需--confirm。 edit/delete仅支持 A(暂存)/ D(重新审核)状态且未过账:其它状态拒绝并提示先在金蝶界面反审核。- 写操作默认 dry-run(
create例外:默认真写,加--dry-run预览),需--confirm才落地。
- 凭证主键字段是
FVoucherID(不是通用的FID)。Save 不识别 FID,会把请求当作"新建"处理。 - 部分字段更新用
{"NeedUpDateFields":[...], "Model":{"FVoucherID":"...", ...}};整单替换传全量 Model 不带 NeedUpDateFields。FYear/FPeriod 由系统按日期自动推算。 voucher copyvsvoucher edit:copy 创建新草稿(产生新 FVoucherID + 新凭证号);edit 就地修改(原 FVoucherID 与凭证号不变)。
| FDocumentStatus | 含义 | edit/delete 行为 | copy 行为 |
|---|---|---|---|
A |
暂存 | ✅ 放行 | ✅ 创建副本 |
B |
审核中/已审核 | ❌ 拒绝(需手动反审核) | ✅ 创建副本 |
D |
重新审核 | ✅ 放行 | ✅ 创建副本 |
# 列出(多重过滤)
voucher list --book=DEMO001 --period=2026.3 --status=A
voucher list --book=DEMO001 --search="工资"
voucher list --book=DEMO001 --account=1002 --period=2026.1-2026.3
# 显示单张凭证详情(表头 + 分录)
voucher show --book=DEMO001 --bill=888008
voucher show --book=DEMO001 --id=888009
# 从 JSON 文件创建草稿
voucher create --file=path.json [--dry-run]
# 复制凭证(创建新草稿,原凭证保留)默认 dry-run
voucher copy --book=DEMO001 --bill=888008 --target=2026.12 # dry-run
voucher copy --book=DEMO001 --bill=888008 --target=2026.12 --confirm
# 就地修改(摘要/金额/科目/维度/日期,凭证号不变;仅 A/D 状态)默认 dry-run
voucher edit --book=DEMO001 --bill=888008 --set 1.debit=100.00 --confirm
voucher edit --book=DEMO001 --bill=888008 --set date=2026-04-15 --confirm
# 整凭证红字冲销 / 删除草稿 / 过账,均需 --confirm
voucher reverse --book=DEMO001 --id=888009 --target=2026.5 --confirm
voucher delete --book=DEMO001 --bill=888008 --confirm
voucher post --book=DEMO001 --period=2026.3 --confirm单张凭证:
{
"book": "DEMO001",
"date": "2026-04-01",
"year": 2026,
"period": 4,
"voucherGroupNo": "记",
"explanation": "凭证摘要(可选,分录可单独覆盖)",
"entries": [
{ "account": "1002", "debit": 1000, "credit": 0, "explanation": "明细摘要" },
{ "account": "6001", "debit": 0, "credit": 1000 }
]
}多张凭证(数组形式):
[
{ "book": "...", "date": "...", "entries": [ ... ] },
{ "book": "...", "date": "...", "entries": [ ... ] }
]校验规则:
- 借贷必须平衡(误差 ≤ 0.005)
- 每条分录借/贷只能一个 > 0
- 科目编码必须存在于
BD_ACCOUNT - 创建后凭证为
A(暂存)状态,需用户手动审核
把金蝶网页"现金流量查询"页面的 17 列凭证级明细搬到 CLI,并支持按 CI 项目下钻、按
科目过滤、按摘要 grep。回答"丙公司 2025 年收到其他与经营活动有关的现金里有多少
利息收入"这种"汇总单元格 → 具体凭证"的下钻问题。与 report --name=cash_flow(汇总报
表)解耦:报表是 4 列汇总,本命令是 17 列凭证级明细。
| 参数 | 必填 | 说明 |
|---|---|---|
--book |
是 | 账簿编码或 ID |
--period |
是 | 期间表达式(单期 2025.6 / 范围 2025.1-2025.12 / 跨年) |
--ci-code |
否 | CI 项目前缀过滤(如 CI01.01.03 命中本身 + .* 子级) |
--account |
否 | 凭证分录主科目编码精确或末尾 * 前缀(客户端过滤;非对方科目) |
--explanation |
否 | 摘要 substring 匹配 |
--format |
否 | table / csv / json(默认 table) |
--output |
否 | 导出到文件(csv/json 格式) |
日期 / 凭证字 / 凭证号 / 行号 / 摘要 / 科目编码 / 科目名称 / 币别 / 原币金额 / 借方 / 贷方 / 流量币别 / 流量金额(原币) / 流量金额(本币) / 主表项目编码 / 主表项目名称 / 对方科目。
# 丙公司 2025 全年 收到其他与经营活动有关的现金 全部明细
python -m k3c.cli cashflow query --book=DEMO003 \
--period=2025.1-2025.12 --ci-code=CI01.01.03
# 加摘要过滤,只看利息收入(4 笔季度结息)
python -m k3c.cli cashflow query --book=DEMO003 \
--period=2025.1-2025.12 --ci-code=CI01.01.03 --explanation=利息
# 甲公司 2025.6 凭证主科目 = 1002(银行存款)的全部明细
# 注:--account 过滤的是分录主科目(accountNumber),不是对方科目(opp_account)
python -m k3c.cli cashflow query --book=DEMO001 \
--period=2025.6 --account=1002
# 列多控制台不友好时导出 CSV
python -m k3c.cli cashflow query --book=DEMO003 \
--period=2025.1-2025.12 --format=csv --output=cashflow_2025.csvsum(借方 + 贷方) = report --name=cash_flow 对应 CI 项目当期金额(已在真实账簿
验证多个 CI 项目与报表完全一致)。
--ci-code走^CI[0-9.]+$白名单校验,杜绝 SQL 注入--account走 _validate_code 白名单校验- 命令完全只读,不写金蝶
判断"某笔应收是否回款"分两个层次:
- Step A(内部配对):应收明细表内借贷自相配平——业务发生时记借方(挂账),
收款时记贷方(已核销)。
ar match/list/show把贷方逐条配回借方,识别已回款 / 未回款,不读银行流水。 - Step B(银行流水外部匹配):当账上贷方仍有遗漏(如代付、延期、跨账户),
导入银行流水按金额 + 时间 + 摘要给候选;
ar pay-in import/match/list/show写 本地审核队列;ar payer-map list/add/remove维护"付款人 → 客户"映射。
v1 完成 Step A + Step B(含 web 审核 dry-run,某次改动)。核销凭证草稿生成写 金蝶(Step 8)留 v2。
# 1. 拉应收明细 + 跑配对(默认 dry-run,屏幕看汇总)
python -m k3c.cli ar match --book=DEMO001 --account=1122 --period=2025.1-2025.12
# 2. 满意后写入本地缓存
python -m k3c.cli ar match --book=DEMO001 --account=1122 --period=2025.1-2025.12 --apply
# 3. 列出全部未回款(从缓存读,不再调 K3Cloud)
python -m k3c.cli ar list --book=DEMO001 --status=unpaid
# 4. 看某客户的详细配对清单
python -m k3c.cli ar show --book=DEMO001 --customer=100002
# 5. 单客户增量同步
python -m k3c.cli ar match --book=DEMO001 --customer=100002 --period=2025.1-2026.4 --apply| Pass | 策略 | 置信度 | 说明 |
|---|---|---|---|
| A | 1:1 完全等额匹配 | high | 一笔贷方对一笔等额借方;多匹配选日期最早 |
| B | 结构化线索 + tier 3 金额组合 | high | 摘要里抽业务对象标识/期间/引用凭证号,先用 cue 锁候选集再做组合(标识形态可配,见下) |
| C | 纯 tier 3 金额组合 | medium | 1 笔贷方对 ≤3 笔借方,唯一解才出建议 |
| D | tier 5 / tier 10 → manual | — | 找到候选直接转人工,不出建议(不硬猜) |
剩下未消费的借方 = 未回款;剩下未消费的贷方 = 异常孤立 credit(应收没挂就来了核销)。
Pass B 判断"这笔核销和那笔挂账是同一件事",靠的是两条摘要里出现同一个业务对象标识——
合同号、订单号、工单号、房号,各行业写法不同。内置形态见
k3c/ar.py DEFAULT_SUBJECT_PATTERNS(带业务前缀的单据号、#编号 /
No.编号、位置型编号)。认不出你的编号时,在 config/<客户>/cues.json 里补:
{
"subject_patterns": ["(?:结算单|对账单)\\s*[--::]?\\s*([A-Za-z]{0,8}\\d{4,})"],
"replace_defaults": false
}- 每条正则的第一个捕获组是标识本身(没写捕获组就取整段匹配)
replace_defaults缺省false= 追加在内置形态之后;置true则只用你写的 (内置形态在你的数据上会误伤时用)- 正则写错会在加载时报错并指出是哪份配置,不会拖到配对时才炸
- 账簿与客户目录的对应关系在
config/customers.json;未注册的账簿用内置形态
- 直接查
GL_Voucher的 entry-level 字段(金蝶把GL_Voucher暴露为 header×entry 平铺行) - 客户解码:
BD_FLEXITEMDETAILV上HSWD02_SYS("客户"维度)对应的FFLEX{n}.FNumber/.FName - 缓存:
~/.k3c/ar_cache/<账簿>.json(每账簿一文件,2026-07 起),文件内按customer_id分桶;要重置某账簿直接rm对应文件即可
ar match默认 dry-run,必须--apply才写入本地缓存- 本命令族只读 K3Cloud + 写本地缓存,不生成凭证、不动金蝶
- 详见 k3c/ar.py 顶部 docstring 与 docs/KNOWN_LIMITATIONS.md §6
account list # 全部启用末级科目
account list --account=6401 # 6401 段(前缀,不用写 *)
account list --all # 含父级科目
account list --include-forbidden # 含停用科目
account list --format=csv --output=accounts.csv
account show 1122.01 # 单科目关键字段
account show 1122.01 --format=json # 金蝶 View 返的完整 modelaccount show --format=json 能看到该科目挂了哪些核算维度(BD_ACCOUNTFLEXENTRY)——
录凭证前不确定某科目要不要填客户/项目维度时查这个。
与金蝶 UI「财务会计 → 内部往来协同 → 往来通知单勾稽」同源,集团内多法人对账用:
internal list --book=DEMO000 --period=2026.6
internal list --book=DEMO001 --period=2026.1-2026.6 --direction=recv # 只看接收方向
internal list --book=DEMO000 --period=2026.6 --counterparty=DEMO004 # 只看某对方组织
internal list --book=DEMO000 --period=2026.6 --format=json --output=notices.json--direction:recv(对方发来)/send(本账簿发出)/both(默认)--status:all(默认)/unconfirmed/confirmed- 每个方向表尾给借合计 / 贷合计 / 净额,净额口径对齐 UI「合计金额」
- 只读;勾稽、确认等写操作请在金蝶界面完成
两条命令用法完全一致(都支持 --person 自然人模式):
customer create --name="某某有限公司" # dry-run:校验名称 + 查重名
customer create --name="某某有限公司" --confirm # 真建
customer create --name="张三" --person --confirm # 自然人(2-4 中文字)
customer forbid --number=CUST0999 --confirm # 停用(金蝶不能物理删)
supplier create --name="某某供应商有限公司" --confirm
supplier forbid --number=VEN00456 --confirm--confirm 走完整流程:名称校验 → 查重 → Save → Submit → Audit → Allocate
分配到各子公司组织 → 子公司端 Submit/Audit → 刷新本地 cache。这是本工具唯一
会自动走 Submit/Audit 的地方,理由是基础资料不能物理删、编码由金蝶自动生成,
唯一风险是重名建档,而重名有三层防护:
- 完全重名 → 硬拒(直接告诉你用现有的 FNumber)
- 模糊重名 → 警告,要
--force才继续 - 默认 dry-run,不加
--confirm只查不写
建错了只能 forbid 停用(停用后新凭证选不到),这也是金蝶本身的限制。
执行金蝶端预先配置好的结转损益方案(CLI 不负责配方案),由金蝶按账簿当前 期间生成一张"结转本期损益"暂存草稿:
transferpl run --book=DEMO001 --period=2026.6 # dry-run:方案信息 + 预计结转额
transferpl run --book=DEMO001 --period=2026.6 --confirm # 执行金蝶执行接口本身没有期间参数(按账簿当前期间走),所以 --period 是 CLI 加的
三重护栏:执行前查该期是否已有结转凭证(有则拒绝,防重复结转)、预览预计结转额、
执行后核对生成的凭证确实落在该期间。账簿配了多个方案时用 --scheme 指定。
closing run --book=DEMO001 --period=2026.6 # dry-run:前置体检 + 影响面
closing run --book=DEMO001 --period=2026.6 --confirm # 执行这是最重的不可逆操作——结账后该期不能再录凭证。四重护栏:--period 必须等于
账簿当前期间(防结错期)、本期不能有未过账凭证(有则列出并拒绝)、默认 dry-run +
--confirm 显式确认并打印影响面、执行后核对账簿当前期间确实推进了。反结账 CLI
不实现,结错了去金蝶界面手动反结账。
典型月末流程:
transferpl run --book=X --period=2026.6 --confirm # 1. 结转损益(出草稿)
# 2. 在金蝶界面审核本期全部凭证(含结转凭证)—— CLI 不做 Submit/Audit
voucher post --book=X --period=2026.6 --confirm # 3. 已审核凭证过账
closing run --book=X --period=2026.6 --confirm # 4. 期末结账balance --dimension触发后启用核算维度展开,输出多dimNumber/dimName两列。金蝶后端FSHOWDETAIL=true + FDETAILSHOWACCT=true直接返回维度行 (含科目编码),dimNumber取FDETAILNUMBER(复合编码字符串,如CUST0123/F10),dimName取FDETAILNAME(含客户名 + 项目名)。不返回FDETAILID,下游应用dimNumber字符串做客户/项目 key- 启用维度后自动剔除"科目合计行"(避免与维度明细行重复双计):金蝶后端返回
科目合计行 + 维度行,CLI 层在 schema 转换循环里剔
dimNumber为空的科目 合计行(仅保留维度行) - 不带
--dimension:用FSHOWDETAILONLY=true让后端只返末级科目行 (父级 + 合计行都剔) ar命令族内部走独立的 GL_BALANCE 通路(get_account_balance_multi), 按FDetailID数字 ID 联查BD_FLEXITEMDETAILV解码客户/项目名称——这是ar/ar_payment写核销凭证需要数字 ID 的内部实现细节,不是用户可选参数 (详见 docs/KINGDEE_API_PITFALLS.md 坑点 #9)
推荐(日常):终端直接 login,交互输入用户名和密码(密码 getpass 隐藏
不回显,"飞书 CLI 式"),验证成功后存入 macOS 钥匙串——磁盘零明文,之后
所有命令与自动重登静默取用:
python -m k3c.cli login
# 用户名: demo_user
# 密码(输入不回显):兜底(CI / 脚本 / 非 macOS):K3C_USERNAME + K3C_PASSWORD
环境变量,仓库根 .env 管理(已在 .gitignore),优先级高于钥匙串:
cp .env.example .env # 复制模板并编辑填账号
set -a && source .env && set +a
python -m k3c.cli login清除钥匙串里保存的凭据:python -m k3c.cli logout --forget。
配置文件保存在用户目录下的 .k3c/config.json 中。
端点: Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc
请求方式: POST,请求体为 JSON 对象
参数格式(注意:必须是对象,不是数组):
{
"acctid": "1234567890abcd",
"username": "demo_user",
"password": "<your_password>",
"lcid": 2052
}成功响应:
{
"LoginResultType": 1,
"Message": "登录成功",
"Context": {
"UserName": "demo_user",
"UserId": "10000001",
"CurrentOrganizationInfo": ["..."]
}
}失败响应:
{
"LoginResultType": 0,
"Message": "用户名或密码错误",
"ExceptionMsg": "用户名或密码错误"
}Cookie: 登录成功后,响应头会返回 Set-Cookie: kdservice-sessionid=xxx,后续请求需要带上这个 Cookie。
端点: Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery.common.kdsvc
请求方式: POST,请求体格式如下:
{
"formid": "GL_BALANCE",
"data": "{\"FormId\":\"GL_BALANCE\",...}"
}参数说明:
formid: 表单ID(如GL_BALANCE、BD_ACCOUNT、BD_ACCOUNTBOOK)data: JSON 字符串,包含查询条件:FormId: 表单ID(与外层相同)TopRowCount: 返回的最大行数(0表示不限)Limit: 每页行数(0表示不分页)StartRow: 起始行号FilterString: 过滤条件(SQL WHERE 语法)OrderString: 排序条件FieldKeys: 要查询的字段,用逗号分隔
示例请求体:
{
"formid": "GL_BALANCE",
"data": "{\"FormId\":\"GL_BALANCE\",\"TopRowCount\":0,\"Limit\":0,\"StartRow\":0,\"FilterString\":\"FYear=2025 and FPeriod=1\",\"OrderString\":\"\",\"FieldKeys\":\"FAccountID,FYear,FPeriod,FBeginBalance,FDebit,FCredit,FEndBalance\"}"
}响应格式: 返回二维数组 List[List],第一行是列标题,后续行是数据:
[
["FACCOUNTID", "FBeginBalance", "FDebit", "FCredit", "FEndBalance"],
[100001, 10000.00, 0.0, 0.0, 10000.00],
[100001, 10000.00, 0.0, 0.0, 10000.00]
]GL_BALANCE 表中存在币种重复问题:同一个科目、同一期间会有两行数据,分别对应:
FCurrencyID=0:本位币FCurrencyID=1:综合本位币
这两行的金额通常完全相同,直接相加会导致数据翻倍。必须去重。
去重方法:按 (账簿ID, 科目ID, 年份, 期间, 期初余额, 借方, 贷方, 期末余额) 去重:
seen = set()
unique_rows = []
for row in rows:
key = (row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7])
if key not in seen:
seen.add(key)
unique_rows.append(row)GL_BALANCE 只有科目ID,没有科目编码和名称。需要联查 BD_ACCOUNT 表:
# 获取科目映射
acct_rows = client.execute_bill_query(
"BD_ACCOUNT",
"FACCTID,FNumber,FName,FLevel",
limit=10000
)
acct_map = {r[0]: {"number": r[1], "name": r[2], "level": r[3]} for r in acct_rows}金蝶 WebAPI 的参数格式比较特殊:
- 登录接口:参数是 JSON 对象
{"acctid": "...", ...},不是数组["{\"acctid\": \"...\"}"] - 查询接口:外层是对象
{"formid": "...", "data": "..."},内层的data必须是 JSON 字符串 - 如果参数格式不对,会返回 500 错误 "Additional text found in JSON string"
| 表单ID | 说明 |
|---|---|
GL_BALANCE |
科目余额表 |
BD_ACCOUNT |
会计科目 |
BD_ACCOUNTBOOK |
账簿 |
BD_ORGANIZATION |
组织 |
BD_FLEXITEMDETAILV |
核算维度组合(FDetailID 解码源) |
GL_BALANCE.FDetailID 是维度组合 ID,需联查 BD_FLEXITEMDETAILV:
# 字段命名约定:FF1000XX 为弹性字段编号
# 只有"基础资料/辅助资料"类型的弹性字段支持联查 .FNumber / .FDataValue
# 简单字段(如 FF100002 整数类型)不支持联查,必须排除
field_keys = "FID,FF100003.FNumber,FF100003.FDataValue"
filter_str = "FID IN (100001, 100002, ...)"
# 返回: [100001, "F01", "甲公司-业务A"]不同数据中心启用的弹性字段编号不同,本工具会在首次维度查询时自动探测 FF100001~FF100020 中可联查的字段,并在会话内缓存。
k3cloudy-cli/
├── k3c/ # 库代码 + CLI(启动 `python -m k3c.cli`)
│ ├── cli/ # 命令派发与各业务域(common/session/balance/report/voucher/ar + main 入口)
│ ├── web/ # AR Step B 网页审核界面
│ ├── __main__.py # python -m k3c 入口
│ └── 库层:api / ar / ar_payment / cashflow / formula / session_io / voucher_save_model
├── skills/ # AI agent 用法指南(k3c-cli-usage)
├── tools/ # FML 转换 + 一次性调研脚本
├── reports/ # 报表 JSON 模板
├── config/ # 多租户客户配置(rules / dimensions / cues)
├── tests/ # pytest(库层 + web)
├── docs/ # ARCHITECTURE / KINGDEE_API_PITFALLS / KNOWN_LIMITATIONS / ...
├── k3c.bat / .ps1 # Windows 启动 wrapper
└── README.md / LICENSE
想接更多金蝶接口(本工具只覆盖了财务会计域的一部分),按这个顺序走:
- 查官方接口文档:金蝶云·星空开放平台 · API 列表
—— 业务对象的 FormId、请求/响应字段、必填项、示例 JSON 都在这里,是字段层面的
唯一权威源。查到 FormId 后,多数查询能直接套本项目已有的
ExecuteBillQuery/GetSysReportData封装。 - 先读坑点集:docs/KINGDEE_API_PITFALLS.md。
官方文档不会告诉你的那些——
GL_Voucher新建用FID="0"而更新要用FVoucherID(用错会静默生成副本)、ExecuteBillQuery不传OrderString会 静默截断 5000 行、父子科目 +FDetailID双计等,17 条都是实测踩出来的。 写任何新的 WebAPI 调用前先扫一遍这页。 - 照现有结构加代码:库层业务逻辑放
k3c/<域>.py,CLI 层只做参数解析 + 调库 + 输出,放k3c/cli/<域>.py(库层不 import CLI)。取数封装看 k3c/api.py,命令派发看 k3c/cli/init.py, 模块依赖与数据流见 docs/ARCHITECTURE.md。 - 测试:
pytest tests/ -q。现有测试全部用桩数据、不连金蝶,新增命令建议照此 办理(tests/test_balance_rpt.py的RecordingPost是可抄的样板)。改了--help文本要跑UPDATE_HELP_SNAPSHOTS=1 pytest tests/test_cli_help_snapshots.py -q重新生成快照。
写操作请沿用现有约定:默认 dry-run、--confirm 才落地、只创建暂存草稿——理由见
凭证读写 → 安全规则。
- 金蝶云·星空开放平台 — 官方 API 列表与字段说明
- docs/KINGDEE_API_PITFALLS.md — 本项目实测踩坑记录
MIT © 2026 kukubob