重构项目为LLM 驱动
This commit is contained in:
184
README.md
184
README.md
@@ -1,31 +1,44 @@
|
||||
# 财务报销自动化
|
||||
|
||||
自动从 PDF 发票提取信息,OCR 识别支付记录截图,生成发票汇总表与易耗品出库单,并可选在财务系统中自动填报报销单。
|
||||
自动从 PDF 发票提取信息,生成发票汇总表与易耗品出库单,并可选在财务系统中自动填报报销单。
|
||||
|
||||
**支持发票类型区分**:系统自动识别高铁票、酒店住宿等差旅发票与普通发票。差旅发票不生成易耗品出库单,走差旅报销流程;普通发票生成出库单,走普通报销流程。
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
├── run.py # CLI 入口(发票提取 → OCR → 浏览器填报)
|
||||
├── config.json # 配置文件(登录凭据、默认值、存放地点等)
|
||||
├── 易耗品、出库单.doc # 易耗品出库单 Word 模板(Web/CLI 填写用)
|
||||
├── app/
|
||||
│ ├── config.py # 配置加载
|
||||
│ ├── extractor.py # PDF 发票信息提取
|
||||
│ ├── ocr.py # OCR 刷卡信息识别
|
||||
│ ├── bot.py # 浏览器自动填报
|
||||
│ ├── pipeline.py # CLI 流程编排
|
||||
│ └── fill_consumable_doc.py # 将 CSV 填入易耗品出库单(Word COM)
|
||||
├── web/
|
||||
│ ├── app.py # Web 服务入口
|
||||
│ ├── templates/
|
||||
│ │ ├── index.html # PC 端主页
|
||||
│ │ └── mobile_upload.html # 移动端扫码上传
|
||||
│ ├── static/ # 前端 CSS / JS
|
||||
│ └── uploads/ # 按会话隔离的上传与产物目录
|
||||
├── *.pdf # 发票 PDF(CLI 模式,放在项目根目录)
|
||||
├── *.png / *.jpg # 与 PDF 配对的支付截图
|
||||
├── invoice_summary.csv # 发票汇总表(CLI 产物)
|
||||
└── images/ # 浏览器调试截图
|
||||
├── pyproject.toml # 项目配置(依赖、工具链)
|
||||
├── uv.lock # 依赖锁定文件
|
||||
├── Makefile # 任务脚本(跨平台)
|
||||
├── tasks.py # 任务脚本(Windows 兼容)
|
||||
├── config.json # 配置文件(登录凭据、默认值等)
|
||||
├── config.example.json # 配置示例
|
||||
├── 易耗品、出库单.doc # 易耗品出库单 Word 模板
|
||||
├── src/
|
||||
│ ├── __init__.py # 包初始化 / 日志器
|
||||
│ ├── config.py # 配置加载
|
||||
│ ├── bot.py # 浏览器自动填报
|
||||
│ ├── pipeline.py # CLI 流程编排
|
||||
│ ├── main.py # CLI 入口
|
||||
│ ├── doc/ # 文档处理模块
|
||||
│ │ ├── extractor.py # 编排入口:串联 PDF 读取 → LLM 提取 → 分类
|
||||
│ │ ├── pdf.py # PDF 文件发现与文本提取
|
||||
│ │ ├── llm_extractor.py # LLM 信息提取
|
||||
│ │ ├── invoice.py # 发票类型常量、分类逻辑、CSV 读写工具
|
||||
│ │ ├── fill_consumable_doc.py # 将 CSV 填入易耗品出库单(Word COM)
|
||||
│ │ ├── prompt.py # LLM 提示词模板
|
||||
│ │ └── prompts/ # 提示词模板文件
|
||||
│ └── web/
|
||||
│ ├── app.py # Web 服务入口
|
||||
│ ├── templates/
|
||||
│ │ ├── index.html # PC 端主页
|
||||
│ │ └── mobile_upload.html # 移动端扫码上传
|
||||
│ ├── static/ # 前端 CSS / JS
|
||||
│ └── uploads/ # 按会话隔离的上传与产物目录
|
||||
├── tests/ # 测试目录
|
||||
├── *.pdf # 发票 PDF(CLI 模式,放在项目根目录)
|
||||
├── invoice_summary.csv # 发票汇总表(CLI 产物)
|
||||
└── images/ # 浏览器调试截图
|
||||
```
|
||||
|
||||
## 数据流
|
||||
@@ -33,49 +46,47 @@
|
||||
```mermaid
|
||||
flowchart TB
|
||||
PDF[PDF 发票] --> Extract[extractor 提取]
|
||||
Extract --> List[发票列表]
|
||||
Img[支付截图] --> OCR[OCR 识别]
|
||||
List --> OCR
|
||||
OCR --> CSV[(invoice_summary.csv)]
|
||||
CSV --> Fill[fill_consumable_doc]
|
||||
Extract --> Classify{发票类型分类}
|
||||
Classify -->|差旅发票| Travel[高铁票 / 酒店住宿]
|
||||
Classify -->|普通发票| General[普通发票]
|
||||
Travel --> CSV[(invoice_summary.csv)]
|
||||
General --> CSV
|
||||
CSV -->|仅普通发票| Fill[fill_consumable_doc]
|
||||
Fill --> Doc[易耗品、出库单.doc]
|
||||
CSV --> Bot[bot 浏览器自动化]
|
||||
Bot --> Submit[财务系统填报<br/>可选]
|
||||
Bot -->|差旅模式| Submit_T[差旅报销填报<br/>TODO]
|
||||
Bot -->|普通模式| Submit_G[普通报销填报]
|
||||
```
|
||||
|
||||
## 环境要求
|
||||
|
||||
- Python 3.10+
|
||||
- **Python 3.12+**
|
||||
- **uv** 包管理器([安装指南](https://docs.astral.sh/uv/getting-started/installation/))
|
||||
- Windows(易耗品出库单填写依赖 Microsoft Word + COM,仅 Windows 可用)
|
||||
- 主要依赖见下方安装步骤
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 安装依赖
|
||||
|
||||
> OCR 相关依赖建议在已有 PaddleOCR 的环境中安装(如 MinerU 虚拟环境)。
|
||||
|
||||
```bash
|
||||
pip install pdfplumber==0.11.9 paddleocr==2.8.1 playwright==1.60.0 flask==3.0.3 pywin32
|
||||
playwright install chromium
|
||||
# 同步所有依赖(运行时 + 开发工具)
|
||||
make install
|
||||
# Windows 上等效命令:
|
||||
python tasks.py install
|
||||
```
|
||||
|
||||
项目使用 `uv` 管理依赖,所有包版本锁定在 `uv.lock` 中,确保可复现。
|
||||
|
||||
| 依赖 | 用途 |
|
||||
|------|------|
|
||||
| pdfplumber | PDF 发票文本提取 |
|
||||
| paddleocr | 支付截图 OCR |
|
||||
| playwright | 财务系统浏览器自动化 |
|
||||
| flask | Web 服务 |
|
||||
| pywin32 | 填写 Word 出库单(`fill_consumable_doc`) |
|
||||
|
||||
### 2. 准备数据(CLI 模式)
|
||||
|
||||
将发票 PDF 和对应的支付截图放在项目根目录下。脚本会自动匹配 PDF 与截图:
|
||||
|
||||
1. **优先文件名匹配** — PDF 与截图同名(如 `发票.pdf` ↔ `发票.png`)
|
||||
2. **金额近邻匹配** — 文件名不同时,按价税合计与刷卡金额就近配对
|
||||
|
||||
截图支持格式:`.png`、`.jpg`、`.jpeg`、`.bmp`、`.webp`。
|
||||
将发票 PDF 放在项目根目录下。
|
||||
|
||||
### 3. 配置
|
||||
|
||||
@@ -104,16 +115,17 @@ playwright install chromium
|
||||
### 4. 运行(CLI)
|
||||
|
||||
```bash
|
||||
# 全流程(发票提取 → OCR 识别 → 浏览器填报)
|
||||
python run.py
|
||||
# 全流程(发票提取 → 浏览器填报)
|
||||
make run
|
||||
# Windows 等效:
|
||||
python tasks.py run
|
||||
|
||||
# 仅执行某一步
|
||||
python run.py --step invoice # 仅发票提取
|
||||
python run.py --step ocr # 仅 OCR 识别
|
||||
python run.py --step submit # 仅浏览器填报
|
||||
uv run python src/main.py --step invoice # 仅发票提取
|
||||
uv run python src/main.py --step submit # 仅浏览器填报
|
||||
|
||||
# 覆盖配置中的登录凭据
|
||||
python run.py -u 工号 -p 密码
|
||||
uv run python src/main.py -u 工号 -p 密码
|
||||
```
|
||||
|
||||
### 5. 填写易耗品出库单(CLI)
|
||||
@@ -121,9 +133,9 @@ python run.py -u 工号 -p 密码
|
||||
需已生成 `invoice_summary.csv`,且本机已安装 **Microsoft Word**:
|
||||
|
||||
```bash
|
||||
python -m app.fill_consumable_doc
|
||||
python -m app.fill_consumable_doc --csv invoice_summary.csv --doc "易耗品、出库单.doc"
|
||||
python -m app.fill_consumable_doc --no-backup # 不生成 .doc.bak 备份
|
||||
uv run python -m src.doc.fill_consumable_doc
|
||||
uv run python -m src.doc.fill_consumable_doc --csv invoice_summary.csv --doc "易耗品、出库单.doc"
|
||||
uv run python -m src.doc.fill_consumable_doc --no-backup # 不生成 .doc.bak 备份
|
||||
```
|
||||
|
||||
填写规则概要:
|
||||
@@ -137,8 +149,7 @@ python -m app.fill_consumable_doc --no-backup # 不生成 .doc.bak 备份
|
||||
|
||||
| 步骤 | 命令 | 说明 |
|
||||
|------|------|------|
|
||||
| 发票提取 | `--step invoice` | 扫描根目录 PDF,生成 `invoice_summary.csv` / `.md` |
|
||||
| OCR 识别 | `--step ocr` | 识别支付截图,回填刷卡日期、金额、持卡人等到 CSV |
|
||||
| 发票提取 | `--step invoice` | 扫描根目录 PDF,生成 `invoice_summary.csv` |
|
||||
| 浏览器填报 | `--step submit` | 登录信息门户 → 报销系统 → 自动填单、上传附件 |
|
||||
|
||||
> 分步执行时,上一步的 CSV 会自动成为下一步的输入。
|
||||
@@ -148,12 +159,14 @@ python -m app.fill_consumable_doc --no-backup # 不生成 .doc.bak 备份
|
||||
| 列名 | 说明 |
|
||||
|------|------|
|
||||
| 序号 | 行号 |
|
||||
| 发票类型 | 自动识别:`高铁票` / `酒店住宿` / `普通发票` |
|
||||
| 发票号码 | 电子发票号码 |
|
||||
| 开票日期 | 开票日期 |
|
||||
| 项目名称 / 规格型号 | 货物或应税劳务信息 |
|
||||
| 项目名称 / 规格型号 | 货物或应税劳务信息(差旅发票为出发站→到达站) |
|
||||
| 价税合计 | 发票含税金额 |
|
||||
| 销售方名称 | 销方名称 |
|
||||
| 人员姓名 / 刷卡日期 / 公务卡号 / 刷卡金额 | OCR 自支付截图回填 |
|
||||
| 出发站 / 到达站 / 车次 / 乘车日期 / 座位等级 | 高铁票专用字段 |
|
||||
| 人员姓名 / 刷卡日期 / 公务卡号 / 刷卡金额 | 可手工或 Web 端编辑补充 |
|
||||
| 备注 / 工号 | 可手工或 Web 端编辑补充 |
|
||||
|
||||
## Web 服务
|
||||
@@ -161,48 +174,85 @@ python -m app.fill_consumable_doc --no-backup # 不生成 .doc.bak 备份
|
||||
提供浏览器界面:上传文件 → 自动处理 → 在线编辑 → 下载产物 → 可选提交财务系统。
|
||||
|
||||
```bash
|
||||
python web/app.py
|
||||
uv run python src/web/app.py
|
||||
```
|
||||
|
||||
访问 `http://localhost:5000`。
|
||||
|
||||
### 推荐使用流程
|
||||
|
||||
1. 上传 PDF + 支付截图(或上传已有 CSV)
|
||||
1. 上传 PDF(或上传已有 CSV)
|
||||
2. 填写配置(账号、密码、姓名、公务卡号、存放地点等),可上传 `config.json` 一键填充
|
||||
3. 点击 **开始处理** — 完成发票提取、OCR、生成 CSV,并自动填写 **易耗品、出库单.doc**
|
||||
4. 在 **下载文件** 区域下载 CSV / Markdown / 出库单 Word
|
||||
5. 在表格中核对、修改发票数据(提交财务系统前会自动保存)
|
||||
6. 确认无误后点击 **提交到财务系统**
|
||||
3. 点击 **开始处理** — 完成发票提取、生成 CSV,系统自动识别发票类型并分类统计
|
||||
4. **普通发票**:自动生成 **易耗品、出库单.doc**,可下载
|
||||
5. **差旅发票**(高铁票/酒店住宿):跳过出库单生成,直接进入差旅报销流程
|
||||
6. 在表格中核对、修改发票数据(提交财务系统前会自动保存)
|
||||
7. 确认无误后点击 **提交到财务系统**
|
||||
|
||||
### 处理模式
|
||||
|
||||
| 模式 | 入口 | 说明 |
|
||||
|------|------|------|
|
||||
| **PDF 模式** | 上传 PDF + 截图 | 提取发票 → OCR → 生成 CSV + 出库单 |
|
||||
| **CSV 快捷模式** | 仅上传 CSV | 跳过提取与 OCR,直接生成出库单并进入编辑/提交 |
|
||||
| **PDF 模式** | 上传 PDF | 提取发票 → 生成 CSV + 自动分类 → 普通发票生成出库单 |
|
||||
| **CSV 快捷模式** | 仅上传 CSV | 跳过提取,读取 CSV 中的发票类型,按需生成出库单 |
|
||||
|
||||
### 发票类型区分
|
||||
|
||||
系统自动识别以下发票类型并按类型分流:
|
||||
|
||||
| 发票类型 | 识别依据 | 出库单 | 填报模式 |
|
||||
|----------|----------|--------|----------|
|
||||
| **高铁票** | 含"电子客票"、"中国铁路"、"12306"等关键词 | 不生成 | 差旅报销(TODO) |
|
||||
| **酒店住宿** | 含"住宿费"、"餐饮服务"、"租赁服务"等关键词 | 不生成 | 差旅报销(TODO) |
|
||||
| **普通发票** | 其他所有发票 | 自动生成 | 普通报销(已实现) |
|
||||
|
||||
当同一批次同时包含差旅发票和普通发票时,系统会为普通发票生成出库单,并在填报时分别处理。
|
||||
|
||||
### 功能一览
|
||||
|
||||
| 功能 | 说明 |
|
||||
|------|------|
|
||||
| 发票提取 + OCR | 上传 PDF 后自动完成 |
|
||||
| 易耗品出库单 | 处理完成后自动生成 Word,可下载 |
|
||||
| 发票提取 | 上传 PDF 后自动完成 |
|
||||
| 发票类型自动分类 | 高铁票/酒店住宿/普通发票,自动分流处理 |
|
||||
| 易耗品出库单 | 仅普通发票自动生成 Word,差旅发票跳过 |
|
||||
| 表格在线编辑 | 处理完成后可修改 CSV 各字段;保存后重新生成出库单 |
|
||||
| 财务系统填报 | 单独按钮触发,处理阶段不会自动提交 |
|
||||
| 实时日志 | SSE 推送处理进度 |
|
||||
| 配置上传 | 支持上传 `config.json` 填充表单 |
|
||||
| 手机扫码上传 | 二维码打开移动端页面,拍照上传支付截图,PC 端轮询同步 |
|
||||
| 手机扫码上传 | 二维码打开移动端页面,拍照上传,PC 端轮询同步 |
|
||||
|
||||
> Web 端浏览器填报以无头模式运行。未上传 PDF 时,填报阶段会跳过附件上传。
|
||||
> Web 端浏览器填报以无头模式运行。未上传 PDF 时,填报阶段会跳过附件上传。
|
||||
> 出库单生成需要 **Windows + Word + pywin32**;若失败,页面会显示具体原因,CSV 等其它产物仍可正常使用。
|
||||
|
||||
接口说明见 [API.md](./API.md)。
|
||||
|
||||
## 开发任务
|
||||
|
||||
项目提供统一的任务脚本,支持跨平台使用:
|
||||
|
||||
| 任务 | Makefile | tasks.py | 说明 |
|
||||
|------|----------|----------|------|
|
||||
| 安装依赖 | `make install` | `python tasks.py install` | 同步依赖 + 安装 pre-commit |
|
||||
| 代码检查 | `make check` | `python tasks.py check` | Ruff lint + 格式化 + MyPy 类型检查 + deptry 依赖检查 |
|
||||
| 运行测试 | `make test` | `python tasks.py test` | pytest + 覆盖率报告 |
|
||||
| 运行 CLI | `make run` | `python tasks.py run` | 执行全流程 |
|
||||
| 清理缓存 | `make clean` | `python tasks.py clean` | 删除虚拟环境和缓存 |
|
||||
|
||||
## 代码质量
|
||||
|
||||
项目配置了完整的代码质量工具链:
|
||||
|
||||
- **Ruff** — 快速 lint 检查和代码格式化(替代 flake8 + isort + black)
|
||||
- **MyPy** — 严格模式类型检查(`strict = true`)
|
||||
- **deptry** — 检测未声明、未使用、过时依赖
|
||||
- **pre-commit** — 提交前自动运行 Ruff 检查和格式化
|
||||
|
||||
所有检查通过后方可提交代码。
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 浏览器填报时会打开或使用 Chromium,请勿手动干扰自动化流程
|
||||
- 调试截图保存在 `images/` 目录
|
||||
- OCR 不会覆盖 CSV 中已有非空字段
|
||||
- 项目根目录需保留 `易耗品、出库单.doc` 模板;Web 每次从模板复制到会话目录再填写,不修改原模板
|
||||
- `config.json` 含敏感信息,请勿提交到公开仓库
|
||||
- **发票类型区分**:差旅发票(高铁票/酒店住宿)不会生成易耗品出库单,当前差旅报销填报流程仍在开发中(TODO)
|
||||
Reference in New Issue
Block a user