# 项目交接说明

更新时间：2026-08-06
核对基线：`main` / `b3043f9`（生成本文档前与 `origin/main` 一致）

本文档基于当前仓库代码、六个银行样本、现有测试、产品/行为规范和 Git 状态核实，不把仅存在于页面中的演示交互视为已落地的生产功能。

## 1. 项目目标和当前状态

### 项目目标

本项目用于集中管理集团内部多家公司的银行流水，并以软件核算为主、人工审核为辅，形成可追溯的公司间往来关系。核心目标包括：

- 集中保存各公司、各银行账户的原始流水，避免本地电脑故障造成数据丢失。
- 按银行表头签名识别不同 Excel 模板，不依赖固定行号、列顺序或文件名。
- 将同一经济转账的双方银行流水归并为一个规范事件，避免重复统计。
- 排除同一公司不同银行账户间的内部调拨，不计入公司间往来。
- 按公司、方向、对方公司、会计科目和原始银行证据逐层查询。
- 区分总账管理端和公司出纳端，并在服务端实施真实的数据权限边界。
- 支持起算日、期初余额、覆盖断档、人工无业务校准、月结和重开审计。

### 当前状态

当前版本是“真实银行流水解析内核 + 双端高保真交互原型”，还不是可上线的财务系统。

| 能力 | 当前状态 | 事实依据 |
|---|---|---|
| 六家银行 Excel 解析 | 已实现 | `src/bank_importer/`，六个样本和 6 项单元测试均通过 |
| 本地上传并调用解析器 | 已实现最小闭环 | `POST /api/parse` 返回银行、模板、表头行、期间和明细数 |
| 总账端/公司端页面与交互 | 高保真原型 | `web/admin.html`、`web/company.html`、`web/app.js` |
| 生产数据持久化 | 未实现 | 无数据库、对象存储或导入批次持久层 |
| 身份认证与权限隔离 | 未实现 | 登录页不校验密码；服务端仅有解析接口 |
| 双边匹配与公司间核算 | 未实现 | `pairData()` 根据公司序号生成演示数据 |
| 覆盖连续性、期初、月结 | 仅前端演示 | 操作只修改当前 DOM 或显示 Toast |
| 提醒与审核 | 部分浏览器原型 | 手工记录/账户申请用 `localStorage`；无多用户服务端状态 |

### 最近验证结果

- `python -m unittest discover -s tests -v`：6 项通过。
- `python -m bank_importer.cli 流水模板`：6 个样本全部识别，合计 20 条规范化交易，余额校验无警告。
- `node --check web/app.js`：通过。
- Git：生成本文档前 `main` 与 `origin/main` 均指向 `b3043f9430a93ae98139408bd582c2db32e11143`，工作区干净。

## 2. 技术架构与主要目录

### 当前架构

```text
浏览器静态页面
  ├─ index.html：角色入口
  ├─ admin.html：总账管理端原型
  └─ company.html：公司出纳端原型
          │
          │ POST /api/parse（multipart/form-data）
          ▼
Python 标准库 ThreadingHTTPServer
          │
          ▼
bank_importer 解析内核
  ├─ 读取 .xlsx：openpyxl
  ├─ 读取 .xls：xlrd
  ├─ 表头签名识别
  └─ 规范化交易与余额连续性检查
```

当前没有数据库、ORM、认证服务、后台任务、对象存储、消息队列或生产部署配置。`server.py` 仅适合本地原型运行。

### 主要目录

| 路径 | 作用 | 当前成熟度 |
|---|---|---|
| `src/bank_importer/` | 银行模板、工作簿读取、表头检测、字段规范化、余额校验、CLI | 可复用内核 |
| `tests/test_parser.py` | 六个现有样本及基础表头识别回归测试 | 覆盖有限 |
| `server.py` | 静态文件服务和 `/api/parse` 最小接口 | 原型服务 |
| `web/` | 登录、总账端、公司端、样式、图标和原生 JS 交互 | 高保真原型 |
| `流水模板/` | 六家银行的 `.xls`/`.xlsx` 样本 | 已纳入 Git，需确认脱敏级别 |
| `docs/issues/` | 本次拆分的独立待办 Issue | 交接清单 |
| `PRODUCT.md` | 产品边界和核心会计模型 | 规范来源 |
| `BEHAVIOR_SPEC.md` | 导入、审核、核算、月结、提醒的行为规范 | 目标行为，非当前实现说明 |
| `AGENTS.md` | 不可破坏的业务与工程行为规则 | 开发约束 |
| `DESIGN.md` / `DESIGN-TOKENS.md` | 当前深色玻璃财务工作台设计系统 | 已落地 |
| `.impeccable/design.json` | 设计系统机器可读 sidecar | 已落地 |

