---
last_reviewed: 2026-06-12
---

# src — 主源码目录

包含财务报销自动化系统的核心模块。

## 模块清单

| 文件/目录 | 说明 |
|-----------|------|
| `__init__.py` | 包初始化：提供 `get_logger()` 日志工厂（支持终端 + 文件双输出，按日期自动分文件） |
| `config.py` | 配置加载：从 `config.json` 读取用户凭据和默认值，从环境变量读取服务端配置（SSO 地址、LLM 参数） |
| `pipeline.py` | 流程编排：串联发票提取 → 类型判断 → 差旅/普通信息提取 → 浏览器填报，支持分步执行 |
| `main.py` | CLI 入口：支持 `--step` 分步执行、`-u/-p` 覆盖凭据、`--cache-dir` 指定缓存目录 |
| `bot/` | 浏览器自动化：Playwright 驱动的财务系统填报机器人（仅负责接收信息并填报） |
| `doc/` | 文档处理模块：PDF 渲染、LLM 提取、支付匹配、发票分类、出库单生成 |
| `web/` | Web 界面模块：Flask 应用、SSE 日志、可编辑表格、移动端上传、会话隔离 |

## 数据流

```mermaid
graph TD
    A[CLI/Web 入口] --> B["pipeline.py (编排)"]
    B --> C["doc/extractor.py (统一提取入口)"]
    C --> D["doc/pdf.py (PDF 渲染为图片)"]
    C --> E["doc/llm_extractor.py (多模态 LLM 识别)"]
    E --> F["发票 invoice_type=train/hotel/general"]
    E --> G["支付记录 invoice_type=payment"]
    E --> H["出差事前申请单 invoice_type=application"]
    C --> I["doc/matcher.py (发票与支付记录按金额匹配)"]
    I --> J["一对一匹配 发票数 == 刷卡数"]
    I --> K["一对多匹配 贪心算法 相对容差 3%"]
    C --> L["doc/invoice.py (CSV/JSON 读写)"]
    L --> M["payment_records.csv (支付记录级别)"]
    L --> N["invoice_summary.csv (发票级别)"]
    L --> O["travel_applications.json (出差申请单)"]
    B --> R{"判断报销类型"}
    R -->|差旅| T["doc/llm_extractor.py (差旅信息提取)"]
    R -->|普通| V["doc/llm_extractor.py (普通发票信息提取)"]
    T --> W["travel_info.json (差旅信息: 交通/住宿明细、补贴、附件清单)"]
    V --> X["normal_info.json (普通发票信息: 报销说明、发票总数、总金额、支付方式、附件清单)"]
    W --> P["bot/ (浏览器填报 - 仅接收信息并填报)"]
    X --> P
    P --> Q["差旅模式: travel_info.json → 填报差旅单 → 上传差旅附件"]
    P --> S["普通模式: 基本信息 → 录入明细 → 支付信息 → 上传附件"]
```

**数据流变更（2026-06-11）：** 差旅信息提取从 `bot.py` 提升到 `pipeline.py` 编排层。在发票提取和匹配完成后立即判断报销类型，差旅发票调用 LLM 提取 `travel_info.json`，普通发票调用 LLM 提取 `normal_info.json`。Bot 仅负责接收信息并填报，不再承担信息提取职责。

## 文档处理子模块 (`doc/`)

详见 [`doc/README.md`](doc/README.md)

核心能力：
- **统一文档提取**：LLM 自行判断文档类型（发票/支付记录/出差事前申请单），无需正则回退
- **JSON 缓存**：提取结果缓存于 `.invoice_cache/`，避免重复处理
- **金额匹配**：支持一对多匹配，相对容差 3%，未匹配发票单独列为记录
- **差旅信息提取**：综合发票、支付记录和匹配结果，提取出差事由、地点、时间等
- **普通发票信息提取**：综合普通发票、支付记录和匹配结果，提取报销说明、发票总数、总金额、支付方式、附件清单
- **出库单生成**：将 CSV 数据填入 Word 模板（pywin32 COM，仅 Windows）

## Web 界面子模块 (`web/`)

详见 [`web/README.md`](web/README.md)

核心能力：
- **会话隔离**：每次上传生成独立 `session_id`，文件/日志/配置/结果各自隔离
- **移动端同步**：PC 端生成二维码指向 `/mobile/<sid>`，跨设备协作上传
- **可编辑表格**：前端加载 CSV 数据，支持在线编辑后保存

## 启动方式

```bash
# CLI 模式
uv run python src/main.py --step all

# Web 模式
uv run python src/web/app.py
# 访问: http://localhost:5000
```

## 发票类型与路由

系统根据 `invoice_type` 字段自动分流：

| 发票类型 | 走什么流程 | 是否生成出库单 |
|----------|-----------|--------------|
| `train` / `hotel` | 差旅报销 | 否 |
| `general` | 普通报销 | 是（易耗品出库单） |
| `application` | 出差事前申请单 | 否（单独存储为 JSON） |

**注意**：差旅发票和普通发票不支持混报，混合时会报错。