Files
Auto-Finance/API.md
wandering a72c4ffaab feat: Web 表格编辑、易耗品出库单自动生成与文档完善
- 新增 fill_consumable_doc,根据 CSV 填写 Word 出库单(宋体五号)
- Web 处理完成后自动生成出库单并提供下载
- 前端拆分为 static 资源,支持在线编辑 CSV 与分步提交财务系统
- 补充 API.md、README(含 Mermaid 数据流)及 config.example.json

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-26 14:17:26 +08:00

464 lines
9.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 财务报销自动化 — API 文档
> 基础地址: `http://localhost:5000`
> 启动: `python web/app.py`
## 总览
| # | 方法 | 路径 | 说明 |
|---|------|------|------|
| 1 | GET | `/` | PC 端主页 |
| 2 | POST | `/api/session` | 创建会话 |
| 3 | POST | `/api/upload/<session_id>` | 上传文件PDF/图片) |
| 4 | POST | `/api/upload-csv/<session_id>` | 上传 CSV 发票数据 |
| 5 | GET | `/api/files/<session_id>` | 列出会话目录中的文件 |
| 6 | POST | `/api/process/<session_id>` | 启动处理(提取+OCR+出库单) |
| 7 | GET | `/api/logs/<session_id>` | SSE 日志流 |
| 8 | GET | `/api/download/<session_id>/<filename>` | 下载生成的文件 |
| 9 | GET | `/api/data/<session_id>` | 获取发票数据JSON |
| 10 | POST | `/api/save/<session_id>` | 保存编辑后的发票数据 |
| 11 | POST | `/api/submit-financial/<session_id>` | 提交到财务系统 |
| 12 | GET | `/mobile/<session_id>` | 移动端上传页面 |
| 13 | POST | `/api/mobile-upload/<session_id>` | 移动端上传图片 |
---
## 会话与目录
- 调用 `POST /api/session` 获得 `session_id`
- 该会话下所有文件存放在 `web/uploads/<session_id>/`
- 典型产物:`invoice_summary.csv``invoice_summary.md``易耗品、出库单.doc``config.json``session.log``result.json`
---
## 接口详情
### 1. 创建会话
```
POST /api/session
```
**响应:**
```json
{ "session_id": "a1b2c3d4e5f6" }
```
---
### 2. 上传文件PDF/图片)
```
POST /api/upload/<session_id>
Content-Type: multipart/form-data
```
| 字段 | 类型 | 说明 |
|------|------|------|
| file | File | PDF 发票或支付截图 |
**响应(成功):**
```json
{ "ok": true, "filename": "1. 电容一批.pdf" }
```
**响应(失败):**
```json
{ "error": "未选择文件" }
```
HTTP `400`
---
### 3. 上传 CSV 发票数据
```
POST /api/upload-csv/<session_id>
Content-Type: multipart/form-data
```
| 字段 | 类型 | 说明 |
|------|------|------|
| file | File | 发票汇总 CSV |
**响应(成功):**
```json
{ "ok": true, "filename": "invoice_summary.csv" }
```
> 上传 CSV 后可跳过 PDF 提取和 OCR直接进入处理/编辑流程。
---
### 4. 列出会话文件
```
GET /api/files/<session_id>
```
**响应:**
```json
{
"pdfs": ["1. 电容一批.pdf"],
"images": ["payment_01.jpg"]
}
```
`images` 包含扩展名:`.png``.jpg``.jpeg``.bmp``.webp`
---
### 5. 启动管道处理
```
POST /api/process/<session_id>
Content-Type: application/json
```
**请求体:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| mode | string | 否 | `"pdf"` / `"csv"` / `"auto"`(默认 `auto` |
| username | string | 否 | 财务系统工号 |
| password | string | 否 | 登录密码 |
| default_name | string | 否 | 默认报销人姓名 |
| default_card_no | string | 否 | 默认公务卡号 |
| default_person_id | string | 否 | 默认人员编号 |
| consumable_storage | string | 否 | 出库单存放地点;未填则用 `config.json` 中的值 |
**mode 行为:**
| mode | 行为 |
|------|------|
| `auto` | 仅有 CSV、无 PDF → CSV 模式;否则 → PDF 提取 + OCR |
| `csv` | 使用已上传 CSV跳过提取与 OCR |
| `pdf` | 执行 PDF 提取 + OCR |
**处理内容PDF 模式):**
1. 从会话目录 PDF 提取发票信息 → `invoice_summary.csv` / `.md`
2. 对支付截图 OCR回填刷卡字段
3. 从项目根目录复制 `易耗品、出库单.doc` 模板到会话目录并自动填写(需 Windows + Word
配置会写入 `web/uploads/<session_id>/config.json`
**响应(立即):**
```json
{ "status": "started" }
```
处理在后台线程执行,进度与结果通过 `GET /api/logs/<session_id>`SSE获取。
**SSE 完成时 `result` 示例(成功):**
```json
{
"ok": true,
"elapsed": "45.2s",
"invoice_count": 4,
"csv_url": "/api/download/<session_id>/invoice_summary.csv",
"md_url": "/api/download/<session_id>/invoice_summary.md",
"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
}
```
**出库单生成失败时CSV 等仍可能成功):**
```json
{
"ok": true,
"invoice_count": 4,
"csv_url": "/api/download/<session_id>/invoice_summary.csv",
"doc_ok": false,
"doc_error": "服务器未安装 pywin32无法生成 Word 出库单"
}
```
---
### 6. SSE 日志流
```
GET /api/logs/<session_id>
Accept: text/event-stream
```
**日志行格式:**
```
data: 2026-05-26 12:00:01 [INFO ] extractor: 正在提取发票...
```
**结束消息:**
```json
{
"type": "done",
"result": { }
}
```
`result` 结构取决于触发来源:
| 来源 | 典型字段 |
|------|----------|
| `/api/process` | `ok`, `elapsed`, `invoice_count`, `csv_url`, `md_url`, `doc_url`, `doc_ok`, `doc_error` |
| `/api/submit-financial` | `ok`, `submit_ok`, `submit_error` |
---
### 7. 下载文件
```
GET /api/download/<session_id>/<filename>
```
**响应:** 文件二进制流,带 `Content-Disposition: attachment` 与 UTF-8 文件名。
| 扩展名 | Content-Type |
|--------|----------------|
| `.csv` | `text/csv; charset=utf-8` |
| `.md` | `text/markdown; charset=utf-8` |
| `.doc` | `application/msword` |
| 其它 | `application/octet-stream` |
**常见文件名:**
| 文件名 | 说明 |
|--------|------|
| `invoice_summary.csv` | 发票汇总(含 OCR 结果) |
| `invoice_summary.md` | Markdown 摘要 |
| `易耗品、出库单.doc` | 自动填写的出库单 |
| 用户上传的 CSV 名 | CSV 快捷模式下的原始文件 |
**错误:**
```json
{ "error": "文件不存在" }
```
HTTP `404``filename` 仅允许会话目录内的文件名(防止路径穿越)。
---
### 8. 获取发票数据
```
GET /api/data/<session_id>
```
**响应:**
```json
{
"csv_filename": "invoice_summary.csv",
"fields": [
"序号", "发票号码", "开票日期", "项目名称", "规格型号",
"价税合计", "销售方名称", "人员姓名", "刷卡日期",
"公务卡号", "刷卡金额", "备注", "工号"
],
"data": [
{
"__row": 0,
"序号": "1",
"发票号码": "26442000005432755951",
"价税合计": "2900.00"
}
]
}
```
- `fields`:列顺序
- `data[].__row`:内部行索引(保存时不需要提交,服务端按数组顺序写回)
**错误:** `404` 未找到 CSV`500` 读取失败。
---
### 9. 保存编辑后的发票数据
```
POST /api/save/<session_id>
Content-Type: application/json
```
**请求体:**
```json
{
"csv_filename": "invoice_summary.csv",
"data": [
{
"序号": "1",
"发票号码": "26442000005432755951",
"开票日期": "2026/05/18",
"项目名称": "...",
"规格型号": "...",
"价税合计": "2900.00",
"销售方名称": "...",
"人员姓名": "",
"刷卡日期": "2026/04/28",
"公务卡号": "",
"刷卡金额": "2850.00",
"备注": "",
"工号": "202407021"
}
]
}
```
**响应(成功):**
```json
{
"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` 等配置一致)。
若出库单生成失败:
```json
{
"ok": true,
"doc_ok": false,
"doc_error": "出库单模板不存在,请将模板放在项目根目录"
}
```
---
### 10. 提交到财务系统
```
POST /api/submit-financial/<session_id>
```
**前置条件:**
- 会话目录存在 `config.json`(由 `/api/process` 写入)
- 存在可用的发票 CSV通常为 `invoice_summary.csv`
**说明:** 前端一般在提交前调用 `/api/save` 保存表格修改。本接口**不会**自动执行发票提取或 OCR。
**响应(立即):**
```json
{ "status": "started" }
```
**SSE 完成示例:**
```json
{
"type": "done",
"result": {
"ok": true,
"submit_ok": true
}
}
```
失败时 `submit_ok: false``submit_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 读取失败等内部错误 |
统一错误体:
```json
{ "error": "错误描述" }
```
---
## 端到端流程
```mermaid
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 提取 + OCR + 写 config.json
Server->>Word: 复制模板并填写出库单
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、在本地直接填写出库单
```bash
python -m app.fill_consumable_doc --csv invoice_summary.csv --doc "易耗品、出库单.doc"
```
详见 [README.md](./README.md)。