### 关键代码边界

- `server.py` 目前只有 `POST /api/parse`，解析成功后取 `batches[0]` 返回摘要，不保存文件或交易。
- `src/bank_importer/models.py` 的 dataclass 是解析结果，不是持久化领域模型。
- `web/app.js` 中除上传解析外，大部分操作在 DOM 或 `localStorage` 中完成。
- `web/app.js::pairData()` 是演示算法，不可作为财务计算依据。

## 3. 已完成功能

### 真实实现

1. 支持中信银行、农业银行、工商银行、建设银行、河南农商银行、郑州银行六种样本格式。
2. 支持 `.xls` 和 `.xlsx`，扫描每个工作表前 50 行寻找表头。
3. 表头别名经过空白和全角字符规范化，列顺序变化不影响识别。
4. 规范化交易日期、收入、支出、余额、本方账户/户名、对方账户/户名/银行、摘要、用途、银行参考号、币种和源行定位。
5. 金额使用 `Decimal`，支持逗号、括号负数和人民币符号清理。
6. 对同一时间组按余额执行连续性检查，并输出警告。
7. 未识别或歧义模板拒绝猜测；服务器错误会替换临时文件名为原始上传文件名。
8. CLI 可批量解析目录并只输出批次摘要，不打印敏感逐笔内容。
9. 本地页面可上传文件并调用同一解析内核。

### 已完成的原型交互

1. 登录入口明确区分总账管理端与公司业务端。
2. 总账端包含管理总览、公司对查询、审核中心、流水管理、公司与账号、结账与期初、提醒管理。
3. 公司端包含工作台、流水导入、手工记录、流水管理、往来确认、银行账户、通知。
4. 手工记录和账户登记可在公司端提交到 `localStorage`，并在同一浏览器的总账审核中心处理。
5. 已启用的浏览器本地账户可加入上传账户选项；待复核账户不加入。
6. 流水列表可按现有静态数据筛选并导出 CSV。
7. 双端具有独立导航、首页优先级、桌面/移动布局、键盘焦点和减少动效支持。
8. 深色玻璃设计系统、四个首页统计卡和响应式动效已完成并通过视觉审查。

## 4. 尚未完成的功能

未完成事项已拆分到 `docs/issues/`，以文件编号表示推荐依赖关系：

| Issue | 未完成事项 | 优先级 |
|---|---|---|
| [001](issues/001-p0-repository-data-hygiene.md) | 仓库银行样本的数据分级、脱敏和真实上传文件隔离 | P0 |
| [002](issues/002-p0-persistence-and-immutable-imports.md) | 数据库、不可变原始文件、导入批次、哈希与去重基础 | P0 |
| [003](issues/003-p0-auth-and-tenant-isolation.md) | 正式认证、RBAC 和公司级服务端权限隔离 | P0 |
| [004](issues/004-p1-dynamic-master-data.md) | 动态公司/用户/账户/别名主数据及账户审核工作流 | P1 |
| [005](issues/005-p1-import-api-hardening.md) | 导入 API 加固、完整诊断、多工作表与接口回归测试 | P1 |
| [006](issues/006-p1-canonical-transfer-matching.md) | 规范转账事件、双边匹配、同公司调拨和个人过账映射 | P1 |
| [007](issues/007-p1-position-calculation.md) | 往来科目、余额计算、手工记录审批后入账和逐层追溯 | P1 |
| [008](issues/008-p1-calculation-window-coverage.md) | 全局起算日、覆盖区间、期初余额和无业务断档校准 | P1 |
| [009](issues/009-p1-monthly-close.md) | 月结、锁定、重开、冲销/调整和完整审计报告 | P1 |
| [010](issues/010-p2-flow-query-export.md) | 服务端流水查询、权限过滤和可追溯导出 | P2 |
| [011](issues/011-p2-reminder-engine.md) | 自动/手工站内提醒、状态流转和外部提醒扩展点 | P2 |
| [012](issues/012-p1-frontend-production-api-integration.md) | 前端接入生产 API，移除静态数据、`pairData()` 和 `localStorage` 业务状态 | P1 |

