Skip to content

Repository files navigation

本项目采用「小河狸工作室非转售许可 1.0」—— 个人使用与企业内部使用免费(含内部办公、财务与会计处理、内部系统集成); 对外销售、集成进收费产品或服务、托管 / SaaS / 代运营、以及向第三方交付成果或提供服务,须事先取得书面授权。 许可全文见 LICENSE。商业授权:https://littlebeaver.top

License

金蝶云星空报销助手 Skill

让员工不登录金蝶云星空,直接在对话框里把发票交上来,由 AI 完成「费用申请单 → 报销单 → 挂发票 → 提交审批」的全过程。适合需要报销但不想学金蝶操作的业务同事,以及想把报销流程接进自己系统的开发者。

✨ 能做什么

  • 建费用申请单 / 出差申请单,并提交、下推报销单
  • 把发票挂进报销单的「收票信息」(纯金蝶 WebAPI,不需要发票云授权)
  • 提交硬闸门:收票 0 行 / 缺发票云流水号 / 跨组织挂票 / 发票合计 < 报销金额 —— 命中即中止,无绕过参数
  • 发票不在收票池时,指引用员工在报销软件里上传一次拿到发票云流水号(手工建票已证伪,见下)
  • 让报销明细与发票一致(金额、费用项目对齐,写入「明细 ↔ 发票」联动关系)
  • 把行程单传成附件,避免与发票重复计入金额
  • 提交前体检:金额链条、收票信息、往来单位一次查清
  • 提交审批(提交后收票信息保持)

覆盖 ER_ExpenseRequest / ER_ExpReimbursement(费用线)与 ER_ExpenseRequest_Travel / ER_ExpReimbursement_Travel(差旅线)。

🚀 三步开始

1. 检查运行环境

核心链路只用 Python 标准库,不需要装任何第三方包:

python --version   # 需要 3.8 或更高

2. 连接配置:通常不需要你做任何事

本 Skill 不单独保存账号密码,也没有独立的配置项。只要机器上装好并配置过 kingdee-data-exporter (金蝶云星空数据导出),本 Skill 会自动复用它的连接配置,不需要重复填写。

确认是否已就绪 —— 在导出技能目录执行(五步全绿即可):

python data_exporter.py --doctor

只有这几种情况才需要自己配:

情况 做法
没装导出技能,想单独用本 Skill 写 ~/.workbuddy/kingdee/config.json,只填账套名称即可
CI / 无人值守 用环境变量 KINGDEE_BASE_URL / KINGDEE_ACCTID(或 KINGDEE_ACCT_NAME)/ KINGDEE_USERNAME / KINGDEE_PASSWORD
已经在用导出技能的 config.py 旧写法 无需操作,同样兼容

自己配的话写这个(~/.workbuddy/kingdee/config.json,在技能目录之外,升级不覆盖):

{
  "base_url": "https://你的域名/k3cloud/",
  "acct_name": "账套名称",
  "username": "集成账号",
  "password": "密码"
}

账套 ID 不用自己找 —— 只填账套名称会自动解析;想列出来看看就跑一次 (免账号密码):python data_exporter.py --list-datacenters

🔐 无论哪种方式,都不要把真实账号、密码或账套 ID 提交到公开仓库。 建议给这个 Skill 单独建一个集成用户,只授予报销相关单据与收票单的权限,不要用管理员账号。

为什么本 Skill 自己也要读一次凭据?因为它要做写操作(提交单据、下推、挂传附件), 而导出技能是只读的、不提供写接口。连接动作必须自己完成,但读的是同一份配置, 用户不需要多填任何东西。

3. 先做一次只读体检

任何写操作之前,先体检一下,确认能连通、单据状态符合预期:

python helpers/recvin_link.py precheck <报销单FID>
python helpers/expense_edit.py check <报销单FID>

🧭 推荐使用顺序

第一步:下推报销单

# 费用申请单 → 费用报销单
# formid=ER_ExpenseRequest, TargetFormId=ER_ExpReimbursement

也可以手工新建报销单,两种来源都能走后面的流程。

第二步:先「找」发票,再「建」收票单

python helpers/recvin_link.py find 24000000000000000001        # 按发票号码找
python helpers/recvin_link.py find SPD00000001                 # 按收票单号找

查不到 → ⚠️ 不要手工建收票单:手工建的票FGENERATETYPE 为空、永远拿不到发票云流水号, 而 v2.0.11 起「无流水号」是硬闸门,这种票根本提交不过去。 正确做法是让员工在报销软件 / 发票云里把这张票上传一次,当天进池、当天就有流水号。

