Files
Auto-Finance/docs/API.md
2026-06-11 19:22:34 +08:00

11 KiB
Raw Blame History

last_reviewed
last_reviewed
2026-06-09

财务报销自动化 — API 文档

基础地址: http://localhost:5000
启动: uv run python src/web/app.py

总览

# 方法 路径 说明
1 GET / PC 端主页
2 POST /api/session 创建会话
3 POST /api/upload/<session_id> 上传文件PDF/图片)
4 GET /api/files/<session_id> 列出会话目录中的文件
5 POST /api/process/<session_id> 启动处理(提取+LLM识别+出库单)
6 GET /api/logs/<session_id> SSE 日志流
7 GET /api/download/<session_id>/<filename> 下载生成的文件
8 GET /api/data/<session_id> 获取发票数据JSON
9 POST /api/save/<session_id> 保存编辑后的发票数据
10 POST /api/submit-financial/<session_id> 提交到财务系统
11 GET /mobile/<session_id> 移动端上传页面
12 POST /api/mobile-upload/<session_id> 移动端上传图片

会话与目录

  • 调用 POST /api/session 获得 session_id
  • 该会话下所有文件存放在 src/web/uploads/<session_id>/
  • 典型产物:invoice_summary.csv易耗品、出库单.docconfig.jsonsession.logresult.json

接口详情

1. 创建会话

POST /api/session

响应:

{ "session_id": "a1b2c3d4e5f6" }

2. 上传文件PDF/图片)

POST /api/upload/<session_id>
Content-Type: multipart/form-data
字段 类型 说明
file File PDF 发票或支付截图

响应(成功):

{ "ok": true, "filename": "1. 电容一批.pdf" }

响应(失败):

{ "error": "未选择文件" }

HTTP 400


3. 列出会话文件

GET /api/files/<session_id>

响应:

{
  "pdfs": ["1. 电容一批.pdf"],
  "images": ["payment_01.jpg"]
}

images 包含扩展名:.png.jpg.jpeg.bmp.webp


5. 启动管道处理

POST /api/process/<session_id>
Content-Type: application/json

请求体:

字段 类型 必填 说明
username string 财务系统工号
password string 登录密码
default_name string 默认报销人姓名
default_card_no string 默认公务卡号
default_person_id string 默认人员编号
consumable_storage string 出库单存放地点;未填则用 config.json 中的值

处理内容:

  1. 从会话目录 PDF 提取发票信息 → invoice_summary.csv
  2. 对支付截图多模态 LLM 识别,回填刷卡字段
  3. 根据发票类型自动分类:差旅发票(高铁票/酒店住宿)不生成出库单;普通发票从模板复制并自动填写

配置会写入 src/web/uploads/<session_id>/config.json

响应(立即):

{ "status": "started" }

处理在后台线程执行,进度与结果通过 GET /api/logs/<session_id>SSE获取。

SSE 完成时 result 示例(成功):

{
  "ok": true,
  "elapsed": "45.2s",
  "invoice_count": 4,
  "csv_url": "/api/download/<session_id>/invoice_summary.csv",
  "travel_count": 2,
  "general_count": 2,
  "doc_url": "/api/download/<session_id>/%E6%98%93%E8%80%97%E5%93%81%E3%80%81%E5%87%BA%E5%BA%93%E5%8D%95.doc",
  "doc_ok": true
}

纯差旅发票(跳过出库单生成):

{
  "ok": true,
  "invoice_count": 3,
  "csv_url": "/api/download/<session_id>/invoice_summary.csv",
  "travel_count": 3,
  "general_count": 0,
  "doc_ok": null,
  "doc_skipped": true,
  "doc_message": "差旅发票无需生成易耗品出库单"
}

出库单生成失败时CSV 等仍可能成功):

{
  "ok": true,
  "invoice_count": 4,
  "csv_url": "/api/download/<session_id>/invoice_summary.csv",
  "travel_count": 2,
  "general_count": 2,
  "doc_ok": false,
  "doc_error": "服务器未安装 pywin32无法生成 Word 出库单"
}

字段说明:

字段 类型 说明
travel_count int 差旅发票数量(高铁票/酒店住宿)
general_count int 普通发票数量
doc_ok bool/null true=成功,false=失败,null=已跳过(纯差旅发票)
doc_skipped bool 是否因纯差旅发票而跳过出库单生成
doc_message string 跳过时的提示信息

6. SSE 日志流

GET /api/logs/<session_id>
Accept: text/event-stream

日志行格式:

data: 2026-05-26 12:00:01 [INFO ] extractor: 正在提取发票...

结束消息:

{
  "type": "done",
  "result": { }
}

result 结构取决于触发来源:

来源 典型字段
/api/process ok, elapsed, invoice_count, csv_url, travel_count, general_count, doc_url, doc_ok, doc_skipped, doc_error
/api/submit-financial ok, submit_ok, submit_error

SSE 超时时间为 10 分钟600 秒)。


7. 下载文件

GET /api/download/<session_id>/<filename>

响应: 文件二进制流,带 Content-Disposition: attachment 与 UTF-8 文件名。

扩展名 Content-Type
.csv text/csv; charset=utf-8
.doc application/msword
其它 application/octet-stream

常见文件名:

文件名 说明
invoice_summary.csv 发票汇总(含 LLM 识别结果)
易耗品、出库单.doc 自动填写的出库单