## 5. 已知问题

### 核算与数据一致性

1. `pairData()` 使用 A-F 公司序号生成模拟金额和交易，不读取解析结果、手工记录或账户主数据。
2. 管理员将手工记录审核为“已确认”后，仅更新 `localStorage` 状态，不会进入往来合计或公司对查询。
3. 公司间同一笔转账的双边流水尚未归并，无法保证“一笔经济事件只计一次”。
4. 同公司跨银行调拨、外部交易、个人过账仅有静态演示，没有服务端判定链。

### 导入与证据

1. `/api/parse` 不保存原文件、哈希、导入批次、规范化交易或异常记录；页面声称“已保留”仅是原型文案。
2. 多工作表成功解析时，接口只返回 `batches[0]`，其他批次未暴露给前端。
3. 只有单个非空单元格的候选行会被 `_header_candidate_summary()` 忽略；全空工作簿的错误缺少工作表、扫描行数和候选表头四项完整诊断。
4. 手工记录附件只保存文件名，附件内容没有上传或保留。
5. 当前 multipart 解析由 `server.py` 手写，未覆盖复杂文件名、边界和二进制尾部的接口测试。

### 权限与持久化

1. 登录不验证账号或密码，公司端固定为 A 公司。
2. 服务端没有用户、会话、权限检查或公司数据隔离。
3. 公司、账号、期初、结账、提醒、确认结果多数只存在当前 DOM；刷新即丢失。
4. `localStorage` 数据仅限同一浏览器，不支持不同出纳客户端与总账端同步。
5. 银行账号唯一性只在当前浏览器本地申请中检查，不能防止并发或跨公司冲突。

### 测试与运行

1. 现有 6 项测试只覆盖解析内核，没有 `/api/parse`、认证、导入持久化、匹配、核算、权限或端到端测试。
2. `server.py` 基于标准库开发服务器，默认绑定 `0.0.0.0`（可用 `APP_HOST` 覆盖），没有生产部署、TLS、日志、备份或监控方案。
3. `流水模板/` 已进入 Git 历史；必须确认均为合成或已脱敏数据，真实生产流水不得继续提交到仓库。

## 6. 已作出的重要技术决策及原因

| 决策 | 原因 |
|---|---|
| 以表头签名识别银行模板 | 银行模板表头稳定，而标题行位置、列顺序和明细内容会变化 |
| 未识别/歧义模板进入异常，不自动猜测 | 财务系统错误入账的代价高于人工处理少量异常 |
| 原始银行行不可修改 | 保留证据链；修正通过映射、冲销或审计调整完成 |
| 银行侧观察与经济转账分层 | A/B 双方各一条流水只能形成一个规范事件，避免双计 |
| 同公司不同账户调拨不计公司间往来 | 只影响账户现金轨迹，不改变公司间债权债务 |
| 账号优先于户名识别对方 | 户名可能缩写、别名或人工录入不一致，账号确定性更高 |
| 金额使用 `Decimal` | 避免浮点误差进入余额与核算逻辑 |
| 科目只做确定性规则，歧义进入审核 | 摘要不足以可靠区分应收/其他应收等法定科目 |
| 手工记录与银行证据分开 | 防止人工信息覆盖不可变银行事实，并保留独立审核轨迹 |
| 公司端账户登记需总账审核后启用 | 未审核账户不能参与所有权识别、上传和覆盖计算 |
| 总账端与公司端为独立页面 | 两类用户的信息优先级、权限范围和高频操作不同 |
| 前端原型使用 `localStorage`，但明确不作为生产方案 | 在无数据库阶段验证流程，同时避免误认为已具备多用户一致性 |
| 深色设计系统直接替换旧 token，不追加主题覆盖层 | 防止 CSS 权重叠加和后续新旧视觉规则混用 |

## 7. 当前正在处理的事项

当前没有功能代码正在开发。本轮已经将项目事实、风险、依赖和验收标准固化到本文档，并将生产化未完成事项拆成 12 个独立 Issue 规格。当前唯一未闭环的交接事项是把这些规格创建为远程 Gitea Issues。

Gitea SSH 推送已可用；本机没有 `tea` CLI、Gitea API Token 或已配置的 Gitea CLI 登录。`192.168.200.36:3000` 不可访问，默认 HTTP 端口是 fnOS 管理页面，因此当前只能保证 Issue 规格已进入仓库，不能在没有 API/Web 入口和认证信息的情况下伪造远程 Issue 创建成功。

