Commit bb3bd4ab4327632e1a5fcda460658debddab1610
1 parent
b3817b05
docs(module_mod): add module completion report
Showing
1 changed file
with
174 additions
and
0 deletions
docs/superpowers/module-reports/2026-04-30-module_mod.md
0 → 100644
| 1 | +--- | ||
| 2 | +module_id: module_mod | ||
| 3 | +date: 2026-04-30 | ||
| 4 | +git_range: 642c5f9..b3817b0 | ||
| 5 | +--- | ||
| 6 | + | ||
| 7 | +# 模块完成报告 — module_mod 模块管理 | ||
| 8 | + | ||
| 9 | +## ① 模块信息 | ||
| 10 | +- 模块 ID: module_mod | ||
| 11 | +- 模块名: 模块管理 | ||
| 12 | +- 开发区间: `642c5f9..b3817b0`(33 commits,4035 行新增) | ||
| 13 | +- 分支: `module-module_mod` | ||
| 14 | +- 起点:项目首个模块(首个 REQ 同时承担 Spring Boot 工程脚手架建立) | ||
| 15 | + | ||
| 16 | +## ② REQ 完成清单 | ||
| 17 | + | ||
| 18 | +- [x] REQ-MOD-001 — 模块新增 | ||
| 19 | + - spec: docs/superpowers/specs/2026-04-29-REQ-MOD-001.md | ||
| 20 | + - plan: docs/superpowers/plans/2026-04-29-REQ-MOD-001.md | ||
| 21 | + - review: docs/superpowers/reviews/2026-04-29-REQ-MOD-001.md | ||
| 22 | +- [x] REQ-MOD-002 — 模块修改 | ||
| 23 | + - spec: docs/superpowers/specs/2026-04-29-REQ-MOD-002.md | ||
| 24 | + - plan: docs/superpowers/plans/2026-04-29-REQ-MOD-002.md | ||
| 25 | + - review: docs/superpowers/reviews/2026-04-29-REQ-MOD-002.md | ||
| 26 | +- [x] REQ-MOD-003 — 模块删除 | ||
| 27 | + - spec: docs/superpowers/specs/2026-04-29-REQ-MOD-003.md | ||
| 28 | + - plan: docs/superpowers/plans/2026-04-29-REQ-MOD-003.md | ||
| 29 | + - review: docs/superpowers/reviews/2026-04-29-REQ-MOD-003.md | ||
| 30 | +- [x] REQ-MOD-004 — 模块查询 | ||
| 31 | + - spec: docs/superpowers/specs/2026-04-29-REQ-MOD-004.md | ||
| 32 | + - plan: docs/superpowers/plans/2026-04-29-REQ-MOD-004.md | ||
| 33 | + - review: docs/superpowers/reviews/2026-04-29-REQ-MOD-004.md | ||
| 34 | + | ||
| 35 | +## ③ 文件变更表 | ||
| 36 | + | ||
| 37 | +| 文件 | 操作 | 说明 | | ||
| 38 | +|---|---|---| | ||
| 39 | +| backend/pom.xml | 新建 | Spring Boot 3.3.5 + MyBatis-Plus 3.5.9 + Flyway + jjwt 0.12.6 | | ||
| 40 | +| backend/.gitignore | 新建 | target / *.iml / .idea | | ||
| 41 | +| backend/src/main/java/com/xly/erp/ErpApplication.java | 新建 | Spring Boot 启动类 + EnableConfigurationProperties | | ||
| 42 | +| backend/src/main/java/com/xly/erp/common/config/MybatisPlusConfig.java | 新建 | @MapperScan | | ||
| 43 | +| backend/src/main/java/com/xly/erp/common/config/TenantProperties.java | 新建 | erp.tenant.* 多租户字段 | | ||
| 44 | +| backend/src/main/java/com/xly/erp/common/config/StubSecurityProperties.java | 新建 | erp.security.stub-user-no / jwt-secret | | ||
| 45 | +| backend/src/main/java/com/xly/erp/common/response/Result.java | 新建 | 统一响应 {code,msg,data} | | ||
| 46 | +| backend/src/main/java/com/xly/erp/common/exception/BizException.java | 新建 | 业务异常 | | ||
| 47 | +| backend/src/main/java/com/xly/erp/common/exception/GlobalExceptionHandler.java | 新建 | @RestControllerAdvice 三类 handler | | ||
| 48 | +| backend/src/main/java/com/xly/erp/common/security/JwtUtil.java | 新建 | HS256 sign/parse | | ||
| 49 | +| backend/src/main/java/com/xly/erp/common/security/JwtAuthenticationFilter.java | 新建 | OncePerRequestFilter 解析 token | | ||
| 50 | +| backend/src/main/java/com/xly/erp/common/security/SecurityConfig.java | 新建 | /api/mod/** permitAll(USR-004 stub) | | ||
| 51 | +| backend/src/main/java/com/xly/erp/common/security/SecurityContextHelper.java | 新建 | currentUserNo 含 anonymous 识别 | | ||
| 52 | +| backend/src/main/java/com/xly/erp/module/mod/entity/Module.java | 新建 | tModule 1:1 PO(17 字段) | | ||
| 53 | +| backend/src/main/java/com/xly/erp/module/mod/dto/CreateModuleDTO.java | 新建 | REQ-MOD-001 入参(Bean Validation) | | ||
| 54 | +| backend/src/main/java/com/xly/erp/module/mod/dto/UpdateModuleDTO.java | 新建 | REQ-MOD-002 入参(剔除 sProcedureName) | | ||
| 55 | +| backend/src/main/java/com/xly/erp/module/mod/vo/ModuleTreeVO.java | 新建 | REQ-MOD-004 出参(递归 children) | | ||
| 56 | +| backend/src/main/java/com/xly/erp/module/mod/mapper/ModuleMapper.java | 新建 | BaseMapper + 4 个自定义 SELECT | | ||
| 57 | +| backend/src/main/java/com/xly/erp/module/mod/service/ModuleService.java | 新建 | create/update/delete/listTree | | ||
| 58 | +| backend/src/main/java/com/xly/erp/module/mod/service/impl/ModuleServiceImpl.java | 新建 | 含枚举/父链/子模块/拼树 全部业务校验 | | ||
| 59 | +| backend/src/main/java/com/xly/erp/module/mod/controller/ModuleController.java | 新建 | POST/PUT/DELETE/GET /api/mod/modules | | ||
| 60 | +| backend/src/main/resources/application.yml | 新建 | DB / Flyway / 端口 / erp.* 配置 | | ||
| 61 | +| backend/src/main/resources/application-test.yml | 新建 | test profile override | | ||
| 62 | +| backend/src/main/resources/logback-spring.xml | 新建 | 默认 console appender | | ||
| 63 | +| backend/src/test/java/com/xly/erp/SmokeTest.java | 新建 | Spring 启动 + Flyway apply 验证 | | ||
| 64 | +| backend/src/test/java/com/xly/erp/common/exception/GlobalExceptionHandlerTest.java | 新建 | 4 用例(standalone MockMvc) | | ||
| 65 | +| backend/src/test/java/com/xly/erp/common/security/JwtUtilTest.java | 新建 | 3 用例 | | ||
| 66 | +| backend/src/test/java/com/xly/erp/common/security/TestJwtHelper.java | 新建 | 测试辅助签发 JWT | | ||
| 67 | +| backend/src/test/java/com/xly/erp/common/security/JwtAuthenticationFilterTest.java | 新建 | 3 用例(filter 三分支) | | ||
| 68 | +| backend/src/test/java/com/xly/erp/module/mod/mapper/ModuleMapperIT.java | 新建 | 5 用例(insert/parent/child queries) | | ||
| 69 | +| backend/src/test/java/com/xly/erp/module/mod/service/ModuleServiceImplTest.java | 新建 | 25 用例(create/update/delete/listTree) | | ||
| 70 | +| backend/src/test/java/com/xly/erp/module/mod/controller/ModuleControllerIT.java | 新建 | 26 用例(4 接口端到端 + JWT 路径) | | ||
| 71 | +| docs/superpowers/specs/2026-04-29-REQ-MOD-{001,002,003,004}.md | 新建 | 4 份功能规格 | | ||
| 72 | +| docs/superpowers/plans/2026-04-29-REQ-MOD-{001,002,003,004}.md | 新建 | 4 份 TDD 计划 | | ||
| 73 | +| docs/superpowers/reviews/2026-04-29-REQ-MOD-{001,002,003,004}.md | 新建 | 4 份 AI 自审报告 | | ||
| 74 | +| docs/superpowers/module-reports/module_mod-test-gate.md | 新建 | 本模块 test-gate 证据 | | ||
| 75 | +| docs/08-模块任务管理.md | 修改 | 4 个 REQ checkbox 勾上 | | ||
| 76 | +| scripts/setup-test-db.sh | 修改 | macOS Homebrew mysql-client 路径自动 prepend | | ||
| 77 | +| scripts/test.sh | 修改 | frontend 段在 frontend/ 缺失时跳过 | | ||
| 78 | + | ||
| 79 | +## ④ 数据库使用表 | ||
| 80 | + | ||
| 81 | +- 读: `tModule`(REQ-MOD-001/002/003/004 均涉及) | ||
| 82 | +- 写: `tModule` | ||
| 83 | + - INSERT:REQ-MOD-001(新增) | ||
| 84 | + - UPDATE:REQ-MOD-002(更新可编辑字段,依赖 MyBatis-Plus FieldStrategy.NOT_NULL 跳过 null 不动 sProcedureName/sCreatedBy/标准列);REQ-MOD-003(软删除:`bDeleted=1` + `tDeletedDate` + `sDeletedBy`) | ||
| 85 | + | ||
| 86 | +## ⑤ 测试结果 | ||
| 87 | + | ||
| 88 | +- `scripts/test.sh` 最终:**GREEN** | ||
| 89 | +- 通过: 67 / 失败: 0 / 跳过: 0(前端段因 `frontend/` 未初始化而 skip 不计入) | ||
| 90 | +- 覆盖率:未配置 jacoco,本期不报告(建议 USR 模块开始前在 pom 引入) | ||
| 91 | +- 详见: `docs/superpowers/module-reports/module_mod-test-gate.md` | ||
| 92 | +- 测试分布: | ||
| 93 | + - SmokeTest: 1 | ||
| 94 | + - GlobalExceptionHandlerTest: 4 | ||
| 95 | + - JwtUtilTest: 3 | ||
| 96 | + - JwtAuthenticationFilterTest: 3 | ||
| 97 | + - ModuleMapperIT: 5 | ||
| 98 | + - ModuleServiceImplTest: 25 | ||
| 99 | + - ModuleControllerIT: 26 | ||
| 100 | + | ||
| 101 | +## ⑥ 本模块新增 Migration | ||
| 102 | + | ||
| 103 | +—(本模块无 schema 改动;`tModule` 表由 A4 阶段 `V1__initial_schema.sql` 已落地) | ||
| 104 | + | ||
| 105 | +## ⑦ 跨模块改动清单(软规则 S2) | ||
| 106 | + | ||
| 107 | +无跨模块改动。本模块所有源码改动均位于 `backend/src/main/java/com/xly/erp/module/mod/**` + `backend/src/main/java/com/xly/erp/common/**`(首 REQ 必要的全局基础设施:Result/Exception/Security/Config)+ `backend/src/test/**`。`common/` 下的类(Result / GlobalExceptionHandler / JwtAuthenticationFilter / SecurityConfig 等)属于"项目级共用脚手架",由首 REQ MOD-001 一次建立,后续模块复用,不视为 S2 跨模块。 | ||
| 108 | + | ||
| 109 | +## ⑧ 偏离 spec 清单 | ||
| 110 | + | ||
| 111 | +- **REQ-MOD-002**:错误码段位与 docs/05 偏离——MOD-002 spec 选择复用 MOD-001 的 `40010`(显示类型枚举非法),而 docs/05 § REQ-MOD-002 错误码列表只列 40001/40021/40400。 (原因: 同字段在两个接口语义一致更优;spec § 业务规则 #2 已显式声明该决策,docs/05 后续可补一行) | ||
| 112 | +- **REQ-MOD-002**:spec 与 plan 写"controller 先 trim",实际实现 trim 在 service。 (原因: service 集中归一化更易测,行为等价;REQ-MOD-004 review 已指出,建议改 spec 文案对齐) | ||
| 113 | +- **REQ-MOD-003**:未实现 docs/05 § REQ-MOD-003 列出的 `40902` 外部引用拦截。 (原因: docs/03 当前 schema 中 tModule 无引用方表;spec § 业务规则 #3 + § 实现范围与边界抉择 #4 双处显式声明本期不实现,待引用方表落地后回填) | ||
| 114 | +- **REQ-MOD-004**:拼树策略不扩展祖先链——子节点命中而父节点未命中时,子节点直接挂为森林 root。 (原因: spec § 实现范围与边界抉择 #1 已声明,REQ 卡仅要求"以树形展示匹配结果",森林是合法树形;扩展祖先需二次查询或 CTE,复杂度收益不匹配本期需求) | ||
| 115 | +- **REQ-MOD-004**:LIKE 通配符 `%` / `_` 不做转义。 (原因: spec § 边界与约束已声明,业务上不敏感;docs/05 未要求;后续可通过 `replace("%","\\%")` 收口) | ||
| 116 | + | ||
| 117 | +## ⑨ AI reviewer 报告汇总 | ||
| 118 | + | ||
| 119 | +- REQ-MOD-001: round 1 — approve(link: docs/superpowers/reviews/2026-04-29-REQ-MOD-001.md) | ||
| 120 | +- REQ-MOD-002: round 1 — approve(link: docs/superpowers/reviews/2026-04-29-REQ-MOD-002.md) | ||
| 121 | +- REQ-MOD-003: round 1 — approve(link: docs/superpowers/reviews/2026-04-29-REQ-MOD-003.md) | ||
| 122 | +- REQ-MOD-004: round 1 — approve(link: docs/superpowers/reviews/2026-04-29-REQ-MOD-004.md) | ||
| 123 | + | ||
| 124 | +全部 round 1 一次性通过;4 份 review 共 25 条 nice-to-have,无 must-fix。 | ||
| 125 | + | ||
| 126 | +## ⑩ 已知问题 | ||
| 127 | + | ||
| 128 | +整合自 4 份 review 的非阻塞 nice-to-have,按主题分组: | ||
| 129 | + | ||
| 130 | +**鉴权 stub 收尾(USR-004 闭环时一次性处理)** | ||
| 131 | +1. `SecurityConfig` 的 `requestMatchers("/api/mod/**").permitAll()` → 改为 `authenticated()` 或 `hasAuthority('SUPER_ADMIN')`(按 docs/05 § 各 REQ 的 Permission 字段精细化) | ||
| 132 | +2. `ModuleServiceImpl#create` 的 `stub.getStubUserNo()` 回退路径需移除(`sCreatedBy` 必须来自 JWT principal) | ||
| 133 | +3. 6 处 IT stub 用例(`postWithoutJwt_*` / `putWithoutJwt_*` / `deleteWithoutJwt_*` / `getWithoutJwt_*`)缺 `// REQ-MOD-001 stub: see USR-004 follow-up` 锚点;USR-004 上线时 grep 替换会漏 | ||
| 134 | + | ||
| 135 | +**架构遗留** | ||
| 136 | +4. `backend/src/main/java/com/xly/erp/module/mod/entity/Module.java` 类名 `Module` 与 `java.lang.Module`(JPMS)冲突;建议未来重命名为 `ModuleEntity` 或 `TModule` | ||
| 137 | +5. `JwtAuthenticationFilter` 加 `@Component` 同时被 Spring Security `addFilterBefore` 与原生 servlet 注册重复登记(`OncePerRequestFilter` 防住执行,但作用域不清);建议 USR-004 时改为 `@Bean` + `FilterRegistrationBean(setEnabled(false))` | ||
| 138 | +6. `JwtUtil` 暴露两个 public 构造器,`JwtUtil(String secret)` 实质 test-only;可改 package-private + 注释 | ||
| 139 | + | ||
| 140 | +**配置 / 校验** | ||
| 141 | +7. `application.yml` 中 `${JWT_SECRET}` 缺 fail-fast 默认值;建议改为 `${JWT_SECRET:?JWT_SECRET 必须从 .env.local 注入}` | ||
| 142 | +8. `application-dev.yml` 缺失(docs/09 § 二 列出但未生成);下一个模块本机 dev 启动时需要 | ||
| 143 | +9. `GlobalExceptionHandler#handleAny` 把 `HttpMessageNotReadableException` / `HttpRequestMethodNotSupportedException` 转 `code=50000`(应当是 40001);建议增加专用 4xx handler | ||
| 144 | +10. `DTO` `iParentId` / `iSortOrder` 缺 `@PositiveOrZero` / `@Min` 约束 | ||
| 145 | +11. `ModuleServiceImpl#updateById` / `delete` 的返回值(受影响行数)丢弃;并发场景下 `affected=0` 仍返回成功——可断言 `affected==1` 否则抛兜底异常 | ||
| 146 | + | ||
| 147 | +**测试覆盖缺口(非阻塞)** | ||
| 148 | +12. `@Size` 长度溢出(如 `sProcedureName > 100` 字符)路径仅在"缺必填"用例顺带覆盖,未独立断言 | ||
| 149 | +13. `iParentId` 指向 `bDeleted=1` 旧记录是否回 `40021` 未单独验证 | ||
| 150 | +14. 环检测 `MAX_PARENT_DEPTH=50` 超深路径仅有间接覆盖(未构造 50 层脏数据链) | ||
| 151 | +15. `tCreateDate` / `sBrandsId` / `sSubsidiaryId` 在 update / delete IT 端未端到端断言保留(service 单测已 captureArgument 验 entity 字段为 null + 依赖 NOT_NULL 策略) | ||
| 152 | +16. 业务方法行内 `// REQ-MOD-XXX:` 锚点缺失(4 处:create/update/delete/listTree);建议下个模块开始前一次性补齐 | ||
| 153 | +17. `ModuleMapperIT#selectActiveByKeyword_filtersAndOrders` 第 108–110 行 `namesByEmpty` 局部变量构造后未被任何 assert 使用(dead code),建议清理 | ||
| 154 | + | ||
| 155 | +## ⑪ 下一模块预览 | ||
| 156 | + | ||
| 157 | +**module_usr 用户管理**(docs/02 § 二 顺序的 REQ 5–8) | ||
| 158 | +- REQ-USR-001 用户新增(依赖 `tStaff` / `tPermissionCategory` 作下拉数据源) | ||
| 159 | +- REQ-USR-002 用户修改 | ||
| 160 | +- REQ-USR-003 用户查询(多条件 + 分页) | ||
| 161 | +- REQ-USR-004 用户登录(**关键**——完成后才能把 `/api/mod/**` 与 `/api/usr/**` 的 stub permitAll 收紧为 `hasAuthority('SUPER_ADMIN')`,并移除 service 层 `stub.getStubUserNo()` 回退路径) | ||
| 162 | + | ||
| 163 | +预期范围:`backend/src/main/java/com/xly/erp/module/usr/**` 全新模块树;`tUser` / `tStaff` / `tPermissionCategory` / `tUserPermission` schema 已在 V1 就位;JWT 签发由 USR-004 接管(覆写 MOD 期间手工签发的逻辑)。 | ||
| 164 | + | ||
| 165 | +USR 模块开工前的"扫尾建议": | ||
| 166 | +- 处理 § ⑩ #16(业务方法行内 REQ 锚点 4 处) | ||
| 167 | +- 处理 § ⑩ #8(生成 application-dev.yml 占位) | ||
| 168 | +- 处理 § ⑩ #17(删除 dead code) | ||
| 169 | + | ||
| 170 | +这三项是低成本一次性收口,建议作为 module_usr 的 REQ-USR-001 开工前第一个 chore commit 完成;其余 § ⑩ 项均围绕 USR-004 / 后续模块自然解决。 | ||
| 171 | + | ||
| 172 | +## ⑫ MR 链接 | ||
| 173 | + | ||
| 174 | +待 mr-create 填入。 |