# 往来台账

当前版本包含银行流水表头识别内核，以及相互独立的总账管理端和公司业务端原型。

## How recognition works

1. Scan the first 50 rows of every worksheet.
2. Normalize whitespace and full-width characters in candidate headers.
3. Match required header aliases against known bank template signatures.
4. Map columns by header name, independent of their order.
5. Normalize transaction dates, income, expense, balance, counterparty, and
   reference fields.
6. Reject unknown or ambiguous templates instead of guessing.

The original Excel file is never modified.

## Run

```powershell
python -m pip install -r requirements.txt
$env:PYTHONPATH = "src"
python -m bank_importer.db            # 创建/迁移 SQLite 数据库（默认 data/app.db）
python -m bank_importer.cli "流水模板"
python -m unittest discover -s tests -v
python server.py
```

数据库与原始文件默认保存在 `data/`（已加入 `.gitignore`）。上传文件按
SHA-256 内容哈希不可变保存，重复上传返回 `duplicate` 状态并复用已有批次。
同一公司重复上传返回原批次摘要；不同公司相同内容只返回通用重复状态，
不暴露其他公司的批次标识或摘要。
技术决策见 `docs/decisions/002-persistence.md`。

## 登录与账号

系统已启用真实身份认证（决策见 `docs/decisions/003-auth.md`）：

- 首次启动若无管理员，自动创建引导管理员：用户名取环境变量
  `APP_ADMIN_USERNAME`（默认 `group-admin`），密码取
  `APP_BOOTSTRAP_ADMIN_PASSWORD`；未设置该变量则生成随机初始密码并
  只在控制台打印一次。
- 引导管理员及管理员创建的公司账号首次登录都必须修改密码。
- 公司、公司账号由管理员在总账端「公司与账号 → 新增公司」或
  `/api/admin/companies`、`/api/admin/users` 动态创建；
  公司账号创建时生成随机一次性初始密码，只在创建响应中显示一次，
  首次登录强制改密（「重置密码」同样生成随机一次性密码并吊销会话）。
- 会话有效期 8 小时；同一账号同一 IP 10 分钟内登录失败 5 次将被限流。
  内网测试环境可设 `APP_LOGIN_RATE_LIMIT_DISABLED=1` 暂时关闭该锁定
  （默认未设置 = 保持限流，正式环境不得开启该变量）。

访问地址（服务默认监听 `0.0.0.0:4173`，同局域网设备把 `127.0.0.1` 换成本机局域网 IP 即可访问；可用环境变量 `APP_HOST` / `APP_PORT` 覆盖）：

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

公司端上传会把所选工作簿提交到本地 `/api/parse`，与 CLI 使用同一个确定性表头解析器；解析结果、原始文件、批次和源行会持久化到 SQLite，并按登录账号绑定的公司隔离。当前前端仍是交互原型，期初、提醒、往来匹配等业务状态仅保存在当前浏览器页面中，尚未接入数据库。

## 样本数据政策

`流水模板/` 中的六份银行样本（中信、农行、工行、建行、河南农商、郑州银行）已经项目所有者（白栖知，2026-08-08）书面确认：**基于真实银行流水脱敏后的测试数据**，可以保留在仓库中作为解析器 fixture。新增银行样本的审核要求：必须先脱敏（户名、账号、对方信息等），由项目所有者确认后方可提交；真实生产流水、真实上传文件和导出文件一律不进仓库（见 `.gitignore` 中的 `data/`、`uploads/`、`exports/` 规则）。

The CLI prints batch summaries only. It does not print sensitive transaction
details.