⚠️ 一张收票单只能属于一张报销单。 把它挂到第二张单上会静默改掉原单的关联, 造成「旧单还列着这张票、票却说属于别人」的不一致。工具默认拦截,确需改挂要显式加 --allow-steal。

第三步:把发票挂进「收票信息」

python helpers/recvin_link.py link <报销单FID> <收票单号>             # 追加
python helpers/recvin_link.py link <报销单FID> <收票单号> --replace   # 覆盖
python helpers/recvin_link.py clear <报销单FID>                       # 清空

差旅费报销单加 --travel:

python helpers/recvin_link.py --travel link <报销单FID> <收票单号>

第四步:让明细与发票一致

体检一下,再按发票金额改明细:

python helpers/expense_edit.py set-detail <报销单FID> --entry <明细分录内码> --amount 88.00
python helpers/expense_edit.py linkage <报销单FID> --recv SPD00000001 --entry <明细分录内码>

linkage 写的是「明细 ↔ 发票分录」的联动关系 —— 也就是金蝶界面上选票时那个**「合并生成费用明细」**的底层数据。

第五步:行程单进附件

python helpers/expense_edit.py attach <报销单FID> "D:/票据/行程单.pdf"

第六步:补往来单位 → 体检 → 提交

python helpers/recvin_link.py set-contact <报销单FID> <员工号>
python helpers/recvin_link.py precheck <报销单FID>
python helpers/recvin_link.py submit <报销单FID>

submit 会先跑硬闸门:收票 0 行、缺发票云流水号、跨组织挂票、发票合计 < 报销金额 命中任意一条 都会直接中止、不发起提交,而且 v2.0.11 起没有任何 --force 之类的绕过参数。 有阻断项时正确动作是修数据:expense_edit.py fit 把报销额调到发票合计,或让员工把缺的票补上传。

🧾 金额与费用类型口径

  • 硬规则:报销金额 ≤ 发票价税合计。否则金蝶会报「发票金额不允许小于报销金额」。
  • 明细跟发票走。费用申请单的金额只是预估,实际发生可以在报销时调整: 申请 100 元(招待 80 + 交通 20)→ 实际发票 90 元(招待 85 + 交通 5),明细就按发票写 85 / 5, 必要时连费用项目一起改。
  • 发票 > 申请单:先跟申请人确认按哪个金额提交,并排查是否多开。 若属多开,不能按发票金额,必须按实际付款金额报销。
  • 发票 < 申请单:属正常下调,按发票金额提交。
  • 凡申请单 ↔ 发票不一致,一律先跟申请人确认再提交,不要自行拍板。

🎒 发票和行程单要分开放(关键)

放哪 用什么 参与金额校验?
收票信息 报销单 RecInvInfo 单据体 → 关联收票单 ✅ 是,「发票金额 ≥ 报销金额」读这里
附件 AttachmentUpLoad ❌ 否
  • 网约车必须同步提交行程单。识别到就传附件;没识别到要提醒申请人财务可能驳回(但不硬拦)。
  • ⚠️ 行程单金额绝不能当发票金额。部分环境会把行程单也 OCR 成发票金额,造成同一笔业务双算。
  • 校验报错「发票金额不允许小于报销金额」= 收票信息里没有有效收票单(发票传错了位置,或被传到了附件)。

🛠️ 命令速查

# 收票信息 / 提交(helpers/recvin_link.py)
python helpers/recvin_link.py find <发票号码|收票单号>
python helpers/recvin_link.py list <报销单FID>
python helpers/recvin_link.py link <报销单FID> <收票单号> [--replace] [--allow-steal]
python helpers/recvin_link.py clear <报销单FID>
python helpers/recvin_link.py set-contact <报销单FID> <员工号>
python helpers/recvin_link.py precheck <报销单FID>
python helpers/recvin_link.py submit <报销单FID>
python helpers/recvin_link.py verify <报销单FID> <收票单号>

# 明细 / 联动 / 附件(helpers/expense_edit.py)
python helpers/expense_edit.py set-detail <报销单FID> --entry <分录内码> --amount <金额>
python helpers/expense_edit.py linkage <报销单FID> --recv <收票单号> --entry <分录内码>
python helpers/expense_edit.py attach <报销单FID> <文件路径>
python helpers/expense_edit.py download <FileId> [--out 本地路径]
python helpers/expense_edit.py check <报销单FID>

# 差旅费报销单:以上命令都加 --travel(写在子命令前或后均可,如 `--travel attach ...`)

🤖 让 AI 工具识别这个 Skill

仓库采用“一个仓库一个 Skill”的通用结构,SKILL.md 位于仓库根目录:

KingdeeExpenseFlow/
├── SKILL.md                     AI 执行说明与触发描述
├── README.md
├── LICENSE
├── config.example.py            安全配置示例
├── requirements.txt
├── agents/openai.yaml           AI 客户端展示信息
├── helpers/
│   ├── recvin_link.py           收票信息写入 / 提交(核心)
│   ├── expense_edit.py          明细对齐 / 联动 / 附件(核心)
│   ├── invoice_classifier.py    发票 vs 行程单分类与双算预警
│   └── piazzone_*.py            发票云兜底(可选,默认不需要)
├── references/
│   ├── field_cookbook.md        字段级接口配方(实测)
│   └── policy_rules.md          报销制度**模板**(全是【待填】空位;本公司规则请放 `references/policy_rules.local.md`,该文件不进仓库)
└── 官方接口说明/                金蝶 WebAPI 原始文档

支持从 GitHub 扫描 Skill 的工具,可以直接使用仓库地址:

https://github.com/LittleBeaverStudio/KingdeeExpenseFlow

识别后可这样发起任务:

请使用 kingdee-expense-flow,帮我把这张发票提交成费用报销单,员工不登录金蝶。

SkillHub / 其他管理器

能递归扫描 SKILL.md 的 SkillHub 或桌面管理器可以直接识别本仓库。若平台要求上传压缩包,请压缩整个仓库,并确认解压后根目录中仍有 SKILL.md。

📋 报销制度:本 Skill 只管机制,制度请自己填

各公司制度不一样(住宿限额、招待费审批、报销时限、税号……),所以本 Skill 不内置任何具体制度, references/policy_rules.md 是一份全是【待填】空位的模板。

要接入贵司制度:

cp references/policy_rules.md references/policy_rules.local.md   # 然后按贵司规则填空
  • policy_rules.local.md 已在 .gitignore / .clawhubignore 里,不会进仓库、不会外泄。
  • agent 会优先读它;读不到就只按通用口径处理,并且对【待填】的项明确说"还没登记",不会替你编一个限额。
  • 只有两块是通用的(与实现绑定,任何公司都适用):① 金额与发票一致性口径(按发票金额调低报销额); ② 行程单必须传附件(防止与发票重复计入)。

🛠️ 常见问题

提示「发票金额不允许小于报销金额」

报销金额比收票信息里的发票金额大。两种情况:

  1. 发票没挂对位置 —— 用 recvin_link.py list <FID> 看收票信息是不是空的;
  2. 报销金额该下调 —— 按实际发票金额改明细:expense_edit.py set-detail … --amount <实际额>。

find 查不到发票

  • 发票还没进收票池 —— ⚠️ 不要指望"系统会自动归集":金蝶后台的"下载发票"每次都要电子税务局账号的手机验证码,无法定时无人值守。可靠做法是让员工在报销软件 / 发票云里把这张票上传一次(当天进池、当天有流水号);
  • 号码填错;
  • 该发票属于其它组织/账套;
  • 该票已被删除(删单会释放归属)。

附件上传返回成功,但金蝶里看不到

AttachmentUpLoad 的 IsLast 是必填布尔,漏传会被当成「非最后分片」——接口照样返回 IsSuccess=true 和一个 FileId,但内容根本没落库。

判断办法只有一个:回环下载比字节(expense_edit.py attach 已内置该校验,会打印 md5 是否一致)。

报「单据编辑冲突,请稍候再使用」

这是编辑互斥锁的瞬时占用,等几秒重试即可(工具已内置自动重试)。不需要关客户端,也不需要重新下推单据。

提交后还能改吗

B(已提交)和 C(已审核)状态的单据都能继续 Save 改。但操作已审核单据前务必确认状态,别误改历史单。

📁 主要文件

SKILL.md                     AI 执行说明与触发描述
README.md                    中文使用介绍
helpers/recvin_link.py       收票信息写入 / 往来单位 / 体检 / 提交(纯标准库)
helpers/expense_edit.py      明细金额对齐 / 明细↔发票联动 / 附件上传(纯标准库)
helpers/invoice_classifier.py 发票与行程单分类、字段提取、双算预警
references/field_cookbook.md  字段与接口配方手册(全部为实测结论)
references/policy_rules.md    差旅住宿/招待费等报销制度**模板**(全是【待填】空位;本公司规则请放 `references/policy_rules.local.md`,该文件不进仓库)
官方接口说明/                 金蝶 WebAPI 官方文档(Save / Submit / 收票单)

本工具仅用于你有权访问的金蝶环境。使用者需要自行负责凭据保管、权限控制和数据合规。 报销金额、费用项目与发票的匹配口径,请以贵司财务制度为准。

About

金蝶云星空费用/差旅报销全流程提交 Skill|员工发票→申请→下推报销→提交审批(expense/reimbursement flow)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages