Skip to content

About

Unofficial CLI for Kingdee K3Cloud WebAPI — 金蝶云星空非官方命令行工具,面向财务/审计自动化,为 AI agent 优先设计

Resources

Stars

0 stars

Watchers

0 watching

Forks

 
 

Repository files navigation

k3cloudy-cli

⚠️ 非官方声明 / 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。

文档索引

安装

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 钥匙串改造):

  1. K3C_USERNAME + K3C_PASSWORD 环境变量(CI / 脚本兜底,优先级最高)
  2. macOS 钥匙串(login 交互输入后自动存入;日常推荐,无需 .env)
  3. 都没有 → 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.csv

财务报表查询 (report)

K3Cloud 标准 WebAPI 不直接暴露 资产负债表 / 利润表 / 现金流量表。本工具通过解析金蝶 FR 报表导出的 FML 模板(XML 格式)+ 在本地评估每行公式(Acct() / AcctCash() / R[N]C[M] / 跨表引用 / 算术)取数:

  • Acct(...) 走 GL_BALANCE(资产负债表 / 利润表均用此)
  • AcctCash(...) 走 GL_Rpt_CashflowQuery(现金流量表,凭证级 CI 编码明细)—— 走独立 API 而非 GL_BALANCE
  • AcctItem(...) 暂未实现(cash_flow.json row=42 / CI04 汇率变动行单元格 N/A)

一次性准备:把 FML 转成 JSON 配置

# 在金蝶界面:报表 → 引入引出 → 引出 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,后续无需再跑转换工具,除非金蝶财务后台改了报表模板。

report 命令模式

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

v1 已知限制

限制 影响范围
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 行(避免合计 + 维度行双计)

凭证读写 (voucher)

凭证模块子命令: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 copy vs voucher 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

voucher create JSON 格式

单张凭证:

{
  "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(暂存)状态,需用户手动审核

现金流量明细查询 (cashflow query)

把金蝶网页"现金流量查询"页面的 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 格式)

输出列(17 列)

日期 / 凭证字 / 凭证号 / 行号 / 摘要 / 科目编码 / 科目名称 / 币别 / 原币金额 / 借方 / 贷方 / 流量币别 / 流量金额(原币) / 流量金额(本币) / 主表项目编码 / 主表项目名称 / 对方科目。

示例

# 丙公司 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.csv

对账提示

sum(借方 + 贷方) = report --name=cash_flow 对应 CI 项目当期金额(已在真实账簿 验证多个 CI 项目与报表完全一致)。

⚠️ 不要直接 sum "流量金额(本币)" 列——它是金蝶按整张凭证计算的"凭证级流量", 同一张凭证下多 CI 项目分录会显示同一数值,求和会重复。求和请用 借方+贷方。

安全规则

  • --ci-code 走 ^CI[0-9.]+$ 白名单校验,杜绝 SQL 注入
  • --account 走 _validate_code 白名单校验
  • 命令完全只读,不写金蝶

应收回款匹配 (ar)

判断"某笔应收是否回款"分两个层次:

  • 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 的判据)

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)

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 返的完整 model

account show --format=json 能看到该科目挂了哪些核算维度(BD_ACCOUNTFLEXENTRY)—— 录凭证前不确定某科目要不要填客户/项目维度时查这个。

内部往来通知单 (internal list)

与金蝶 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「合计金额」
  • 只读;勾稽、确认等写操作请在金蝶界面完成

基础资料建档 (supplier / customer)

两条命令用法完全一致(都支持 --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 停用(停用后新凭证选不到),这也是金蝶本身的限制。

结转损益 (transferpl run)

执行金蝶端预先配置好的结转损益方案(CLI 不负责配方案),由金蝶按账簿当前 期间生成一张"结转本期损益"暂存草稿:

transferpl run --book=DEMO001 --period=2026.6            # dry-run:方案信息 + 预计结转额
transferpl run --book=DEMO001 --period=2026.6 --confirm  # 执行

金蝶执行接口本身没有期间参数(按账簿当前期间走),所以 --period 是 CLI 加的 三重护栏:执行前查该期是否已有结转凭证(有则拒绝,防重复结转)、预览预计结转额、 执行后核对生成的凭证确实落在该期间。账簿配了多个方案时用 --scheme 指定。

⚠️ 该期若有暂存(A)凭证会警告——未过账凭证会被计入结转,之后再改动这些凭证会让 结转金额失准,建议先把凭证审核定稿再结转。

期末结账 (closing run)

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 中。

WebAPI 调用方式详解

1. 登录接口

端点: 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。

2. 单据查询接口

端点: 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]
]

3. 关键注意事项

数据去重

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 的参数格式比较特殊:

  1. 登录接口:参数是 JSON 对象 {"acctid": "...", ...},不是数组 ["{\"acctid\": \"...\"}"]
  2. 查询接口:外层是对象 {"formid": "...", "data": "..."},内层的 data 必须是 JSON 字符串
  3. 如果参数格式不对,会返回 500 错误 "Additional text found in JSON string"

常用表单ID

表单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

二次开发

想接更多金蝶接口(本工具只覆盖了财务会计域的一部分),按这个顺序走:

  1. 查官方接口文档:金蝶云·星空开放平台 · API 列表 —— 业务对象的 FormId、请求/响应字段、必填项、示例 JSON 都在这里,是字段层面的 唯一权威源。查到 FormId 后,多数查询能直接套本项目已有的 ExecuteBillQuery / GetSysReportData 封装。
  2. 先读坑点集:docs/KINGDEE_API_PITFALLS.md。 官方文档不会告诉你的那些——GL_Voucher 新建用 FID="0" 而更新要用 FVoucherID(用错会静默生成副本)、ExecuteBillQuery 不传 OrderString 会 静默截断 5000 行、父子科目 + FDetailID 双计等,17 条都是实测踩出来的。 写任何新的 WebAPI 调用前先扫一遍这页。
  3. 照现有结构加代码:库层业务逻辑放 k3c/<域>.py,CLI 层只做参数解析 + 调库 + 输出,放 k3c/cli/<域>.py(库层不 import CLI)。取数封装看 k3c/api.py,命令派发看 k3c/cli/init.py, 模块依赖与数据流见 docs/ARCHITECTURE.md。
  4. 测试: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 才落地、只创建暂存草稿——理由见 凭证读写 → 安全规则。

参考文档

License

MIT © 2026 kukubob

About

Unofficial CLI for Kingdee K3Cloud WebAPI — 金蝶云星空非官方命令行工具,面向财务/审计自动化,为 AI agent 优先设计

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages