# 飞书报销审批模板整合方案

更新时间：2026-06-05

## 1. 当前结论

现有 `finance-assistant` skill 与当前云端财务系统采用“机器人优先 + 审批边界”的流程：

```text
用户/内部成员口述或上传发票
  -> 财务机器人读取入库规则
  -> 解析主体/项目/金额/发票/附件
  -> 创建 intake_draft 草稿
  -> 生成 preview 给用户/审批人确认
  -> 飞书审批或人工确认边界
  -> 审批通过后 commit
  -> PostgreSQL 正式事实表：reimbursement_order / reimbursement_item / invoice / attachment / audit_log
  -> 实际付款后再写 fund_transaction + reimbursement_payment 核销
```

当前线上系统已经支持 `approval_instance_id`、`approved_by` 和 commit 边界，但尚未真实自动发起飞书审批，也尚未接入飞书审批回调。也就是说：

- 已有“审批边界”和“审批引用字段”；
- 可以手工确认后正式入库；
- 暂时没有自动走飞书审批模板；
- 需要把用户已创建的报销审批模板映射到系统字段和回调逻辑。

## 2. 推荐整合方式

不要把飞书审批当成最终账本。飞书审批只负责：

1. 收集/展示申请信息；
2. 审批人同意/驳回；
3. 提供审批实例号和审批状态；
4. 附带发票/附件凭证。

财务系统仍然以 PostgreSQL 事实表为 source of truth。

推荐状态流：

```text
intake_draft.VALIDATED
  -> 发起飞书审批
intake_draft.APPROVAL_PENDING
  -> 飞书审批通过回调
intake_draft.APPROVED
  -> 自动或人工触发 commit
intake_draft.COMMITTED
  -> reimbursement_order.status = PENDING_PAYMENT
  -> 后续付款核销
```

驳回/撤回：

```text
intake_draft.APPROVAL_PENDING
  -> REJECTED / VOID
  -> 不创建正式 reimbursement_order
```

## 3. 模板建议分类

用户已创建的模板需要先登记到配置中。建议至少区分以下几类：

| 模板用途 | 系统 intent | 适用场景 | 通过后动作 |
|---|---|---|---|
| 公共账报销专用 | `record_reimbursement` | 员工/个人先垫付，向公司公共账报销 | commit 报销单，等待付款核销 |
| 有票费用报销 | `record_reimbursement` | 已有电子发票/纸票，发票状态为 `INVOICED`/`VERIFIED` | commit 报销单 + invoice |
| 无票/待补票报销 | `record_reimbursement` | 无票、待补票、个人垫付，可能影响个人账 | commit 报销单，标记 risk flag |
| 公司还个人/报销付款 | `company_repay_person` / `record_fund_out` | 已经付款给个人，核销已批准报销 | 创建 fund_transaction + reimbursement_payment |
| 项目采购/供应商付款 | `record_payable` / `record_fund_out` | 对外供应商付款，不一定是个人报销 | 进入应付/付款流程 |

如果你已经创建的是多个飞书模板，不一定要全部走报销单；有些模板可能更适合映射为“付款申请”或“供应商应付”。

## 4. 需要从飞书模板中拿到的信息

每个模板请记录以下非密钥信息：

```text
模板显示名称
审批定义 code / approval_code
模板链接或工作台路径
适用业务类型
审批人/抄送规则简述
字段清单：字段名、控件类型、是否必填、选项值
附件字段名称
金额字段名称
项目/主体字段名称
费用类别字段名称
发票字段名称
备注字段名称
是否允许多明细
是否有付款账户/收款账户字段
```

不要把 App Secret、Verification Token、Encrypt Key、cookie、用户登录态写入文档。

## 5. 字段映射草案

### 5.1 报销申请模板 -> `record_reimbursement`

| 飞书字段 | 系统字段 | 说明 |
|---|---|---|
| 申请人 | `applicant_subject_id` | 映射到 subject |
| 报销人/收款人 | `payee_subject_id` | 默认可等于申请人 |
| 报销金额 | `items[].amount` 或合计拆明细 | 多明细时逐条入 item |
| 所属项目 | `items[].project_id` | 无项目时用主体基础经营项目 |
| 费用归属主体 | `items[].owner_subject_id` | 从项目或字段推导 |
| 费用类别 | `items[].expense_category_id` | 映射 expense_category |
| 发票状态 | `items[].invoice_status` | NO_INVOICE / PENDING_INVOICE / INVOICED / VERIFIED |
| 发票号码 | `items[].invoice.invoice_no` | 可选 |
| 开票日期 | `items[].invoice.issued_at` | 可选 |
| 发票金额 | `items[].invoice.amount_total` | 通常等于明细金额或可部分关联 |
| 发票附件 | `items[].invoice.file_attachment` / `attachments[]` | 存文件 token/路径/对象存储引用 |
| 备注/事由 | `items[].description` / `remark` | 用于 preview 和审计 |

### 5.2 审批实例 -> 系统审计

| 飞书信息 | 系统字段 |
|---|---|
| approval_code | `approval_template_code`（待新增或放入 JSON metadata） |
| instance_code | `intake_draft.approval_instance_id` |
| approval status | `intake_draft.status` |
| approver | `approved_by` / audit_log.after_json |
| approval time | `reimbursement_order.approved_at` / audit_log.operated_at |
| reject reason | `intake_draft.validation` 或待新增 `approval_result_json` |

## 6. 后端待补能力

建议下一步新增以下后端能力：

1. `feishu_approval_templates` 配置文件：保存模板 code 和字段映射；
2. `POST /api/approval/feishu/start`：基于 draft 发起飞书审批；
3. `POST /api/approval/feishu/callback`：接收审批通过/拒绝/撤回事件；
4. `finance_start_reimbursement_approval` MCP 工具；
5. `finance_handle_approval_callback` 内部工具或 webhook handler；
6. 数据库字段增强：审批模板 code、审批状态、审批原始事件摘要；
7. 回调去重：按 `instance_code` + event idempotency key 去重。

## 7. 整合顺序

建议按这个顺序做，避免一上来就调真实审批导致错单：

1. 用户提供已创建模板的字段清单/截图/链接；
2. 先整理模板配置，不写生产数据；
3. 用一条测试报销草稿生成“将要提交给飞书的 payload”；
4. 用户确认字段映射无误；
5. 接入发起审批 API；
6. 接入审批回调；
7. 用测试模板/测试金额跑通：发起 -> 通过 -> commit -> 查询；
8. 再把正式模板接到真实报销流程。

## 8. 用户需要提供

请把你创建的报销审批模板信息发过来，任选一种方式即可：

1. 每个模板的飞书链接；
2. 模板字段截图；
3. 审批模板导出的字段清单；
4. 直接口述：模板名、字段名、哪些必填、附件字段叫啥、金额字段叫啥。

我拿到后会把它们整理成模板配置，并接入当前云端财务系统。