错误:

{ "error": "文件不存在" }

HTTP 404filename 仅允许会话目录内的文件名(防止路径穿越)。


8. 获取发票数据

GET /api/data/<session_id>

响应:

{
  "csv_filename": "invoice_summary.csv",
  "fields": [
    "序号", "发票号码", "开票日期", "项目名称", "规格型号",
    "价税合计", "销售方名称", "人员姓名", "刷卡日期",
    "公务卡号", "刷卡金额", "备注", "工号"
  ],
  "data": [
    {
      "__row": 0,
      "序号": "1",
      "发票号码": "26442000005432755951",
      "价税合计": "2900.00"
    }
  ]
}
  • fields:列顺序
  • data[].__row:内部行索引(保存时不需要提交,服务端按数组顺序写回)

错误: 404 未找到 CSV500 读取失败。


9. 保存编辑后的发票数据

POST /api/save/<session_id>
Content-Type: application/json

请求体:

{
  "csv_filename": "invoice_summary.csv",
  "data": [
    {
      "序号": "1",
      "发票号码": "26442000005432755951",
      "开票日期": "2026/05/18",
      "项目名称": "...",
      "规格型号": "...",
      "价税合计": "2900.00",
      "销售方名称": "...",
      "人员姓名": "",
      "刷卡日期": "2026/04/28",
      "公务卡号": "",
      "刷卡金额": "2850.00",
      "备注": "",
      "工号": "202407021"
    }
  ]
}

响应(成功):

{
  "ok": true,
  "doc_ok": true,
  "doc_url": "/api/download/<session_id>/%E6%98%93%E8%80%97%E5%93%81%E3%80%81%E5%87%BA%E5%BA%93%E5%8D%95.doc"
}

保存后会根据最新 CSV 重新生成 出库单 Word与会话 config.json 中的 consumable_storage 等配置一致)。

纯差旅发票跳过出库单:

{
  "ok": true,
  "doc_ok": null,
  "doc_skipped": true
}

出库单生成失败:

{
  "ok": true,
  "doc_ok": false,
  "doc_error": "出库单模板不存在,请将模板放在项目根目录"
}

10. 提交到财务系统

POST /api/submit-financial/<session_id>

前置条件:

  • 会话目录存在 config.json(由 /api/process 写入),否则返回 400
  • 存在可用的发票 CSV通常为 invoice_summary.csv

说明:

  • 前端一般在提交前调用 /api/save 保存表格修改
  • 本接口不会自动执行发票提取或 LLM 识别
  • 根据发票类型选择填报模式:纯差旅发票走差旅报销流程,含普通发票走普通报销流程

响应(立即):

{ "status": "started" }

SSE 完成示例:

{
  "type": "done",
  "result": {
    "ok": true,
    "submit_ok": true
  }
}

失败时 submit_ok: falsesubmit_error 为错误描述。


11. 移动端上传页面

GET /mobile/<session_id>

返回移动端 HTML 页面。扫码上传的图片与 PC 端共用同一会话目录PC 通过轮询 GET /api/files/<session_id> 同步文件列表。


12. 移动端上传图片

POST /api/mobile-upload/<session_id>
Content-Type: multipart/form-data
字段 类型 说明
file File 图片文件

逻辑与 POST /api/upload/<session_id> 相同。


错误码汇总

HTTP 场景
400 参数缺失、未找到配置等
404 session_id 不存在、文件不存在
500 CSV 读取失败等内部错误

统一错误体:

{ "error": "错误描述" }

发票类型分类

系统自动将发票分为两类,影响出库单生成和后续报销流程:

类型 判断依据 出库单 报销流程
差旅发票 高铁票、酒店住宿等 不生成 差旅报销
普通发票 其他(办公用品、耗材等) 自动生成 普通报销

/api/process/api/save 的响应中 travel_count / general_count 即为分类统计。


端到端流程

sequenceDiagram
    participant PC as PC 端
    participant Server as Server
    participant Mobile as 移动端
    participant Word as Word COM

    PC->>Server: POST /api/session
    Server-->>PC: session_id

    PC->>Server: POST /api/upload/{sid}
    PC->>Server: POST /api/process/{sid}
    Note over Server: PDF 提取 + LLM 识别 + 写 config.json
    alt 含普通发票
        Server->>Word: 从模板复制并填写出库单
    else 纯差旅发票
        Note over Server: 跳过出库单生成
    end
    Server-->>PC: SSE done (csv_url, doc_url, ...)

    PC->>Server: GET /api/data/{sid}
    Server-->>PC: fields + data
    PC->>Server: POST /api/save/{sid}
    Note over Server: 更新 CSV重新生成出库单
    Server-->>PC: doc_url

    PC->>Server: GET /api/download/{sid}/易耗品、出库单.doc

    PC->>Server: POST /api/submit-financial/{sid}
    Note over Server: Playwright 浏览器填报
    Server-->>PC: SSE done (submit_ok)

    Mobile->>Server: POST /api/mobile-upload/{sid}
    PC->>Server: GET /api/files/{sid} (轮询)

相关 CLI

不经过 Web、在本地直接填写出库单

uv run python -m src.doc.fill_consumable_doc --csv invoice_summary.csv --doc "易耗品、出库单.doc"

详见 README.md