docs: add project handoff and implementation backlog

This commit is contained in:
leefer
2026-08-07 00:04:51 +08:00
parent b3043f9430
commit 13a5b2787d
14 changed files with 647 additions and 0 deletions
+238
View File
@@ -0,0 +1,238 @@
# 项目交接说明
更新时间: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/parsemultipart/form-data
Python 标准库 ThreadingHTTPServer
bank_importer 解析内核
├─ 读取 .xlsxopenpyxl
├─ 读取 .xlsxlrd
├─ 表头签名识别
└─ 规范化交易与余额连续性检查
```
当前没有数据库、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` 基于标准库开发服务器,只绑定 `127.0.0.1`,没有生产部署、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 隐藏当作权限、不得从户名单独推断财务事实、每个新银行模板或解析边界都必须有回归测试。
@@ -0,0 +1,34 @@
# [P0] 仓库银行样本数据分级与脱敏治理
## 背景
`流水模板/` 中六个 Excel 文件已进入 Git 历史。项目尚未记录这些文件是合成样本、完全脱敏样本还是实际账户流水。财务数据一旦推送到远程仓库,仅删除工作区文件不能消除历史对象。
## 范围
- 对六个样本逐一确认来源、所有者、敏感字段和允许的使用范围。
- 将真实数据替换为能覆盖相同表头/格式边界的合成或脱敏 fixture。
- 建立真实上传文件、导出文件和本地运行数据目录的 `.gitignore` 规则。
- 如发现敏感数据,制定并执行 Git 历史清理、远程强制更新和访问凭据轮换方案。
- 在 README 中记录样本数据政策和新增银行 fixture 的审核要求。
## 不包含
- 生产对象存储实现,归 Issue 002。
## 验收标准
- [ ] 六个文件都有书面数据分级结论和负责人确认。
- [ ] 仓库中只保留合成或已批准脱敏的测试数据。
- [ ] 真实上传/导出目录不会被 `git add --all` 纳入。
- [ ] 如需清理历史,克隆远程仓库后无法再找到被清理的敏感 Git 对象。
- [ ] 解析器的 6 项现有测试在替换 fixture 后仍通过。
## 测试
- `git ls-files` 不包含真实运行数据目录。
- 全新克隆后运行 `python -m unittest discover -s tests -v`
## 依赖
无。应在其他生产化开发前完成。
@@ -0,0 +1,37 @@
# [P0] 持久化层与不可变银行导入基础
## 背景
当前 `/api/parse` 只在临时文件中解析并返回摘要,随后删除文件。公司、账户、交易、导入批次和异常均无数据库记录,页面“原始文件已保留”的文案与实际行为不一致。
## 范围
- 选择并记录数据库、迁移工具和文件存储方案。
- 建立公司、账户、源文件、导入批次、工作表批次、规范化源行、解析异常和审计字段的最小模型。
- 源文件在解析前计算内容哈希并不可变保存。
- 每条规范化交易保存源文件、工作表、原始行号和模板版本。
- 实现文件级与源行级幂等,重复上传不重复影响后续计算。
- 定义失败状态、重试状态和事务边界。
## 约束
- 原始文件和源行不能被静默修改或覆盖。
- 金额继续使用十进制定点类型,不能转为二进制浮点。
## 验收标准
- [ ] 空数据库可通过迁移命令完整创建,重复执行无副作用。
- [ ] 上传成功后重启服务,原文件、批次、工作表和源行仍可查询。
- [ ] 同一文件重复上传返回已存在批次或明确重复状态,不创建第二份有效事实。
- [ ] 每条源行可反查文件哈希、工作表、行号和解析模板版本。
- [ ] 解析失败也保留异常批次和诊断,但不产生已确认交易。
- [ ] 有数据库约束和自动化测试证明幂等与不可变性。
## 测试
- 迁移向前/回滚测试。
- 重复文件、重复行、解析失败、服务重启后的集成测试。
## 依赖
Issue 001。
@@ -0,0 +1,31 @@
# [P0] 正式认证、RBAC 与公司级数据隔离
## 背景
当前登录页不校验密码;公司端固定显示 A 公司。服务端没有用户、会话和授权逻辑,任何浏览器都可直接访问总账或公司页面并调用解析接口。
## 范围
- 实现系统管理员和公司出纳两类角色的真实账号、密码哈希、首次改密、停用和会话。
- 公司账号绑定且只绑定一个公司;总账角色拥有跨公司管理权限。
- 对读取、上传、导出、审核、提醒、设置和结账接口逐项做服务端授权。
- 定义会话过期、退出、失败登录限速和审计日志。
- 页面路由保护只作为体验层,不能代替 API 权限。
## 验收标准
- [ ] 无会话访问受保护页面/API 返回未认证状态。
- [ ] 公司用户无法通过修改 URL、参数或请求体访问其他公司数据。
- [ ] 公司用户不能调用总账审核、主数据、起算日和结账接口。
- [ ] 管理员可创建、停用、重置公司账号;初始密码只显示一次并强制修改。
- [ ] 密码不以明文保存或记录到日志。
- [ ] 权限矩阵有自动化测试,覆盖 IDOR、跨公司导出和跨公司上传。
## 测试
- 登录、退出、过期会话、停用账号、首次改密测试。
- 每个资源类型至少一个跨公司拒绝测试。
## 依赖
Issue 002。
+31
View File
@@ -0,0 +1,31 @@
# [P1] 动态公司、用户、账户和别名主数据
## 背景
HTML 和 `pairData()` 硬编码 A-F 公司、账户尾号和出纳名称。公司/账户新增只修改 DOM 或 `localStorage`,无法支持新增公司、并发审核或跨客户端同步。
## 范围
- 建立动态公司、公司账号、银行账户、账户类型、户名/账号别名和生效区间模型。
- 公司创建时可选择同时创建公司账号。
- 公司端提交账户登记,总账端审核为启用、退回或停用。
- 只有启用且在有效期内的账户可识别所有权、出现在上传选择中并参与覆盖计算。
- 账号规范化、脱敏显示和数据库唯一约束。
- 所有主数据变更记录前值、后值、操作人、时间和原因。
## 验收标准
- [ ] 新增公司无需修改代码即可出现在总账检索和账号管理中。
- [ ] 公司用户始终绑定正确公司,不能自行改变公司归属。
- [ ] 待复核账户不参与识别、上传或覆盖;通过后自动生效;停用后按有效期退出。
- [ ] 完整账号唯一性由数据库保证,并发提交不会生成两个有效账户。
- [ ] 别名匹配有明确优先级、有效期和审核轨迹。
- [ ] 前端只显示必要的脱敏账号,授权审计视图才显示完整账号。
## 测试
- 公司新增、账户审批、退回重提、停用、并发重复账号和有效期边界测试。
## 依赖
Issue 002、003。
@@ -0,0 +1,32 @@
# [P1] 银行导入 API 加固与回归测试
## 背景
解析内核能识别现有六个样本,但 `/api/parse` 仍是最小原型:只返回第一个批次、手写 multipart、诊断边界不完整,也没有接口级测试。
## 范围
- API 返回所有成功工作表批次,而不是固定使用 `batches[0]`
- 未知模板诊断始终包含原始文件名、工作表名、扫描行数和候选表头;空表和单单元格行也有明确结果。
- 解析失败不得创建成功导入记录,临时文件名不得泄露。
- 使用成熟 multipart 处理方式,严格限制扩展名、大小、文件数量和资源消耗。
- 覆盖重复文件、损坏文件、无工作表、多工作表、歧义模板和余额异常。
- 每新增银行模板必须有脱敏 fixture 和回归测试。
## 验收标准
- [ ] 多工作表文件的每个批次都可确认、异常或忽略,不丢失成功工作表。
- [ ] 空工作簿、单单元格候选和未知表头错误都返回四项诊断证据。
- [ ] API 错误只显示原始上传文件名,不显示服务器临时路径。
- [ ] 损坏文件和超限请求返回稳定错误码,不产生已确认交易。
- [ ] 前端失败流程不增加导入成功行。
- [ ] `/api/parse` 有接口回归测试,包含现有工商银行样本。
## 测试
- 单元测试:候选摘要、空表、多表、歧义、余额异常。
- API 测试:原始文件名、multipart、大小限制、失败不建成功批次、全部批次返回。
## 依赖
Issue 002、004。
@@ -0,0 +1,32 @@
# [P1] 规范转账事件、双边匹配与调拨排除
## 背景
当前没有规范事件存储。A 公司转出和 B 公司转入会成为两条银行观察,若直接汇总会重复统计;同公司不同账户调拨也必须排除。
## 范围
- 将银行源行作为不可变观察,将一个或两个观察关联到一个规范转账事件。
- 按本方账号确定所有者,按对方账号优先、已审核别名次之确定对方。
- 双边候选至少考虑金额、相反方向、双方账号、日期窗口、银行参考号和摘要。
- 同一所有者标记为同公司调拨,保留流水但排除公司间余额。
- 未可靠识别对方的交易标记外部或待识别,不进入内部余额。
- 支持个人过账账户映射和人工关联,保留操作依据。
- 重复导入、反向导入和重新匹配必须幂等。
## 验收标准
- [ ] A 转出 100 万与 B 转入 100 万只形成一个规范事件和一次公司间影响。
- [ ] 先导入任意一方、后导入另一方,最终结果一致。
- [ ] 同公司跨银行调拨不进入任何公司间借贷合计。
- [ ] 多候选场景进入人工审核,不自动选择低置信候选。
- [ ] 未识别、外部、已匹配、同公司调拨状态互斥且可追溯。
- [ ] 重新运行匹配不会复制事件或改变已锁定人工决定。
## 测试
- 双边顺序、日期跨日、相同金额多候选、重复导入、同公司调拨、外部交易、个人过账测试。
## 依赖
Issue 004、005。
@@ -0,0 +1,31 @@
# [P1] 公司间科目与余额计算、手工记录入账
## 背景
`web/app.js::pairData()` 生成演示金额。已确认手工记录不会进入计算,四个会计科目和公司对结果也没有服务端核算引擎。
## 范围
- 以规范事件和已批准手工记录为唯一期间发生额来源。
- 建立应收、应付、其他应收、其他应付的确定性分类规则和人工确认流程。
- 定义双方视角、借贷方向、冲销/归还和净额计算规则。
- 输出公司总借方/贷方、方向明细、对方公司+科目汇总、逐笔事件和原始证据。
- 每个余额显示截止日、期初、本期借贷、期末结果和未决金额。
- 手工记录审批前排除,审批通过后幂等进入规范事件;退回/异常不影响余额。
## 验收标准
- [ ] 计算不读取静态 HTML、`pairData()` 或客户端 `localStorage`
- [ ] A 对 B 的应收与 B 对 A 的应付金额绝对值一致,方向相反。
- [ ] 已批准手工记录只影响一次;状态回退或冲销有审计事件,不修改原事实。
- [ ] 科目不确定时进入审核,未确认金额单独展示且不混入已确认余额。
- [ ] 任意公司总额可下钻到方向、对方+科目、事件和银行源行。
- [ ] 金额全程使用 Decimal/数据库定点类型,舍入规则有文档和测试。
## 测试
- 双方守恒、还款、冲销、手工记录状态、科目歧义、截止日和未决金额测试。
## 依赖
Issue 006。
@@ -0,0 +1,31 @@
# [P1] 起算日、覆盖连续性、期初和断档校准
## 背景
总账页面已有起算日、期初和断档界面,但设置只显示 Toast,覆盖区间是静态数据。实际流水可能按 6.21-7.21 导出,不能按“上传月份”判断连续性。
## 范围
- 建立全局计算起算日和每公司对/科目的期初余额。
- 起算日前源行继续保存和可查询,但从所有核算聚合中排除。
- 按账户有效期和已接受流水的实际日期区间合并覆盖,不按文件月份推断。
- 检测起算日至最早流水、批次之间和最近应提交区间的缺口。
- 公司端可提交“期间无业务”校准,要求理由和证据;总账审核后只关闭覆盖缺口,不生成银行交易。
- 无可靠期初时明确显示“期间净变动”,不称为期末余额。
## 验收标准
- [ ] 起算日前后同批文件可正确截断,源行仍可审计查询。
- [ ] 6.21-7.21 与 7.22-8.21 被识别为连续;6.21-7.21 与 7.23-8.21 产生 7.22 缺口。
- [ ] 每个有效账户独立计算覆盖,停用区间不要求流水。
- [ ] 期初从双方视角守恒,修改已确认期初必须走调整/审核而非直接覆盖。
- [ ] 无业务校准有提交人、理由、审核人和时间,不制造金额或银行行。
- [ ] 缺口在总账端和对应公司端一致显示。
## 测试
- 边界日、重叠区间、相邻区间、缺一天、账户启停、起算截断、无业务审核和无期初标签测试。
## 依赖
Issue 004、005、007。
+31
View File
@@ -0,0 +1,31 @@
# [P1] 月结、重开、调整和审计报告
## 背景
当前月结仅修改 DOM。没有服务端前置条件、冻结快照、闭期补录处理、重开审批或调整/冲销模型。
## 范围
- 定义月结期间、状态、前置条件和服务端执行事务。
- 前置条件至少包含公司提交、账户覆盖、未决匹配/科目、期初和待审核手工记录。
- 结账生成可重算校验的结果快照和审计摘要。
- 闭期后到达的相关流水或手工记录进入重开异常,不静默改写快照。
- 重开、调整、冲销和再次结账均需权限、原因和完整历史。
- 输出月结审计报告,包括口径、阻断项、操作者、时间和前后结果差异。
## 验收标准
- [ ] 任一阻断条件未满足时,服务端拒绝结账,而非只禁用前端按钮。
- [ ] 结账后相同输入可验证快照;普通写接口不能修改闭期结果。
- [ ] 闭期补录创建重开异常,管理员审批前不改变已结账数字。
- [ ] 重开和再次结账形成版本链,可比较每版差异。
- [ ] 调整以新增审计事件完成,不编辑原始银行行。
- [ ] 审计报告可导出并追溯到源事件和源行。
## 测试
- 并发结账、阻断条件、闭期补录、重开拒绝/通过、调整、重复执行幂等和快照校验测试。
## 依赖
Issue 007、008。
+31
View File
@@ -0,0 +1,31 @@
# [P2] 服务端流水查询与可追溯导出
## 背景
当前流水查询只过滤静态表格,CSV 中的导入批次和源行定位由前端生成 `IMP-DEMO-*``Sheet1!R*`,不是真实证据标识。
## 范围
- 提供服务端分页查询,支持公司、银行、账户、日期、方向、对方、匹配状态和关键词。
- 总账端可查全部授权公司,公司端强制限定绑定公司。
- 查询结果包含源文件、工作表、源行、银行参考号、导入批次、规范事件和匹配状态。
- 导出使用稳定版本化 schema,复用相同权限和筛选条件。
- 大结果集采用流式/后台导出,避免浏览器内存拼接全部 CSV。
- 记录导出人、条件、时间和结果规模。
## 验收标准
- [ ] 页面显示、总数、金额汇总和导出使用同一服务端过滤语义。
- [ ] 公司用户无法导出其他公司记录,即使篡改请求参数。
- [ ] 导出中的批次和源行定位均来自真实持久化数据,不含演示占位符。
- [ ] 同公司调拨、外部、待识别和双边匹配状态可筛选。
- [ ] 日期和金额边界有明确时区/精度规则。
- [ ] 目标数据量下分页和导出性能达到约定指标,且不会阻塞上传解析。
## 测试
- 权限、组合筛选、分页稳定性、导出字段、CSV 注入防护和大数据量测试。
## 依赖
Issue 003、005、006。
+31
View File
@@ -0,0 +1,31 @@
# [P2] 自动/手动提醒引擎与状态流转
## 背景
当前提醒只在页面内新增 DOM,刷新后丢失,也不会同步到公司端。自动提醒触发器和状态机尚未实现。
## 范围
- 为未按期上传、覆盖断档、单边候选、未匹配内部流水和逾期审核生成自动提醒。
- 总账管理员可向一个公司发送带期限和关联任务的手动站内提醒。
- 持久化未读、已读、处理中、已完成状态和全部时间戳。
- 自动触发幂等:同一公司、任务、期间不重复轰炸;状态变化可关闭或重新打开提醒。
- 公司端点击提醒可回到具体上传、匹配、审核或覆盖任务。
- 预留外部通讯适配器,但当前默认仅启用站内提醒。
## 验收标准
- [ ] 五类自动触发器均有确定条件和幂等键。
- [ ] 手动提醒在对应公司账号登录后可见,其他公司不可见。
- [ ] 已读/处理中/完成状态跨设备持久化,并记录操作者与时间。
- [ ] 底层问题解决后相关提醒自动完成或等待明确确认,不永久悬空。
- [ ] 提醒链接能定位到原任务和证据。
- [ ] 外部通道未配置时不影响站内提醒,也不会伪报发送成功。
## 测试
- 定时触发、重复任务幂等、跨公司隔离、状态流转、任务解决和失败重试测试。
## 依赖
Issue 003、008、009。
@@ -0,0 +1,37 @@
# [P1] 前端生产 API 集成并移除演示数据
## 背景
当前双端 UI 已完成,但公司、账户、流水、审核、余额、结账和提醒主要来自静态 HTML、`pairData()`、DOM 修改或 `localStorage`。这会造成页面看似成功但服务端没有事实记录。
## 范围
- 为每个后端垂直切片建立 API 客户端、加载/空/错误/重试状态。
- 用服务端真实数据替换 A-F 公司、A 公司固定上下文、静态流水和演示审核行。
- 删除 `pairData()` 模拟核算和业务状态 `localStorage`;仅允许保留无业务风险的 UI 偏好。
- 表单提交以服务端响应为权威,失败时不得先显示成功或修改最终状态。
- 保留总账/公司独立路由、四统计卡层级、响应式、键盘和减少动效支持。
- 为上传、账户审批、手工记录审批、匹配确认、查询导出和结账建立端到端测试。
## 验收标准
- [ ] 刷新页面、重新登录和换一台客户端后,业务状态一致。
- [ ] 仓库中不再存在用于业务结果的 `pairData()``IMP-DEMO-*` 或硬编码 A-F 数据源。
- [ ] 公司上下文来自认证会话,不能由客户端选择或篡改。
- [ ] 所有成功提示都对应已提交的服务端事务;失败有明确恢复动作。
- [ ] 管理端和公司端仍是独立页面和不同首页优先级。
- [ ] 375、768、1024、1440px 下无页面级溢出,关键流程键盘可操作,状态不只依赖颜色。
- [ ] 关键端到端流程在 CI 中通过,浏览器控制台无未处理错误。
## 实施建议
不要等所有后端完成后一次性重写前端。按 Issue 004-011 的垂直切片逐步接入,每完成一个资源就删除对应演示状态。
## 测试
- 总账端和公司端分别覆盖登录、上传、审核、匹配、查询、导出、结账和刷新恢复的端到端测试。
- 覆盖公司级权限篡改、API 失败重试、空状态、慢响应、重复提交、移动端布局、键盘操作和减少动效模式。
## 依赖
Issue 003-011,按垂直切片推进。
+20
View File
@@ -0,0 +1,20 @@
# 未完成事项 Issue 索引
这些文件是可独立提交到 Gitea 的 Issue 规格。每项包含背景、范围、依赖、验收标准和测试要求。
| 编号 | 标题 | 优先级 | 依赖 |
|---|---|---|---|
| [001](001-p0-repository-data-hygiene.md) | 仓库银行样本数据分级与脱敏治理 | P0 | 无 |
| [002](002-p0-persistence-and-immutable-imports.md) | 持久化层与不可变银行导入基础 | P0 | 001 |
| [003](003-p0-auth-and-tenant-isolation.md) | 正式认证、RBAC 与公司级数据隔离 | P0 | 002 |
| [004](004-p1-dynamic-master-data.md) | 动态公司、用户、账户和别名主数据 | P1 | 002, 003 |
| [005](005-p1-import-api-hardening.md) | 银行导入 API 加固与回归测试 | P1 | 002, 004 |
| [006](006-p1-canonical-transfer-matching.md) | 规范转账事件、双边匹配与调拨排除 | P1 | 004, 005 |
| [007](007-p1-position-calculation.md) | 公司间科目与余额计算、手工记录入账 | P1 | 006 |
| [008](008-p1-calculation-window-coverage.md) | 起算日、覆盖连续性、期初和断档校准 | P1 | 004, 005, 007 |
| [009](009-p1-monthly-close.md) | 月结、重开、调整和审计报告 | P1 | 007, 008 |
| [010](010-p2-flow-query-export.md) | 服务端流水查询与可追溯导出 | P2 | 003, 005, 006 |
| [011](011-p2-reminder-engine.md) | 自动/手动提醒引擎与状态流转 | P2 | 003, 008, 009 |
| [012](012-p1-frontend-production-api-integration.md) | 前端生产 API 集成并移除演示数据 | P1 | 003-011,按垂直切片推进 |
远程仓库当前只确认了 SSH Git 入口:`ssh://git@192.168.200.36:222/leefer/caiwuzongzhang.git`。本机没有 Gitea API Token 或 `tea` 登录,且尚未定位可用的 Gitea Web/API 入口,因此这些 Issue 先作为独立仓库文件保存,待提供 Web/API 入口和凭据后再创建远程 Issue。