借款出借人改为从现有员工选择并复用资料(09-17-company-loan-principal-repayment)
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

- 新增员工来源预览、关联与显式刷新接口,受 loan.manage 与员工银行卡权限保护;服务端读取并加密保存,客户端不能另传姓名账号
- 同公司同员工唯一复用,请求键绑定来源;锁序出借人→员工,员工使用 FOR NO KEY UPDATE
- 员工关联出借人禁止手工改账号;在途还款期间禁止刷新,刷新推进版本并使旧公司代表授权失效
- 电脑/手机共用对话框,写请求在卸载或身份切换时取消
- 无新增迁移;本地 126 组 HTTP、45 组浏览器、9 个变异通过,两名只读复核及 Claude 独立复核无阻断

Co-Authored-By: Claude Opus 5.5 <[email protected]>
这个提交包含在:
2026-10-09 21:03:07 +08:00
共同撰写人 Claude Opus 5.5
父节点 c1034bbe38
当前提交 45737ccb9a
共修改 20 个文件,包含 1157 行新增和 28 行删除
@@ -1,3 +1,18 @@
## 2026-10-09 N5 员工出借人选择方案(已批准,已本地实现)
本节对应 PRD 的 AC28–AC31。员工资料已存在于 `Employee`;现有 `loan-lenders/identity-options` 仅提供身份选择,借款登记尚未复用银行卡。目标是让财务选择现有员工并核对资料,服务端建立或复用借款出借人关系,保持现有贷款、授权和付款快照模型。
1. **选择与资料来源**:在原借款页面增加员工选择流程,复用现有选择框与人员检索样式。返回允许的身份摘要、公司关联、银行与遮罩账号、资料是否完整及来源版本;不向浏览器传完整账号或身份证件。来源为员工主档的当前银行资料,账户名沿现有员工付款规则使用真实姓名。公司关联可作为借款主体默认值,但必须由财务确认借款所属公司,不能把任职公司自动当作债务人。
2. **服务端关联**:新增明确的“从员工关联出借人”动作,只接收员工、借款公司、所见来源版本、核对声明及幂等键。服务端重读员工与银行资料,校验可选身份、公司、银行支持、账号格式/可解密性及资料版本,再沿现有加密方式保存借款侧资料、员工关联和审计。不能通过客户端提供姓名或账号覆盖来源。身份核对由财务此次明确确认完成,不再让同一员工先手填、再另做一次身份绑定。
3. **敏感权限与维护入口**:保留 `loan.manage` 的财务角色条件,并沿用 `employee.bank.read` / `employee.bank.manage` 的现有银行卡读取权限;不借员工选择扩展到完整人员档案、身份证件或银行卡明文查看。资料不全时定位原员工资料维护入口,有维护权限才可修正。姓名、开户行或账号修改不在借款选择弹窗内重复提供。
4. **重复选择及锁序**:同公司同员工存在唯一可用登记时复用;多个历史登记时返回明确冲突,不自动合并借款、账户或授权。新建关联在事务内对来源员工及经办人排序串行,重查重复并保存创建/复用的请求键绑定;刷新已有出借人沿“出借人 → 人员”的顺序锁定,不持人员锁反向锁已有出借人。员工使用 `FOR NO KEY UPDATE`,保留串行保护并兼容审计外键的 `KEY SHARE`。旧身份关联路径也参加同一重复检查;发现并发关系变化时结束事务,按正确锁序重新核对或拒绝,不建立错误关系。
5. **资料变更与历史**:预览至保存间来源变化要求重新核对。已有借款资料与员工主档不同,不静默覆盖;显式“使用当前员工资料”动作由服务端读源、比较版本,沿既有在途禁止修改、账户/身份版本与授权失效规则处理并留审计。已审批或已付批次仍消费原冻结快照。后续员工资料维护不直接重写出借人、付款批次、银行事实或本金。
6. **数据与范围**:优先复用 `employee_id`、出借人版本和既有审计,无需为员工再建一套人员档案。不得为减少手工录入而增加无依据身份、放宽审批排除或恢复 Q6。若实施研究证明必须新增数据库约束或字段,先明确迁移、存量与兼容影响,再扩展本方案;本节不预先授权存量合并、生产迁移或业务录入。
验证包括:资料完整的员工正常关联、缺字段/账号不可用/银行不支持、无银行卡读取权限、客户端伪造、重复及并发选择、预览后资料改变、已有借款资料不一致、在途禁止刷新、员工改号后旧付款快照保持,以及财务/马经理后续授权分工。只用合成数据,不读取真实账户或调用银行/OCR;沿现有测试入口完成针对性验证和只读复核。
界面查询按身份/员工/公司隔离;两个新写动作透传取消信号,随组件卸载或身份变化终止请求,成功回调再次核对身份。不能只隔离回调而让迟到 401 在另一身份下重发原动作;保留同身份的正常令牌刷新。只保护本次入口,不改变共享 HTTP 恢复语义。
## 2026-10-08 实样发现后的凭证处理方案(N1–N2 已本地实现)
本节对应 PRD 顶部 R4/AC5 补充及 implement 的 N1–N2,用户已明确“开始执行”。沿用已实现的两人关联模式、回单存储、人工核对和核销流程;不重新设计 S1–S8/SR,不把 S002 专项格式兼容纳入必修范围。
@@ -1,3 +1,45 @@
## 2026-10-09 N5 员工出借人选择调整(本地实现与验证完成,未提交)
用户提出从现有员工选择出借人并复用资料,避免重复手录。已只读核对员工主档、敏感银行卡维护接口、借款登记/身份/账户接口及电脑手机共用页面;实现基线为本地 `c1034bbe`,线上仍为 `beb9f02c`。用户已明确确认方案,本轮接续本地实现及针对性验证;不连接生产、不代录真实数据,提交、推送和部署不在本轮授权内。
实施顺序:
1. 增加受现有财务和银行卡权限保护的员工资料预览及关联动作;服务端读取姓名、银行和加密账号,版本、重复及并发检查与审计同事务处理。
2. 把员工出借人入口改为选择与确认,移除该路径重复手录;已有登记复用,缺资料指向原员工维护入口;需要使用更新后的员工资料时显式核对并沿既有在途/版本规则刷新。使用既有组件,不引入新视觉体系。
3. 以合成数据完成 AC28–AC31 的正常与拒绝场景、并发和桌面/手机办理流程;资金守卫做必要的针对性变异,并检查旧付款快照及两人关联审批规则保持。
4. 做任务与相关前后端检查、只读复核,按实际能力报告独立复核状态。完成后汇报本地差异及验证,再按授权提交;推送、生产查询、部署和真实台账写入仍各自批准。新候选发布时重新取得完整门禁,不沿用 `beb9f02c` 回执。
范围限于现有员工资料复用与相关借款入口;不改当前报销待办、回单核验口径或生产批次状态。原非员工入口保留,技术员工不参与审批。优先复用现有表;若需要新迁移或存量合并,先补具体影响与批准,不顺手执行。
### 已实现内容
- 新增员工来源预览、关联和显式刷新服务及三个接口;受财务角色、`loan.manage` 和银行卡权限保护。只返回遮罩摘要;客户端不能另传姓名或账号。服务端读源、核对公司与版本,关联真实员工并加密保存借款侧资料及审计,不创建员工、不生成借款或付款。
- 同公司同员工的唯一匹配登记复用;历史重复、归档、旧入口绕过及预览后来源变化均拒绝。复用和创建都保存当前经办人的请求键绑定,防止同一键跨员工或公司使用。已有出借人先锁出借人,再排序锁员工;员工使用 `FOR NO KEY UPDATE`,兼容审计外键的 `KEY SHARE`。
- 员工资料不一致时要求显式“使用当前员工资料”,有在途占用不能刷新。刷新重验身份/账户/来源版本,同时推进身份与账户版本、留存核对审计并使旧公司代表授权失效;原本金及历史付款快照不改。员工关联记录不能再走手工收款账号 PATCH。
- 电脑、手机共用原组件样式:默认员工选择、公司明确核对、遮罩资料、缺项提示及有权限时的维护入口;非员工登记单列保留。资料查询按身份/员工/公司隔离并可取消;两个新写请求在卸载或切换身份时取消,避免迟到 401 以新账号重发。此保护不宣称已覆盖所有旧页面写请求。
- 本轮无新增迁移,仍为 82 项。旧测试为同一员工反复建立同公司出借人,现改为每个独立场景使用独立的合成公司;原业务断言保留。测试错误包装改为正式服务的 `requestId/error` 结构,保留原拒绝断言并验证实际页面错误提示。
### 独立只读复核与修复
本次复用了财务与界面两名只读复核代理,均不改文件、不重跑测试、不连接生产;本轮结论不借用 N3 的历史复核。两者接收修复与专项回执后均为 **REVIEWED_NO_BLOCKER**。
| 发现 | 修复及见证 |
| --- | --- |
| 财务 P2:复用未绑定请求键,旧键可能用于另一个员工 | 创建/复用的审计均保存来源及请求键,按经办人串行;顺序、并发与移除绑定的反例通过。 |
| 财务 P2:员工 `FOR UPDATE` 与审计员工外键形成锁循环 | 改为 `FOR NO KEY UPDATE`;实际 HTTP 关联和刷新经数据库 gate 确定性交错,两请求均完成;恢复旧锁时观测 PostgreSQL 死锁计数增长。 |
| 界面 P1:仅隔离回调不能阻止旧 POST 在切换身份后因 401 被重发 | 两个写动作透传并在卸载/身份变化时终止 `AbortSignal`;同一浏览器文档中真实退出/登录另一财务,延迟旧 401,验证取消、无重发、无错误写入/审计,同时验证同身份自动刷新仍成功。 |
### 验证回执
证据根目录:`artifacts/qa-flow/loan-employee-source-20261009/`,均为本地合成数据。
- `mutations-r6.log`:82 迁移、10 组员工 HTTP、9 个针对性变异、资源清理全部 PASS。变异覆盖银行卡权限、来源版本、旧身份重复入口、员工串行锁、外键锁兼容、在途占用、出借人版本、复用请求键及必要审计;普通超时或环境失败不能算捕获。
- `browser-r3.log`:10 组员工 HTTP 和 8 组电脑/手机浏览器场景 PASS,包括历史借入、余额核对、财务登记授权及指定经理确认;关联/刷新同身份 401 恢复、跨身份迟到请求取消均实际执行。截图在 `browser-LWICsl/`;横向溢出检查和主会话截图走查通过。
- `unit-r1.log`:本轮针对授权策略和错误消息合同的 2 文件、948 项通过;其输入未改变,后续复用。`frontend-build-r5.log` 的类型检查及构建、Prisma 校验、错误码合同、UI 规则和差异检查通过。未运行本次服务端全量或完整发布门禁。
- 完整借款 HTTP/浏览器回归:`regression-r2.log`、`regression-r2-process.json` 和去重汇总 `regression-r2-summary.json` 为 PASS,退出 0;82 迁移、原有 116 组 HTTP 加新增 10 组(共 126 组)、45 组浏览器、9 组基础数据库检查及资源清理通过。45 组已包含关联模式的 18 组和新入口的 8 组,不重复累加。首轮收到 SIGTERM(退出 143),没有最终回执,不能算通过;信号来源未证实,原日志和 `regression-r1-interruption.json` 保留,已按 owner 标签核对并只清理该轮隔离容器/临时目录。第二轮使用同一命令和断言在独立进程执行,不缩小范围、不增加用例重试。
- 较早失败记录保留:首轮账号解密返回空值的分类问题已修;前两轮浏览器分别暴露选择框可访问名称和测试错误包装问题,已修并完整重跑专项;`mutations-r3`–`r5` 的合成交错类型/顺序及捕获分类未通过,不计入通过次数,最终以 r6 为准。
AC28–AC31 的本地实现及验收已完成,最终文档治理结果见本目录 `final-checks.json`。文档索引保留既有 22 份未登记文件的警告,无新增错误,不在本轮整理无关文档。N5 真实台账/公司授权登记和 N6 首笔真实还款仍待办理,整体任务保持 `in_progress`;没有提交、推送、部署、访问生产、调用真实 OCR 或代录真实资料。线上仍为 `beb9f02c`;新候选以后发布须重新跑完整门禁。
## 2026-10-09 N4 发布结果与 N5/N6 接续
本节记录已完成的发布,候选为 `beb9f02c19970aa452c3fac02debfb10db0d4a3d`。Claude 会话执行发布及核对、由用户转交结果;主会话另核对本地候选、只读汇总、部署与补验日志、独立复核记录及生产 PDF 冒烟回执。本轮只更新现有任务文档,没有重新连接生产、执行付款或改动程序;整体任务仍为 `in_progress`。
@@ -1,5 +1,16 @@
# 公司借款台账与本金归还
## 2026-10-09 N5 员工出借人选择调整(本地验证完成,未发布)
用户要求员工出借人从已有员工中选择,复用系统中已维护的资料,不重复录入姓名和银行卡。已核对:员工主档存在姓名、公司关联、银行机构及加密账号;原借款入口要求手填,再另行核实员工关联。用户已确认本方案,授权本地实现与验证;不包含提交、推送、部署或真实业务录入。
- 员工出借人从已有 OA 员工选择,财务核对姓名、所属公司、开户行和遮罩账号后关联;姓名与银行资料由服务端读取,不接受浏览器另传一套值,也不创建新员工。借款所属公司仍须明确确认。
- 沿用现有员工资料和银行卡维护权限;资料缺失、不可用或不符合现行付款条件时,说明缺项并引导有权限的人到员工资料维护,不在借款表单重复填写或自行替换真实开户行。
- 同公司同员工已有出借人登记时优先复用;历史重复或资料不一致必须显式处理,不按姓名合并。员工资料更新不自动改写借款授权或在途付款;复用后的账户刷新按既有版本、占用和审计规则核对。
- 仅调整员工出借人的资料入口;原非员工个人出借人能力保留,关联方审批、技术员工不参与、Q6 禁用和真实付款授权边界不变。具体实现及验证范围见 design、implement 顶部。
AC28–AC31 已本地实现并通过独立只读复核:126 组借款 HTTP、45 组电脑/手机浏览器、82 迁移、9 个针对性变异及相关类型/构建/合同检查通过;实际范围、前期失败和完整重跑证据见 implement。未提交、未发布,也未录入真实台账;不把本次软件验收算作 N5 真实登记或 N6 银行还款闭环完成。
## 2026-10-09 N4 发布完成,真实业务验收待办
已接收并核对本次发布证据:`beb9f02c` 完整门禁 PASS,独立只读代码复核无阻断项;发布前只读核实借款相关存量均为 0、实际待应用迁移为 9 个。该候选已推送并部署,部署后 82/82 迁移全部应用、13/13 复核及合同刷新通过;公网健康、就绪、浏览器页面和静态资源检查正常(Claude 会话核对、用户转交);部署前按用户决定未做快照。生产合成 PDF 解析冒烟 PASS,运行版本与候选一致,识别为正式支出回单、PDF 文字、明确成功、无问题标记,耗时 521 毫秒。发布中断与补验过程、证据位置及核验边界见 implement 顶部。
@@ -181,6 +192,11 @@ R3 的模式同时作用于付款审批、提交清单、成功/失败归属、
- [x] AC26(页面与访问):电脑和手机以现有组件走通两人流程;财务无自审按钮,经理无经办按钮,必要材料按本批范围及用途审计读取;技术员工不获候选、待办、通知或材料。前端隐藏不能替代服务端鉴权。
- [x] AC27(数据与回退):仅新增型迁移,历史记录明确归为独立模式且不伪造授权;新字段、外键、模式/关联身份及不可变约束在数据库验收。新增关联决定后禁止不经评估降回不理解该模式的旧代码;最终候选重新验证并按规则只读复核,不沿用旧门禁宣称通过。数据库合成验收、独立代码复核及 `beb9f02c` 完整门禁已取得,生产已应用 82/82 迁移。
- [x] AC28(员工选择,本地验收完成):财务可从现有员工选择出借人并使用已有姓名、银行和账号,直接关联真实员工身份;不新建员工、不要求再次录入同一资料,列表与确认页只显示遮罩账号。借款所属公司明确,非员工路径不隐瞒已有员工身份。
- [x] AC29(来源与权限,本地验收完成):只有现有合格财务可以选择并关联;银行卡资料权限继续校验,不扩大员工或技术人员权限。缺资料、不可用银行或账号、越权及伪造客户端姓名/账户均拒绝;资料只在原员工维护入口补正。
- [x] AC30(重复与版本,本地验收完成):重复或并发选择同公司同员工复用明确的已有登记,不产生新员工或无声合并历史记录;预览至确认间来源变更时要求重新核对。已有出借人刷新保持既有锁序、版本、在途限制和审计;员工主档变化不改写已批准付款、已发生银行事实或本金。
- [x] AC31(办理验证,本地验收完成):合成数据贯通选择员工、登记历史借入、确认余额、登记公司授权及经理确认;电脑/手机入口和缺资料提示可用。验证来源变更、并发重复、无权限和旧快照保持的反例,不用真实员工资料或付款作为开发测试。
## Out of Scope
- 不处理利息、工资/分红、员工向公司借备用金、资本金、债转股、机构借款、外币、一般退款或债务冲销;仅保留本任务已定义的超额还款实际追回,不做冲抵后续本金。
@@ -194,6 +210,8 @@ R3 的模式同时作用于付款审批、提交清单、成功/失败归属、
## Current Status
N5 办理前新增“员工出借人从已有员工选择并复用资料”的调整要求,方案已列于本任务顶部,尚待批准实施。线上仍为原登记入口;本轮没有真实业务登记,也不重复索取已确认的借款事实。
当前线上及 `origin/main` 为 `beb9f02c`;N3 独立复核和 N4 本次发布检查已完成,实际发布过程及证据见 implement 顶部。完整门禁为 82 迁移、服务端 4558 通过/1 项既有可选跳过、浏览器 372 全通过且零失败/跳过/重试;生产迁移、部署后复核、公网基础检查及合成 PDF 解析已核对。本轮只更新任务文档,未重跑应用测试或操作生产。
整体任务保持 `in_progress`。真实 OA 台账及关联授权尚未登记,首笔真实还款的网银提交、正式回单、核销及会计交接尚未验收;AC5 及未覆盖的真实材料边界继续开放。无需重新索取已确认的借款事实或要求技术员工参与;真实录入和付款仍按各自授权执行,不从未还本金推定本次全额支付。