## 8. 推荐的后续执行顺序

1. **先做 Issue 001**：确认仓库内 Excel 的数据级别；若包含真实信息，先脱敏并清理 Git 历史，再继续协作。
2. **并行设计 Issue 002 与 003**：确定数据库/文件存储和认证授权边界，但先落地最小数据库迁移与不可变导入模型。
3. **完成 Issue 004 与 005**：主数据和加固后的导入 API 是后续识别、覆盖和权限的基础。
4. **完成 Issue 006**：建立规范事件和双边匹配，先确保不重复计算。
5. **完成 Issue 007**：在规范事件之上实现科目和公司间余额，并补齐已确认手工记录入账。
6. **完成 Issue 008**：加入起算日、期初和覆盖连续性，明确“期间净变动”与“期末余额”。
7. **完成 Issue 009**：核算结果稳定后再实现月结、重开和调整审批。
8. **完成 Issue 010 与 011**：以已持久化的事件、异常和覆盖状态实现查询导出与提醒。
9. **贯穿各后端阶段推进 Issue 012**：按垂直切片替换静态数据，最后删除 `pairData()` 和业务 `localStorage`。
10. 每个阶段都增加自动化测试、迁移回滚方案和审计字段，不要把测试集中留到最后。

## 9. 每项任务的验收标准

以下是摘要，完整范围和测试要求见对应 Issue 文件。

| Issue | 核心验收标准 |
|---|---|
| 001 | 六个样本完成数据分级；确认已脱敏或替换为合成数据；真实上传目录被 Git 忽略；如需清历史，远程仓库验证不再含敏感对象 |
| 002 | 数据库迁移可重复执行；原文件按内容哈希不可变保存；重复文件/行幂等；导入批次、源行和异常可查询；重启后数据不丢失 |
| 003 | 真实登录、密码策略和会话生效；总账/公司角色在服务端授权；公司用户无法读取、导出或修改其他公司数据；有权限回归测试 |
| 004 | 公司、用户、账户、别名和生效期均来自数据库；账户审批前不参与识别/上传/覆盖；账号唯一约束由数据库保证；审核全留痕 |
| 005 | API 返回全部工作表批次；未知模板始终含原文件名、工作表、扫描行数、候选表头；失败不建成功批次；覆盖空表、单单元格、临时文件名和 multipart 回归测试 |
| 006 | 双边流水归并为一个规范事件；反向导入和重复导入不改变结果；同公司调拨排除；未识别对方不入公司间余额；个人过账映射可审计 |
| 007 | 余额只来源于已确认规范事件和已批准手工记录；双方视角守恒；四科目可追溯到原始证据；未决金额和截止日始终显示 |
| 008 | 起算日前行保留但不计算；每账户覆盖区间正确合并并检测缺口；期初双边守恒；无业务校准需要理由且不生成银行行；无期初时标记期间净变动 |
| 009 | 结账前置条件服务端校验；结账快照不可静默改写；闭期补录进入重开异常；调整/冲销经审批；能导出完整月结审计报告 |
| 010 | 总账和公司端查询均由服务端权限过滤；筛选、分页和金额汇总一致；导出包含银行标识、批次、源行和匹配状态；大数据量测试通过 |
| 011 | 五类自动触发器可幂等生成提醒；手动提醒可指定公司/期限；未读/已读/处理中/完成状态持久化；链接回原任务；外部通道保持可插拔但默认关闭 |
| 012 | 所有页面从 API 读取真实数据；刷新和跨客户端状态一致；删除模拟 `pairData()`、静态业务行和业务 `localStorage`；保留双端独立路由、响应式和无障碍行为；关键流程端到端通过 |

## 运行与交接注意事项

```powershell
python -m pip install -r requirements.txt
$env:PYTHONPATH = "src"
python -m unittest discover -s tests -v
python -m bank_importer.cli "流水模板"
python server.py
```

本地地址：

- 登录：`http://127.0.0.1:4173/`
- 总账管理端：`http://127.0.0.1:4173/admin.html`
- 公司业务端：`http://127.0.0.1:4173/company.html`

开发时必须继续遵守 `AGENTS.md`：不修改原始银行证据、不把 UI 隐藏当作权限、不得从户名单独推断财务事实、每个新银行模板或解析边界都必须有回归测试。
