# 004 动态主数据技术决策 对应 Issue:B-41(`docs/issues/004-p1-dynamic-master-data.md`)。 ## 账户状态机与生效区间 - `bank_accounts.status`:`pending → active → disabled`,审核退回为 `returned`;退回后同公司重新提交复用同一行并回到 `pending`,不产生 第二条记录。停用这个动作只对 `active` 开放,退回只对 `pending` 开放, 越界操作返回 409。 - 生效区间 `effective_from` / `effective_to`(含当天):公司提交时填写 期望启用日,管理员审核通过时确认;停用时写入 `effective_to`(默认当天)。 - 两个判定函数分开: - `is_usable`(上传选择、当期操作):仅 `active` 且在生效区间内。 - `is_identifiable`(历史流水所有权识别):`active` 或 `disabled` 且在 生效区间内——停用只终止未来参与,不改写历史归属。 ## 账号规范化与唯一性 - 账号入库前统一规范化:去空格/短横线、全角数字转半角,只存 6–32 位 数字的规范形式;唯一性由数据库 `UNIQUE(account_number)` 保证,并发 提交必然只有一个成功(有并发测试)。 - 公司端任何响应只含脱敏形式 `****尾四位`;完整账号只在总账管理端 (授权审计视图)返回。审计日志 detail 也只写脱敏账号。 ## 别名匹配优先级 - `account_aliases` 支持户名(`name`)与账号(`account`)两类别名, 各自带生效区间和 `priority` 列。 - 匹配优先级确定:精确账号(0)< 账号别名(1000+priority)< 户名别名(2000+priority);同层内按 `priority` 再按账户 id 排序。 别名只在自身生效区间且账户 `is_identifiable` 时参与匹配。 ## 审计轨迹 - 所有主数据变更写入 `master_data_changes`:实体、动作、前值 JSON、 后值 JSON、原因、操作人、时间。公司创建、账户提交/退回重提/ 审核/停用、别名创建全部覆盖,管理员可按实体查询。 ## 前端边界 - 公司下拉(往来查询、审核筛选、流水筛选、提醒、期初)和公司表格全部 由 `/api/admin/companies` 渲染,新增公司无需改代码即可被检索。 - 公司端账户目录、上传账户选择、手工记录资金来源只来自 `/api/company/accounts`,且只有 `usable` 账户进入上传选择。 - 手工记录仍是浏览器 localStorage 演示数据(属 Issue 007/012 范围), 账户登记已完全切换到服务端。