--- req_id: REQ-USR-002 date: 2026-05-06 round: 1 reviewer: superpower-code-reviewer --- # Review: REQ-USR-002 — round 1 ## 结论 approve ## Must-fix (无) ## Nice-to-have - backend/src/test/java/com/xly/erp/module/usr/controller/UserControllerIT.java:285 — `put_permissionCategoryNotFound_returns40422` 只断言响应 code,未断言 spec § 验收 #11 要求的 "DB user 与 tUserPermission 都不变(事务回滚)"。受 IT 类整体 `@Transactional+@Rollback` 制约,需另起 `Propagation.NOT_SUPPORTED` 测试或在 service 抛异常前后分别 reload 校验字段未变。 - backend/src/test/java/com/xly/erp/module/usr/controller/UserControllerIT.java:235 — `put_validUpdate_returns200_andDbReflects` 仅断言 `upCount==2L`,没显式断言新 2 条关联指向 `catNew1/catNew2` 且原 3 条已不存在。建议追加 `containsExactlyInAnyOrder(catNew1, catNew2)` + `doesNotContain(cat1, cat2, cat3)`。 - backend/src/test/java/com/xly/erp/module/usr/controller/UserControllerIT.java — IT 缺 `put_targetSoftDeleted_returns40431` 和 `put_staffSoftDeleted_returns40421` 两条端到端用例(spec § 验收 #7 / #10 仅在 service 单测覆盖)。 - backend/src/test/java/com/xly/erp/module/usr/controller/UserControllerIT.java:327 — `put_ignoresProtectedFields_doesNotChangeUserNoOrName` 未断言 tCreateDate 保留(spec § 业务规则 #7 / 验收 #4 列入"不被修改"范围)。 - backend/src/main/java/com/xly/erp/module/usr/entity/UserEntity.java:40 — `iStaffId` 全局 `FieldStrategy.IGNORED` 是已知副作用(注释已说明)。建议在 module_usr 完成报告 § ⑦ 跨模块改动 / 风险登记追加一条:"UserEntity.iStaffId 已加 IGNORED;后续 partial-update path 必须 selectById 后再 updateById",与 module_mod ModuleEntity.iParentId 同类风险并案管理。 - backend/src/main/java/com/xly/erp/module/usr/service/impl/UserServiceImpl.java — Service 中 iStaffId/sUserType/sLanguage 直接覆盖、bCanModifyDocs null 保留——建议加注释或抽 mergeUpdate 私有方法集中 null 语义。 - backend/src/test/java/com/xly/erp/module/usr/service/UserServiceImplTest.java — 未覆盖 `dto.permissionCategoryIds == null` 分支(spec § 业务规则 #5 "不传则只删不插")。当前所有相关测试都用 `List.of()` 而非 null。 ## 反例 / 测试覆盖缺口 1. **AC11 回滚证据**:`put_permissionCategoryNotFound_returns40422` 受 `@Transactional+@Rollback` 制约,无法直接观测 service 层的回滚。 2. **AC1 重建关联粒度**:`upCount==2` 可被任何 insert 顺序异常掩盖,需细化断言。 3. **AC7 / AC10 端到端缺失**:目标软删除 / staff 软删除均仅在 service 单测覆盖。 4. **AC4 tCreateDate 保留**:实现走 load-then-modify 默认 NOT_NULL 策略行为正确,但缺测试佐证。 5. **业务规则 #5 null permissionCategoryIds 分支**:单测未直接覆盖。 6. **iStaffId IGNORED 全局副作用**:本期安全,未来 partial-update path 风险,需在 module_usr 完成报告中登记。 **核心结论**:Spec/Plan 业务规则 1-9 全部实现到位,错误码 40010 / 40421 / 40422 / 40431 全部回归,UserVO 不暴露 sPasswordHash,保留字段 sUserNo / sUserName / sPasswordHash 不被改通过 IT 验证。docs/05 § REQ-USR-002 列的 40331 / 40931 是 RBAC 范畴的本期不实施项,spec 已说明,不阻塞。verdict: approve;改进项放下一 REQ 或 module-report sweep。